[llvm-branch-commits] [llvm] [InstCombine] Enable select freeze poison folding when storing value (PR #129776)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Mar 4 19:52:11 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-ir

Author: John McIver (jmciver)

<details>
<summary>Changes</summary>

The non-freeze poison argument to select can be one of the following: global,
constant, and noundef arguments.

Alive2 test validation: https://alive2.llvm.org/ce/z/jbtCS6

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


3 Files Affected:

- (modified) llvm/include/llvm/IR/PatternMatch.h (+13) 
- (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+16-6) 
- (modified) llvm/test/Transforms/InstCombine/select.ll (+3-6) 


``````````diff
diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h
index b3eeb1d7ba88a..c66235f33cd9e 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -3124,6 +3124,19 @@ inline auto m_c_LogicalOp(const LHS &L, const RHS &R) {
   return m_LogicalOp<LHS, RHS, /*Commutable=*/true>(L, R);
 }
 
+struct GuaranteedNotToBeUndefOrPoison_match {
+  template <typename ITy> bool match(ITy *V) {
+    if (auto *AsValue = dyn_cast<Value>(V))
+      return isGuaranteedNotToBeUndefOrPoison(AsValue);
+    else
+      return false;
+  }
+};
+
+inline GuaranteedNotToBeUndefOrPoison_match m_guaranteedNotToBeUndefOrPoison() {
+  return GuaranteedNotToBeUndefOrPoison_match();
+}
+
 } // end namespace PatternMatch
 } // end namespace llvm
 
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 4c14dcfb4d75f..6b9254692a857 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -4813,15 +4813,22 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
   // TODO: This could use getBinopAbsorber() / getBinopIdentity() to avoid
   //       duplicating logic for binops at least.
   auto getUndefReplacement = [&I](Type *Ty) {
-    Constant *BestValue = nullptr;
-    Constant *NullValue = Constant::getNullValue(Ty);
+    Value *BestValue = nullptr;
+    Value *NullValue = Constant::getNullValue(Ty);
     for (const auto *U : I.users()) {
-      Constant *C = NullValue;
+      Value *C = NullValue;
       if (match(U, m_Or(m_Value(), m_Value())))
         C = ConstantInt::getAllOnesValue(Ty);
       else if (match(U, m_Select(m_Specific(&I), m_Constant(), m_Value())))
         C = ConstantInt::getTrue(Ty);
-
+      else if (I.hasOneUse() &&
+               match(U, m_c_Select(m_Specific(&I),
+                                   m_guaranteedNotToBeUndefOrPoison()))) {
+        if (match(U->getOperand(1), m_Specific(&I)))
+          C = U->getOperand(2);
+        else
+          C = U->getOperand(1);
+      }
       if (!BestValue)
         BestValue = C;
       else if (BestValue != C)
@@ -4842,8 +4849,11 @@ Instruction *InstCombinerImpl::visitFreeze(FreezeInst &I) {
 
   Constant *C;
   if (match(Op0, m_Constant(C)) && C->containsUndefOrPoisonElement()) {
-    Constant *ReplaceC = getUndefReplacement(I.getType()->getScalarType());
-    return replaceInstUsesWith(I, Constant::replaceUndefsWith(C, ReplaceC));
+    Value *Replace = getUndefReplacement(I.getType()->getScalarType());
+    if (Constant *ReplaceC = dyn_cast<Constant>(Replace))
+      return replaceInstUsesWith(I, Constant::replaceUndefsWith(C, ReplaceC));
+    else
+      return replaceInstUsesWith(I, Replace);
   }
 
   // Replace uses of Op with freeze(Op).
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index cc25f4ce24d9a..789d98197d878 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -4904,8 +4904,7 @@ define i32 @src_simplify_2x_at_once_and(i32 %x, i32 %y) {
 
 define void @select_freeze_poison_parameter(ptr noundef %addr.src, ptr %addr.tgt, i1 %cond) {
 ; CHECK-LABEL: @select_freeze_poison_parameter(
-; CHECK-NEXT:    [[ADDR_SRC:%.*]] = select i1 [[COND:%.*]], ptr [[ADDR_SRC1:%.*]], ptr null
-; CHECK-NEXT:    store ptr [[ADDR_SRC]], ptr [[ADDR_TGT:%.*]], align 8
+; CHECK-NEXT:    store ptr [[ADDR_SRC:%.*]], ptr [[ADDR_TGT:%.*]], align 8
 ; CHECK-NEXT:    ret void
 ;
   %freeze = freeze ptr poison
@@ -4918,8 +4917,7 @@ define void @select_freeze_poison_parameter(ptr noundef %addr.src, ptr %addr.tgt
 
 define void @select_freeze_poison_global(ptr %addr.tgt, i1 %cond) {
 ; CHECK-LABEL: @select_freeze_poison_global(
-; CHECK-NEXT:    [[SELECT_ADDR:%.*]] = select i1 [[COND:%.*]], ptr @glb, ptr null
-; CHECK-NEXT:    store ptr [[SELECT_ADDR]], ptr [[ADDR_TGT:%.*]], align 8
+; CHECK-NEXT:    store ptr @glb, ptr [[ADDR_TGT:%.*]], align 8
 ; CHECK-NEXT:    ret void
 ;
   %freeze = freeze ptr poison
@@ -4930,8 +4928,7 @@ define void @select_freeze_poison_global(ptr %addr.tgt, i1 %cond) {
 
 define void @select_freeze_poison_constant(ptr %addr.tgt, i1 %cond) {
 ; CHECK-LABEL: @select_freeze_poison_constant(
-; CHECK-NEXT:    [[SELECT_ADDR:%.*]] = select i1 [[COND:%.*]], i32 72, i32 0
-; CHECK-NEXT:    store i32 [[SELECT_ADDR]], ptr [[ADDR_TGT:%.*]], align 4
+; CHECK-NEXT:    store i32 72, ptr [[ADDR_TGT:%.*]], align 4
 ; CHECK-NEXT:    ret void
 ;
   %freeze = freeze i32 poison

``````````

</details>


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


More information about the llvm-branch-commits mailing list