auto BuildUDIVPattern = [&](const Constant *C) {
auto *CI = cast<ConstantInt>(C);
const APInt &Divisor = CI->getValue();
- UnsignedDivisionByConstantInfo magics =
- UnsignedDivisionByConstantInfo::get(Divisor);
+
+ bool SelNPQ = false;
+ APInt Magic(Divisor.getBitWidth(), 0);
unsigned PreShift = 0, PostShift = 0;
- unsigned SelNPQ;
- if (!magics.IsAdd || Divisor.isOneValue()) {
- assert(magics.ShiftAmount < Divisor.getBitWidth() &&
- "We shouldn't generate an undefined shift!");
- PostShift = magics.ShiftAmount;
- PreShift = magics.PreShift;
- SelNPQ = false;
- } else {
- assert(magics.PreShift == 0 && "Unexpected pre-shift");
- PostShift = magics.ShiftAmount - 1;
- SelNPQ = true;
+ // Magic algorithm doesn't work for division by 1. We need to emit a select
+ // at the end.
+ // TODO: Use undef values for divisor of 1.
+ if (!Divisor.isOneValue()) {
+ UnsignedDivisionByConstantInfo magics =
+ UnsignedDivisionByConstantInfo::get(Divisor);
+
+ Magic = std::move(magics.Magic);
+
+ if (!magics.IsAdd) {
+ assert(magics.ShiftAmount < Divisor.getBitWidth() &&
+ "We shouldn't generate an undefined shift!");
+ PostShift = magics.ShiftAmount;
+ PreShift = magics.PreShift;
+ } else {
+ assert(magics.PreShift == 0 && "Unexpected pre-shift");
+ PostShift = magics.ShiftAmount - 1;
+ SelNPQ = true;
+ }
}
PreShifts.push_back(
MIB.buildConstant(ScalarShiftAmtTy, PreShift).getReg(0));
- MagicFactors.push_back(MIB.buildConstant(ScalarTy, magics.Magic).getReg(0));
+ MagicFactors.push_back(MIB.buildConstant(ScalarTy, Magic).getReg(0));
NPQFactors.push_back(
MIB.buildConstant(ScalarTy,
SelNPQ ? APInt::getOneBitSet(EltBits, EltBits - 1)
// FIXME: We should use a narrower constant when the upper
// bits are known to be zero.
const APInt& Divisor = C->getAPIntValue();
- UnsignedDivisionByConstantInfo magics =
- UnsignedDivisionByConstantInfo::get(Divisor, LeadingZeros);
+
+ bool SelNPQ = false;
+ APInt Magic(Divisor.getBitWidth(), 0);
unsigned PreShift = 0, PostShift = 0;
- unsigned SelNPQ;
- if (!magics.IsAdd || Divisor.isOne()) {
- assert(magics.ShiftAmount < Divisor.getBitWidth() &&
- "We shouldn't generate an undefined shift!");
- PostShift = magics.ShiftAmount;
- PreShift = magics.PreShift;
- SelNPQ = false;
- } else {
- assert(magics.PreShift == 0 && "Unexpected pre-shift");
- PostShift = magics.ShiftAmount - 1;
- SelNPQ = true;
+ // Magic algorithm doesn't work for division by 1. We need to emit a select
+ // at the end.
+ // TODO: Use undef values for divisor of 1.
+ if (!Divisor.isOne()) {
+ UnsignedDivisionByConstantInfo magics =
+ UnsignedDivisionByConstantInfo::get(Divisor, LeadingZeros);
+
+ Magic = std::move(magics.Magic);
+
+ if (!magics.IsAdd) {
+ assert(magics.ShiftAmount < Divisor.getBitWidth() &&
+ "We shouldn't generate an undefined shift!");
+ PostShift = magics.ShiftAmount;
+ PreShift = magics.PreShift;
+ } else {
+ assert(magics.PreShift == 0 && "Unexpected pre-shift");
+ PostShift = magics.ShiftAmount - 1;
+ SelNPQ = true;
+ }
}
PreShifts.push_back(DAG.getConstant(PreShift, dl, ShSVT));
- MagicFactors.push_back(DAG.getConstant(magics.Magic, dl, SVT));
+ MagicFactors.push_back(DAG.getConstant(Magic, dl, SVT));
NPQFactors.push_back(
DAG.getConstant(SelNPQ ? APInt::getOneBitSet(EltBits, EltBits - 1)
: APInt::getZero(EltBits),
UnsignedDivisionByConstantInfo
UnsignedDivisionByConstantInfo::get(const APInt &D, unsigned LeadingZeros,
bool AllowEvenDivisorOptimization) {
- assert(!D.isZero() && "Precondition violation.");
+ assert(!D.isZero() && !D.isOne() && "Precondition violation.");
assert(D.getBitWidth() > 1 && "Does not work at smaller bitwidths.");
APInt Delta;
bool LZOptimization,
bool AllowEvenDivisorOptimization, bool ForceNPQ,
UnsignedDivisionByConstantInfo Magics) {
+ assert(!Divisor.isOne() && "Division by 1 is not supported using Magic.");
+
unsigned Bits = Numerator.getBitWidth();
- if (LZOptimization && !Divisor.isOne()) {
+ if (LZOptimization) {
unsigned LeadingZeros = Numerator.countLeadingZeros();
// Clip to the number of leading zeros in the divisor.
LeadingZeros = std::min(LeadingZeros, Divisor.countLeadingZeros());
unsigned PreShift = 0;
unsigned PostShift = 0;
bool UseNPQ = false;
- if (!Magics.IsAdd || Divisor.isOne()) {
+ if (!Magics.IsAdd) {
assert(Magics.ShiftAmount < Divisor.getBitWidth() &&
"We shouldn't generate an undefined shift!");
PreShift = Magics.PreShift;
Q = Q.lshr(PostShift);
- return Divisor.isOne() ? Numerator : Q;
+ return Q;
}
TEST(UnsignedDivisionByConstantTest, Test) {
EnumerateAPInts(Bits, [Bits](const APInt &Divisor) {
if (Divisor.isZero())
return; // Division by zero is undefined behavior.
+ if (Divisor.isOne())
+ return; // Division by one is the numerator.
+
const UnsignedDivisionByConstantInfo Magics =
UnsignedDivisionByConstantInfo::get(Divisor);
EnumerateAPInts(Bits, [Divisor, Magics, Bits](const APInt &Numerator) {