Skip to content

Commit ae96839

Browse files
committed
support folding icmp of gep chains with common base
1 parent 591b876 commit ae96839

File tree

2 files changed

+51
-49
lines changed

2 files changed

+51
-49
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -755,8 +755,7 @@ Instruction *InstCombinerImpl::foldGEPICmp(GEPOperator *GEPLHS, Value *RHS,
755755

756756
// If the base pointers are different, but the indices are the same, just
757757
// compare the base pointer.
758-
Value *PtrBase = GEPLHS->getOperand(0);
759-
if (PtrBase != GEPRHS->getOperand(0)) {
758+
if (GEPLHS->getOperand(0) != GEPRHS->getOperand(0)) {
760759
bool IndicesTheSame =
761760
GEPLHS->getNumOperands() == GEPRHS->getNumOperands() &&
762761
GEPLHS->getPointerOperand()->getType() ==
@@ -782,7 +781,7 @@ Instruction *InstCombinerImpl::foldGEPICmp(GEPOperator *GEPLHS, Value *RHS,
782781
if (GEPLHS->isInBounds() && GEPRHS->isInBounds() &&
783782
(GEPLHS->hasAllConstantIndices() || GEPLHS->hasOneUse()) &&
784783
(GEPRHS->hasAllConstantIndices() || GEPRHS->hasOneUse()) &&
785-
PtrBase->stripPointerCasts() ==
784+
GEPLHS->getOperand(0)->stripPointerCasts() ==
786785
GEPRHS->getOperand(0)->stripPointerCasts() &&
787786
!GEPLHS->getType()->isVectorTy()) {
788787
Value *LOffset = EmitGEPOffset(GEPLHS);
@@ -805,14 +804,10 @@ Instruction *InstCombinerImpl::foldGEPICmp(GEPOperator *GEPLHS, Value *RHS,
805804
LOffset, ROffset);
806805
return replaceInstUsesWith(I, Cmp);
807806
}
808-
809-
// Otherwise, the base pointers are different and the indices are
810-
// different. Try convert this to an indexed compare by looking through
811-
// PHIs/casts.
812-
return transformToIndexedCompare(GEPLHS, RHS, Cond, DL, *this);
813807
}
814808

815-
if (GEPLHS->getNumOperands() == GEPRHS->getNumOperands() &&
809+
if (GEPLHS->getOperand(0) == GEPRHS->getOperand(0) &&
810+
GEPLHS->getNumOperands() == GEPRHS->getNumOperands() &&
816811
GEPLHS->getSourceElementType() == GEPRHS->getSourceElementType()) {
817812
// If the GEPs only differ by one index, compare it.
818813
unsigned NumDifferences = 0; // Keep track of # differences.
@@ -849,11 +844,14 @@ Instruction *InstCombinerImpl::foldGEPICmp(GEPOperator *GEPLHS, Value *RHS,
849844
}
850845
}
851846

852-
if (CanFold(NW)) {
847+
if (Base.Ptr && CanFold(Base.LHSNW & Base.RHSNW) && !Base.isExpensive()) {
853848
// ((gep Ptr, OFFSET1) cmp (gep Ptr, OFFSET2) ---> (OFFSET1 cmp OFFSET2)
854-
Value *L = EmitGEPOffset(GEPLHS, /*RewriteGEP=*/true);
855-
Value *R = EmitGEPOffset(GEPRHS, /*RewriteGEP=*/true);
856-
return NewICmp(NW, L, R);
849+
Type *IdxTy = DL.getIndexType(GEPLHS->getType());
850+
Value *L =
851+
EmitGEPOffsets(Base.LHSGEPs, Base.LHSNW, IdxTy, /*RewriteGEP=*/true);
852+
Value *R =
853+
EmitGEPOffsets(Base.RHSGEPs, Base.RHSNW, IdxTy, /*RewriteGEP=*/true);
854+
return NewICmp(Base.LHSNW & Base.RHSNW, L, R);
857855
}
858856
}
859857

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

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -984,11 +984,11 @@ define i1 @gep_multiple_multi_use_above_limit(ptr %base, i64 %idx1, i64 %idx2, i
984984

985985
define i1 @gep_gep_multiple_eq(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {
986986
; CHECK-LABEL: @gep_gep_multiple_eq(
987-
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i32, ptr [[BASE:%.*]], i64 [[IDX1:%.*]]
988-
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i32, ptr [[GEP1]], i64 [[IDX2:%.*]]
989-
; CHECK-NEXT: [[GEP3:%.*]] = getelementptr i32, ptr [[BASE]], i64 [[IDX3:%.*]]
990-
; CHECK-NEXT: [[GEP4:%.*]] = getelementptr i32, ptr [[GEP3]], i64 [[IDX4:%.*]]
991-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[GEP2]], [[GEP4]]
987+
; CHECK-NEXT: [[GEP1_IDX1:%.*]] = add i64 [[IDX1:%.*]], [[IDX2:%.*]]
988+
; CHECK-NEXT: [[GEP3_IDX2:%.*]] = add i64 [[IDX3:%.*]], [[IDX4:%.*]]
989+
; CHECK-NEXT: [[CMP_UNSHIFTED:%.*]] = xor i64 [[GEP1_IDX1]], [[GEP3_IDX2]]
990+
; CHECK-NEXT: [[CMP_MASK:%.*]] = and i64 [[CMP_UNSHIFTED]], 4611686018427387903
991+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[CMP_MASK]], 0
992992
; CHECK-NEXT: ret i1 [[CMP]]
993993
;
994994
%gep1 = getelementptr i32, ptr %base, i64 %idx1
@@ -1001,11 +1001,9 @@ define i1 @gep_gep_multiple_eq(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %
10011001

10021002
define i1 @gep_gep_multiple_eq_nuw(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {
10031003
; CHECK-LABEL: @gep_gep_multiple_eq_nuw(
1004-
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nuw i32, ptr [[BASE:%.*]], i64 [[IDX1:%.*]]
1005-
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr nuw i32, ptr [[GEP1]], i64 [[IDX2:%.*]]
1006-
; CHECK-NEXT: [[GEP3:%.*]] = getelementptr nuw i32, ptr [[BASE]], i64 [[IDX3:%.*]]
1007-
; CHECK-NEXT: [[GEP4:%.*]] = getelementptr nuw i32, ptr [[GEP3]], i64 [[IDX4:%.*]]
1008-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[GEP2]], [[GEP4]]
1004+
; CHECK-NEXT: [[GEP1_IDX1:%.*]] = add i64 [[IDX1:%.*]], [[IDX2:%.*]]
1005+
; CHECK-NEXT: [[GEP3_IDX2:%.*]] = add i64 [[IDX3:%.*]], [[IDX4:%.*]]
1006+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[GEP1_IDX1]], [[GEP3_IDX2]]
10091007
; CHECK-NEXT: ret i1 [[CMP]]
10101008
;
10111009
%gep1 = getelementptr nuw i32, ptr %base, i64 %idx1
@@ -1018,11 +1016,13 @@ define i1 @gep_gep_multiple_eq_nuw(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i
10181016

10191017
define i1 @gep_gep_multiple_eq_nuw_different_scales(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {
10201018
; CHECK-LABEL: @gep_gep_multiple_eq_nuw_different_scales(
1021-
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nuw i32, ptr [[BASE:%.*]], i64 [[IDX1:%.*]]
1022-
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr nuw i64, ptr [[GEP1]], i64 [[IDX2:%.*]]
1023-
; CHECK-NEXT: [[GEP3:%.*]] = getelementptr nuw i32, ptr [[BASE]], i64 [[IDX3:%.*]]
1024-
; CHECK-NEXT: [[GEP4:%.*]] = getelementptr nuw i64, ptr [[GEP3]], i64 [[IDX4:%.*]]
1025-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[GEP2]], [[GEP4]]
1019+
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i64 [[IDX1:%.*]], 2
1020+
; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl nuw i64 [[IDX2:%.*]], 3
1021+
; CHECK-NEXT: [[TMP1:%.*]] = add nuw i64 [[GEP1_IDX]], [[GEP2_IDX]]
1022+
; CHECK-NEXT: [[GEP3_IDX:%.*]] = shl nuw i64 [[IDX3:%.*]], 2
1023+
; CHECK-NEXT: [[GEP4_IDX:%.*]] = shl nuw i64 [[IDX4:%.*]], 3
1024+
; CHECK-NEXT: [[TMP2:%.*]] = add nuw i64 [[GEP3_IDX]], [[GEP4_IDX]]
1025+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP1]], [[TMP2]]
10261026
; CHECK-NEXT: ret i1 [[CMP]]
10271027
;
10281028
%gep1 = getelementptr nuw i32, ptr %base, i64 %idx1
@@ -1035,11 +1035,13 @@ define i1 @gep_gep_multiple_eq_nuw_different_scales(ptr %base, i64 %idx1, i64 %i
10351035

10361036
define i1 @gep_gep_multiple_eq_partial_nuw_different_scales(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {
10371037
; CHECK-LABEL: @gep_gep_multiple_eq_partial_nuw_different_scales(
1038-
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nuw i32, ptr [[BASE:%.*]], i64 [[IDX1:%.*]]
1039-
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr nuw i64, ptr [[GEP1]], i64 [[IDX2:%.*]]
1040-
; CHECK-NEXT: [[GEP3:%.*]] = getelementptr nuw i32, ptr [[BASE]], i64 [[IDX3:%.*]]
1041-
; CHECK-NEXT: [[GEP4:%.*]] = getelementptr i64, ptr [[GEP3]], i64 [[IDX4:%.*]]
1042-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[GEP2]], [[GEP4]]
1038+
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i64 [[IDX1:%.*]], 2
1039+
; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl nuw i64 [[IDX2:%.*]], 3
1040+
; CHECK-NEXT: [[TMP1:%.*]] = add nuw i64 [[GEP1_IDX]], [[GEP2_IDX]]
1041+
; CHECK-NEXT: [[GEP3_IDX:%.*]] = shl nuw i64 [[IDX3:%.*]], 2
1042+
; CHECK-NEXT: [[GEP4_IDX:%.*]] = shl i64 [[IDX4:%.*]], 3
1043+
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[GEP3_IDX]], [[GEP4_IDX]]
1044+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP1]], [[TMP2]]
10431045
; CHECK-NEXT: ret i1 [[CMP]]
10441046
;
10451047
%gep1 = getelementptr nuw i32, ptr %base, i64 %idx1
@@ -1052,11 +1054,13 @@ define i1 @gep_gep_multiple_eq_partial_nuw_different_scales(ptr %base, i64 %idx1
10521054

10531055
define i1 @gep_gep_multiple_eq_partial_inbounds_different_scales(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {
10541056
; CHECK-LABEL: @gep_gep_multiple_eq_partial_inbounds_different_scales(
1055-
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i32, ptr [[BASE:%.*]], i64 [[IDX1:%.*]]
1056-
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i64, ptr [[GEP1]], i64 [[IDX2:%.*]]
1057-
; CHECK-NEXT: [[GEP3:%.*]] = getelementptr inbounds i32, ptr [[BASE]], i64 [[IDX3:%.*]]
1058-
; CHECK-NEXT: [[GEP4:%.*]] = getelementptr i64, ptr [[GEP3]], i64 [[IDX4:%.*]]
1059-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[GEP2]], [[GEP4]]
1057+
; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nsw i64 [[IDX1:%.*]], 2
1058+
; CHECK-NEXT: [[GEP2_IDX:%.*]] = shl nsw i64 [[IDX2:%.*]], 3
1059+
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[GEP1_IDX]], [[GEP2_IDX]]
1060+
; CHECK-NEXT: [[GEP3_IDX:%.*]] = shl nsw i64 [[IDX3:%.*]], 2
1061+
; CHECK-NEXT: [[GEP4_IDX:%.*]] = shl i64 [[IDX4:%.*]], 3
1062+
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[GEP3_IDX]], [[GEP4_IDX]]
1063+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP1]], [[TMP2]]
10601064
; CHECK-NEXT: ret i1 [[CMP]]
10611065
;
10621066
%gep1 = getelementptr inbounds i32, ptr %base, i64 %idx1
@@ -1069,11 +1073,9 @@ define i1 @gep_gep_multiple_eq_partial_inbounds_different_scales(ptr %base, i64
10691073

10701074
define i1 @gep_gep_multiple_ult_nuw(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {
10711075
; CHECK-LABEL: @gep_gep_multiple_ult_nuw(
1072-
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nuw i32, ptr [[BASE:%.*]], i64 [[IDX1:%.*]]
1073-
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr nuw i32, ptr [[GEP1]], i64 [[IDX2:%.*]]
1074-
; CHECK-NEXT: [[GEP3:%.*]] = getelementptr nuw i32, ptr [[BASE]], i64 [[IDX3:%.*]]
1075-
; CHECK-NEXT: [[GEP4:%.*]] = getelementptr nuw i32, ptr [[GEP3]], i64 [[IDX4:%.*]]
1076-
; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[GEP2]], [[GEP4]]
1076+
; CHECK-NEXT: [[GEP1_IDX1:%.*]] = add i64 [[IDX1:%.*]], [[IDX2:%.*]]
1077+
; CHECK-NEXT: [[GEP3_IDX2:%.*]] = add i64 [[IDX3:%.*]], [[IDX4:%.*]]
1078+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[GEP1_IDX1]], [[GEP3_IDX2]]
10771079
; CHECK-NEXT: ret i1 [[CMP]]
10781080
;
10791081
%gep1 = getelementptr nuw i32, ptr %base, i64 %idx1
@@ -1103,13 +1105,15 @@ define i1 @gep_gep_multiple_ult_missing_nuw(ptr %base, i64 %idx1, i64 %idx2, i64
11031105

11041106
define i1 @gep_gep_multiple_ult_nuw_multi_use(ptr %base, i64 %idx1, i64 %idx2, i64 %idx3, i64 %idx4) {
11051107
; CHECK-LABEL: @gep_gep_multiple_ult_nuw_multi_use(
1106-
; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nuw i32, ptr [[BASE:%.*]], i64 [[IDX1:%.*]]
1107-
; CHECK-NEXT: [[GEP2:%.*]] = getelementptr nuw i32, ptr [[GEP1]], i64 [[IDX2:%.*]]
1108-
; CHECK-NEXT: [[GEP3:%.*]] = getelementptr nuw i32, ptr [[BASE]], i64 [[IDX3:%.*]]
1109-
; CHECK-NEXT: [[GEP5:%.*]] = getelementptr nuw i32, ptr [[GEP3]], i64 [[IDX4:%.*]]
1110-
; CHECK-NEXT: call void @use(ptr [[GEP2]])
1108+
; CHECK-NEXT: [[IDX3:%.*]] = add i64 [[IDX1:%.*]], [[IDX2:%.*]]
1109+
; CHECK-NEXT: [[GEP3_IDX:%.*]] = shl nuw i64 [[IDX3]], 2
1110+
; CHECK-NEXT: [[GEP3:%.*]] = getelementptr nuw i8, ptr [[BASE:%.*]], i64 [[GEP3_IDX]]
1111+
; CHECK-NEXT: [[IDX4:%.*]] = add i64 [[IDX5:%.*]], [[IDX6:%.*]]
1112+
; CHECK-NEXT: [[GEP4_IDX:%.*]] = shl nuw i64 [[IDX4]], 2
1113+
; CHECK-NEXT: [[GEP5:%.*]] = getelementptr nuw i8, ptr [[BASE]], i64 [[GEP4_IDX]]
1114+
; CHECK-NEXT: call void @use(ptr [[GEP3]])
11111115
; CHECK-NEXT: call void @use(ptr [[GEP5]])
1112-
; CHECK-NEXT: [[CMP:%.*]] = icmp ult ptr [[GEP2]], [[GEP5]]
1116+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[GEP3_IDX]], [[GEP4_IDX]]
11131117
; CHECK-NEXT: ret i1 [[CMP]]
11141118
;
11151119
%gep1 = getelementptr nuw i32, ptr %base, i64 %idx1

0 commit comments

Comments
 (0)