xref: /aosp_15_r20/external/llvm/test/Transforms/EarlyCSE/guards.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; RUN: opt -S -early-cse < %s | FileCheck %s
2*9880d681SAndroid Build Coastguard Worker
3*9880d681SAndroid Build Coastguard Workerdeclare void @llvm.experimental.guard(i1,...)
4*9880d681SAndroid Build Coastguard Worker
5*9880d681SAndroid Build Coastguard Workerdefine i32 @test0(i32* %ptr, i1 %cond) {
6*9880d681SAndroid Build Coastguard Worker; We can do store to load forwarding over a guard, since it does not
7*9880d681SAndroid Build Coastguard Worker; clobber memory
8*9880d681SAndroid Build Coastguard Worker
9*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test0(
10*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  store i32 40, i32* %ptr
11*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
12*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  ret i32 40
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard Worker  store i32 40, i32* %ptr
15*9880d681SAndroid Build Coastguard Worker  call void(i1,...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
16*9880d681SAndroid Build Coastguard Worker  %rval = load i32, i32* %ptr
17*9880d681SAndroid Build Coastguard Worker  ret i32 %rval
18*9880d681SAndroid Build Coastguard Worker}
19*9880d681SAndroid Build Coastguard Worker
20*9880d681SAndroid Build Coastguard Workerdefine i32 @test1(i32* %val, i1 %cond) {
21*9880d681SAndroid Build Coastguard Worker; We can CSE loads over a guard, since it does not clobber memory
22*9880d681SAndroid Build Coastguard Worker
23*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test1(
24*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  %val0 = load i32, i32* %val
25*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
26*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  ret i32 0
27*9880d681SAndroid Build Coastguard Worker
28*9880d681SAndroid Build Coastguard Worker  %val0 = load i32, i32* %val
29*9880d681SAndroid Build Coastguard Worker  call void(i1,...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
30*9880d681SAndroid Build Coastguard Worker  %val1 = load i32, i32* %val
31*9880d681SAndroid Build Coastguard Worker  %rval = sub i32 %val0, %val1
32*9880d681SAndroid Build Coastguard Worker  ret i32 %rval
33*9880d681SAndroid Build Coastguard Worker}
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard Workerdefine i32 @test2() {
36*9880d681SAndroid Build Coastguard Worker; Guards on "true" get removed
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test2(
39*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: ret i32 0
40*9880d681SAndroid Build Coastguard Worker  call void(i1, ...) @llvm.experimental.guard(i1 true) [ "deopt"() ]
41*9880d681SAndroid Build Coastguard Worker  ret i32 0
42*9880d681SAndroid Build Coastguard Worker}
43*9880d681SAndroid Build Coastguard Worker
44*9880d681SAndroid Build Coastguard Workerdefine i32 @test3(i32 %val) {
45*9880d681SAndroid Build Coastguard Worker; After a guard has executed the condition it was guarding is known to
46*9880d681SAndroid Build Coastguard Worker; be true.
47*9880d681SAndroid Build Coastguard Worker
48*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test3(
49*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  %cond0 = icmp slt i32 %val, 40
50*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond0) [ "deopt"() ]
51*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  ret i32 -1
52*9880d681SAndroid Build Coastguard Worker
53*9880d681SAndroid Build Coastguard Worker  %cond0 = icmp slt i32 %val, 40
54*9880d681SAndroid Build Coastguard Worker  call void(i1,...) @llvm.experimental.guard(i1 %cond0) [ "deopt"() ]
55*9880d681SAndroid Build Coastguard Worker  %cond1 = icmp slt i32 %val, 40
56*9880d681SAndroid Build Coastguard Worker  call void(i1,...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]
57*9880d681SAndroid Build Coastguard Worker
58*9880d681SAndroid Build Coastguard Worker  %cond2 = icmp slt i32 %val, 40
59*9880d681SAndroid Build Coastguard Worker  %rval = sext i1 %cond2 to i32
60*9880d681SAndroid Build Coastguard Worker  ret i32 %rval
61*9880d681SAndroid Build Coastguard Worker}
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Workerdefine i32 @test3.unhandled(i32 %val) {
64*9880d681SAndroid Build Coastguard Worker; After a guard has executed the condition it was guarding is known to
65*9880d681SAndroid Build Coastguard Worker; be true.
66*9880d681SAndroid Build Coastguard Worker
67*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test3.unhandled(
68*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  %cond0 = icmp slt i32 %val, 40
69*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond0) [ "deopt"() ]
70*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  %cond1 = icmp sge i32 %val, 40
71*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]
72*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  ret i32 0
73*9880d681SAndroid Build Coastguard Worker
74*9880d681SAndroid Build Coastguard Worker; Demonstrates a case we do not yet handle (it is legal to fold %cond2
75*9880d681SAndroid Build Coastguard Worker; to false)
76*9880d681SAndroid Build Coastguard Worker  %cond0 = icmp slt i32 %val, 40
77*9880d681SAndroid Build Coastguard Worker  call void(i1,...) @llvm.experimental.guard(i1 %cond0) [ "deopt"() ]
78*9880d681SAndroid Build Coastguard Worker  %cond1 = icmp sge i32 %val, 40
79*9880d681SAndroid Build Coastguard Worker  call void(i1,...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]
80*9880d681SAndroid Build Coastguard Worker  ret i32 0
81*9880d681SAndroid Build Coastguard Worker}
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Workerdefine i32 @test4(i32 %val, i1 %c) {
84*9880d681SAndroid Build Coastguard Worker; Same as test3, but with some control flow involved.
85*9880d681SAndroid Build Coastguard Worker
86*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test4(
87*9880d681SAndroid Build Coastguard Worker; CHECK: entry:
88*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  %cond0 = icmp slt i32 %val, 40
89*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond0
90*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  br label %bb0
91*9880d681SAndroid Build Coastguard Worker
92*9880d681SAndroid Build Coastguard Worker; CHECK:     bb0:
93*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  %cond2 = icmp ult i32 %val, 200
94*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond2
95*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  br i1 %c, label %left, label %right
96*9880d681SAndroid Build Coastguard Worker
97*9880d681SAndroid Build Coastguard Worker; CHECK:     left:
98*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  ret i32 0
99*9880d681SAndroid Build Coastguard Worker
100*9880d681SAndroid Build Coastguard Worker; CHECK:     right:
101*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  ret i32 20
102*9880d681SAndroid Build Coastguard Worker
103*9880d681SAndroid Build Coastguard Workerentry:
104*9880d681SAndroid Build Coastguard Worker  %cond0 = icmp slt i32 %val, 40
105*9880d681SAndroid Build Coastguard Worker  call void(i1,...) @llvm.experimental.guard(i1 %cond0) [ "deopt"() ]
106*9880d681SAndroid Build Coastguard Worker  %cond1 = icmp slt i32 %val, 40
107*9880d681SAndroid Build Coastguard Worker  call void(i1,...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]
108*9880d681SAndroid Build Coastguard Worker  br label %bb0
109*9880d681SAndroid Build Coastguard Worker
110*9880d681SAndroid Build Coastguard Workerbb0:
111*9880d681SAndroid Build Coastguard Worker  %cond2 = icmp ult i32 %val, 200
112*9880d681SAndroid Build Coastguard Worker  call void(i1,...) @llvm.experimental.guard(i1 %cond2) [ "deopt"() ]
113*9880d681SAndroid Build Coastguard Worker  br i1 %c, label %left, label %right
114*9880d681SAndroid Build Coastguard Worker
115*9880d681SAndroid Build Coastguard Workerleft:
116*9880d681SAndroid Build Coastguard Worker  %cond3 = icmp ult i32 %val, 200
117*9880d681SAndroid Build Coastguard Worker  call void(i1,...) @llvm.experimental.guard(i1 %cond3) [ "deopt"() ]
118*9880d681SAndroid Build Coastguard Worker  ret i32 0
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Workerright:
121*9880d681SAndroid Build Coastguard Worker ret i32 20
122*9880d681SAndroid Build Coastguard Worker}
123*9880d681SAndroid Build Coastguard Worker
124*9880d681SAndroid Build Coastguard Workerdefine i32 @test5(i32 %val, i1 %c) {
125*9880d681SAndroid Build Coastguard Worker; Same as test4, but the %left block has mutliple predecessors.
126*9880d681SAndroid Build Coastguard Worker
127*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test5(
128*9880d681SAndroid Build Coastguard Worker
129*9880d681SAndroid Build Coastguard Worker; CHECK: entry:
130*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  %cond0 = icmp slt i32 %val, 40
131*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond0
132*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  br label %bb0
133*9880d681SAndroid Build Coastguard Worker
134*9880d681SAndroid Build Coastguard Worker; CHECK: bb0:
135*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  %cond2 = icmp ult i32 %val, 200
136*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %cond2
137*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  br i1 %c, label %left, label %right
138*9880d681SAndroid Build Coastguard Worker
139*9880d681SAndroid Build Coastguard Worker; CHECK: left:
140*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  br label %right
141*9880d681SAndroid Build Coastguard Worker
142*9880d681SAndroid Build Coastguard Worker; CHECK: right:
143*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  br label %left
144*9880d681SAndroid Build Coastguard Worker
145*9880d681SAndroid Build Coastguard Workerentry:
146*9880d681SAndroid Build Coastguard Worker  %cond0 = icmp slt i32 %val, 40
147*9880d681SAndroid Build Coastguard Worker  call void(i1,...) @llvm.experimental.guard(i1 %cond0) [ "deopt"() ]
148*9880d681SAndroid Build Coastguard Worker  %cond1 = icmp slt i32 %val, 40
149*9880d681SAndroid Build Coastguard Worker  call void(i1,...) @llvm.experimental.guard(i1 %cond1) [ "deopt"() ]
150*9880d681SAndroid Build Coastguard Worker  br label %bb0
151*9880d681SAndroid Build Coastguard Worker
152*9880d681SAndroid Build Coastguard Workerbb0:
153*9880d681SAndroid Build Coastguard Worker  %cond2 = icmp ult i32 %val, 200
154*9880d681SAndroid Build Coastguard Worker  call void(i1,...) @llvm.experimental.guard(i1 %cond2) [ "deopt"() ]
155*9880d681SAndroid Build Coastguard Worker  br i1 %c, label %left, label %right
156*9880d681SAndroid Build Coastguard Worker
157*9880d681SAndroid Build Coastguard Workerleft:
158*9880d681SAndroid Build Coastguard Worker  %cond3 = icmp ult i32 %val, 200
159*9880d681SAndroid Build Coastguard Worker  call void(i1,...) @llvm.experimental.guard(i1 %cond3) [ "deopt"() ]
160*9880d681SAndroid Build Coastguard Worker  br label %right
161*9880d681SAndroid Build Coastguard Worker
162*9880d681SAndroid Build Coastguard Workerright:
163*9880d681SAndroid Build Coastguard Worker  br label %left
164*9880d681SAndroid Build Coastguard Worker}
165*9880d681SAndroid Build Coastguard Worker
166*9880d681SAndroid Build Coastguard Workerdefine void @test6(i1 %c, i32* %ptr) {
167*9880d681SAndroid Build Coastguard Worker; Check that we do not DSE over calls to @llvm.experimental.guard.
168*9880d681SAndroid Build Coastguard Worker; Guard intrinsics do _read_ memory, so th call to guard below needs
169*9880d681SAndroid Build Coastguard Worker; to see the store of 500 to %ptr
170*9880d681SAndroid Build Coastguard Worker
171*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @test6(
172*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  store i32 500, i32* %ptr
173*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  call void (i1, ...) @llvm.experimental.guard(i1 %c) [ "deopt"() ]
174*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT:  store i32 600, i32* %ptr
175*9880d681SAndroid Build Coastguard Worker
176*9880d681SAndroid Build Coastguard Worker
177*9880d681SAndroid Build Coastguard Worker  store i32 500, i32* %ptr
178*9880d681SAndroid Build Coastguard Worker  call void(i1,...) @llvm.experimental.guard(i1 %c) [ "deopt"() ]
179*9880d681SAndroid Build Coastguard Worker  store i32 600, i32* %ptr
180*9880d681SAndroid Build Coastguard Worker  ret void
181*9880d681SAndroid Build Coastguard Worker}
182