[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / llvm / test / Transforms / CorrelatedValuePropagation / urem-expansion.ll
blobcd0ba2f189dc83cd97417898f09e72e60c527b4e
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
4 declare void @llvm.assume(i1)
6 ; Divisor is constant. X's range is known
8 define i8 @constant.divisor.v3(i8 %x) {
9 ; CHECK-LABEL: @constant.divisor.v3(
10 ; CHECK-NEXT:    [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], 3
11 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X_UPPER]])
12 ; CHECK-NEXT:    ret i8 [[X]]
14   %cmp.x.upper = icmp ult i8 %x, 3
15   call void @llvm.assume(i1 %cmp.x.upper)
16   %rem = urem i8 %x, 3
17   ret i8 %rem
19 define i8 @constant.divisor.v4(i8 %x) {
20 ; CHECK-LABEL: @constant.divisor.v4(
21 ; CHECK-NEXT:    [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], 4
22 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X_UPPER]])
23 ; CHECK-NEXT:    [[X_FROZEN:%.*]] = freeze i8 [[X]]
24 ; CHECK-NEXT:    [[REM_UREM:%.*]] = sub nuw i8 [[X_FROZEN]], 3
25 ; CHECK-NEXT:    [[REM_CMP:%.*]] = icmp ult i8 [[X_FROZEN]], 3
26 ; CHECK-NEXT:    [[REM:%.*]] = select i1 [[REM_CMP]], i8 [[X_FROZEN]], i8 [[REM_UREM]]
27 ; CHECK-NEXT:    ret i8 [[REM]]
29   %cmp.x.upper = icmp ult i8 %x, 4
30   call void @llvm.assume(i1 %cmp.x.upper)
31   %rem = urem i8 %x, 3
32   ret i8 %rem
34 define i8 @constant.divisor.x.range.v4(ptr %x.ptr) {
35 ; CHECK-LABEL: @constant.divisor.x.range.v4(
36 ; CHECK-NEXT:    [[X:%.*]] = load i8, ptr [[X_PTR:%.*]], align 1, !range [[RNG0:![0-9]+]]
37 ; CHECK-NEXT:    [[X_FROZEN:%.*]] = freeze i8 [[X]]
38 ; CHECK-NEXT:    [[REM_UREM:%.*]] = sub nuw i8 [[X_FROZEN]], 3
39 ; CHECK-NEXT:    [[REM_CMP:%.*]] = icmp ult i8 [[X_FROZEN]], 3
40 ; CHECK-NEXT:    [[REM:%.*]] = select i1 [[REM_CMP]], i8 [[X_FROZEN]], i8 [[REM_UREM]]
41 ; CHECK-NEXT:    ret i8 [[REM]]
43   %x = load i8, ptr %x.ptr, !range !{ i8 0, i8 4 }
44   %rem = urem i8 %x, 3
45   ret i8 %rem
47 define i8 @constant.divisor.x.mask.v4(i8 %x) {
48 ; CHECK-LABEL: @constant.divisor.x.mask.v4(
49 ; CHECK-NEXT:    [[X_MASKED:%.*]] = and i8 [[X:%.*]], 3
50 ; CHECK-NEXT:    [[X_MASKED_FROZEN:%.*]] = freeze i8 [[X_MASKED]]
51 ; CHECK-NEXT:    [[REM_UREM:%.*]] = sub nuw i8 [[X_MASKED_FROZEN]], 3
52 ; CHECK-NEXT:    [[REM_CMP:%.*]] = icmp ult i8 [[X_MASKED_FROZEN]], 3
53 ; CHECK-NEXT:    [[REM:%.*]] = select i1 [[REM_CMP]], i8 [[X_MASKED_FROZEN]], i8 [[REM_UREM]]
54 ; CHECK-NEXT:    ret i8 [[REM]]
56   %x.masked = and i8 %x, 3
57   %rem = urem i8 %x.masked, 3
58   ret i8 %rem
60 define i8 @constant.divisor.v5(i8 %x) {
61 ; CHECK-LABEL: @constant.divisor.v5(
62 ; CHECK-NEXT:    [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], 5
63 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X_UPPER]])
64 ; CHECK-NEXT:    [[X_FROZEN:%.*]] = freeze i8 [[X]]
65 ; CHECK-NEXT:    [[REM_UREM:%.*]] = sub nuw i8 [[X_FROZEN]], 3
66 ; CHECK-NEXT:    [[REM_CMP:%.*]] = icmp ult i8 [[X_FROZEN]], 3
67 ; CHECK-NEXT:    [[REM:%.*]] = select i1 [[REM_CMP]], i8 [[X_FROZEN]], i8 [[REM_UREM]]
68 ; CHECK-NEXT:    ret i8 [[REM]]
70   %cmp.x.upper = icmp ult i8 %x, 5
71   call void @llvm.assume(i1 %cmp.x.upper)
72   %rem = urem i8 %x, 3
73   ret i8 %rem
75 define i8 @constant.divisor.v6(i8 %x) {
76 ; CHECK-LABEL: @constant.divisor.v6(
77 ; CHECK-NEXT:    [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], 6
78 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X_UPPER]])
79 ; CHECK-NEXT:    [[X_FROZEN:%.*]] = freeze i8 [[X]]
80 ; CHECK-NEXT:    [[REM_UREM:%.*]] = sub nuw i8 [[X_FROZEN]], 3
81 ; CHECK-NEXT:    [[REM_CMP:%.*]] = icmp ult i8 [[X_FROZEN]], 3
82 ; CHECK-NEXT:    [[REM:%.*]] = select i1 [[REM_CMP]], i8 [[X_FROZEN]], i8 [[REM_UREM]]
83 ; CHECK-NEXT:    ret i8 [[REM]]
85   %cmp.x.upper = icmp ult i8 %x, 6
86   call void @llvm.assume(i1 %cmp.x.upper)
87   %rem = urem i8 %x, 3
88   ret i8 %rem
90 define i8 @constant.divisor.v7(i8 %x) {
91 ; CHECK-LABEL: @constant.divisor.v7(
92 ; CHECK-NEXT:    [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], 7
93 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X_UPPER]])
94 ; CHECK-NEXT:    [[REM:%.*]] = urem i8 [[X]], 3
95 ; CHECK-NEXT:    ret i8 [[REM]]
97   %cmp.x.upper = icmp ult i8 %x, 7
98   call void @llvm.assume(i1 %cmp.x.upper)
99   %rem = urem i8 %x, 3
100   ret i8 %rem
103 ; Both are variable. Bounds are known
105 define i8 @variable.v3(i8 %x, i8 %y) {
106 ; CHECK-LABEL: @variable.v3(
107 ; CHECK-NEXT:    [[CMP_X:%.*]] = icmp ult i8 [[X:%.*]], 3
108 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X]])
109 ; CHECK-NEXT:    [[CMP_Y_LOWER:%.*]] = icmp uge i8 [[Y:%.*]], 3
110 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_Y_LOWER]])
111 ; CHECK-NEXT:    [[CMP_Y_UPPER:%.*]] = icmp ule i8 [[Y]], 4
112 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_Y_UPPER]])
113 ; CHECK-NEXT:    ret i8 [[X]]
115   %cmp.x = icmp ult i8 %x, 3
116   call void @llvm.assume(i1 %cmp.x)
117   %cmp.y.lower = icmp uge i8 %y, 3
118   call void @llvm.assume(i1 %cmp.y.lower)
119   %cmp.y.upper = icmp ule i8 %y, 4
120   call void @llvm.assume(i1 %cmp.y.upper)
121   %rem = urem i8 %x, %y
122   ret i8 %rem
124 define i8 @variable.v4(i8 %x, i8 %y) {
125 ; CHECK-LABEL: @variable.v4(
126 ; CHECK-NEXT:    [[CMP_X:%.*]] = icmp ult i8 [[X:%.*]], 4
127 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X]])
128 ; CHECK-NEXT:    [[CMP_Y_LOWER:%.*]] = icmp uge i8 [[Y:%.*]], 3
129 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_Y_LOWER]])
130 ; CHECK-NEXT:    [[CMP_Y_UPPER:%.*]] = icmp ule i8 [[Y]], 4
131 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_Y_UPPER]])
132 ; CHECK-NEXT:    [[X_FROZEN:%.*]] = freeze i8 [[X]]
133 ; CHECK-NEXT:    [[REM_UREM:%.*]] = sub nuw i8 [[X_FROZEN]], [[Y]]
134 ; CHECK-NEXT:    [[REM_CMP:%.*]] = icmp ult i8 [[X_FROZEN]], [[Y]]
135 ; CHECK-NEXT:    [[REM:%.*]] = select i1 [[REM_CMP]], i8 [[X_FROZEN]], i8 [[REM_UREM]]
136 ; CHECK-NEXT:    ret i8 [[REM]]
138   %cmp.x = icmp ult i8 %x, 4
139   call void @llvm.assume(i1 %cmp.x)
140   %cmp.y.lower = icmp uge i8 %y, 3
141   call void @llvm.assume(i1 %cmp.y.lower)
142   %cmp.y.upper = icmp ule i8 %y, 4
143   call void @llvm.assume(i1 %cmp.y.upper)
144   %rem = urem i8 %x, %y
145   ret i8 %rem
147 define i8 @variable.v4.range(ptr %x.ptr, ptr %y.ptr) {
148 ; CHECK-LABEL: @variable.v4.range(
149 ; CHECK-NEXT:    [[X:%.*]] = load i8, ptr [[X_PTR:%.*]], align 1, !range [[RNG0]]
150 ; CHECK-NEXT:    [[Y:%.*]] = load i8, ptr [[Y_PTR:%.*]], align 1, !range [[RNG1:![0-9]+]]
151 ; CHECK-NEXT:    [[X_FROZEN:%.*]] = freeze i8 [[X]]
152 ; CHECK-NEXT:    [[REM_UREM:%.*]] = sub nuw i8 [[X_FROZEN]], [[Y]]
153 ; CHECK-NEXT:    [[REM_CMP:%.*]] = icmp ult i8 [[X_FROZEN]], [[Y]]
154 ; CHECK-NEXT:    [[REM:%.*]] = select i1 [[REM_CMP]], i8 [[X_FROZEN]], i8 [[REM_UREM]]
155 ; CHECK-NEXT:    ret i8 [[REM]]
157   %x = load i8, ptr %x.ptr, !range !{ i8 0, i8 4 }
158   %y = load i8, ptr %y.ptr, !range !{ i8 3, i8 5 }
159   %rem = urem i8 %x, %y
160   ret i8 %rem
162 define i8 @variable.v5(i8 %x, i8 %y) {
163 ; CHECK-LABEL: @variable.v5(
164 ; CHECK-NEXT:    [[CMP_X:%.*]] = icmp ult i8 [[X:%.*]], 5
165 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X]])
166 ; CHECK-NEXT:    [[CMP_Y_LOWER:%.*]] = icmp uge i8 [[Y:%.*]], 3
167 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_Y_LOWER]])
168 ; CHECK-NEXT:    [[CMP_Y_UPPER:%.*]] = icmp ule i8 [[Y]], 4
169 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_Y_UPPER]])
170 ; CHECK-NEXT:    [[X_FROZEN:%.*]] = freeze i8 [[X]]
171 ; CHECK-NEXT:    [[REM_UREM:%.*]] = sub nuw i8 [[X_FROZEN]], [[Y]]
172 ; CHECK-NEXT:    [[REM_CMP:%.*]] = icmp ult i8 [[X_FROZEN]], [[Y]]
173 ; CHECK-NEXT:    [[REM:%.*]] = select i1 [[REM_CMP]], i8 [[X_FROZEN]], i8 [[REM_UREM]]
174 ; CHECK-NEXT:    ret i8 [[REM]]
176   %cmp.x = icmp ult i8 %x, 5
177   call void @llvm.assume(i1 %cmp.x)
178   %cmp.y.lower = icmp uge i8 %y, 3
179   call void @llvm.assume(i1 %cmp.y.lower)
180   %cmp.y.upper = icmp ule i8 %y, 4
181   call void @llvm.assume(i1 %cmp.y.upper)
182   %rem = urem i8 %x, %y
183   ret i8 %rem
185 define i8 @variable.v6(i8 %x, i8 %y) {
186 ; CHECK-LABEL: @variable.v6(
187 ; CHECK-NEXT:    [[CMP_X:%.*]] = icmp ult i8 [[X:%.*]], 6
188 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X]])
189 ; CHECK-NEXT:    [[CMP_Y_LOWER:%.*]] = icmp uge i8 [[Y:%.*]], 3
190 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_Y_LOWER]])
191 ; CHECK-NEXT:    [[CMP_Y_UPPER:%.*]] = icmp ule i8 [[Y]], 4
192 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_Y_UPPER]])
193 ; CHECK-NEXT:    [[X_FROZEN:%.*]] = freeze i8 [[X]]
194 ; CHECK-NEXT:    [[REM_UREM:%.*]] = sub nuw i8 [[X_FROZEN]], [[Y]]
195 ; CHECK-NEXT:    [[REM_CMP:%.*]] = icmp ult i8 [[X_FROZEN]], [[Y]]
196 ; CHECK-NEXT:    [[REM:%.*]] = select i1 [[REM_CMP]], i8 [[X_FROZEN]], i8 [[REM_UREM]]
197 ; CHECK-NEXT:    ret i8 [[REM]]
199   %cmp.x = icmp ult i8 %x, 6
200   call void @llvm.assume(i1 %cmp.x)
201   %cmp.y.lower = icmp uge i8 %y, 3
202   call void @llvm.assume(i1 %cmp.y.lower)
203   %cmp.y.upper = icmp ule i8 %y, 4
204   call void @llvm.assume(i1 %cmp.y.upper)
205   %rem = urem i8 %x, %y
206   ret i8 %rem
208 define i8 @variable.v7(i8 %x, i8 %y) {
209 ; CHECK-LABEL: @variable.v7(
210 ; CHECK-NEXT:    [[CMP_X:%.*]] = icmp ult i8 [[X:%.*]], 7
211 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X]])
212 ; CHECK-NEXT:    [[CMP_Y_LOWER:%.*]] = icmp uge i8 [[Y:%.*]], 3
213 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_Y_LOWER]])
214 ; CHECK-NEXT:    [[CMP_Y_UPPER:%.*]] = icmp ule i8 [[Y]], 4
215 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_Y_UPPER]])
216 ; CHECK-NEXT:    [[REM:%.*]] = urem i8 [[X]], [[Y]]
217 ; CHECK-NEXT:    ret i8 [[REM]]
219   %cmp.x = icmp ult i8 %x, 7
220   call void @llvm.assume(i1 %cmp.x)
221   %cmp.y.lower = icmp uge i8 %y, 3
222   call void @llvm.assume(i1 %cmp.y.lower)
223   %cmp.y.upper = icmp ule i8 %y, 4
224   call void @llvm.assume(i1 %cmp.y.upper)
225   %rem = urem i8 %x, %y
226   ret i8 %rem
229 ; Constant divisor
231 define i8 @large.divisor.v0(i8 %x) {
232 ; CHECK-LABEL: @large.divisor.v0(
233 ; CHECK-NEXT:    [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], 127
234 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X_UPPER]])
235 ; CHECK-NEXT:    ret i8 [[X]]
237   %cmp.x.upper = icmp ult i8 %x, 127
238   call void @llvm.assume(i1 %cmp.x.upper)
239   %rem = urem i8 %x, 127
240   ret i8 %rem
242 define i8 @large.divisor.v1(i8 %x) {
243 ; CHECK-LABEL: @large.divisor.v1(
244 ; CHECK-NEXT:    [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], -128
245 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X_UPPER]])
246 ; CHECK-NEXT:    [[X_FROZEN:%.*]] = freeze i8 [[X]]
247 ; CHECK-NEXT:    [[REM_UREM:%.*]] = sub nuw i8 [[X_FROZEN]], 127
248 ; CHECK-NEXT:    [[REM_CMP:%.*]] = icmp ult i8 [[X_FROZEN]], 127
249 ; CHECK-NEXT:    [[REM:%.*]] = select i1 [[REM_CMP]], i8 [[X_FROZEN]], i8 [[REM_UREM]]
250 ; CHECK-NEXT:    ret i8 [[REM]]
252   %cmp.x.upper = icmp ult i8 %x, 128
253   call void @llvm.assume(i1 %cmp.x.upper)
254   %rem = urem i8 %x, 127
255   ret i8 %rem
257 define i8 @large.divisor.v1.range(ptr %x.ptr) {
258 ; CHECK-LABEL: @large.divisor.v1.range(
259 ; CHECK-NEXT:    [[X:%.*]] = load i8, ptr [[X_PTR:%.*]], align 1, !range [[RNG2:![0-9]+]]
260 ; CHECK-NEXT:    [[X_FROZEN:%.*]] = freeze i8 [[X]]
261 ; CHECK-NEXT:    [[REM_UREM:%.*]] = sub nuw i8 [[X_FROZEN]], 127
262 ; CHECK-NEXT:    [[REM_CMP:%.*]] = icmp ult i8 [[X_FROZEN]], 127
263 ; CHECK-NEXT:    [[REM:%.*]] = select i1 [[REM_CMP]], i8 [[X_FROZEN]], i8 [[REM_UREM]]
264 ; CHECK-NEXT:    ret i8 [[REM]]
266   %x = load i8, ptr %x.ptr, !range !{ i8 0, i8 128 }
267   %rem = urem i8 %x, 127
268   ret i8 %rem
270 define i8 @large.divisor.v2.unbound.x(i8 %x) {
271 ; CHECK-LABEL: @large.divisor.v2.unbound.x(
272 ; CHECK-NEXT:    [[REM:%.*]] = urem i8 [[X:%.*]], 127
273 ; CHECK-NEXT:    ret i8 [[REM]]
275   %rem = urem i8 %x, 127
276   ret i8 %rem
279 define i8 @large.divisor.with.overflow.v0(i8 %x) {
280 ; CHECK-LABEL: @large.divisor.with.overflow.v0(
281 ; CHECK-NEXT:    [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], -128
282 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X_UPPER]])
283 ; CHECK-NEXT:    ret i8 [[X]]
285   %cmp.x.upper = icmp ult i8 %x, 128
286   call void @llvm.assume(i1 %cmp.x.upper)
287   %rem = urem i8 %x, 128
288   ret i8 %rem
290 define i8 @large.divisor.with.overflow.v1(i8 %x) {
291 ; CHECK-LABEL: @large.divisor.with.overflow.v1(
292 ; CHECK-NEXT:    [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], -127
293 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X_UPPER]])
294 ; CHECK-NEXT:    [[X_FROZEN:%.*]] = freeze i8 [[X]]
295 ; CHECK-NEXT:    [[REM_UREM:%.*]] = sub nuw i8 [[X_FROZEN]], -128
296 ; CHECK-NEXT:    [[REM_CMP:%.*]] = icmp ult i8 [[X_FROZEN]], -128
297 ; CHECK-NEXT:    [[REM:%.*]] = select i1 [[REM_CMP]], i8 [[X_FROZEN]], i8 [[REM_UREM]]
298 ; CHECK-NEXT:    ret i8 [[REM]]
300   %cmp.x.upper = icmp ult i8 %x, 129
301   call void @llvm.assume(i1 %cmp.x.upper)
302   %rem = urem i8 %x, 128
303   ret i8 %rem
305 define i8 @large.divisor.with.overflow.v1.range(ptr %x.ptr) {
306 ; CHECK-LABEL: @large.divisor.with.overflow.v1.range(
307 ; CHECK-NEXT:    [[X:%.*]] = load i8, ptr [[X_PTR:%.*]], align 1, !range [[RNG3:![0-9]+]]
308 ; CHECK-NEXT:    [[X_FROZEN:%.*]] = freeze i8 [[X]]
309 ; CHECK-NEXT:    [[REM_UREM:%.*]] = sub nuw i8 [[X_FROZEN]], -128
310 ; CHECK-NEXT:    [[REM_CMP:%.*]] = icmp ult i8 [[X_FROZEN]], -128
311 ; CHECK-NEXT:    [[REM:%.*]] = select i1 [[REM_CMP]], i8 [[X_FROZEN]], i8 [[REM_UREM]]
312 ; CHECK-NEXT:    ret i8 [[REM]]
314   %x = load i8, ptr %x.ptr, !range !{ i8 0, i8 129 }
315   %rem = urem i8 %x, 128
316   ret i8 %rem
318 define i8 @large.divisor.with.overflow.v2.unbound.x(i8 %x) {
319 ; CHECK-LABEL: @large.divisor.with.overflow.v2.unbound.x(
320 ; CHECK-NEXT:    [[X_FROZEN:%.*]] = freeze i8 [[X:%.*]]
321 ; CHECK-NEXT:    [[REM_UREM:%.*]] = sub nuw i8 [[X_FROZEN]], -128
322 ; CHECK-NEXT:    [[REM_CMP:%.*]] = icmp ult i8 [[X_FROZEN]], -128
323 ; CHECK-NEXT:    [[REM:%.*]] = select i1 [[REM_CMP]], i8 [[X_FROZEN]], i8 [[REM_UREM]]
324 ; CHECK-NEXT:    ret i8 [[REM]]
326   %rem = urem i8 %x, 128
327   ret i8 %rem
330 define i1 @icmp_after_expansion(i8 noundef %x) {
331 ; CHECK-LABEL: @icmp_after_expansion(
332 ; CHECK-NEXT:    [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], 6
333 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X_UPPER]])
334 ; CHECK-NEXT:    [[REM_UREM:%.*]] = sub nuw i8 [[X]], 3
335 ; CHECK-NEXT:    [[REM_CMP:%.*]] = icmp ult i8 [[X]], 3
336 ; CHECK-NEXT:    [[REM:%.*]] = select i1 [[REM_CMP]], i8 [[X]], i8 [[REM_UREM]]
337 ; CHECK-NEXT:    ret i1 false
339   %cmp.x.upper = icmp ult i8 %x, 6
340   call void @llvm.assume(i1 %cmp.x.upper)
341   %rem = urem i8 %x, 3
342   %cmp = icmp eq i8 %rem, 3
343   ret i1 %cmp
346 define i8 @known_uge(i8 noundef %x) {
347 ; CHECK-LABEL: @known_uge(
348 ; CHECK-NEXT:    [[CMP_X_UPPER:%.*]] = icmp ult i8 [[X:%.*]], 6
349 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X_UPPER]])
350 ; CHECK-NEXT:    [[CMP_X_LOWER:%.*]] = icmp uge i8 [[X]], 3
351 ; CHECK-NEXT:    call void @llvm.assume(i1 [[CMP_X_LOWER]])
352 ; CHECK-NEXT:    [[REM:%.*]] = sub nuw i8 [[X]], 3
353 ; CHECK-NEXT:    ret i8 [[REM]]
355   %cmp.x.upper = icmp ult i8 %x, 6
356   call void @llvm.assume(i1 %cmp.x.upper)
357   %cmp.x.lower = icmp uge i8 %x, 3
358   call void @llvm.assume(i1 %cmp.x.lower)
359   %rem = urem i8 %x, 3
360   ret i8 %rem