diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -4948,26 +4948,35 @@ auto BuildUDIVPattern = [&](const Constant *C) { auto *CI = cast(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) diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -6042,25 +6042,34 @@ // 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), diff --git a/llvm/lib/Support/DivisionByConstantInfo.cpp b/llvm/lib/Support/DivisionByConstantInfo.cpp --- a/llvm/lib/Support/DivisionByConstantInfo.cpp +++ b/llvm/lib/Support/DivisionByConstantInfo.cpp @@ -73,7 +73,7 @@ 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; diff --git a/llvm/unittests/Support/DivisionByConstantTest.cpp b/llvm/unittests/Support/DivisionByConstantTest.cpp --- a/llvm/unittests/Support/DivisionByConstantTest.cpp +++ b/llvm/unittests/Support/DivisionByConstantTest.cpp @@ -101,9 +101,11 @@ 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()); @@ -117,7 +119,7 @@ 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; @@ -154,7 +156,7 @@ Q = Q.lshr(PostShift); - return Divisor.isOne() ? Numerator : Q; + return Q; } TEST(UnsignedDivisionByConstantTest, Test) { @@ -166,6 +168,9 @@ 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) {