xref: /llvm-project/llvm/test/Transforms/IRNormalizer/reordering.ll (revision 2e9f8696e9533fdd464e025bd504302fa1a22f14)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt -S -passes=normalize -verify-each -norm-rename-all=false < %s | FileCheck %s
3
4define void @foo() {
5; CHECK-LABEL: define void @foo() {
6; CHECK-NEXT:  bb17254:
7; CHECK-NEXT:    ret void
8;
9  ret void
10}
11
12define void @empty_basic_block() {
13; CHECK-LABEL: define void @empty_basic_block() {
14; CHECK-NEXT:  exit:
15; CHECK-NEXT:    ret void
16;
17exit:
18  ret void
19}
20
21declare void @effecting()
22
23; Place dead instruction(s) before the terminator
24define void @call_effecting() {
25; CHECK-LABEL: define void @call_effecting() {
26; CHECK-NEXT:  bb15160:
27; CHECK-NEXT:    call void @effecting()
28; CHECK-NEXT:    [[TMP0:%.*]] = add i32 0, 1
29; CHECK-NEXT:    ret void
30;
31  %1 = add i32 0, 1
32  call void @effecting()
33  ret void
34}
35
36define void @dont_move_above_phi() {
37; CHECK-LABEL: define void @dont_move_above_phi() {
38; CHECK-NEXT:  bb76951:
39; CHECK-NEXT:    br label [[EXIT:%.*]]
40; CHECK:       exit:
41; CHECK-NEXT:    [[TMP0:%.*]] = phi i32 [ 0, [[BB76951:%.*]] ]
42; CHECK-NEXT:    call void @effecting()
43; CHECK-NEXT:    ret void
44;
45  br label %exit
46exit:
47  %1 = phi i32 [0, %0]
48  call void @effecting()
49  ret void
50}
51
52define void @dont_move_above_alloca() {
53; CHECK-LABEL: define void @dont_move_above_alloca() {
54; CHECK-NEXT:  bb15160:
55; CHECK-NEXT:    [[TMP0:%.*]] = alloca i32, align 4
56; CHECK-NEXT:    call void @effecting()
57; CHECK-NEXT:    ret void
58;
59  %1 = alloca i32
60  call void @effecting()
61  ret void
62}
63
64declare void @effecting1()
65
66define void @dont_reorder_effecting() {
67; CHECK-LABEL: define void @dont_reorder_effecting() {
68; CHECK-NEXT:  bb10075:
69; CHECK-NEXT:    call void @effecting()
70; CHECK-NEXT:    call void @effecting1()
71; CHECK-NEXT:    ret void
72;
73  call void @effecting()
74  call void @effecting1()
75  ret void
76}
77
78declare void @effecting2(i32)
79
80define void @dont_reorder_effecting1() {
81; CHECK-LABEL: define void @dont_reorder_effecting1() {
82; CHECK-NEXT:  bb10075:
83; CHECK-NEXT:    [[ONE:%.*]] = add i32 1, 1
84; CHECK-NEXT:    call void @effecting2(i32 [[ONE]])
85; CHECK-NEXT:    [[TWO:%.*]] = add i32 2, 2
86; CHECK-NEXT:    call void @effecting2(i32 [[TWO]])
87; CHECK-NEXT:    ret void
88;
89  %one = add i32 1, 1
90  %two = add i32 2, 2
91  call void @effecting2(i32 %one)
92  call void @effecting2(i32 %two)
93  ret void
94}
95
96define void @dont_reorder_across_blocks() {
97; CHECK-LABEL: define void @dont_reorder_across_blocks() {
98; CHECK-NEXT:  bb76951:
99; CHECK-NEXT:    [[ONE:%.*]] = add i32 1, 1
100; CHECK-NEXT:    br label [[EXIT:%.*]]
101; CHECK:       exit:
102; CHECK-NEXT:    call void @effecting2(i32 [[ONE]])
103; CHECK-NEXT:    ret void
104;
105  %one = add i32 1, 1
106  br label %exit
107exit:
108  call void @effecting2(i32 %one)
109  ret void
110}
111
112define void @independentldst(ptr %a, ptr %b) {
113; CHECK-LABEL: define void @independentldst(
114; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
115; CHECK-NEXT:  bb10495:
116; CHECK-NEXT:    %"vl12961([[B]])" = load i32, ptr [[B]], align 4
117; CHECK-NEXT:    store i32 %"vl12961([[B]])", ptr [[A]], align 4
118; CHECK-NEXT:    %"vl89528([[A]])" = load i32, ptr [[A]], align 4
119; CHECK-NEXT:    store i32 %"vl89528([[A]])", ptr [[B]], align 4
120; CHECK-NEXT:    ret void
121;
122  %2 = load i32, ptr %a
123  %3 = load i32, ptr %b
124  store i32 %3, ptr %a
125  store i32 %2, ptr %b
126  ret void
127}
128
129define void @multiple_use_ld(ptr %a, ptr %b) {
130; CHECK-LABEL: define void @multiple_use_ld(
131; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
132; CHECK-NEXT:  bb14927:
133; CHECK-NEXT:    %"vl16793([[A]])" = load i32, ptr [[A]], align 4
134; CHECK-NEXT:    store i32 %"vl16793([[A]])", ptr [[A]], align 4
135; CHECK-NEXT:    %"vl89528([[B]])" = load i32, ptr [[B]], align 4
136; CHECK-NEXT:    store i32 %"vl89528([[B]])", ptr [[B]], align 4
137; CHECK-NEXT:    store i32 %"vl16793([[A]])", ptr [[A]], align 4
138; CHECK-NEXT:    ret void
139;
140  %2 = load i32, ptr %a
141  store i32 %2, ptr %a
142  %3 = load i32, ptr %b
143  store i32 %3, ptr %b
144  store i32 %2, ptr %a
145  ret void
146}
147
148; This is an incorrect transformation. Moving the store above the load could
149; change the loaded value. To do this, the pointers would need to be `noalias`.
150define void @undef_st(ptr %a, ptr %b) {
151; CHECK-LABEL: define void @undef_st(
152; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
153; CHECK-NEXT:  bb10495:
154; CHECK-NEXT:    store i32 undef, ptr [[B]], align 4
155; CHECK-NEXT:    %"vl16028([[A]])" = load i32, ptr [[A]], align 4
156; CHECK-NEXT:    store i32 %"vl16028([[A]])", ptr [[A]], align 4
157; CHECK-NEXT:    ret void
158;
159  %2 = load i32, ptr %a
160  store i32 undef, ptr %b
161  store i32 %2, ptr %a
162  ret void
163}
164