@@ -109,6 +109,58 @@ entry:
109109 ret void
110110}
111111
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+
112164define ptr @gep_inbounds_add_nsw_nonneg (ptr %ptr , i64 %a , i64 %b ) {
113165; CHECK-LABEL: define ptr @gep_inbounds_add_nsw_nonneg(
114166; CHECK-SAME: ptr [[PTR:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) {
@@ -219,6 +271,27 @@ define ptr @gep_inbounds_sext_add_nonneg(ptr %ptr, i32 %a) {
219271 ret ptr %gep
220272}
221273
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+
222295define ptr @gep_inbounds_sext_add_not_nonneg_1 (ptr %ptr , i32 %a ) {
223296; CHECK-LABEL: define ptr @gep_inbounds_sext_add_not_nonneg_1(
224297; CHECK-SAME: ptr [[PTR:%.*]], i32 [[A:%.*]]) {
0 commit comments