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(
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:%.*]]
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:%.*]]
22 ; CHECK-NEXT: [[RVAL1:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]
23 ; CHECK-NEXT: ret i32 [[RVAL1]]
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:%.*]]
29 ; CHECK-NEXT: call void @side_effect()
30 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
31 ; CHECK-NEXT: br label [[LOOP]]
33 ; CHECK-NEXT: ret i32 -1
35 ; CHECK-NEXT: [[RVAL2:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]
36 ; CHECK-NEXT: ret i32 [[RVAL2]]
39 %cond = icmp eq i32 %start, %x
40 %wc1 = call i1 @llvm.experimental.widenable.condition()
44 %iv = phi i32 [ %start, %entry ], [ %iv.next, %backedge ]
45 br i1 %wc1, label %guard_block, label %exit_by_wc
48 %rval1 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]
52 %wc2 = call i1 @llvm.experimental.widenable.condition()
53 %guard = and i1 %cond, %wc2
54 br i1 %guard, label %backedge, label %failure
57 call void @side_effect()
58 %iv.next = add i32 %iv, 1
65 %rval2 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]
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(
74 ; CHECK-NEXT: [[WC1:%.*]] = call i1 @llvm.experimental.widenable.condition()
75 ; CHECK-NEXT: br label [[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:%.*]]
80 ; CHECK-NEXT: [[RVAL1:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]
81 ; CHECK-NEXT: ret i32 [[RVAL1]]
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:%.*]]
88 ; CHECK-NEXT: call void @side_effect()
89 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
90 ; CHECK-NEXT: br label [[LOOP]]
92 ; CHECK-NEXT: ret i32 -1
94 ; CHECK-NEXT: [[RVAL2:%.*]] = call i32 (...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 [[IV]]) ]
95 ; CHECK-NEXT: ret i32 [[RVAL2]]
98 %wc1 = call i1 @llvm.experimental.widenable.condition()
102 %iv = phi i32 [ %start, %entry ], [ %iv.next, %backedge ]
103 br i1 %wc1, label %guard_block, label %exit_by_wc
106 %rval1 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]
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
116 call void @side_effect()
117 %iv.next = add i32 %iv, 1
124 %rval2 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]
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(
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:%.*]]
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:%.*]]
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:%.*]]
150 ; CHECK-NEXT: call void @side_effect()
151 ; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
152 ; CHECK-NEXT: br label [[LOOP]]
154 ; CHECK-NEXT: ret i32 -1
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]]
163 %cond = icmp eq i32 %start, %x
164 %wc1 = call i1 @llvm.experimental.widenable.condition()
165 %invariant = and i1 %c, %wc1
169 %iv = phi i32 [ %start, %entry ], [ %iv.next, %backedge ]
170 br i1 %invariant, label %guard_block, label %exit_by_wc
173 %rval1 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]
177 %wc2 = call i1 @llvm.experimental.widenable.condition()
178 %guard = and i1 %cond, %wc2
179 br i1 %guard, label %backedge, label %failure
182 call void @side_effect()
183 %iv.next = add i32 %iv, 1
190 %rval2 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %iv) ]
194 %rval3 = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %x) ]
198 ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(inaccessiblemem: readwrite)
199 declare i1 @llvm.experimental.widenable.condition()
201 declare void @side_effect()