[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / CodeGen / ARM / CGP / arm-cgp-overflow.ll
blobc446ddbdd07a7d5b9037624aa26537280adfddd6
1 ; RUN: llc -mtriple=thumbv8m.main -mcpu=cortex-m33 -mattr=-use-misched %s -arm-disable-cgp=false -o - | FileCheck %s
3 ; CHECK: overflow_add
4 ; CHECK: add
5 ; CHECK: uxth
6 ; CHECK: cmp
7 define zeroext i16 @overflow_add(i16 zeroext %a, i16 zeroext %b) {
8   %add = add i16 %a, %b
9   %or = or i16 %add, 1
10   %cmp = icmp ugt i16 %or, 1024
11   %res = select i1 %cmp, i16 2, i16 5
12   ret i16 %res
15 ; CHECK-LABEL: overflow_sub
16 ; CHECK: sub
17 ; CHECK: uxth
18 ; CHECK: cmp
19 define zeroext i16 @overflow_sub(i16 zeroext %a, i16 zeroext %b) {
20   %add = sub i16 %a, %b
21   %or = or i16 %add, 1
22   %cmp = icmp ugt i16 %or, 1024
23   %res = select i1 %cmp, i16 2, i16 5
24   ret i16 %res
27 ; CHECK-LABEL: overflow_mul
28 ; CHECK: mul
29 ; CHECK: uxth
30 ; CHECK: cmp
31 define zeroext i16 @overflow_mul(i16 zeroext %a, i16 zeroext %b) {
32   %add = mul i16 %a, %b
33   %or = or i16 %add, 1
34   %cmp = icmp ugt i16 %or, 1024
35   %res = select i1 %cmp, i16 2, i16 5
36   ret i16 %res
39 ; CHECK-LABEL: overflow_shl
40 ; CHECK-COMMON: lsl
41 ; CHECK-COMMON: uxth
42 ; CHECK-COMMON: cmp
43 define zeroext i16 @overflow_shl(i16 zeroext %a, i16 zeroext %b) {
44   %add = shl i16 %a, %b
45   %or = or i16 %add, 1
46   %cmp = icmp ugt i16 %or, 1024
47   %res = select i1 %cmp, i16 2, i16 5
48   ret i16 %res
51 ; CHECK-LABEL: overflow_add_no_consts:
52 ; CHECK:  add r0, r1
53 ; CHECK:  uxtb [[EXT:r[0-9]+]], r0
54 ; CHECK:  cmp [[EXT]], r2
55 ; CHECK:  movhi r0, #8
56 define i32 @overflow_add_no_consts(i8 zeroext %a, i8 zeroext %b, i8 zeroext %limit) {
57   %add = add i8 %a, %b
58   %cmp = icmp ugt i8 %add, %limit
59   %res = select i1 %cmp, i32 8, i32 16
60   ret i32 %res
63 ; CHECK-LABEL: overflow_add_const_limit:
64 ; CHECK:  add r0, r1
65 ; CHECK:  uxtb [[EXT:r[0-9]+]], r0
66 ; CHECK:  cmp [[EXT]], #128
67 ; CHECK:  movhi r0, #8
68 define i32 @overflow_add_const_limit(i8 zeroext %a, i8 zeroext %b) {
69   %add = add i8 %a, %b
70   %cmp = icmp ugt i8 %add, 128
71   %res = select i1 %cmp, i32 8, i32 16
72   ret i32 %res
75 ; CHECK-LABEL: overflow_add_positive_const_limit:
76 ; CHECK:  adds r0, #1
77 ; CHECK:  uxtb [[EXT:r[0-9]+]], r0
78 ; CHECK:  cmp [[EXT]], #128
79 ; CHECK:  movhi r0, #8
80 define i32 @overflow_add_positive_const_limit(i8 zeroext %a) {
81   %add = add i8 %a, 1
82   %cmp = icmp ugt i8 %add, 128
83   %res = select i1 %cmp, i32 8, i32 16
84   ret i32 %res
87 ; CHECK-LABEL: unsafe_add_underflow:
88 ; CHECK: movs   r1, #16
89 ; CHECK: cmp    r0, #1
90 ; CHECK: it     eq
91 ; CHECK: moveq  r1, #8
92 ; CHECK: mov    r0, r1
93 define i32 @unsafe_add_underflow(i8 zeroext %a) {
94   %add = add i8 %a, -2
95   %cmp = icmp ugt i8 %add, 254
96   %res = select i1 %cmp, i32 8, i32 16
97   ret i32 %res
100 ; CHECK-LABEL: safe_add_underflow:
101 ; CHECK:      subs [[MINUS_1:r[0-9]+]], r0, #1
102 ; CHECK-NOT:  uxtb
103 ; CHECK:      cmp [[MINUS_1]], #254
104 ; CHECK:      movhi r0, #8
105 define i32 @safe_add_underflow(i8 zeroext %a) {
106   %add = add i8 %a, -1
107   %cmp = icmp ugt i8 %add, 254
108   %res = select i1 %cmp, i32 8, i32 16
109   ret i32 %res
112 ; CHECK-LABEL: safe_add_underflow_neg:
113 ; CHECK:      subs [[MINUS_1:r[0-9]+]], r0, #2
114 ; CHECK-NOT:  uxtb
115 ; CHECK:      cmp [[MINUS_1]], #251
116 ; CHECK:      movlo r0, #8
117 define i32 @safe_add_underflow_neg(i8 zeroext %a) {
118   %add = add i8 %a, -2
119   %cmp = icmp ule i8 %add, -6
120   %res = select i1 %cmp, i32 8, i32 16
121   ret i32 %res
124 ; CHECK-LABEL: overflow_sub_negative_const_limit:
125 ; CHECK:  adds r0, #1
126 ; CHECK:  uxtb [[EXT:r[0-9]+]], r0
127 ; CHECK:  cmp [[EXT]], #128
128 ; CHECK:  movhi r0, #8
129 define i32 @overflow_sub_negative_const_limit(i8 zeroext %a) {
130   %sub = sub i8 %a, -1
131   %cmp = icmp ugt i8 %sub, 128
132   %res = select i1 %cmp, i32 8, i32 16
133   ret i32 %res
136 ; CHECK-LABEL: unsafe_sub_underflow:
137 ; CHECK:  subs r0, #6
138 ; CHECK:  uxtb [[EXT:r[0-9]+]], r0
139 ; CHECK:  cmp [[EXT]], #250
140 ; CHECK:  movhi r0, #8
141 define i32 @unsafe_sub_underflow(i8 zeroext %a) {
142   %sub = sub i8 %a, 6
143   %cmp = icmp ugt i8 %sub, 250
144   %res = select i1 %cmp, i32 8, i32 16
145   ret i32 %res
148 ; CHECK-LABEL: safe_sub_underflow:
149 ; CHECK:      subs [[MINUS_1:r[0-9]+]], r0, #1
150 ; CHECK-NOT:  uxtb
151 ; CHECK:      cmp [[MINUS_1]], #255
152 ; CHECK:      movlo r0, #8
153 define i32 @safe_sub_underflow(i8 zeroext %a) {
154   %sub = sub i8 %a, 1
155   %cmp = icmp ule i8 %sub, 254
156   %res = select i1 %cmp, i32 8, i32 16
157   ret i32 %res
160 ; CHECK-LABEL: safe_sub_underflow_neg
161 ; CHECK:      subs [[MINUS_1:r[0-9]+]], r0, #4
162 ; CHECK-NOT:  uxtb
163 ; CHECK:      cmp [[MINUS_1]], #250
164 ; CHECK:      movhi r0, #8
165 define i32 @safe_sub_underflow_neg(i8 zeroext %a) {
166   %sub = sub i8 %a, 4
167   %cmp = icmp uge i8 %sub, -5
168   %res = select i1 %cmp, i32 8, i32 16
169   ret i32 %res
172 ; CHECK-LABEL: unsafe_sub_underflow_neg
173 ; CHECK:  subs r0, #4
174 ; CHECK:  uxtb [[EXT:r[0-9]+]], r0
175 ; CHECK:  cmp [[EXT]], #253
176 ; CHECK:  movlo r0, #8
177 define i32 @unsafe_sub_underflow_neg(i8 zeroext %a) {
178   %sub = sub i8 %a, 4
179   %cmp = icmp ult i8 %sub, -3
180   %res = select i1 %cmp, i32 8, i32 16
181   ret i32 %res
184 ; CHECK:      rsb.w [[RSUB:r[0-9]+]], r0, #248
185 ; CHECK-NOT:  uxt
186 ; CHECK:      cmp [[RSUB]], #252
187 define i32 @safe_sub_imm_var(i8* %b) {
188 entry:
189   %0 = load i8, i8* %b, align 1
190   %sub = sub nuw nsw i8 -8, %0
191   %cmp = icmp ugt i8 %sub, 252
192   %conv4 = zext i1 %cmp to i32
193   ret i32 %conv4
196 ; CHECK-LABEL: safe_sub_var_imm
197 ; CHECK:      sub.w [[ADD:r[0-9]+]], r0, #248
198 ; CHECK-NOT:  uxt
199 ; CHECK:      cmp [[ADD]], #252
200 define i32 @safe_sub_var_imm(i8* %b) {
201 entry:
202   %0 = load i8, i8* %b, align 1
203   %sub = sub nuw nsw i8 %0, -8
204   %cmp = icmp ugt i8 %sub, 252
205   %conv4 = zext i1 %cmp to i32
206   ret i32 %conv4
209 ; CHECK-LABEL: safe_add_imm_var
210 ; CHECK:      add.w [[ADD:r[0-9]+]], r0, #129
211 ; CHECK-NOT:  uxt
212 ; CHECK:      cmp [[ADD]], #127
213 define i32 @safe_add_imm_var(i8* %b) {
214 entry:
215   %0 = load i8, i8* %b, align 1
216   %add = add nuw nsw i8 -127, %0
217   %cmp = icmp ugt i8 %add, 127
218   %conv4 = zext i1 %cmp to i32
219   ret i32 %conv4
222 ; CHECK-LABEL: safe_add_var_imm
223 ; CHECK:      add.w [[SUB:r[0-9]+]], r0, #129
224 ; CHECK-NOT:  uxt
225 ; CHECK:      cmp [[SUB]], #127
226 define i32 @safe_add_var_imm(i8* %b) {
227 entry:
228   %0 = load i8, i8* %b, align 1
229   %add = add nuw nsw i8 %0, -127
230   %cmp = icmp ugt i8 %add, 127
231   %conv4 = zext i1 %cmp to i32
232   ret i32 %conv4
235 ; CHECK-LABEL: convert_add_order
236 ; CHECK: orr{{.*}}, #1
237 ; CHECK: sub{{.*}}, #40
238 ; CHECK-NOT: uxt
239 define i8 @convert_add_order(i8 zeroext %arg) {
240   %mask.0 = and i8 %arg, 1
241   %mask.1 = and i8 %arg, 2
242   %shl = or i8 %arg, 1
243   %add = add nuw i8 %shl, 10
244   %cmp.0 = icmp ult i8 %add, 60
245   %sub = add nsw i8 %shl, -40
246   %cmp.1 = icmp ult i8 %sub, 20
247   %mask.sel = select i1 %cmp.1, i8 %mask.0, i8 %mask.1
248   %res = select i1 %cmp.0, i8 %mask.sel, i8 %arg
249   ret i8 %res
252 ; CHECK-LABEL: underflow_if_sub
253 ; CHECK: add{{.}} [[ADD:r[0-9]+]], #245
254 ; CHECK: cmp [[ADD]], r1
255 define i8 @underflow_if_sub(i32 %arg, i8 zeroext %arg1) {
256   %cmp = icmp sgt i32 %arg, 0
257   %conv = zext i1 %cmp to i32
258   %and = and i32 %arg, %conv
259   %trunc = trunc i32 %and to i8
260   %conv1 = add nuw nsw i8 %trunc, -11
261   %cmp.1 = icmp ult i8 %conv1, %arg1
262   %res = select i1 %cmp.1, i8 %conv1, i8 100
263   ret i8 %res
266 ; CHECK-LABEL: underflow_if_sub_signext
267 ; CHECK:      cmp r0, #0
268 ; CHECK-NEXT: uxtb  r1, r1
269 ; CHECK-NOT:  xtb
270 define i8 @underflow_if_sub_signext(i32 %arg, i8 signext %arg1) {
271   %cmp = icmp sgt i32 %arg, 0
272   %conv = zext i1 %cmp to i32
273   %and = and i32 %arg, %conv
274   %trunc = trunc i32 %and to i8
275   %conv1 = add nuw nsw i8 %trunc, -11
276   %cmp.1 = icmp ugt i8 %arg1, %conv1
277   %res = select i1 %cmp.1, i8 %conv1, i8 100
278   ret i8 %res