[rtsan] Add fork/execve interceptors (#117198)
[llvm-project.git] / llvm / test / Transforms / CorrelatedValuePropagation / uscmp.ll
blob503c715e3bf7c65914755e33ea42b30070b93eff
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
4 ; If nothing is known we can't change anything
5 define i8 @ucmp_0(i32 %x, i32 %y) {
6 ; CHECK-LABEL: @ucmp_0(
7 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
8 ; CHECK-NEXT:    ret i8 [[TMP1]]
10   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
11   ret i8 %1
14 define i8 @scmp_0(i32 %x, i32 %y) {
15 ; CHECK-LABEL: @scmp_0(
16 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
17 ; CHECK-NEXT:    ret i8 [[TMP1]]
19   %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
20   ret i8 %1
23 ; If we know that range of LHS < range of RHS then return -1
24 define i8 @ucmp_1(i32 %x, i32 %y) {
25   ; X is within [4, 8)
26 ; CHECK-LABEL: @ucmp_1(
27 ; CHECK-NEXT:    [[COND1:%.*]] = icmp samesign uge i32 [[X:%.*]], 4
28 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND1]])
29 ; CHECK-NEXT:    [[COND2:%.*]] = icmp ult i32 [[X]], 8
30 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND2]])
31 ; CHECK-NEXT:    [[COND3:%.*]] = icmp uge i32 [[Y:%.*]], 8
32 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND3]])
33 ; CHECK-NEXT:    ret i8 -1
35   %cond1 = icmp uge i32 %x, 4
36   call void @llvm.assume(i1 %cond1)
37   %cond2 = icmp ult i32 %x, 8
38   call void @llvm.assume(i1 %cond2)
39   ; Y is within [8, UNSIGNED_MAX)
40   %cond3 = icmp uge i32 %y, 8
41   call void @llvm.assume(i1 %cond3)
43   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
44   ret i8 %1
47 define i8 @scmp_1(i32 %x, i32 %y) {
48   ; X is within [-5, 3)
49 ; CHECK-LABEL: @scmp_1(
50 ; CHECK-NEXT:    [[COND1:%.*]] = icmp sge i32 [[X:%.*]], -5
51 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND1]])
52 ; CHECK-NEXT:    [[COND2:%.*]] = icmp slt i32 [[X]], 3
53 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND2]])
54 ; CHECK-NEXT:    [[COND3:%.*]] = icmp sge i32 [[Y:%.*]], 3
55 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND3]])
56 ; CHECK-NEXT:    ret i8 -1
58   %cond1 = icmp sge i32 %x, -5
59   call void @llvm.assume(i1 %cond1)
60   %cond2 = icmp slt i32 %x, 3
61   call void @llvm.assume(i1 %cond2)
62   ; Y is within [3, SIGNED_MAX)
63   %cond3 = icmp sge i32 %y, 3
64   call void @llvm.assume(i1 %cond3)
66   %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
67   ret i8 %1
70 ; If we know that range of LHS > range of RHS then return 1
71 define i8 @ucmp_2(i32 %x, i32 %y) {
72   ; X is within [4, UNSIGNED_MAX)
73 ; CHECK-LABEL: @ucmp_2(
74 ; CHECK-NEXT:    [[COND1:%.*]] = icmp uge i32 [[X:%.*]], 4
75 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND1]])
76 ; CHECK-NEXT:    [[COND2:%.*]] = icmp ult i32 [[Y:%.*]], 4
77 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND2]])
78 ; CHECK-NEXT:    ret i8 1
80   %cond1 = icmp uge i32 %x, 4
81   call void @llvm.assume(i1 %cond1)
82   ; Y is within [0, 4)
83   %cond2 = icmp ult i32 %y, 4
84   call void @llvm.assume(i1 %cond2)
86   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
87   ret i8 %1
90 define i8 @scmp_2(i32 %x, i32 %y) {
91   ; X is within [4, SIGNED_MAX)
92 ; CHECK-LABEL: @scmp_2(
93 ; CHECK-NEXT:    [[COND1:%.*]] = icmp sge i32 [[X:%.*]], 4
94 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND1]])
95 ; CHECK-NEXT:    [[COND2:%.*]] = icmp slt i32 [[Y:%.*]], 4
96 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND2]])
97 ; CHECK-NEXT:    ret i8 1
99   %cond1 = icmp sge i32 %x, 4
100   call void @llvm.assume(i1 %cond1)
101   ; Y is within [SIGNED_MIN, 4)
102   %cond2 = icmp slt i32 %y, 4
103   call void @llvm.assume(i1 %cond2)
105   %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
106   ret i8 %1
109 ; If we know that LHS and RHS are both constants then return 0
110 define i8 @ucmp_5(i32 %x, i32 %y) {
111 ; CHECK-LABEL: @ucmp_5(
112 ; CHECK-NEXT:    [[COND1:%.*]] = icmp eq i32 [[X:%.*]], 4
113 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND1]])
114 ; CHECK-NEXT:    [[COND2:%.*]] = icmp eq i32 [[Y:%.*]], 4
115 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND2]])
116 ; CHECK-NEXT:    ret i8 0
118   %cond1 = icmp eq i32 %x, 4
119   call void @llvm.assume(i1 %cond1)
120   %cond2 = icmp eq i32 %y, 4
121   call void @llvm.assume(i1 %cond2)
123   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
124   ret i8 %1
127 define i8 @scmp_5(i32 %x, i32 %y) {
128 ; CHECK-LABEL: @scmp_5(
129 ; CHECK-NEXT:    [[COND1:%.*]] = icmp eq i32 [[X:%.*]], -5
130 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND1]])
131 ; CHECK-NEXT:    [[COND2:%.*]] = icmp eq i32 [[Y:%.*]], -5
132 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND2]])
133 ; CHECK-NEXT:    ret i8 0
135   %cond1 = icmp eq i32 %x, -5
136   call void @llvm.assume(i1 %cond1)
137   %cond2 = icmp eq i32 %y, -5
138   call void @llvm.assume(i1 %cond2)
140   %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
141   ret i8 %1
144 ; We can infer ranges based on the location where a UCMP/SCMP result is used
145 define i8 @scmp_6(i32 noundef %x) {
146 ; CHECK-LABEL: @scmp_6(
147 ; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 10
148 ; CHECK-NEXT:    [[TMP2:%.*]] = select i1 [[TMP1]], i8 -1, i8 5
149 ; CHECK-NEXT:    ret i8 [[TMP2]]
151   %1 = icmp slt i32 %x, 10
152   %2 = call i8 @llvm.scmp(i32 %x, i32 10)
153   %3 = select i1 %1, i8 %2, i8 5
154   ret i8 %3
157 ; Negative test: ranges overlap
158 define i8 @ucmp_3(i32 %x, i32 %y) {
159   ; X is within [4, UNSIGNED_MAX)
160 ; CHECK-LABEL: @ucmp_3(
161 ; CHECK-NEXT:    [[COND1:%.*]] = icmp uge i32 [[X:%.*]], 4
162 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND1]])
163 ; CHECK-NEXT:    [[COND2:%.*]] = icmp ult i32 [[Y:%.*]], 6
164 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND2]])
165 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
166 ; CHECK-NEXT:    ret i8 [[TMP1]]
168   %cond1 = icmp uge i32 %x, 4
169   call void @llvm.assume(i1 %cond1)
170   ; Y is within [0, 6)
171   %cond2 = icmp ult i32 %y, 6
172   call void @llvm.assume(i1 %cond2)
174   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
175   ret i8 %1
178 define i8 @scmp_3(i32 %x, i32 %y) {
179   ; X is within [2, SIGNED_MAX)
180 ; CHECK-LABEL: @scmp_3(
181 ; CHECK-NEXT:    [[COND1:%.*]] = icmp sge i32 [[X:%.*]], 2
182 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND1]])
183 ; CHECK-NEXT:    [[COND2:%.*]] = icmp slt i32 [[Y:%.*]], 4
184 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND2]])
185 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
186 ; CHECK-NEXT:    ret i8 [[TMP1]]
188   %cond1 = icmp sge i32 %x, 2
189   call void @llvm.assume(i1 %cond1)
190   ; Y is within [SIGNED_MIN, 4)
191   %cond2 = icmp slt i32 %y, 4
192   call void @llvm.assume(i1 %cond2)
194   %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
195   ret i8 %1
198 ; Negative test: mismatched signedness of range-establishing comparisons and
199 ;                of the intrinsic
200 define i8 @ucmp_4(i32 %x, i32 %y) {
201   ; X is within [4, SIGNED_MAX)
202 ; CHECK-LABEL: @ucmp_4(
203 ; CHECK-NEXT:    [[COND1:%.*]] = icmp sge i32 [[X:%.*]], 4
204 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND1]])
205 ; CHECK-NEXT:    [[COND2:%.*]] = icmp slt i32 [[Y:%.*]], 4
206 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND2]])
207 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
208 ; CHECK-NEXT:    ret i8 [[TMP1]]
210   %cond1 = icmp sge i32 %x, 4
211   call void @llvm.assume(i1 %cond1)
212   ; Y is within [0, 4)
213   %cond2 = icmp slt i32 %y, 4
214   call void @llvm.assume(i1 %cond2)
216   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
217   ret i8 %1
220 define i8 @scmp_4(i32 %x, i32 %y) {
221   ; X is within [4, UNSIGNED_MAX)
222 ; CHECK-LABEL: @scmp_4(
223 ; CHECK-NEXT:    [[COND1:%.*]] = icmp uge i32 [[X:%.*]], 4
224 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND1]])
225 ; CHECK-NEXT:    [[COND2:%.*]] = icmp ult i32 [[Y:%.*]], 4
226 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND2]])
227 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
228 ; CHECK-NEXT:    ret i8 [[TMP1]]
230   %cond1 = icmp uge i32 %x, 4
231   call void @llvm.assume(i1 %cond1)
232   ; Y is within [0, 4)
233   %cond2 = icmp ult i32 %y, 4
234   call void @llvm.assume(i1 %cond2)
236   %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
237   ret i8 %1
240 ; Negative test: ranges are the same, but we can't be sure the values are equal
241 define i8 @ucmp_6(i32 %x, i32 %y) {
242   ; Both X and Y are within [0, 10]
243 ; CHECK-LABEL: @ucmp_6(
244 ; CHECK-NEXT:    [[COND1:%.*]] = icmp ule i32 [[X:%.*]], 10
245 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND1]])
246 ; CHECK-NEXT:    [[COND2:%.*]] = icmp ule i32 [[Y:%.*]], 10
247 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND2]])
248 ; CHECK-NEXT:    [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
249 ; CHECK-NEXT:    ret i8 [[TMP1]]
251   %cond1 = icmp ule i32 %x, 10
252   call void @llvm.assume(i1 %cond1)
253   %cond2 = icmp ule i32 %y, 10
254   call void @llvm.assume(i1 %cond2)
256   %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
257   ret i8 %1