Skip to content

Conversation

@dtcxzyw
Copy link
Member

@dtcxzyw dtcxzyw commented Jan 7, 2025

Alive2: https://alive2.llvm.org/ce/z/P5XbMx
Closes #121890

TODO: It is still safe to perform this transform without nowrap flags if the corresponding scale factor is 1 byte: https://alive2.llvm.org/ce/z/J-JCJd

@dtcxzyw dtcxzyw requested a review from goldsteinn January 7, 2025 07:08
@dtcxzyw dtcxzyw requested a review from nikic as a code owner January 7, 2025 07:08
@llvmbot llvmbot added llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms labels Jan 7, 2025
@llvmbot
Copy link
Member

llvmbot commented Jan 7, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Yingwei Zheng (dtcxzyw)

Changes

Alive2: https://alive2.llvm.org/ce/z/P5XbMx
Closes #121890

TODO: It is still safe to perform this transform without nowrap flags if the corresponding scale factor is 1 byte: https://alive2.llvm.org/ce/z/J-JCJd


Full diff: https://github.com/llvm/llvm-project/pull/121892.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp (+5-2)
  • (modified) llvm/test/Transforms/InstCombine/opaque-ptr.ll (+35)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 8b23583c510637..9f136860724db8 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -833,8 +833,11 @@ Instruction *InstCombinerImpl::foldGEPICmp(GEPOperator *GEPLHS, Value *RHS,
       if (NumDifferences == 0)   // SAME GEP?
         return replaceInstUsesWith(I, // No comparison is needed here.
           ConstantInt::get(I.getType(), ICmpInst::isTrueWhenEqual(Cond)));
-
-      else if (NumDifferences == 1 && CanFold(NW)) {
+      // If two GEPs only differ by an index/the base pointer, compare them.
+      // Note that nowrap flags are always needed when comparing two indices.
+      else if (NumDifferences == 1 &&
+               (DiffOperand == 0 ? CanFold(NW)
+                                 : NW != GEPNoWrapFlags::none())) {
         Value *LHSV = GEPLHS->getOperand(DiffOperand);
         Value *RHSV = GEPRHS->getOperand(DiffOperand);
         return NewICmp(NW, LHSV, RHSV);
diff --git a/llvm/test/Transforms/InstCombine/opaque-ptr.ll b/llvm/test/Transforms/InstCombine/opaque-ptr.ll
index b05274658e812e..be734243d14a10 100644
--- a/llvm/test/Transforms/InstCombine/opaque-ptr.ll
+++ b/llvm/test/Transforms/InstCombine/opaque-ptr.ll
@@ -467,6 +467,41 @@ define i1 @cmp_gep_same_base_same_type(ptr %ptr, i64 %idx1, i64 %idx2) {
   ret i1 %cmp
 }
 
+define i1 @cmp_gep_same_base_same_type_maywrap(ptr %ptr, i64 %idx1, i64 %idx2) {
+; CHECK-LABEL: @cmp_gep_same_base_same_type_maywrap(
+; CHECK-NEXT:    [[CMP_UNSHIFTED:%.*]] = xor i64 [[IDX1:%.*]], [[IDX2:%.*]]
+; CHECK-NEXT:    [[CMP_MASK:%.*]] = and i64 [[CMP_UNSHIFTED]], 4611686018427387903
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[CMP_MASK]], 0
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %gep1 = getelementptr i32, ptr %ptr, i64 %idx1
+  %gep2 = getelementptr i32, ptr %ptr, i64 %idx2
+  %cmp = icmp eq ptr %gep1, %gep2
+  ret i1 %cmp
+}
+
+define i1 @cmp_gep_same_base_same_type_nuw(ptr %ptr, i64 %idx1, i64 %idx2) {
+; CHECK-LABEL: @cmp_gep_same_base_same_type_nuw(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IDX1:%.*]], [[IDX2:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %gep1 = getelementptr nuw i32, ptr %ptr, i64 %idx1
+  %gep2 = getelementptr nuw i32, ptr %ptr, i64 %idx2
+  %cmp = icmp eq ptr %gep1, %gep2
+  ret i1 %cmp
+}
+
+define i1 @cmp_gep_same_base_same_type_nusw(ptr %ptr, i64 %idx1, i64 %idx2) {
+; CHECK-LABEL: @cmp_gep_same_base_same_type_nusw(
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i64 [[IDX1:%.*]], [[IDX2:%.*]]
+; CHECK-NEXT:    ret i1 [[CMP]]
+;
+  %gep1 = getelementptr nusw i32, ptr %ptr, i64 %idx1
+  %gep2 = getelementptr nusw i32, ptr %ptr, i64 %idx2
+  %cmp = icmp eq ptr %gep1, %gep2
+  ret i1 %cmp
+}
+
 define i1 @cmp_gep_same_base_different_type(ptr %ptr, i64 %idx1, i64 %idx2) {
 ; CHECK-LABEL: @cmp_gep_same_base_different_type(
 ; CHECK-NEXT:    [[GEP1_IDX:%.*]] = shl nsw i64 [[IDX1:%.*]], 2

// If two GEPs only differ by an index/the base pointer, compare them.
// Note that nowrap flags are always needed when comparing two indices.
else if (NumDifferences == 1 &&
(DiffOperand == 0 ? CanFold(NW)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think DiffOperand == 0 can happen here? The above loop only goes over the index operands. The case of base pointer difference is handled by different code further up.

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. We'll still fall back to the generic handling below, so I think the simple check is fine.

@nikic
Copy link
Contributor

nikic commented Jan 29, 2025

Reverse ping :)

@dtcxzyw
Copy link
Member Author

dtcxzyw commented Jan 31, 2025

Reverse ping :)

Is it necessary to merge this PR now? I was previously planning to merge it after fixing the regression.

@nikic
Copy link
Contributor

nikic commented Feb 1, 2025

Reverse ping :)

Is it necessary to merge this PR now? I was previously planning to merge it after fixing the regression.

As it fixes a miscompile and the regression doesn't seem particularly significant, I think it's better to merge it earlier than later.

@dtcxzyw dtcxzyw merged commit 9725595 into llvm:main Feb 1, 2025
6 of 8 checks passed
@dtcxzyw dtcxzyw deleted the perf/fix-121890 branch February 1, 2025 12:41
@nikic nikic added this to the LLVM 20.X Release milestone Feb 2, 2025
@nikic
Copy link
Contributor

nikic commented Feb 2, 2025

/cherry-pick 9725595

@llvmbot
Copy link
Member

llvmbot commented Feb 2, 2025

Failed to cherry-pick: 9725595

https://github.com/llvm/llvm-project/actions/runs/13097312131

Please manually backport the fix and push it to your github fork. Once this is done, please create a pull request

nikic pushed a commit to nikic/llvm-project that referenced this pull request Feb 5, 2025
… the same base pointer (llvm#121892)

Alive2: https://alive2.llvm.org/ce/z/P5XbMx
Closes llvm#121890

TODO: It is still safe to perform this transform without nowrap flags if
the corresponding scale factor is 1 byte:
https://alive2.llvm.org/ce/z/J-JCJd

(cherry picked from commit 9725595)
nikic pushed a commit to nikic/llvm-project that referenced this pull request Feb 11, 2025
… the same base pointer (llvm#121892)

Alive2: https://alive2.llvm.org/ce/z/P5XbMx
Closes llvm#121890

TODO: It is still safe to perform this transform without nowrap flags if
the corresponding scale factor is 1 byte:
https://alive2.llvm.org/ce/z/J-JCJd

(cherry picked from commit 9725595)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

llvm:instcombine Covers the InstCombine, InstSimplify and AggressiveInstCombine passes llvm:transforms release:cherry-pick-failed

Projects

Development

Successfully merging this pull request may close these issues.

[InstCombine] Missing flag check when folding comparison of geps with the same base pointer

3 participants