@@ -109,6 +109,58 @@ entry:
109
109
ret void
110
110
}
111
111
112
+ ; FIXME: Should be transformed as OR+GEP -> GEP+GEP (similar to gep_inbounds_add_nuw below).
113
+ define ptr @gep_inbounds_nuwaddlike (ptr %ptr , i64 %a , i64 %b ) {
114
+ ; CHECK-LABEL: define ptr @gep_inbounds_nuwaddlike(
115
+ ; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
116
+ ; CHECK-NEXT: [[ADD:%.*]] = or disjoint i64 [[A]], [[B]]
117
+ ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw i32, ptr [[PTR]], i64 [[ADD]]
118
+ ; CHECK-NEXT: ret ptr [[GEP]]
119
+ ;
120
+ %add = or disjoint i64 %a , %b
121
+ %gep = getelementptr inbounds nuw i32 , ptr %ptr , i64 %add
122
+ ret ptr %gep
123
+ }
124
+
125
+ ; FIXME: Preserve "inbounds nuw".
126
+ define ptr @gep_inbounds_add_nuw (ptr %ptr , i64 %a , i64 %b ) {
127
+ ; CHECK-LABEL: define ptr @gep_inbounds_add_nuw(
128
+ ; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
129
+ ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[A]]
130
+ ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[TMP1]], i64 [[B]]
131
+ ; CHECK-NEXT: ret ptr [[GEP]]
132
+ ;
133
+ %add = add nuw i64 %a , %b
134
+ %gep = getelementptr inbounds nuw i32 , ptr %ptr , i64 %add
135
+ ret ptr %gep
136
+ }
137
+
138
+ ; FIXME: Preserve "nusw nuw".
139
+ define ptr @gep_inbounds_add_nusw_nuw (ptr %ptr , i64 %a , i64 %b ) {
140
+ ; CHECK-LABEL: define ptr @gep_inbounds_add_nusw_nuw(
141
+ ; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
142
+ ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[A]]
143
+ ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[TMP1]], i64 [[B]]
144
+ ; CHECK-NEXT: ret ptr [[GEP]]
145
+ ;
146
+ %add = add nuw i64 %a , %b
147
+ %gep = getelementptr nusw nuw i32 , ptr %ptr , i64 %add
148
+ ret ptr %gep
149
+ }
150
+
151
+ ; FIXME: Preserve "nuw".
152
+ define ptr @gep_add_nuw (ptr %ptr , i64 %a , i64 %b ) {
153
+ ; CHECK-LABEL: define ptr @gep_add_nuw(
154
+ ; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
155
+ ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR]], i64 [[A]]
156
+ ; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[TMP1]], i64 [[B]]
157
+ ; CHECK-NEXT: ret ptr [[GEP]]
158
+ ;
159
+ %add = add nuw i64 %a , %b
160
+ %gep = getelementptr nuw i32 , ptr %ptr , i64 %add
161
+ ret ptr %gep
162
+ }
163
+
112
164
define ptr @gep_inbounds_add_nsw_nonneg (ptr %ptr , i64 %a , i64 %b ) {
113
165
; CHECK-LABEL: define ptr @gep_inbounds_add_nsw_nonneg(
114
166
; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
@@ -219,6 +271,27 @@ define ptr @gep_inbounds_sext_add_nonneg(ptr %ptr, i32 %a) {
219
271
ret ptr %gep
220
272
}
221
273
274
+ ; FIXME: Could be optimized similar to gep_inbounds_sext_add_nonneg above
275
+ ; (difference is that we are using disjoint OR which is canonical form
276
+ ; of ADD with disjoint operands).
277
+ define ptr @gep_inbounds_sext_addlike_nonneg (ptr %ptr , i32 %a ) {
278
+ ; CHECK-LABEL: define ptr @gep_inbounds_sext_addlike_nonneg(
279
+ ; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]]) {
280
+ ; CHECK-NEXT: [[A_NNEG:%.*]] = icmp sgt i32 [[A]], -1
281
+ ; CHECK-NEXT: call void @llvm.assume(i1 [[A_NNEG]])
282
+ ; CHECK-NEXT: [[ADD:%.*]] = or disjoint i32 [[A]], 10
283
+ ; CHECK-NEXT: [[IDX:%.*]] = zext nneg i32 [[ADD]] to i64
284
+ ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw i32, ptr [[PTR]], i64 [[IDX]]
285
+ ; CHECK-NEXT: ret ptr [[GEP]]
286
+ ;
287
+ %a.nneg = icmp sgt i32 %a , -1
288
+ call void @llvm.assume (i1 %a.nneg )
289
+ %add = or disjoint i32 %a , 10
290
+ %idx = sext i32 %add to i64
291
+ %gep = getelementptr inbounds i32 , ptr %ptr , i64 %idx
292
+ ret ptr %gep
293
+ }
294
+
222
295
define ptr @gep_inbounds_sext_add_not_nonneg_1 (ptr %ptr , i32 %a ) {
223
296
; CHECK-LABEL: define ptr @gep_inbounds_sext_add_not_nonneg_1(
224
297
; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]]) {
0 commit comments