@@ -1158,29 +1158,39 @@ static Value *foldIDivShl(BinaryOperator &I, InstCombiner::BuilderTy &Builder) {
11581158 return nullptr ;
11591159}
11601160
1161- // / This function implements the transforms common to both integer division
1162- // / instructions (udiv and sdiv). It is called by the visitors to those integer
1163- // / division instructions.
1164- // / Common integer divide transforms
1165- Instruction *InstCombinerImpl::commonIDivTransforms (BinaryOperator &I) {
1166- if (Instruction *Phi = foldBinopWithPhiOperands (I))
1167- return Phi;
1168-
1161+ // / Common integer divide/remainder transforms
1162+ Instruction *InstCombinerImpl::commonIDivRemTransforms (BinaryOperator &I) {
1163+ assert (I.isIntDivRem () && " Unexpected instruction" );
11691164 Value *Op0 = I.getOperand (0 ), *Op1 = I.getOperand (1 );
1170- bool IsSigned = I.getOpcode () == Instruction::SDiv;
1165+
1166+ // If any element of a constant divisor fixed width vector is zero or undef
1167+ // the behavior is undefined and we can fold the whole op to poison.
1168+ auto *Op1C = dyn_cast<Constant>(Op1);
11711169 Type *Ty = I.getType ();
1170+ auto *VTy = dyn_cast<FixedVectorType>(Ty);
1171+ if (Op1C && VTy) {
1172+ unsigned NumElts = VTy->getNumElements ();
1173+ for (unsigned i = 0 ; i != NumElts; ++i) {
1174+ Constant *Elt = Op1C->getAggregateElement (i);
1175+ if (Elt && (Elt->isNullValue () || isa<UndefValue>(Elt)))
1176+ return replaceInstUsesWith (I, PoisonValue::get (Ty));
1177+ }
1178+ }
1179+
1180+ if (Instruction *Phi = foldBinopWithPhiOperands (I))
1181+ return Phi;
11721182
11731183 // The RHS is known non-zero.
11741184 if (Value *V = simplifyValueKnownNonZero (I.getOperand (1 ), *this , I))
11751185 return replaceOperand (I, 1 , V);
11761186
1177- // Handle cases involving: [su]div X, (select Cond, Y, Z)
1178- // This does not apply for fdiv.
1187+ // Handle cases involving: div/rem X, (select Cond, Y, Z)
11791188 if (simplifyDivRemOfSelectWithZeroOp (I))
11801189 return &I;
11811190
11821191 // If the divisor is a select-of-constants, try to constant fold all div ops:
1183- // C / (select Cond, TrueC, FalseC) --> select Cond, (C / TrueC), (C / FalseC)
1192+ // C div/rem (select Cond, TrueC, FalseC) --> select Cond, (C div/rem TrueC),
1193+ // (C div/rem FalseC)
11841194 // TODO: Adapt simplifyDivRemOfSelectWithZeroOp to allow this and other folds.
11851195 if (match (Op0, m_ImmConstant ()) &&
11861196 match (Op1, m_Select (m_Value (), m_ImmConstant (), m_ImmConstant ()))) {
@@ -1189,6 +1199,21 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) {
11891199 return R;
11901200 }
11911201
1202+ return nullptr ;
1203+ }
1204+
1205+ // / This function implements the transforms common to both integer division
1206+ // / instructions (udiv and sdiv). It is called by the visitors to those integer
1207+ // / division instructions.
1208+ // / Common integer divide transforms
1209+ Instruction *InstCombinerImpl::commonIDivTransforms (BinaryOperator &I) {
1210+ if (Instruction *Res = commonIDivRemTransforms (I))
1211+ return Res;
1212+
1213+ Value *Op0 = I.getOperand (0 ), *Op1 = I.getOperand (1 );
1214+ bool IsSigned = I.getOpcode () == Instruction::SDiv;
1215+ Type *Ty = I.getType ();
1216+
11921217 const APInt *C2;
11931218 if (match (Op1, m_APInt (C2))) {
11941219 Value *X;
@@ -2138,29 +2163,11 @@ static Instruction *simplifyIRemMulShl(BinaryOperator &I,
21382163// / remainder instructions.
21392164// / Common integer remainder transforms
21402165Instruction *InstCombinerImpl::commonIRemTransforms (BinaryOperator &I) {
2141- if (Instruction *Phi = foldBinopWithPhiOperands (I))
2142- return Phi ;
2166+ if (Instruction *Res = commonIDivRemTransforms (I))
2167+ return Res ;
21432168
21442169 Value *Op0 = I.getOperand (0 ), *Op1 = I.getOperand (1 );
21452170
2146- // The RHS is known non-zero.
2147- if (Value *V = simplifyValueKnownNonZero (I.getOperand (1 ), *this , I))
2148- return replaceOperand (I, 1 , V);
2149-
2150- // Handle cases involving: rem X, (select Cond, Y, Z)
2151- if (simplifyDivRemOfSelectWithZeroOp (I))
2152- return &I;
2153-
2154- // If the divisor is a select-of-constants, try to constant fold all rem ops:
2155- // C % (select Cond, TrueC, FalseC) --> select Cond, (C % TrueC), (C % FalseC)
2156- // TODO: Adapt simplifyDivRemOfSelectWithZeroOp to allow this and other folds.
2157- if (match (Op0, m_ImmConstant ()) &&
2158- match (Op1, m_Select (m_Value (), m_ImmConstant (), m_ImmConstant ()))) {
2159- if (Instruction *R = FoldOpIntoSelect (I, cast<SelectInst>(Op1),
2160- /* FoldWithMultiUse*/ true ))
2161- return R;
2162- }
2163-
21642171 if (isa<Constant>(Op1)) {
21652172 if (Instruction *Op0I = dyn_cast<Instruction>(Op0)) {
21662173 if (SelectInst *SI = dyn_cast<SelectInst>(Op0I)) {
0 commit comments