[InstCombine] Signed saturation patterns
[llvm-core.git] / test / Transforms / InstCombine / unsigned-add-lack-of-overflow-check-via-add.ll
blobb39f2bb8becc8bdcb1d8b958d6676ae31df75c95
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt %s -instcombine -S | FileCheck %s
4 ; Should fold
5 ;   (%x + %y) u>= %x
6 ; or
7 ;   (%x + %y) u>= %y
8 ; to
9 ;   @llvm.uadd.with.overflow(%x, %y) + extractvalue + not
11 ; All tests here have extra uses, to ensure that the pattern isn't perturbed.
13 declare void @use8(i8)
14 declare void @use2x8(<2 x i8>)
16 define i1 @t0_basic(i8 %x, i8 %y) {
17 ; CHECK-LABEL: @t0_basic(
18 ; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
19 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
20 ; CHECK-NEXT:    [[R:%.*]] = icmp uge i8 [[T0]], [[Y]]
21 ; CHECK-NEXT:    ret i1 [[R]]
23   %t0 = add i8 %x, %y
24   call void @use8(i8 %t0)
25   %r = icmp uge i8 %t0, %y
26   ret i1 %r
29 define <2 x i1> @t1_vec(<2 x i8> %x, <2 x i8> %y) {
30 ; CHECK-LABEL: @t1_vec(
31 ; CHECK-NEXT:    [[T0:%.*]] = add <2 x i8> [[X:%.*]], [[Y:%.*]]
32 ; CHECK-NEXT:    call void @use2x8(<2 x i8> [[T0]])
33 ; CHECK-NEXT:    [[R:%.*]] = icmp uge <2 x i8> [[T0]], [[Y]]
34 ; CHECK-NEXT:    ret <2 x i1> [[R]]
36   %t0 = add <2 x i8> %x, %y
37   call void @use2x8(<2 x i8> %t0)
38   %r = icmp uge <2 x i8> %t0, %y
39   ret <2 x i1> %r
42 ; Commutativity
44 define i1 @t2_symmetry(i8 %x, i8 %y) {
45 ; CHECK-LABEL: @t2_symmetry(
46 ; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
47 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
48 ; CHECK-NEXT:    [[R:%.*]] = icmp uge i8 [[T0]], [[X]]
49 ; CHECK-NEXT:    ret i1 [[R]]
51   %t0 = add i8 %x, %y
52   call void @use8(i8 %t0)
53   %r = icmp uge i8 %t0, %x ; can check against either of `add` arguments
54   ret i1 %r
57 declare i8 @gen8()
59 define i1 @t3_commutative(i8 %x) {
60 ; CHECK-LABEL: @t3_commutative(
61 ; CHECK-NEXT:    [[Y:%.*]] = call i8 @gen8()
62 ; CHECK-NEXT:    [[T0:%.*]] = add i8 [[Y]], [[X:%.*]]
63 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
64 ; CHECK-NEXT:    [[R:%.*]] = icmp uge i8 [[T0]], [[Y]]
65 ; CHECK-NEXT:    ret i1 [[R]]
67   %y = call i8 @gen8()
68   %t0 = add i8 %y, %x ; swapped
69   call void @use8(i8 %t0)
70   %r = icmp uge i8 %t0, %y
71   ret i1 %r
74 define i1 @t4_commutative() {
75 ; CHECK-LABEL: @t4_commutative(
76 ; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
77 ; CHECK-NEXT:    [[Y:%.*]] = call i8 @gen8()
78 ; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X]], [[Y]]
79 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
80 ; CHECK-NEXT:    [[R:%.*]] = icmp ule i8 [[Y]], [[T0]]
81 ; CHECK-NEXT:    ret i1 [[R]]
83   %x = call i8 @gen8()
84   %y = call i8 @gen8()
85   %t0 = add i8 %x, %y
86   call void @use8(i8 %t0)
87   %r = icmp ule i8 %y, %t0 ; swapped
88   ret i1 %r
91 define i1 @t5_commutative(i8 %x) {
92 ; CHECK-LABEL: @t5_commutative(
93 ; CHECK-NEXT:    [[Y:%.*]] = call i8 @gen8()
94 ; CHECK-NEXT:    [[T0:%.*]] = add i8 [[Y]], [[X:%.*]]
95 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
96 ; CHECK-NEXT:    [[R:%.*]] = icmp ule i8 [[Y]], [[T0]]
97 ; CHECK-NEXT:    ret i1 [[R]]
99   %y = call i8 @gen8()
100   %t0 = add i8 %y, %x ; swapped
101   call void @use8(i8 %t0)
102   %r = icmp ule i8 %y, %t0 ; swapped
103   ret i1 %r
106 ; Extra-use tests
108 define i1 @t6_no_extrause(i8 %x, i8 %y) {
109 ; CHECK-LABEL: @t6_no_extrause(
110 ; CHECK-NEXT:    [[TMP1:%.*]] = xor i8 [[Y:%.*]], -1
111 ; CHECK-NEXT:    [[R:%.*]] = icmp uge i8 [[TMP1]], [[X:%.*]]
112 ; CHECK-NEXT:    ret i1 [[R]]
114   %t0 = add i8 %x, %y
115   %r = icmp uge i8 %t0, %y
116   ret i1 %r
119 ; Negative tests
121 define i1 @n7_different_y(i8 %x, i8 %y0, i8 %y1) {
122 ; CHECK-LABEL: @n7_different_y(
123 ; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y0:%.*]]
124 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
125 ; CHECK-NEXT:    [[R:%.*]] = icmp uge i8 [[T0]], [[Y1:%.*]]
126 ; CHECK-NEXT:    ret i1 [[R]]
128   %t0 = add i8 %x, %y0
129   call void @use8(i8 %t0)
130   %r = icmp uge i8 %t0, %y1
131   ret i1 %r
134 define i1 @n8_wrong_pred0(i8 %x, i8 %y) {
135 ; CHECK-LABEL: @n8_wrong_pred0(
136 ; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
137 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
138 ; CHECK-NEXT:    [[R:%.*]] = icmp ule i8 [[T0]], [[Y]]
139 ; CHECK-NEXT:    ret i1 [[R]]
141   %t0 = add i8 %x, %y
142   call void @use8(i8 %t0)
143   %r = icmp ule i8 %t0, %y
144   ret i1 %r
147 define i1 @n9_wrong_pred1(i8 %x, i8 %y) {
148 ; CHECK-LABEL: @n9_wrong_pred1(
149 ; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
150 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
151 ; CHECK-NEXT:    [[R:%.*]] = icmp ugt i8 [[T0]], [[Y]]
152 ; CHECK-NEXT:    ret i1 [[R]]
154   %t0 = add i8 %x, %y
155   call void @use8(i8 %t0)
156   %r = icmp ugt i8 %t0, %y
157   ret i1 %r
160 define i1 @n10_wrong_pred2(i8 %x, i8 %y) {
161 ; CHECK-LABEL: @n10_wrong_pred2(
162 ; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
163 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
164 ; CHECK-NEXT:    [[R:%.*]] = icmp eq i8 [[X]], 0
165 ; CHECK-NEXT:    ret i1 [[R]]
167   %t0 = add i8 %x, %y
168   call void @use8(i8 %t0)
169   %r = icmp eq i8 %t0, %y
170   ret i1 %r
173 define i1 @n11_wrong_pred3(i8 %x, i8 %y) {
174 ; CHECK-LABEL: @n11_wrong_pred3(
175 ; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
176 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
177 ; CHECK-NEXT:    [[R:%.*]] = icmp ne i8 [[X]], 0
178 ; CHECK-NEXT:    ret i1 [[R]]
180   %t0 = add i8 %x, %y
181   call void @use8(i8 %t0)
182   %r = icmp ne i8 %t0, %y
183   ret i1 %r
186 define i1 @n12_wrong_pred4(i8 %x, i8 %y) {
187 ; CHECK-LABEL: @n12_wrong_pred4(
188 ; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
189 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
190 ; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[T0]], [[Y]]
191 ; CHECK-NEXT:    ret i1 [[R]]
193   %t0 = add i8 %x, %y
194   call void @use8(i8 %t0)
195   %r = icmp slt i8 %t0, %y
196   ret i1 %r
199 define i1 @n13_wrong_pred5(i8 %x, i8 %y) {
200 ; CHECK-LABEL: @n13_wrong_pred5(
201 ; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
202 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
203 ; CHECK-NEXT:    [[R:%.*]] = icmp sle i8 [[T0]], [[Y]]
204 ; CHECK-NEXT:    ret i1 [[R]]
206   %t0 = add i8 %x, %y
207   call void @use8(i8 %t0)
208   %r = icmp sle i8 %t0, %y
209   ret i1 %r
212 define i1 @n14_wrong_pred6(i8 %x, i8 %y) {
213 ; CHECK-LABEL: @n14_wrong_pred6(
214 ; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
215 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
216 ; CHECK-NEXT:    [[R:%.*]] = icmp sgt i8 [[T0]], [[Y]]
217 ; CHECK-NEXT:    ret i1 [[R]]
219   %t0 = add i8 %x, %y
220   call void @use8(i8 %t0)
221   %r = icmp sgt i8 %t0, %y
222   ret i1 %r
225 define i1 @n15_wrong_pred7(i8 %x, i8 %y) {
226 ; CHECK-LABEL: @n15_wrong_pred7(
227 ; CHECK-NEXT:    [[T0:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
228 ; CHECK-NEXT:    call void @use8(i8 [[T0]])
229 ; CHECK-NEXT:    [[R:%.*]] = icmp sge i8 [[T0]], [[Y]]
230 ; CHECK-NEXT:    ret i1 [[R]]
232   %t0 = add i8 %x, %y
233   call void @use8(i8 %t0)
234   %r = icmp sge i8 %t0, %y
235   ret i1 %r