1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -mtriple=riscv64-unknown-elf -passes='separate-const-offset-from-gep,early-cse' \
3 ; RUN: -S | FileCheck %s
5 ; Several tests for separate-const-offset-from-gep. The transformation
6 ; heavily relies on TargetTransformInfo, so we put these tests under
7 ; target-specific folders.
9 ; Simple case when GEPs should be optimized.
10 define i64 @test1(ptr %array, i64 %i, i64 %j) {
11 ; CHECK-LABEL: @test1(
13 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[I:%.*]], 5
14 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i64, ptr [[ARRAY:%.*]], i64 [[I]]
15 ; CHECK-NEXT: [[GEP4:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 40
16 ; CHECK-NEXT: store i64 [[J:%.*]], ptr [[GEP4]], align 8
17 ; CHECK-NEXT: [[GEP26:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 48
18 ; CHECK-NEXT: store i64 [[J]], ptr [[GEP26]], align 8
19 ; CHECK-NEXT: [[GEP38:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 280
20 ; CHECK-NEXT: store i64 [[ADD]], ptr [[GEP38]], align 8
21 ; CHECK-NEXT: ret i64 undef
24 %add = add nsw i64 %i, 5
25 %gep = getelementptr inbounds i64, ptr %array, i64 %add
26 store i64 %j, ptr %gep
27 %add2 = add nsw i64 %i, 6
28 %gep2 = getelementptr inbounds i64, ptr %array, i64 %add2
29 store i64 %j, ptr %gep2
30 %add3 = add nsw i64 %i, 35
31 %gep3 = getelementptr inbounds i64, ptr %array, i64 %add3
32 store i64 %add, ptr %gep3
36 ; Optimize GEPs when there sext instructions are needed to cast index value to expected type.
37 define i32 @test2(ptr %array, i32 %i, i32 %j) {
38 ; CHECK-LABEL: @test2(
40 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[I:%.*]], 5
41 ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[I]] to i64
42 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[ARRAY:%.*]], i64 [[TMP0]]
43 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 20
44 ; CHECK-NEXT: store i32 [[J:%.*]], ptr [[GEP2]], align 4
45 ; CHECK-NEXT: [[GEP54:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 24
46 ; CHECK-NEXT: store i32 [[J]], ptr [[GEP54]], align 4
47 ; CHECK-NEXT: [[GEP86:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 140
48 ; CHECK-NEXT: store i32 [[ADD]], ptr [[GEP86]], align 4
49 ; CHECK-NEXT: ret i32 undef
52 %add = add nsw i32 %i, 5
53 %sext = sext i32 %add to i64
54 %gep = getelementptr inbounds i32, ptr %array, i64 %sext
55 store i32 %j, ptr %gep
56 %add3 = add nsw i32 %i, 6
57 %sext4 = sext i32 %add3 to i64
58 %gep5 = getelementptr inbounds i32, ptr %array, i64 %sext4
59 store i32 %j, ptr %gep5
60 %add6 = add nsw i32 %i, 35
61 %sext7 = sext i32 %add6 to i64
62 %gep8 = getelementptr inbounds i32, ptr %array, i64 %sext7
63 store i32 %add, ptr %gep8
67 ; No need to modify because all values are also used in other expressions.
68 ; Modification doesn't decrease register pressure.
69 define i32 @test3(ptr %array, i32 %i) {
70 ; CHECK-LABEL: @test3(
72 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[I:%.*]], 5
73 ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[I]] to i64
74 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[ARRAY:%.*]], i64 [[TMP0]]
75 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 20
76 ; CHECK-NEXT: store i32 [[ADD]], ptr [[GEP2]], align 4
77 ; CHECK-NEXT: [[ADD3:%.*]] = add nsw i32 [[I]], 6
78 ; CHECK-NEXT: [[GEP54:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 24
79 ; CHECK-NEXT: store i32 [[ADD3]], ptr [[GEP54]], align 4
80 ; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[I]], 35
81 ; CHECK-NEXT: [[GEP86:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 140
82 ; CHECK-NEXT: store i32 [[ADD6]], ptr [[GEP86]], align 4
83 ; CHECK-NEXT: ret i32 undef
86 %add = add nsw i32 %i, 5
87 %sext = sext i32 %add to i64
88 %gep = getelementptr inbounds i32, ptr %array, i64 %sext
89 store i32 %add, ptr %gep
90 %add3 = add nsw i32 %i, 6
91 %sext4 = sext i32 %add3 to i64
92 %gep5 = getelementptr inbounds i32, ptr %array, i64 %sext4
93 store i32 %add3, ptr %gep5
94 %add6 = add nsw i32 %i, 35
95 %sext7 = sext i32 %add6 to i64
96 %gep8 = getelementptr inbounds i32, ptr %array, i64 %sext7
97 store i32 %add6, ptr %gep8
101 ; Optimized GEPs for multidimensional array with same base
102 define i32 @test4(ptr %array2, i32 %i) {
103 ; CHECK-LABEL: @test4(
105 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[I:%.*]], 5
106 ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[I]] to i64
107 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [50 x i32], ptr [[ARRAY2:%.*]], i64 [[TMP0]], i64 [[TMP0]]
108 ; CHECK-NEXT: [[GEP3:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 1020
109 ; CHECK-NEXT: store i32 [[I]], ptr [[GEP3]], align 4
110 ; CHECK-NEXT: [[GEP56:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 1024
111 ; CHECK-NEXT: store i32 [[ADD]], ptr [[GEP56]], align 4
112 ; CHECK-NEXT: [[GEP89:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 1140
113 ; CHECK-NEXT: store i32 [[I]], ptr [[GEP89]], align 4
114 ; CHECK-NEXT: ret i32 undef
117 %add = add nsw i32 %i, 5
118 %sext = sext i32 %add to i64
119 %gep = getelementptr inbounds [50 x i32], ptr %array2, i64 %sext, i64 %sext
120 store i32 %i, ptr %gep
121 %add3 = add nsw i32 %i, 6
122 %sext4 = sext i32 %add3 to i64
123 %gep5 = getelementptr inbounds [50 x i32], ptr %array2, i64 %sext, i64 %sext4
124 store i32 %add, ptr %gep5
125 %add6 = add nsw i32 %i, 35
126 %sext7 = sext i32 %add6 to i64
127 %gep8 = getelementptr inbounds [50 x i32], ptr %array2, i64 %sext, i64 %sext7
128 store i32 %i, ptr %gep8
132 ; Don't optimize GEPs for multidimensional array with same base because RISC-V doesn't support the addressing mode
133 define i32 @test5(ptr %array2, i32 %i, i64 %j) {
134 ; CHECK-LABEL: @test5(
136 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[I:%.*]], 5
137 ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[I]] to i64
138 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [50 x i32], ptr [[ARRAY2:%.*]], i64 [[TMP0]], i64 [[TMP0]]
139 ; CHECK-NEXT: [[GEP3:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 1020
140 ; CHECK-NEXT: store i32 [[ADD]], ptr [[GEP3]], align 4
141 ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr [50 x i32], ptr [[ARRAY2]], i64 [[TMP0]], i64 [[J:%.*]]
142 ; CHECK-NEXT: [[GEP55:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 1200
143 ; CHECK-NEXT: store i32 [[I]], ptr [[GEP55]], align 4
144 ; CHECK-NEXT: [[ADD6:%.*]] = add nsw i32 [[I]], 35
145 ; CHECK-NEXT: [[SEXT7:%.*]] = sext i32 [[ADD6]] to i64
146 ; CHECK-NEXT: [[GEP8:%.*]] = getelementptr inbounds [50 x i32], ptr [[ARRAY2]], i64 [[SEXT7]], i64 [[J]]
147 ; CHECK-NEXT: store i32 [[I]], ptr [[GEP8]], align 4
148 ; CHECK-NEXT: ret i32 undef
151 %add = add nsw i32 %i, 5
152 %sext = sext i32 %add to i64
153 %gep = getelementptr inbounds [50 x i32], ptr %array2, i64 %sext, i64 %sext
154 store i32 %add, ptr %gep
155 %add3 = add nsw i32 %i, 6
156 %sext4 = sext i32 %add3 to i64
157 %gep5 = getelementptr inbounds [50 x i32], ptr %array2, i64 %sext4, i64 %j
158 store i32 %i, ptr %gep5
159 %add6 = add nsw i32 %i, 35
160 %sext7 = sext i32 %add6 to i64
161 %gep8 = getelementptr inbounds [50 x i32], ptr %array2, i64 %sext7, i64 %j
162 store i32 %i, ptr %gep8
166 ; No need to optimize GEPs, because there is critical amount with non-constant offsets.
167 define i64 @test6(ptr %array, i64 %i, i64 %j) {
168 ; CHECK-LABEL: @test6(
170 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[I:%.*]], 5
171 ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i64, ptr [[ARRAY:%.*]], i64 [[J:%.*]]
172 ; CHECK-NEXT: store i64 [[ADD]], ptr [[GEP]], align 8
173 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr i64, ptr [[ARRAY]], i64 [[I]]
174 ; CHECK-NEXT: [[GEP52:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 48
175 ; CHECK-NEXT: store i64 [[I]], ptr [[GEP52]], align 8
176 ; CHECK-NEXT: store i64 [[I]], ptr [[TMP0]], align 8
177 ; CHECK-NEXT: ret i64 undef
180 %add = add nsw i64 %i, 5
181 %gep = getelementptr inbounds i64, ptr %array, i64 %j
182 store i64 %add, ptr %gep
183 %add3 = add nsw i64 %i, 6
184 %gep5 = getelementptr inbounds i64, ptr %array, i64 %add3
185 store i64 %i, ptr %gep5
186 %add6 = add nsw i64 %i, 35
187 %gep8 = getelementptr inbounds i64, ptr %array, i64 %i
188 store i64 %i, ptr %gep8
192 ; No need to optimize GEPs, because the base variable is different.
193 define i32 @test7(ptr %array, i32 %i, i32 %j, i32 %k) {
194 ; CHECK-LABEL: @test7(
196 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[I:%.*]], 5
197 ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[I]] to i64
198 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[ARRAY:%.*]], i64 [[TMP0]]
199 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 20
200 ; CHECK-NEXT: store i32 [[ADD]], ptr [[GEP2]], align 4
201 ; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[K:%.*]] to i64
202 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[ARRAY]], i64 [[TMP2]]
203 ; CHECK-NEXT: [[GEP54:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 24
204 ; CHECK-NEXT: store i32 [[I]], ptr [[GEP54]], align 4
205 ; CHECK-NEXT: [[TMP4:%.*]] = sext i32 [[J:%.*]] to i64
206 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i32, ptr [[ARRAY]], i64 [[TMP4]]
207 ; CHECK-NEXT: [[GEP86:%.*]] = getelementptr inbounds i8, ptr [[TMP5]], i64 140
208 ; CHECK-NEXT: store i32 [[I]], ptr [[GEP86]], align 4
209 ; CHECK-NEXT: ret i32 undef
212 %add = add nsw i32 %i, 5
213 %sext = sext i32 %add to i64
214 %gep = getelementptr inbounds i32, ptr %array, i64 %sext
215 store i32 %add, ptr %gep
216 %add3 = add nsw i32 %k, 6
217 %sext4 = sext i32 %add3 to i64
218 %gep5 = getelementptr inbounds i32, ptr %array, i64 %sext4
219 store i32 %i, ptr %gep5
220 %add6 = add nsw i32 %j, 35
221 %sext7 = sext i32 %add6 to i64
222 %gep8 = getelementptr inbounds i32, ptr %array, i64 %sext7
223 store i32 %i, ptr %gep8
227 ; No need to optimize GEPs, because the base of GEP instructions is different.
228 define i32 @test8(ptr %array, ptr %array2, ptr %array3, i32 %i) {
229 ; CHECK-LABEL: @test8(
231 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[I:%.*]], 5
232 ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[I]] to i64
233 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[ARRAY:%.*]], i64 [[TMP0]]
234 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 20
235 ; CHECK-NEXT: store i32 [[ADD]], ptr [[GEP2]], align 4
236 ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[ARRAY2:%.*]], i64 [[TMP0]]
237 ; CHECK-NEXT: [[GEP54:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 24
238 ; CHECK-NEXT: store i32 [[I]], ptr [[GEP54]], align 4
239 ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[ARRAY3:%.*]], i64 [[TMP0]]
240 ; CHECK-NEXT: [[GEP86:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 140
241 ; CHECK-NEXT: store i32 [[I]], ptr [[GEP86]], align 4
242 ; CHECK-NEXT: ret i32 undef
245 %add = add nsw i32 %i, 5
246 %sext = sext i32 %add to i64
247 %gep = getelementptr inbounds i32, ptr %array, i64 %sext
248 store i32 %add, ptr %gep
249 %add3 = add nsw i32 %i, 6
250 %sext4 = sext i32 %add3 to i64
251 %gep5 = getelementptr inbounds i32, ptr %array2, i64 %sext4
252 store i32 %i, ptr %gep5
253 %add6 = add nsw i32 %i, 35
254 %sext7 = sext i32 %add6 to i64
255 %gep8 = getelementptr inbounds i32, ptr %array3, i64 %sext7
256 store i32 %i, ptr %gep8
260 ; No need to optimize GEPs of multidimensional array, because the base of GEP instructions is different.
261 define i32 @test9(ptr %array, i32 %i) {
262 ; CHECK-LABEL: @test9(
264 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[I:%.*]], 5
265 ; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[I]] to i64
266 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [50 x i32], ptr [[ARRAY:%.*]], i64 0, i64 [[TMP0]]
267 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 20
268 ; CHECK-NEXT: store i32 [[ADD]], ptr [[GEP2]], align 4
269 ; CHECK-NEXT: [[TMP2:%.*]] = getelementptr [50 x i32], ptr [[ARRAY]], i64 [[TMP0]], i64 [[TMP0]]
270 ; CHECK-NEXT: [[GEP54:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 24
271 ; CHECK-NEXT: store i32 [[I]], ptr [[GEP54]], align 4
272 ; CHECK-NEXT: [[GEP87:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 1340
273 ; CHECK-NEXT: store i32 [[I]], ptr [[GEP87]], align 4
274 ; CHECK-NEXT: ret i32 undef
277 %add = add nsw i32 %i, 5
278 %sext = sext i32 %add to i64
279 %gep = getelementptr inbounds [50 x i32], ptr %array, i64 0, i64 %sext
280 store i32 %add, ptr %gep
281 %add3 = add nsw i32 %i, 6
282 %sext4 = sext i32 %add3 to i64
283 %int = sext i32 %i to i64
284 %gep5 = getelementptr inbounds [50 x i32], ptr %array, i64 %int, i64 %sext4
285 store i32 %i, ptr %gep5
286 %add6 = add nsw i32 %i, 35
287 %sext7 = sext i32 %add6 to i64
288 %gep8 = getelementptr inbounds [50 x i32], ptr %array, i64 %sext4, i64 %sext7
289 store i32 %i, ptr %gep8