Skip to content

Commit cd65bc2

Browse files
nikicrlavaee
authored andcommitted
[InstCombine] Rewrite multi-use GEPs when simplifying comparison (llvm#146100)
We already do this when both sides are a GEP, but not if only one is. This ensures that the offset arithmetic is not duplicated.
1 parent 5dcd770 commit cd65bc2

File tree

3 files changed

+31
-2
lines changed

3 files changed

+31
-2
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ Instruction *InstCombinerImpl::foldGEPICmp(GEPOperator *GEPLHS, Value *RHS,
711711
Value *PtrBase = GEPLHS->getOperand(0);
712712
if (PtrBase == RHS && CanFold(GEPLHS->getNoWrapFlags())) {
713713
// ((gep Ptr, OFFSET) cmp Ptr) ---> (OFFSET cmp 0).
714-
Value *Offset = EmitGEPOffset(GEPLHS);
714+
Value *Offset = EmitGEPOffset(GEPLHS, /*RewriteGEP=*/true);
715715
return NewICmp(GEPLHS->getNoWrapFlags(), Offset,
716716
Constant::getNullValue(Offset->getType()));
717717
}

llvm/test/Transforms/InstCombine/icmp-gep.ll

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,34 @@ define i1 @eq_base_inbounds_commute_use(i64 %y) {
221221
ret i1 %r
222222
}
223223

224+
define i1 @ne_base_inbounds_use_scaled(ptr %x, i64 %y) {
225+
; CHECK-LABEL: @ne_base_inbounds_use_scaled(
226+
; CHECK-NEXT: [[G_IDX:%.*]] = shl nsw i64 [[Y:%.*]], 3
227+
; CHECK-NEXT: [[G:%.*]] = getelementptr inbounds i8, ptr [[X:%.*]], i64 [[G_IDX]]
228+
; CHECK-NEXT: call void @use(ptr [[G]])
229+
; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[Y]], 0
230+
; CHECK-NEXT: ret i1 [[R]]
231+
;
232+
%g = getelementptr inbounds i64, ptr %x, i64 %y
233+
call void @use(ptr %g)
234+
%r = icmp ne ptr %g, %x
235+
ret i1 %r
236+
}
237+
238+
define i1 @ne_base_use_scaled(ptr %x, i64 %y) {
239+
; CHECK-LABEL: @ne_base_use_scaled(
240+
; CHECK-NEXT: [[G_IDX_MASK:%.*]] = shl i64 [[Y:%.*]], 3
241+
; CHECK-NEXT: [[G:%.*]] = getelementptr i8, ptr [[X:%.*]], i64 [[G_IDX_MASK]]
242+
; CHECK-NEXT: call void @use(ptr [[G]])
243+
; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[G_IDX_MASK]], 0
244+
; CHECK-NEXT: ret i1 [[R]]
245+
;
246+
%g = getelementptr i64, ptr %x, i64 %y
247+
call void @use(ptr %g)
248+
%r = icmp ne ptr %g, %x
249+
ret i1 %r
250+
}
251+
224252
define i1 @eq_bitcast_base(ptr %p, i64 %x) {
225253
; CHECK-LABEL: @eq_bitcast_base(
226254
; CHECK-NEXT: [[GEP_IDX_MASK:%.*]] = and i64 [[X:%.*]], 9223372036854775807

llvm/test/Transforms/PhaseOrdering/loop-access-checks.ll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ define void @test_fill_with_foreach([2 x i64] %elems.coerce) {
2424
; CHECK-NEXT: [[ELEMS_COERCE_FCA_0_EXTRACT:%.*]] = extractvalue [2 x i64] [[ELEMS_COERCE]], 0
2525
; CHECK-NEXT: [[TMP0:%.*]] = inttoptr i64 [[ELEMS_COERCE_FCA_0_EXTRACT]] to ptr
2626
; CHECK-NEXT: [[ELEMS_COERCE_FCA_1_EXTRACT:%.*]] = extractvalue [2 x i64] [[ELEMS_COERCE]], 1
27-
; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 [[ELEMS_COERCE_FCA_1_EXTRACT]]
27+
; CHECK-NEXT: [[ADD_PTR_I_IDX:%.*]] = shl nsw i64 [[ELEMS_COERCE_FCA_1_EXTRACT]], 2
28+
; CHECK-NEXT: [[ADD_PTR_I:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 [[ADD_PTR_I_IDX]]
2829
; CHECK-NEXT: [[CMP_NOT_I_I_I_I:%.*]] = icmp slt i64 [[ELEMS_COERCE_FCA_1_EXTRACT]], 0
2930
; CHECK-NEXT: br i1 [[CMP_NOT_I_I_I_I]], label [[ERROR:%.*]], label [[FOR_COND_PREHEADER_SPLIT:%.*]]
3031
; CHECK: for.cond.preheader.split:

0 commit comments

Comments
 (0)