xref: /llvm-project/llvm/test/Transforms/InstCombine/array.ll (revision 462cb3cd6cecd0511ecaf0e3ebcaba455ece587d)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4define void @test(ptr %ptr, i32 %a, i32 %b) {
5; CHECK-LABEL: define void @test(
6; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
7; CHECK-NEXT:  entry:
8; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[A]] to i64
9; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[TMP0]]
10; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[TMP1]], i64 40
11; CHECK-NEXT:    store i32 [[B]], ptr [[GEP]], align 4
12; CHECK-NEXT:    ret void
13;
14entry:
15  %add = add nsw i32 %a, 10
16  %idx = sext i32 %add to i64
17  %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx
18  store i32 %b, ptr %gep
19  ret void
20}
21
22define  i32 @test_add_res_moreoneuse(ptr %ptr, i32 %a, i32 %b) {
23; CHECK-LABEL: define i32 @test_add_res_moreoneuse(
24; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
25; CHECK-NEXT:  entry:
26; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 5
27; CHECK-NEXT:    [[IDX:%.*]] = sext i32 [[ADD]] to i64
28; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i32, ptr [[PTR]], i64 [[IDX]]
29; CHECK-NEXT:    store i32 [[B]], ptr [[GEP]], align 4
30; CHECK-NEXT:    ret i32 [[ADD]]
31;
32entry:
33  %add = add nsw i32 %a, 5
34  %idx = sext i32 %add to i64
35  %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx
36  store i32 %b, ptr %gep
37  ret i32 %add
38}
39
40define void @test_addop_nonsw_flag(ptr %ptr, i32 %a, i32 %b) {
41; CHECK-LABEL: define void @test_addop_nonsw_flag(
42; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
43; CHECK-NEXT:  entry:
44; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[A]], 10
45; CHECK-NEXT:    [[IDX:%.*]] = sext i32 [[ADD]] to i64
46; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i32, ptr [[PTR]], i64 [[IDX]]
47; CHECK-NEXT:    store i32 [[B]], ptr [[GEP]], align 4
48; CHECK-NEXT:    ret void
49;
50entry:
51  %add = add i32 %a, 10
52  %idx = sext i32 %add to i64
53  %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx
54  store i32 %b, ptr %gep
55  ret void
56}
57
58define void @test_add_op2_not_constant(ptr %ptr, i32 %a, i32 %b) {
59; CHECK-LABEL: define void @test_add_op2_not_constant(
60; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
61; CHECK-NEXT:  entry:
62; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[A]], [[B]]
63; CHECK-NEXT:    [[IDX:%.*]] = sext i32 [[ADD]] to i64
64; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds i32, ptr [[PTR]], i64 [[IDX]]
65; CHECK-NEXT:    store i32 [[B]], ptr [[GEP]], align 4
66; CHECK-NEXT:    ret void
67;
68entry:
69  %add = add i32 %a, %b
70  %idx = sext i32 %add to i64
71  %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx
72  store i32 %b, ptr %gep
73  ret void
74}
75
76define void @test_zext_nneg(ptr %ptr, i32 %a, i32 %b) {
77; CHECK-LABEL: define void @test_zext_nneg(
78; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
79; CHECK-NEXT:  entry:
80; CHECK-NEXT:    [[TMP0:%.*]] = sext i32 [[A]] to i64
81; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[TMP0]]
82; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[TMP1]], i64 40
83; CHECK-NEXT:    store i32 [[B]], ptr [[GEP]], align 4
84; CHECK-NEXT:    ret void
85;
86entry:
87  %add = add nsw i32 %a, 10
88  %idx = zext nneg i32 %add to i64
89  %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx
90  store i32 %b, ptr %gep
91  ret void
92}
93
94define void @test_zext_missing_nneg(ptr %ptr, i32 %a, i32 %b) {
95; CHECK-LABEL: define void @test_zext_missing_nneg(
96; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]], i32 [[B:%.*]]) {
97; CHECK-NEXT:  entry:
98; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[A]], 10
99; CHECK-NEXT:    [[IDX:%.*]] = zext i32 [[ADD]] to i64
100; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds nuw i32, ptr [[PTR]], i64 [[IDX]]
101; CHECK-NEXT:    store i32 [[B]], ptr [[GEP]], align 4
102; CHECK-NEXT:    ret void
103;
104entry:
105  %add = add nsw i32 %a, 10
106  %idx = zext i32 %add to i64
107  %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx
108  store i32 %b, ptr %gep
109  ret void
110}
111
112define ptr @gep_inbounds_add_nsw_nonneg(ptr %ptr, i64 %a, i64 %b) {
113; CHECK-LABEL: define ptr @gep_inbounds_add_nsw_nonneg(
114; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
115; CHECK-NEXT:    [[A_NNEG:%.*]] = icmp sgt i64 [[A]], -1
116; CHECK-NEXT:    call void @llvm.assume(i1 [[A_NNEG]])
117; CHECK-NEXT:    [[B_NNEG:%.*]] = icmp sgt i64 [[B]], -1
118; CHECK-NEXT:    call void @llvm.assume(i1 [[B_NNEG]])
119; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr inbounds nuw i32, ptr [[PTR]], i64 [[A]]
120; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds nuw i32, ptr [[TMP1]], i64 [[B]]
121; CHECK-NEXT:    ret ptr [[GEP]]
122;
123  %a.nneg = icmp sgt i64 %a, -1
124  call void @llvm.assume(i1 %a.nneg)
125  %b.nneg = icmp sgt i64 %b, -1
126  call void @llvm.assume(i1 %b.nneg)
127  %add = add nsw i64 %a, %b
128  %gep = getelementptr inbounds i32, ptr %ptr, i64 %add
129  ret ptr %gep
130}
131
132define ptr @gep_inbounds_add_nsw_not_nonneg1(ptr %ptr, i64 %a, i64 %b) {
133; CHECK-LABEL: define ptr @gep_inbounds_add_nsw_not_nonneg1(
134; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
135; CHECK-NEXT:    [[A_NNEG:%.*]] = icmp sgt i64 [[A]], -1
136; CHECK-NEXT:    call void @llvm.assume(i1 [[A_NNEG]])
137; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[A]]
138; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[TMP1]], i64 [[B]]
139; CHECK-NEXT:    ret ptr [[GEP]]
140;
141  %a.nneg = icmp sgt i64 %a, -1
142  call void @llvm.assume(i1 %a.nneg)
143  %add = add nsw i64 %a, %b
144  %gep = getelementptr inbounds i32, ptr %ptr, i64 %add
145  ret ptr %gep
146}
147
148define ptr @gep_inbounds_add_nsw_not_nonneg2(ptr %ptr, i64 %a, i64 %b) {
149; CHECK-LABEL: define ptr @gep_inbounds_add_nsw_not_nonneg2(
150; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
151; CHECK-NEXT:    [[B_NNEG:%.*]] = icmp sgt i64 [[B]], -1
152; CHECK-NEXT:    call void @llvm.assume(i1 [[B_NNEG]])
153; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[A]]
154; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[TMP1]], i64 [[B]]
155; CHECK-NEXT:    ret ptr [[GEP]]
156;
157  %b.nneg = icmp sgt i64 %b, -1
158  call void @llvm.assume(i1 %b.nneg)
159  %add = add nsw i64 %a, %b
160  %gep = getelementptr inbounds i32, ptr %ptr, i64 %add
161  ret ptr %gep
162}
163
164define ptr @gep_not_inbounds_add_nsw_nonneg(ptr %ptr, i64 %a, i64 %b) {
165; CHECK-LABEL: define ptr @gep_not_inbounds_add_nsw_nonneg(
166; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
167; CHECK-NEXT:    [[A_NNEG:%.*]] = icmp sgt i64 [[A]], -1
168; CHECK-NEXT:    call void @llvm.assume(i1 [[A_NNEG]])
169; CHECK-NEXT:    [[B_NNEG:%.*]] = icmp sgt i64 [[B]], -1
170; CHECK-NEXT:    call void @llvm.assume(i1 [[B_NNEG]])
171; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[A]]
172; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[TMP1]], i64 [[B]]
173; CHECK-NEXT:    ret ptr [[GEP]]
174;
175  %a.nneg = icmp sgt i64 %a, -1
176  call void @llvm.assume(i1 %a.nneg)
177  %b.nneg = icmp sgt i64 %b, -1
178  call void @llvm.assume(i1 %b.nneg)
179  %add = add nsw i64 %a, %b
180  %gep = getelementptr i32, ptr %ptr, i64 %add
181  ret ptr %gep
182}
183
184define ptr @gep_inbounds_add_not_nsw_nonneg(ptr %ptr, i64 %a, i64 %b) {
185; CHECK-LABEL: define ptr @gep_inbounds_add_not_nsw_nonneg(
186; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
187; CHECK-NEXT:    [[A_NNEG:%.*]] = icmp sgt i64 [[A]], -1
188; CHECK-NEXT:    call void @llvm.assume(i1 [[A_NNEG]])
189; CHECK-NEXT:    [[B_NNEG:%.*]] = icmp sgt i64 [[B]], -1
190; CHECK-NEXT:    call void @llvm.assume(i1 [[B_NNEG]])
191; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[A]]
192; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i32, ptr [[TMP1]], i64 [[B]]
193; CHECK-NEXT:    ret ptr [[GEP]]
194;
195  %a.nneg = icmp sgt i64 %a, -1
196  call void @llvm.assume(i1 %a.nneg)
197  %b.nneg = icmp sgt i64 %b, -1
198  call void @llvm.assume(i1 %b.nneg)
199  %add = add i64 %a, %b
200  %gep = getelementptr inbounds i32, ptr %ptr, i64 %add
201  ret ptr %gep
202}
203
204define ptr @gep_inbounds_sext_add_nonneg(ptr %ptr, i32 %a) {
205; CHECK-LABEL: define ptr @gep_inbounds_sext_add_nonneg(
206; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]]) {
207; CHECK-NEXT:    [[A_NNEG:%.*]] = icmp sgt i32 [[A]], -1
208; CHECK-NEXT:    call void @llvm.assume(i1 [[A_NNEG]])
209; CHECK-NEXT:    [[TMP1:%.*]] = zext nneg i32 [[A]] to i64
210; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds nuw i32, ptr [[PTR]], i64 [[TMP1]]
211; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP2]], i64 40
212; CHECK-NEXT:    ret ptr [[GEP]]
213;
214  %a.nneg = icmp sgt i32 %a, -1
215  call void @llvm.assume(i1 %a.nneg)
216  %add = add nsw i32 %a, 10
217  %idx = sext i32 %add to i64
218  %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx
219  ret ptr %gep
220}
221
222define ptr @gep_inbounds_sext_add_not_nonneg_1(ptr %ptr, i32 %a) {
223; CHECK-LABEL: define ptr @gep_inbounds_sext_add_not_nonneg_1(
224; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]]) {
225; CHECK-NEXT:    [[A_NNEG:%.*]] = icmp sgt i32 [[A]], -1
226; CHECK-NEXT:    call void @llvm.assume(i1 [[A_NNEG]])
227; CHECK-NEXT:    [[TMP1:%.*]] = zext nneg i32 [[A]] to i64
228; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[TMP1]]
229; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[TMP2]], i64 -40
230; CHECK-NEXT:    ret ptr [[GEP]]
231;
232  %a.nneg = icmp sgt i32 %a, -1
233  call void @llvm.assume(i1 %a.nneg)
234  %add = add nsw i32 %a, -10
235  %idx = sext i32 %add to i64
236  %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx
237  ret ptr %gep
238}
239
240define ptr @gep_inbounds_sext_add_not_nonneg_2(ptr %ptr, i32 %a) {
241; CHECK-LABEL: define ptr @gep_inbounds_sext_add_not_nonneg_2(
242; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]]) {
243; CHECK-NEXT:    [[TMP1:%.*]] = sext i32 [[A]] to i64
244; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[TMP1]]
245; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[TMP2]], i64 40
246; CHECK-NEXT:    ret ptr [[GEP]]
247;
248  %add = add nsw i32 %a, 10
249  %idx = sext i32 %add to i64
250  %gep = getelementptr inbounds i32, ptr %ptr, i64 %idx
251  ret ptr %gep
252}
253
254define ptr @gep_not_inbounds_sext_add_nonneg(ptr %ptr, i32 %a) {
255; CHECK-LABEL: define ptr @gep_not_inbounds_sext_add_nonneg(
256; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]]) {
257; CHECK-NEXT:    [[A_NNEG:%.*]] = icmp sgt i32 [[A]], -1
258; CHECK-NEXT:    call void @llvm.assume(i1 [[A_NNEG]])
259; CHECK-NEXT:    [[TMP1:%.*]] = zext nneg i32 [[A]] to i64
260; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[TMP1]]
261; CHECK-NEXT:    [[GEP:%.*]] = getelementptr i8, ptr [[TMP2]], i64 40
262; CHECK-NEXT:    ret ptr [[GEP]]
263;
264  %a.nneg = icmp sgt i32 %a, -1
265  call void @llvm.assume(i1 %a.nneg)
266  %add = add nsw i32 %a, 10
267  %idx = sext i32 %add to i64
268  %gep = getelementptr i32, ptr %ptr, i64 %idx
269  ret ptr %gep
270}
271