/// These are simplifications common to SDiv and UDiv.
static Value *simplifyDiv(Instruction::BinaryOps Opcode, Value *Op0, Value *Op1,
- const SimplifyQuery &Q, unsigned MaxRecurse) {
+ bool IsExact, const SimplifyQuery &Q,
+ unsigned MaxRecurse) {
if (Constant *C = foldOrCommuteConstant(Opcode, Op0, Op1, Q))
return C;
if (Value *V = simplifyDivRem(Opcode, Op0, Op1, Q, MaxRecurse))
return V;
+ // If this is an exact divide by a constant, then the dividend (Op0) must have
+ // at least as many trailing zeros as the divisor to divide evenly. If it has
+ // less trailing zeros, then the result must be poison.
+ const APInt *DivC;
+ if (IsExact && match(Op1, m_APInt(DivC)) && DivC->countTrailingZeros()) {
+ KnownBits KnownOp0 = computeKnownBits(Op0, Q.DL, 0, Q.AC, Q.CxtI, Q.DT);
+ if (KnownOp0.countMaxTrailingZeros() < DivC->countTrailingZeros())
+ return PoisonValue::get(Op0->getType());
+ }
+
bool IsSigned = Opcode == Instruction::SDiv;
// (X rem Y) / Y -> 0
/// Given operands for an SDiv, see if we can fold the result.
/// If not, this returns null.
-static Value *simplifySDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
- unsigned MaxRecurse) {
+static Value *simplifySDivInst(Value *Op0, Value *Op1, bool IsExact,
+ const SimplifyQuery &Q, unsigned MaxRecurse) {
// If two operands are negated and no signed overflow, return -1.
if (isKnownNegation(Op0, Op1, /*NeedNSW=*/true))
return Constant::getAllOnesValue(Op0->getType());
- return simplifyDiv(Instruction::SDiv, Op0, Op1, Q, MaxRecurse);
+ return simplifyDiv(Instruction::SDiv, Op0, Op1, IsExact, Q, MaxRecurse);
}
-Value *llvm::simplifySDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {
- return ::simplifySDivInst(Op0, Op1, Q, RecursionLimit);
+Value *llvm::simplifySDivInst(Value *Op0, Value *Op1, bool IsExact,
+ const SimplifyQuery &Q) {
+ return ::simplifySDivInst(Op0, Op1, IsExact, Q, RecursionLimit);
}
/// Given operands for a UDiv, see if we can fold the result.
/// If not, this returns null.
-static Value *simplifyUDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
- unsigned MaxRecurse) {
- return simplifyDiv(Instruction::UDiv, Op0, Op1, Q, MaxRecurse);
+static Value *simplifyUDivInst(Value *Op0, Value *Op1, bool IsExact,
+ const SimplifyQuery &Q, unsigned MaxRecurse) {
+ return simplifyDiv(Instruction::UDiv, Op0, Op1, IsExact, Q, MaxRecurse);
}
-Value *llvm::simplifyUDivInst(Value *Op0, Value *Op1, const SimplifyQuery &Q) {
- return ::simplifyUDivInst(Op0, Op1, Q, RecursionLimit);
+Value *llvm::simplifyUDivInst(Value *Op0, Value *Op1, bool IsExact,
+ const SimplifyQuery &Q) {
+ return ::simplifyUDivInst(Op0, Op1, IsExact, Q, RecursionLimit);
}
/// Given operands for an SRem, see if we can fold the result.
return IsExact ? Op0 : Constant::getNullValue(Op0->getType());
// The low bit cannot be shifted out of an exact shift if it is set.
+ // TODO: Generalize by counting trailing zeros (see fold for exact division).
if (IsExact) {
KnownBits Op0Known =
computeKnownBits(Op0, Q.DL, /*Depth=*/0, Q.AC, Q.CxtI, Q.DT);
case Instruction::Mul:
return simplifyMulInst(LHS, RHS, Q, MaxRecurse);
case Instruction::SDiv:
- return simplifySDivInst(LHS, RHS, Q, MaxRecurse);
+ return simplifySDivInst(LHS, RHS, /* IsExact */ false, Q, MaxRecurse);
case Instruction::UDiv:
- return simplifyUDivInst(LHS, RHS, Q, MaxRecurse);
+ return simplifyUDivInst(LHS, RHS, /* IsExact */ false, Q, MaxRecurse);
case Instruction::SRem:
return simplifySRemInst(LHS, RHS, Q, MaxRecurse);
case Instruction::URem:
case Instruction::Mul:
return simplifyMulInst(NewOps[0], NewOps[1], Q);
case Instruction::SDiv:
- return simplifySDivInst(NewOps[0], NewOps[1], Q);
+ return simplifySDivInst(NewOps[0], NewOps[1],
+ Q.IIQ.isExact(cast<BinaryOperator>(I)), Q);
case Instruction::UDiv:
- return simplifyUDivInst(NewOps[0], NewOps[1], Q);
+ return simplifyUDivInst(NewOps[0], NewOps[1],
+ Q.IIQ.isExact(cast<BinaryOperator>(I)), Q);
case Instruction::FDiv:
return simplifyFDivInst(NewOps[0], NewOps[1], I->getFastMathFlags(), Q);
case Instruction::SRem:
ret i1 %rem
}
+; Can't divide evenly, so create poison.
+
define i8 @sdiv_exact_trailing_zeros(i8 %x) {
; CHECK-LABEL: @sdiv_exact_trailing_zeros(
-; CHECK-NEXT: [[O:%.*]] = or i8 [[X:%.*]], 1
-; CHECK-NEXT: [[R:%.*]] = sdiv exact i8 [[O]], -42
-; CHECK-NEXT: ret i8 [[R]]
+; CHECK-NEXT: ret i8 poison
;
%o = or i8 %x, 1 ; odd number
%r = sdiv exact i8 %o, -42 ; can't divide exactly
ret i8 %r
}
+; Negative test - could divide evenly.
+
define i8 @sdiv_exact_trailing_zeros_eq(i8 %x) {
; CHECK-LABEL: @sdiv_exact_trailing_zeros_eq(
; CHECK-NEXT: [[O:%.*]] = or i8 [[X:%.*]], 2
ret i8 %r
}
+; Negative test - must be exact div.
+
define i8 @sdiv_trailing_zeros(i8 %x) {
; CHECK-LABEL: @sdiv_trailing_zeros(
; CHECK-NEXT: [[O:%.*]] = or i8 [[X:%.*]], 1
ret i8 %r
}
+; TODO: Match non-splat vector constants.
+
+define <2 x i8> @sdiv_exact_trailing_zeros_nonuniform_vector(<2 x i8> %x) {
+; CHECK-LABEL: @sdiv_exact_trailing_zeros_nonuniform_vector(
+; CHECK-NEXT: [[O:%.*]] = or <2 x i8> [[X:%.*]], <i8 3, i8 1>
+; CHECK-NEXT: [[R:%.*]] = sdiv exact <2 x i8> [[O]], <i8 12, i8 2>
+; CHECK-NEXT: ret <2 x i8> [[R]]
+;
+ %o = or <2 x i8> %x, <i8 3, i8 1>
+ %r = sdiv exact <2 x i8> %o, <i8 12, i8 2>
+ ret <2 x i8> %r
+}
+
+; Can't divide evenly, so create poison.
+
define <2 x i8> @udiv_exact_trailing_zeros(<2 x i8> %x) {
; CHECK-LABEL: @udiv_exact_trailing_zeros(
-; CHECK-NEXT: [[O:%.*]] = or <2 x i8> [[X:%.*]], <i8 3, i8 3>
-; CHECK-NEXT: [[R:%.*]] = udiv exact <2 x i8> [[O]], <i8 12, i8 12>
-; CHECK-NEXT: ret <2 x i8> [[R]]
+; CHECK-NEXT: ret <2 x i8> poison
;
%o = or <2 x i8> %x, <i8 3, i8 3>
%r = udiv exact <2 x i8> %o, <i8 12, i8 12> ; can't divide exactly
ret <2 x i8> %r
}
+; Negative test - could divide evenly.
+
define <2 x i8> @udiv_exact_trailing_zeros_eq(<2 x i8> %x) {
; CHECK-LABEL: @udiv_exact_trailing_zeros_eq(
; CHECK-NEXT: [[O:%.*]] = or <2 x i8> [[X:%.*]], <i8 28, i8 28>
ret <2 x i8> %r
}
+; Negative test - must be exact div.
+
define i8 @udiv_trailing_zeros(i8 %x) {
; CHECK-LABEL: @udiv_trailing_zeros(
; CHECK-NEXT: [[O:%.*]] = or i8 [[X:%.*]], 1
ret i8 %r
}
+; Negative test - only the first element is poison
+
+define <2 x i8> @udiv_exact_trailing_zeros_nonuniform_vector(<2 x i8> %x) {
+; CHECK-LABEL: @udiv_exact_trailing_zeros_nonuniform_vector(
+; CHECK-NEXT: [[O:%.*]] = or <2 x i8> [[X:%.*]], <i8 3, i8 3>
+; CHECK-NEXT: [[R:%.*]] = udiv exact <2 x i8> [[O]], <i8 12, i8 1>
+; CHECK-NEXT: ret <2 x i8> [[R]]
+;
+ %o = or <2 x i8> %x, <i8 3, i8 3>
+ %r = udiv exact <2 x i8> %o, <i8 12, i8 1>
+ ret <2 x i8> %r
+}
+
!0 = !{i32 0, i32 3}