Follow up to d0858bffa11, add missing REQUIRES x86
[llvm-project.git] / llvm / test / Transforms / GuardWidening / loop_invariant_widenable_condition.ll
blobb528cf021ab6d08fdc9a9007ff829abbf148a283
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=guard-widening -S < %s | FileCheck %s
4 declare i32 @llvm.experimental.deoptimize.i32(...)
6 ; Make sure the two loop-invariant conditions can be widened together,
7 ; and the widening point is outside the loop.
8 define i32 @test_01(i32 %start, i32 %x) {
9 ; CHECK-LABEL: @test_01(
10 ; CHECK-NEXT:  entry:
11 ; CHECK-NEXT:    [[START_GW_FR:%.*]] = freeze i32 [[START:%.*]]
12 ; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
13 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[START_GW_FR]], [[X_GW_FR]]
14 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 true, [[COND]]
15 ; CHECK-NEXT:    [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition()
16 ; CHECK-NEXT:    br label [[LOOP:%.*]]
17 ; CHECK:       loop:
18 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START_GW_FR]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
19 ; CHECK-NEXT:    [[TMP0:%.*]] = and i1 [[WIDE_CHK]], [[WC1]]
20 ; CHECK-NEXT:    br i1 [[TMP0]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]]
21 ; CHECK:       exit_by_wc:
22 ; CHECK-NEXT:    [[RVAL1:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]
23 ; CHECK-NEXT:    ret i32 [[RVAL1]]
24 ; CHECK:       guard_block:
25 ; CHECK-NEXT:    [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition()
26 ; CHECK-NEXT:    [[GUARD:%.*]] = and i1 [[COND]], [[WC2]]
27 ; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[FAILURE:%.*]]
28 ; CHECK:       backedge:
29 ; CHECK-NEXT:    call void @side_effect()
30 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
31 ; CHECK-NEXT:    br label [[LOOP]]
32 ; CHECK:       exit:
33 ; CHECK-NEXT:    ret i32 -1
34 ; CHECK:       failure:
35 ; CHECK-NEXT:    [[RVAL2:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]
36 ; CHECK-NEXT:    ret i32 [[RVAL2]]
38 entry:
39   %cond = icmp eq i32 %start, %x
40   %wc1 = call i1 @llvm.experimental.widenable.condition()
41   br label %loop
43 loop:
44   %iv = phi i32 [ %start, %entry ], [ %iv.next, %backedge ]
45   br i1 %wc1, label %guard_block, label %exit_by_wc
47 exit_by_wc:
48   %rval1 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]
49   ret i32 %rval1
51 guard_block:
52   %wc2 = call i1 @llvm.experimental.widenable.condition()
53   %guard = and i1 %cond, %wc2
54   br i1 %guard, label %backedge, label %failure
56 backedge:
57   call void @side_effect()
58   %iv.next = add i32 %iv, 1
59   br label %loop
61 exit:
62   ret i32 -1
64 failure:
65   %rval2 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]
66   ret i32 %rval2
70 ; Make sure the loop-variant condition is not widened into loop-invariant.
71 define i32 @test_02(i32 %start, i32 %x) {
72 ; CHECK-LABEL: @test_02(
73 ; CHECK-NEXT:  entry:
74 ; CHECK-NEXT:    [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition()
75 ; CHECK-NEXT:    br label [[LOOP:%.*]]
76 ; CHECK:       loop:
77 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
78 ; CHECK-NEXT:    br i1 [[WC1]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]]
79 ; CHECK:       exit_by_wc:
80 ; CHECK-NEXT:    [[RVAL1:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]
81 ; CHECK-NEXT:    ret i32 [[RVAL1]]
82 ; CHECK:       guard_block:
83 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[IV]], [[X:%.*]]
84 ; CHECK-NEXT:    [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition()
85 ; CHECK-NEXT:    [[GUARD:%.*]] = and i1 [[COND]], [[WC2]]
86 ; CHECK-NEXT:    br i1 [[GUARD]], label [[BACKEDGE]], label [[FAILURE:%.*]]
87 ; CHECK:       backedge:
88 ; CHECK-NEXT:    call void @side_effect()
89 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
90 ; CHECK-NEXT:    br label [[LOOP]]
91 ; CHECK:       exit:
92 ; CHECK-NEXT:    ret i32 -1
93 ; CHECK:       failure:
94 ; CHECK-NEXT:    [[RVAL2:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]
95 ; CHECK-NEXT:    ret i32 [[RVAL2]]
97 entry:
98   %wc1 = call i1 @llvm.experimental.widenable.condition()
99   br label %loop
101 loop:
102   %iv = phi i32 [ %start, %entry ], [ %iv.next, %backedge ]
103   br i1 %wc1, label %guard_block, label %exit_by_wc
105 exit_by_wc:
106   %rval1 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]
107   ret i32 %rval1
109 guard_block:
110   %cond = icmp eq i32 %iv, %x
111   %wc2 = call i1 @llvm.experimental.widenable.condition()
112   %guard = and i1 %cond, %wc2
113   br i1 %guard, label %backedge, label %failure
115 backedge:
116   call void @side_effect()
117   %iv.next = add i32 %iv, 1
118   br label %loop
120 exit:
121   ret i32 -1
123 failure:
124   %rval2 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]
125   ret i32 %rval2
128 ; Same as test_01, but the initial condition is not immediately WC.
129 define i32 @test_03(i32 %start, i32 %x, i1 %c) {
130 ; CHECK-LABEL: @test_03(
131 ; CHECK-NEXT:  entry:
132 ; CHECK-NEXT:    [[START_GW_FR:%.*]] = freeze i32 [[START:%.*]]
133 ; CHECK-NEXT:    [[X_GW_FR:%.*]] = freeze i32 [[X:%.*]]
134 ; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[START_GW_FR]], [[X_GW_FR]]
135 ; CHECK-NEXT:    [[WIDE_CHK:%.*]] = and i1 [[C:%.*]], [[COND]]
136 ; CHECK-NEXT:    [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition()
137 ; CHECK-NEXT:    br label [[LOOP:%.*]]
138 ; CHECK:       loop:
139 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ [[START_GW_FR]], [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ]
140 ; CHECK-NEXT:    [[INVARIANT:%.*]] = and i1 [[WIDE_CHK]], [[WC1]]
141 ; CHECK-NEXT:    br i1 [[INVARIANT]], label [[GUARD_BLOCK:%.*]], label [[EXIT_BY_WC:%.*]]
142 ; CHECK:       exit_by_wc:
143 ; CHECK-NEXT:    [[RVAL1:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]
144 ; CHECK-NEXT:    ret i32 [[RVAL1]]
145 ; CHECK:       guard_block:
146 ; CHECK-NEXT:    [[WC2:%.*]] = call i1 @llvm.experimental.widenable.condition()
147 ; CHECK-NEXT:    [[GUARD:%.*]] = and i1 [[COND]], [[WC2]]
148 ; CHECK-NEXT:    br i1 true, label [[BACKEDGE]], label [[FAILURE:%.*]]
149 ; CHECK:       backedge:
150 ; CHECK-NEXT:    call void @side_effect()
151 ; CHECK-NEXT:    [[IV_NEXT]] = add i32 [[IV]], 1
152 ; CHECK-NEXT:    br label [[LOOP]]
153 ; CHECK:       exit:
154 ; CHECK-NEXT:    ret i32 -1
155 ; CHECK:       failure:
156 ; CHECK-NEXT:    [[RVAL2:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]
157 ; CHECK-NEXT:    ret i32 [[RVAL2]]
158 ; CHECK:       early_failure:
159 ; CHECK-NEXT:    [[RVAL3:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[X_GW_FR]]) ]
160 ; CHECK-NEXT:    ret i32 [[RVAL3]]
162 entry:
163   %cond = icmp eq i32 %start, %x
164   %wc1 = call i1 @llvm.experimental.widenable.condition()
165   %invariant = and i1 %c, %wc1
166   br label %loop
168 loop:
169   %iv = phi i32 [ %start, %entry ], [ %iv.next, %backedge ]
170   br i1 %invariant, label %guard_block, label %exit_by_wc
172 exit_by_wc:
173   %rval1 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]
174   ret i32 %rval1
176 guard_block:
177   %wc2 = call i1 @llvm.experimental.widenable.condition()
178   %guard = and i1 %cond, %wc2
179   br i1 %guard, label %backedge, label %failure
181 backedge:
182   call void @side_effect()
183   %iv.next = add i32 %iv, 1
184   br label %loop
186 exit:
187   ret i32 -1
189 failure:
190   %rval2 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]
191   ret i32 %rval2
193 early_failure:
194   %rval3 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %x) ]
195   ret i32 %rval3
198 ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite)
199 declare i1 @llvm.experimental.widenable.condition()
201 declare void @side_effect()