xref: /llvm-project/llvm/test/Transforms/SCCP/add-nuw-nsw-flags.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=ipsccp -S %s | FileCheck %s
3
4define i8 @range_from_lshr(i8 %a) {
5; CHECK-LABEL: @range_from_lshr(
6; CHECK-NEXT:  entry:
7; CHECK-NEXT:    [[A_SHR:%.*]] = lshr i8 [[A:%.*]], 1
8; CHECK-NEXT:    [[ADD_1:%.*]] = add nuw i8 [[A_SHR]], 1
9; CHECK-NEXT:    [[ADD_2:%.*]] = add nuw nsw i8 [[A_SHR]], -128
10; CHECK-NEXT:    [[ADD_3:%.*]] = add nsw i8 [[A_SHR]], -127
11; CHECK-NEXT:    [[ADD_4:%.*]] = add nsw i8 [[A_SHR]], -1
12; CHECK-NEXT:    [[RES_1:%.*]] = xor i8 [[ADD_1]], [[ADD_2]]
13; CHECK-NEXT:    [[RES_2:%.*]] = xor i8 [[RES_1]], [[ADD_3]]
14; CHECK-NEXT:    [[RES_3:%.*]] = xor i8 [[RES_2]], [[ADD_4]]
15; CHECK-NEXT:    ret i8 [[RES_3]]
16;
17entry:
18  %a.shr = lshr i8 %a, 1
19  %add.1 = add i8 %a.shr, 1
20  %add.2 = add i8 %a.shr, 128
21  %add.3 = add i8 %a.shr, 129
22  %add.4 = add i8 %a.shr, -1
23  %res.1 = xor i8 %add.1, %add.2
24  %res.2 = xor i8 %res.1, %add.3
25  %res.3 = xor i8 %res.2, %add.4
26  ret i8 %res.3
27}
28
29define i8 @a_and_15_add_1(i8 %a) {
30; CHECK-LABEL: @a_and_15_add_1(
31; CHECK-NEXT:  entry:
32; CHECK-NEXT:    [[A_AND:%.*]] = and i8 [[A:%.*]], 15
33; CHECK-NEXT:    [[ADD_1:%.*]] = add nuw nsw i8 [[A_AND]], 1
34; CHECK-NEXT:    ret i8 [[ADD_1]]
35;
36entry:
37  %a.and = and i8 %a, 15
38  %add.1 = add i8 %a.and, 1
39  ret i8 %add.1
40}
41
42define <4 x i8> @range_from_lshr_vec(<4 x i8> %a) {
43; CHECK-LABEL: @range_from_lshr_vec(
44; CHECK-NEXT:  entry:
45; CHECK-NEXT:    [[A_SHR:%.*]] = lshr <4 x i8> [[A:%.*]], <i8 1, i8 2, i8 3, i8 4>
46; CHECK-NEXT:    [[ADD_1:%.*]] = add nuw <4 x i8> [[A_SHR]], <i8 1, i8 2, i8 3, i8 4>
47; CHECK-NEXT:    ret <4 x i8> [[ADD_1]]
48;
49entry:
50  %a.shr = lshr <4 x i8> %a, <i8 1, i8 2, i8 3, i8 4>
51  %add.1 = add <4 x i8> %a.shr, <i8 1, i8 2, i8 3, i8 4>
52  ret <4 x i8> %add.1
53}
54
55define <4 x i8> @range_from_lshr_vec_2(<4 x i8> %a) {
56; CHECK-LABEL: @range_from_lshr_vec_2(
57; CHECK-NEXT:  entry:
58; CHECK-NEXT:    [[A_SHR:%.*]] = lshr <4 x i8> [[A:%.*]], splat (i8 1)
59; CHECK-NEXT:    [[ADD_1:%.*]] = add nuw <4 x i8> [[A_SHR]], splat (i8 2)
60; CHECK-NEXT:    ret <4 x i8> [[ADD_1]]
61;
62entry:
63  %a.shr = lshr <4 x i8> %a, <i8 1, i8 1, i8 1, i8 1>
64  %add.1 = add <4 x i8> %a.shr, <i8 2, i8 2, i8 2, i8 2>
65  ret <4 x i8> %add.1
66}
67
68define i8 @sge_0_and_sle_90(i8 %a) {
69; CHECK-LABEL: @sge_0_and_sle_90(
70; CHECK-NEXT:  entry:
71; CHECK-NEXT:    [[SGT:%.*]] = icmp sge i8 [[A:%.*]], 0
72; CHECK-NEXT:    [[SLT:%.*]] = icmp sle i8 [[A]], 90
73; CHECK-NEXT:    [[AND:%.*]] = and i1 [[SGT]], [[SLT]]
74; CHECK-NEXT:    br i1 [[AND]], label [[THEN:%.*]], label [[ELSE:%.*]]
75; CHECK:       then:
76; CHECK-NEXT:    [[ADD_1:%.*]] = add nuw nsw i8 [[A]], 1
77; CHECK-NEXT:    [[ADD_2:%.*]] = add nsw i8 [[A]], -1
78; CHECK-NEXT:    [[ADD_3:%.*]] = add nuw nsw i8 [[A]], -91
79; CHECK-NEXT:    [[ADD_4:%.*]] = add nsw i8 [[A]], -90
80; CHECK-NEXT:    [[RES_1:%.*]] = xor i8 [[ADD_1]], [[ADD_2]]
81; CHECK-NEXT:    [[RES_2:%.*]] = xor i8 [[RES_1]], [[ADD_3]]
82; CHECK-NEXT:    [[RES_3:%.*]] = xor i8 [[RES_2]], [[ADD_4]]
83; CHECK-NEXT:    ret i8 [[RES_3]]
84; CHECK:       else:
85; CHECK-NEXT:    [[ADD_5:%.*]] = add i8 [[A]], 1
86; CHECK-NEXT:    [[ADD_6:%.*]] = add i8 [[A]], -1
87; CHECK-NEXT:    [[ADD_7:%.*]] = add i8 [[A]], -91
88; CHECK-NEXT:    [[ADD_8:%.*]] = add i8 [[A]], -90
89; CHECK-NEXT:    [[RES_4:%.*]] = xor i8 [[ADD_5]], [[ADD_6]]
90; CHECK-NEXT:    [[RES_5:%.*]] = xor i8 [[RES_4]], [[ADD_7]]
91; CHECK-NEXT:    [[RES_6:%.*]] = xor i8 [[RES_5]], [[ADD_8]]
92; CHECK-NEXT:    ret i8 [[RES_6]]
93;
94entry:
95  %sgt = icmp sge i8 %a, 0
96  %slt = icmp sle i8 %a, 90
97  %and = and i1 %sgt, %slt
98  br i1 %and, label %then, label %else
99
100then:
101  %add.1 = add i8 %a, 1
102  %add.2 = add i8 %a, -1
103  %add.3 = add i8 %a, 165
104  %add.4 = add i8 %a, 166
105  %res.1 = xor i8 %add.1, %add.2
106  %res.2 = xor i8 %res.1, %add.3
107  %res.3 = xor i8 %res.2, %add.4
108  ret i8 %res.3
109
110else:
111  %add.5 = add i8 %a, 1
112  %add.6 = add i8 %a, -1
113  %add.7 = add i8 %a, 165
114  %add.8 = add i8 %a, 166
115  %res.4 = xor i8 %add.5, %add.6
116  %res.5 = xor i8 %res.4, %add.7
117  %res.6 = xor i8 %res.5, %add.8
118  ret i8 %res.6
119}
120
121define i16 @sge_with_sext_to_zext_conversion(i8 %a)  {
122; CHECK-LABEL: @sge_with_sext_to_zext_conversion(
123; CHECK-NEXT:  entry:
124; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i8 [[A:%.*]], 0
125; CHECK-NEXT:    br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
126; CHECK:       then:
127; CHECK-NEXT:    [[SEXT:%.*]] = zext nneg i8 [[A]] to i16
128; CHECK-NEXT:    [[ADD_1:%.*]] = add i16 [[SEXT]], 1
129; CHECK-NEXT:    [[ADD_2:%.*]] = add i16 [[SEXT]], -128
130; CHECK-NEXT:    [[ADD_3:%.*]] = add i16 [[SEXT]], -127
131; CHECK-NEXT:    [[RES_1:%.*]] = xor i16 [[ADD_1]], [[ADD_2]]
132; CHECK-NEXT:    [[RES_2:%.*]] = xor i16 [[RES_1]], [[ADD_3]]
133; CHECK-NEXT:    ret i16 [[RES_2]]
134; CHECK:       else:
135; CHECK-NEXT:    [[SEXT_2:%.*]] = sext i8 [[A]] to i16
136; CHECK-NEXT:    [[ADD_4:%.*]] = add nsw i16 [[SEXT_2]], 1
137; CHECK-NEXT:    [[ADD_5:%.*]] = add nsw i16 [[SEXT_2]], -128
138; CHECK-NEXT:    [[ADD_6:%.*]] = add nsw i16 [[SEXT_2]], -127
139; CHECK-NEXT:    [[RES_3:%.*]] = xor i16 [[ADD_4]], [[ADD_5]]
140; CHECK-NEXT:    [[RES_4:%.*]] = xor i16 [[RES_3]], [[ADD_6]]
141; CHECK-NEXT:    ret i16 [[RES_4]]
142;
143entry:
144  %cmp = icmp sgt i8 %a, 0
145  br i1 %cmp, label %then, label %else
146
147then:
148  %sext = sext i8 %a to i16
149  %add.1 = add i16 %sext, 1
150  %add.2 = add i16 %sext, 65408
151  %add.3 = add i16 %sext, 65409
152  %res.1 = xor i16 %add.1, %add.2
153  %res.2 = xor i16 %res.1, %add.3
154  ret i16 %res.2
155
156else:
157  %sext.2 = sext i8 %a to i16
158  %add.4 = add i16 %sext.2, 1
159  %add.5 = add i16 %sext.2, 65408
160  %add.6 = add i16 %sext.2, 65409
161  %res.3 = xor i16 %add.4, %add.5
162  %res.4 = xor i16 %res.3, %add.6
163  ret i16 %res.4
164}
165
166@c = internal global <6 x i8> zeroinitializer, align 8
167
168; Test case for PR60280.
169define <6 x i8> @vector_constant_replacement_in_add(<6 x i8> %a) {
170; CHECK-LABEL: @vector_constant_replacement_in_add(
171; CHECK-NEXT:  entry:
172; CHECK-NEXT:    [[ADD:%.*]] = add nuw nsw <6 x i8> [[A:%.*]], zeroinitializer
173; CHECK-NEXT:    ret <6 x i8> [[ADD]]
174;
175entry:
176  %c = load <6 x i8>, ptr @c, align 8
177  %add = add <6 x i8> %a, %c
178  ret <6 x i8> %add
179}
180
181declare i32 @callee()
182
183; Test case for PR60278.
184define i64 @constant_ptrtoint_replacement(i64 %a) {
185; CHECK-LABEL: @constant_ptrtoint_replacement(
186; CHECK-NEXT:  entry:
187; CHECK-NEXT:    [[RES:%.*]] = add i64 [[A:%.*]], ptrtoint (ptr @callee to i64)
188; CHECK-NEXT:    ret i64 [[RES]]
189;
190entry:
191  %fn.addr = ptrtoint ptr @callee to i64
192  %res = add i64 %a, %fn.addr
193  ret i64 %res
194}
195
196define internal <4 x i8> @test_propagate_argument(<4 x i8> %a, <4 x i8> %b) {
197; CHECK-LABEL: @test_propagate_argument(
198; CHECK-NEXT:  entry:
199; CHECK-NEXT:    [[ADD:%.*]] = add <4 x i8> [[A:%.*]], splat (i8 3)
200; CHECK-NEXT:    ret <4 x i8> [[ADD]]
201;
202entry:
203  %add = add <4 x i8> %a, %b
204  ret <4 x i8> %add
205}
206
207define <4 x i8> @test_propagate_caller(<4 x i8> %a) {
208; CHECK-LABEL: @test_propagate_caller(
209; CHECK-NEXT:    [[RES_1:%.*]] = call <4 x i8> @test_propagate_argument(<4 x i8> [[A:%.*]], <4 x i8> splat (i8 3))
210; CHECK-NEXT:    ret <4 x i8> [[RES_1]]
211;
212  %add = add <4 x i8> <i8 1, i8 1, i8 1, i8 1>, <i8 2, i8 2, i8 2, i8 2>
213  %res.1 = call <4 x i8> @test_propagate_argument(<4 x i8> %a, <4 x i8> %add)
214  ret <4 x i8> %res.1
215}
216
217define i16 @test_add_in_different_block(i1 %c, i8 %a) {
218; CHECK-LABEL: @test_add_in_different_block(
219; CHECK-NEXT:  entry:
220; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i8 [[A:%.*]], 0
221; CHECK-NEXT:    [[COND4:%.*]] = select i1 [[CMP]], i8 1, i8 0
222; CHECK-NEXT:    [[CONV:%.*]] = zext nneg i8 [[COND4]] to i16
223; CHECK-NEXT:    br i1 [[C:%.*]], label [[THEN:%.*]], label [[ELSE:%.*]]
224; CHECK:       then:
225; CHECK-NEXT:    [[ADD:%.*]] = add i16 1, [[CONV]]
226; CHECK-NEXT:    ret i16 [[ADD]]
227; CHECK:       else:
228; CHECK-NEXT:    ret i16 0
229;
230entry:
231  %cmp = icmp eq i8 %a, 0
232  %cond4 = select i1 %cmp, i8 1, i8 0
233  %conv = sext i8 %cond4 to i16
234  br i1 %c, label %then, label %else
235
236then:
237  %add = add i16 1, %conv
238  ret i16 %add
239
240else:
241  ret i16 0
242}
243
244define i1 @test_add_nuw_sub(i32 %a) {
245; CHECK-LABEL: @test_add_nuw_sub(
246; CHECK-NEXT:  entry:
247; CHECK-NEXT:    [[ADD:%.*]] = add nuw i32 [[A:%.*]], 10000
248; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[ADD]], -5000
249; CHECK-NEXT:    ret i1 false
250;
251entry:
252  %add = add nuw i32 %a, 10000
253  %sub = add i32 %add, -5000
254  %cond = icmp ult i32 %sub, 5000
255  ret i1 %cond
256}
257
258define i1 @test_add_nsw_sub(i32 %a) {
259; CHECK-LABEL: @test_add_nsw_sub(
260; CHECK-NEXT:  entry:
261; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A:%.*]], 10000
262; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[ADD]], -5000
263; CHECK-NEXT:    [[COND:%.*]] = icmp ult i32 [[SUB]], 5000
264; CHECK-NEXT:    ret i1 [[COND]]
265;
266entry:
267  %add = add nsw i32 %a, 10000
268  %sub = add i32 %add, -5000
269  %cond = icmp ult i32 %sub, 5000
270  ret i1 %cond
271}
272