[llvm] [InstSimplify][InstCombine][ConstantFold] Move vector div/rem by zero fold to InstCombine (PR #114280)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 30 17:14:40 PDT 2024


================
@@ -1158,29 +1158,39 @@ static Value *foldIDivShl(BinaryOperator &I, InstCombiner::BuilderTy &Builder) {
   return nullptr;
 }
 
-/// This function implements the transforms common to both integer division
-/// instructions (udiv and sdiv). It is called by the visitors to those integer
-/// division instructions.
-/// Common integer divide transforms
-Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
-  if (Instruction *Phi = foldBinopWithPhiOperands(I))
-    return Phi;
-
+/// Common integer divide/remainder transforms
+Instruction *InstCombinerImpl::commonIDivRemTransforms(BinaryOperator &I) {
+  assert(I.isIntDivRem() && "Unexpected instruction");
   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
-  bool IsSigned = I.getOpcode() == Instruction::SDiv;
   Type *Ty = I.getType();
 
+  // If any element of a constant divisor fixed width vector is zero or undef
+  // the behavior is undefined and we can fold the whole op to poison.
+  if (auto *Op1C = dyn_cast<Constant>(Op1)) {
+    if (auto *VTy = dyn_cast<FixedVectorType>(Ty)) {
+      unsigned NumElts = VTy->getNumElements();
+      for (unsigned i = 0; i != NumElts; ++i) {
+        Constant *Elt = Op1C->getAggregateElement(i);
+        if (Elt && (Elt->isNullValue() || isa<UndefValue>(Elt)))
+          return replaceInstUsesWith(I, PoisonValue::get(Ty));
----------------
dtcxzyw wrote:

It doesn't block `udiv <i32 42, i32 -7> <i32 0, i32 1> -> poison` if the udiv is indeed an instruction. It just blocks this transform when threading udiv over selects.


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


More information about the llvm-commits mailing list