[llvm] [InstCombine] Use InstSimplify in FoldOpIntoSelect (PR #116073)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 14 01:22:05 PST 2024


================
@@ -1649,39 +1649,34 @@ Instruction *InstCombinerImpl::foldBinopOfSextBoolToSelect(BinaryOperator &BO) {
   return SelectInst::Create(X, TVal, FVal);
 }
 
-static Constant *constantFoldOperationIntoSelectOperand(Instruction &I,
-                                                        SelectInst *SI,
-                                                        bool IsTrueArm) {
-  SmallVector<Constant *> ConstOps;
+static Value *simplifyOperationIntoSelectOperand(Instruction &I, SelectInst *SI,
+                                                 bool IsTrueArm) {
+  SmallVector<Value *> Ops;
   for (Value *Op : I.operands()) {
-    Constant *C = nullptr;
+    Value *V = nullptr;
     if (Op == SI) {
-      C = dyn_cast<Constant>(IsTrueArm ? SI->getTrueValue()
-                                       : SI->getFalseValue());
+      V = IsTrueArm ? SI->getTrueValue() : SI->getFalseValue();
     } else if (match(SI->getCondition(),
                      m_SpecificICmp(IsTrueArm ? ICmpInst::ICMP_EQ
                                               : ICmpInst::ICMP_NE,
-                                    m_Specific(Op), m_Constant(C))) &&
-               isGuaranteedNotToBeUndefOrPoison(C)) {
+                                    m_Specific(Op), m_Value(V))) &&
+               isGuaranteedNotToBeUndefOrPoison(V)) {
       // Pass
     } else {
-      C = dyn_cast<Constant>(Op);
+      V = Op;
     }
-    if (C == nullptr)
-      return nullptr;
-
-    ConstOps.push_back(C);
+    Ops.push_back(V);
   }
 
-  return ConstantFoldInstOperands(&I, ConstOps, I.getDataLayout());
+  return simplifyInstructionWithOperands(&I, Ops, I.getDataLayout());
 }
 
 static Value *foldOperationIntoSelectOperand(Instruction &I, SelectInst *SI,
                                              Value *NewOp, InstCombiner &IC) {
   Instruction *Clone = I.clone();
   Clone->replaceUsesOfWith(SI, NewOp);
   Clone->dropUBImplyingAttrsAndMetadata();
-  IC.InsertNewInstBefore(Clone, SI->getIterator());
+  IC.InsertNewInstBefore(Clone, I.getIterator());
----------------
nikic wrote:

Consider this test:
```
define i32 @sel_umin_simplify(i1 %c, i32 %x, i16 %y) {
  %sel = select i1 %c, i32 %x, i32 0
  %y.ext = zext i16 %y to i32
  %res = call i32 @llvm.umin.i32(i32 %sel, i32 %y.ext)
  ret i32 %res
}
```
If we insert the umin clone before the select, it still uses `%y.ext`, which is only defined after the select, so we get a verifier error. Inserting the instruction at the same position as the old one makes sure that we don't violate the dominance requirement.

I believe this previously wasn't an issue because the transform would bail out anyway if the non-select operands were non-constant, so we didn't run into the problem.

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


More information about the llvm-commits mailing list