[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / UnifyLoopExits / restore-ssa.ll
blobd06437ec5e0aeef572a0351641a81ea04a054439
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -unify-loop-exits -enable-new-pm=0 -S | FileCheck %s
3 ; RUN: opt < %s -passes='lowerswitch,unify-loop-exits' -S | FileCheck %s
5 ; Loop consists of A and B:
6 ; - A is the header
7 ; - A and B are exiting blocks
8 ; - C and return are exit blocks.
9 ; Pattern: Value (%mytmp42) defined in exiting block (A) and used in
10 ;          exit block (return).
11 ;          The relevant code uses DT::dominates(Value,
12 ;          BasicBlock). This is misnamed because it actually checks
13 ;          strict dominance, causing the pattern to be miscompiled
14 ;          (the use receives an undef value).
15 define i32 @exiting-used-in-exit(i32* %arg1, i32* %arg2) local_unnamed_addr align 2 {
16 ; CHECK-LABEL: @exiting-used-in-exit(
17 ; CHECK-NEXT:  entry:
18 ; CHECK-NEXT:    br label [[A:%.*]]
19 ; CHECK:       A:
20 ; CHECK-NEXT:    [[MYTMP42:%.*]] = load i32, i32* [[ARG1:%.*]], align 4
21 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[MYTMP42]], 0
22 ; CHECK-NEXT:    br i1 [[CMP1]], label [[B:%.*]], label [[LOOP_EXIT_GUARD:%.*]]
23 ; CHECK:       B:
24 ; CHECK-NEXT:    [[MYTMP41:%.*]] = load i32, i32* [[ARG2:%.*]], align 4
25 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[MYTMP41]], 0
26 ; CHECK-NEXT:    br i1 [[CMP]], label [[A]], label [[LOOP_EXIT_GUARD]]
27 ; CHECK:       C:
28 ; CHECK-NEXT:    [[INC:%.*]] = add i32 [[MYTMP41_MOVED:%.*]], 1
29 ; CHECK-NEXT:    br label [[RETURN:%.*]]
30 ; CHECK:       return:
31 ; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[INC]], [[C:%.*]] ], [ [[PHI_MOVED:%.*]], [[LOOP_EXIT_GUARD]] ]
32 ; CHECK-NEXT:    ret i32 [[PHI]]
33 ; CHECK:       loop.exit.guard:
34 ; CHECK-NEXT:    [[GUARD_RETURN:%.*]] = phi i1 [ true, [[A]] ], [ false, [[B]] ]
35 ; CHECK-NEXT:    [[PHI_MOVED]] = phi i32 [ [[MYTMP42]], [[A]] ], [ undef, [[B]] ]
36 ; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ undef, [[A]] ], [ [[MYTMP41]], [[B]] ]
37 ; CHECK-NEXT:    br i1 [[GUARD_RETURN]], label [[RETURN]], label [[C]]
39 entry:
40   br label %A
43   %mytmp42 = load i32, i32* %arg1, align 4
44   %cmp1 = icmp slt i32 %mytmp42, 0
45   br i1 %cmp1, label %B, label %return
48   %mytmp41 = load i32, i32* %arg2, align 4
49   %cmp = icmp slt i32 %mytmp41, 0
50   br i1 %cmp, label %A, label %C
53   %inc = add i32 %mytmp41, 1
54   br label %return
56 return:
57   %phi = phi i32 [ %inc, %C ], [ %mytmp42, %A ]
58   ret i32 %phi
61 ; Loop consists of A, B and C:
62 ; - A is the header
63 ; - A and C are exiting blocks
64 ; - B is an "internal" block that dominates exiting block C
65 ; - D and return are exit blocks.
66 ; Pattern: Value (%mytmp41) defined in internal block (B) and used in an
67 ;          exit block (D).
68 define i32 @internal-used-in-exit(i32* %arg1, i32* %arg2) local_unnamed_addr align 2 {
69 ; CHECK-LABEL: @internal-used-in-exit(
70 ; CHECK-NEXT:  entry:
71 ; CHECK-NEXT:    [[MYTMP42:%.*]] = load i32, i32* [[ARG1:%.*]], align 4
72 ; CHECK-NEXT:    br label [[A:%.*]]
73 ; CHECK:       A:
74 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[MYTMP42]], 0
75 ; CHECK-NEXT:    br i1 [[CMP1]], label [[B:%.*]], label [[LOOP_EXIT_GUARD:%.*]]
76 ; CHECK:       B:
77 ; CHECK-NEXT:    [[MYTMP41:%.*]] = load i32, i32* [[ARG2:%.*]], align 4
78 ; CHECK-NEXT:    br label [[C:%.*]]
79 ; CHECK:       C:
80 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[MYTMP42]], 0
81 ; CHECK-NEXT:    br i1 [[CMP]], label [[A]], label [[LOOP_EXIT_GUARD]]
82 ; CHECK:       D:
83 ; CHECK-NEXT:    [[INC:%.*]] = add i32 [[MYTMP41_MOVED:%.*]], 1
84 ; CHECK-NEXT:    br label [[RETURN:%.*]]
85 ; CHECK:       return:
86 ; CHECK-NEXT:    ret i32 0
87 ; CHECK:       loop.exit.guard:
88 ; CHECK-NEXT:    [[GUARD_RETURN:%.*]] = phi i1 [ true, [[A]] ], [ false, [[C]] ]
89 ; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ undef, [[A]] ], [ [[MYTMP41]], [[C]] ]
90 ; CHECK-NEXT:    br i1 [[GUARD_RETURN]], label [[RETURN]], label [[D:%.*]]
92 entry:
93   %mytmp42 = load i32, i32* %arg1, align 4
94   br label %A
97   %cmp1 = icmp slt i32 %mytmp42, 0
98   br i1 %cmp1, label %B, label %return
101   %mytmp41 = load i32, i32* %arg2, align 4
102   br label %C
105   %cmp = icmp slt i32 %mytmp42, 0
106   br i1 %cmp, label %A, label %D
109   %inc = add i32 %mytmp41, 1
110   br label %return
112 return:
113   ret i32 0
116 ; Loop consists of A, B and C:
117 ; - A is the header
118 ; - A and C are exiting blocks
119 ; - B is an "internal" block that dominates exiting block C
120 ; - D and return are exit blocks.
121 ; Pattern: %return contains a phi node that receives values from
122 ;          %entry, %A and %D. This mixes all the special cases in a single phi.
123 define i32 @mixed-use-in-exit(i32* %arg1, i32* %arg2) local_unnamed_addr align 2 {
124 ; CHECK-LABEL: @mixed-use-in-exit(
125 ; CHECK-NEXT:  entry:
126 ; CHECK-NEXT:    [[MYTMP42:%.*]] = load i32, i32* [[ARG1:%.*]], align 4
127 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[MYTMP42]], 0
128 ; CHECK-NEXT:    br i1 [[CMP2]], label [[A:%.*]], label [[RETURN:%.*]]
129 ; CHECK:       A:
130 ; CHECK-NEXT:    [[MYTMP43:%.*]] = add i32 [[MYTMP42]], 1
131 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[MYTMP42]], 0
132 ; CHECK-NEXT:    br i1 [[CMP1]], label [[B:%.*]], label [[LOOP_EXIT_GUARD:%.*]]
133 ; CHECK:       B:
134 ; CHECK-NEXT:    [[MYTMP41:%.*]] = load i32, i32* [[ARG2:%.*]], align 4
135 ; CHECK-NEXT:    br label [[C:%.*]]
136 ; CHECK:       C:
137 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[MYTMP42]], 0
138 ; CHECK-NEXT:    br i1 [[CMP]], label [[A]], label [[LOOP_EXIT_GUARD]]
139 ; CHECK:       D:
140 ; CHECK-NEXT:    br label [[RETURN]]
141 ; CHECK:       return:
142 ; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[MYTMP41_MOVED:%.*]], [[D:%.*]] ], [ [[MYTMP42]], [[ENTRY:%.*]] ], [ [[PHI_MOVED:%.*]], [[LOOP_EXIT_GUARD]] ]
143 ; CHECK-NEXT:    ret i32 [[PHI]]
144 ; CHECK:       loop.exit.guard:
145 ; CHECK-NEXT:    [[GUARD_RETURN:%.*]] = phi i1 [ true, [[A]] ], [ false, [[C]] ]
146 ; CHECK-NEXT:    [[PHI_MOVED]] = phi i32 [ [[MYTMP43]], [[A]] ], [ undef, [[C]] ]
147 ; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ undef, [[A]] ], [ [[MYTMP41]], [[C]] ]
148 ; CHECK-NEXT:    br i1 [[GUARD_RETURN]], label [[RETURN]], label [[D]]
150 entry:
151   %mytmp42 = load i32, i32* %arg1, align 4
152   %cmp2 = icmp slt i32 %mytmp42, 0
153   br i1 %cmp2, label %A, label %return
156   %mytmp43 = add i32 %mytmp42, 1
157   %cmp1 = icmp slt i32 %mytmp42, 0
158   br i1 %cmp1, label %B, label %return
161   %mytmp41 = load i32, i32* %arg2, align 4
162   br label %C
165   %cmp = icmp slt i32 %mytmp42, 0
166   br i1 %cmp, label %A, label %D
169   br label %return
171 return:
172   %phi = phi i32 [ %mytmp41, %D ], [ %mytmp43, %A ], [%mytmp42, %entry]
173   ret i32 %phi
176 ; Loop consists of A, B and C:
177 ; - A is the header
178 ; - A and C are exiting blocks
179 ; - B is an "internal" block that dominates exiting block C
180 ; - D and E are exit blocks.
181 ; Pattern: Value (%mytmp41) defined in internal block (B) and used in a
182 ;          downstream block not related to the loop (return). The use
183 ;          is a phi where the incoming block for %mytmp41 is not related
184 ;          to the loop (D).
185 ;          This pattern does not involve either the exiting blocks or
186 ;          the exit blocks, which catches any such assumptions built
187 ;          into the SSA reconstruction phase.
188 define i32 @phi-via-external-block(i32* %arg1, i32* %arg2) local_unnamed_addr align 2 {
189 ; CHECK-LABEL: @phi-via-external-block(
190 ; CHECK-NEXT:  entry:
191 ; CHECK-NEXT:    [[MYTMP42:%.*]] = load i32, i32* [[ARG1:%.*]], align 4
192 ; CHECK-NEXT:    br label [[A:%.*]]
193 ; CHECK:       A:
194 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp slt i32 [[MYTMP42]], 0
195 ; CHECK-NEXT:    br i1 [[CMP1]], label [[B:%.*]], label [[LOOP_EXIT_GUARD:%.*]]
196 ; CHECK:       B:
197 ; CHECK-NEXT:    [[MYTMP41:%.*]] = load i32, i32* [[ARG2:%.*]], align 4
198 ; CHECK-NEXT:    br label [[C:%.*]]
199 ; CHECK:       C:
200 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[MYTMP42]], 0
201 ; CHECK-NEXT:    br i1 [[CMP]], label [[A]], label [[LOOP_EXIT_GUARD]]
202 ; CHECK:       D:
203 ; CHECK-NEXT:    br label [[RETURN:%.*]]
204 ; CHECK:       E:
205 ; CHECK-NEXT:    br label [[RETURN]]
206 ; CHECK:       return:
207 ; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[MYTMP41_MOVED:%.*]], [[D:%.*]] ], [ [[MYTMP42]], [[E:%.*]] ]
208 ; CHECK-NEXT:    ret i32 [[PHI]]
209 ; CHECK:       loop.exit.guard:
210 ; CHECK-NEXT:    [[GUARD_E:%.*]] = phi i1 [ true, [[A]] ], [ false, [[C]] ]
211 ; CHECK-NEXT:    [[MYTMP41_MOVED]] = phi i32 [ undef, [[A]] ], [ [[MYTMP41]], [[C]] ]
212 ; CHECK-NEXT:    br i1 [[GUARD_E]], label [[E]], label [[D]]
214 entry:
215   %mytmp42 = load i32, i32* %arg1, align 4
216   br label %A
219   %cmp1 = icmp slt i32 %mytmp42, 0
220   br i1 %cmp1, label %B, label %E
223   %mytmp41 = load i32, i32* %arg2, align 4
224   br label %C
227   %cmp = icmp slt i32 %mytmp42, 0
228   br i1 %cmp, label %A, label %D
231   br label %return
234   br label %return
236 return:
237   %phi = phi i32 [ %mytmp41, %D ], [ %mytmp42, %E ]
238   ret i32 %phi