[llvm] [InstCombine] Fix pointer replacement in `foldSelectValueEquivalence` (PR #161701)

via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 2 10:10:05 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Yingwei Zheng (dtcxzyw)

<details>
<summary>Changes</summary>

Closes https://github.com/llvm/llvm-project/issues/161636.

Compile-time impact (+0.02%): https://llvm-compile-time-tracker.com/compare.php?from=17f6888d1771c9f61378a0a58725f3359277ddda&to=44cdcb84b1a9d996cd61f2c37ac4c9df5bc531af&stat=instructions%3Au
I used to disable this fold for pointers, because I cannot construct a positive test that is covered by `foldSelectValueEquivalence ` but not covered by `simplifySelectWithICmpCond`. But the IR diff shows we still benefit from the fold in InstCombine:
+ Bail out on pointers: https://github.com/dtcxzyw/llvm-opt-benchmark/pull/2880
+ This patch: https://github.com/dtcxzyw/llvm-opt-benchmark/pull/2882

Perhaps we can cache the query result of `getUnderlyingObjectAggressive` to improve the compile time.


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


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp (+11-6) 
- (modified) llvm/test/Transforms/InstCombine/select-gep.ll (+32) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 87000a1c36eef..5ea79b92633d9 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -17,6 +17,7 @@
 #include "llvm/Analysis/AssumptionCache.h"
 #include "llvm/Analysis/CmpInstAnalysis.h"
 #include "llvm/Analysis/InstructionSimplify.h"
+#include "llvm/Analysis/Loads.h"
 #include "llvm/Analysis/OverflowInstAnalysis.h"
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/Analysis/VectorUtils.h"
@@ -1411,6 +1412,8 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel,
     // in the cmp and in f(Y).
     if (TrueVal == OldOp && (isa<Constant>(OldOp) || !isa<Constant>(NewOp)))
       return nullptr;
+    if (!canReplacePointersIfEqual(OldOp, NewOp, DL))
+      return nullptr;
 
     if (Value *V = simplifyWithOpReplaced(TrueVal, OldOp, NewOp, SQ,
                                           /* AllowRefinement=*/true)) {
@@ -1466,12 +1469,14 @@ Instruction *InstCombinerImpl::foldSelectValueEquivalence(SelectInst &Sel,
   // Example:
   // (X == 42) ? 43 : (X + 1) --> (X == 42) ? (X + 1) : (X + 1) --> X + 1
   SmallVector<Instruction *> DropFlags;
-  if (simplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, SQ,
-                             /* AllowRefinement */ false,
-                             &DropFlags) == TrueVal ||
-      simplifyWithOpReplaced(FalseVal, CmpRHS, CmpLHS, SQ,
-                             /* AllowRefinement */ false,
-                             &DropFlags) == TrueVal) {
+  if ((canReplacePointersIfEqual(CmpLHS, CmpRHS, DL) &&
+       simplifyWithOpReplaced(FalseVal, CmpLHS, CmpRHS, SQ,
+                              /* AllowRefinement */ false,
+                              &DropFlags) == TrueVal) ||
+      (canReplacePointersIfEqual(CmpRHS, CmpLHS, DL) &&
+       simplifyWithOpReplaced(FalseVal, CmpRHS, CmpLHS, SQ,
+                              /* AllowRefinement */ false,
+                              &DropFlags) == TrueVal)) {
     for (Instruction *I : DropFlags) {
       I->dropPoisonGeneratingAnnotations();
       Worklist.add(I);
diff --git a/llvm/test/Transforms/InstCombine/select-gep.ll b/llvm/test/Transforms/InstCombine/select-gep.ll
index dd8dffba11b05..718133699a8a7 100644
--- a/llvm/test/Transforms/InstCombine/select-gep.ll
+++ b/llvm/test/Transforms/InstCombine/select-gep.ll
@@ -286,3 +286,35 @@ define <2 x ptr> @test7(<2 x ptr> %p1, i64 %idx, <2 x i1> %cc) {
   %select = select <2 x i1> %cc, <2 x ptr> %p1, <2 x ptr> %gep
   ret <2 x ptr> %select
 }
+
+define ptr @ptr_eq_replace_freeze1(ptr %p, ptr %q) {
+; CHECK-LABEL: @ptr_eq_replace_freeze1(
+; CHECK-NEXT:    [[Q_FR:%.*]] = freeze ptr [[Q:%.*]]
+; CHECK-NEXT:    [[Q_FR1:%.*]] = freeze ptr [[Q1:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[Q_FR]], [[Q_FR1]]
+; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], ptr [[Q_FR]], ptr [[Q_FR1]]
+; CHECK-NEXT:    ret ptr [[SELECT]]
+;
+  %p.fr = freeze ptr %p
+  %q.fr = freeze ptr %q
+  %cmp = icmp eq ptr %p.fr, %q.fr
+  %select = select i1 %cmp, ptr %p.fr, ptr %q.fr
+  ret ptr %select
+}
+
+define ptr @ptr_eq_replace_freeze2(ptr %p, ptr %q) {
+; CHECK-LABEL: @ptr_eq_replace_freeze2(
+; CHECK-NEXT:    [[P_FR:%.*]] = freeze ptr [[P:%.*]]
+; CHECK-NEXT:    [[P_FR1:%.*]] = freeze ptr [[P1:%.*]]
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[P_FR1]], [[P_FR]]
+; CHECK-NEXT:    [[SELECT_V:%.*]] = select i1 [[CMP]], ptr [[P_FR1]], ptr [[P_FR]]
+; CHECK-NEXT:    [[SELECT:%.*]] = getelementptr i8, ptr [[SELECT_V]], i64 16
+; CHECK-NEXT:    ret ptr [[SELECT]]
+;
+  %gep1 = getelementptr i32, ptr %p, i64 4
+  %gep2 = getelementptr i32, ptr %q, i64 4
+  %cmp = icmp eq ptr %p, %q
+  %cmp.fr = freeze i1 %cmp
+  %select = select i1 %cmp.fr, ptr %gep1, ptr %gep2
+  ret ptr %select
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/161701


More information about the llvm-commits mailing list