forked from OSchip/llvm-project
[TargetLowering] Add BuildSDIVPattern helper to BuildExactSDIV (NFCI).
As requested in D50392, pull the magic constant calculations out into a helper function. llvm-svn: 339346
This commit is contained in:
parent
bdd8493f2b
commit
a9f95429d9
|
@ -3440,34 +3440,43 @@ static SDValue BuildExactSDIV(const TargetLowering &TLI, SDNode *N,
|
|||
EVT VT = N->getValueType(0);
|
||||
EVT ShVT = TLI.getShiftAmountTy(VT, DAG.getDataLayout());
|
||||
|
||||
auto BuildSDIVPattern = [](APInt Divisor, unsigned &Shift, APInt &Factor) {
|
||||
bool UseSRA = false;
|
||||
Shift = Divisor.countTrailingZeros();
|
||||
if (Shift) {
|
||||
Divisor.ashrInPlace(Shift);
|
||||
UseSRA = true;
|
||||
}
|
||||
// Calculate the multiplicative inverse, using Newton's method.
|
||||
APInt t;
|
||||
Factor = Divisor;
|
||||
while ((t = Divisor * Factor) != 1)
|
||||
Factor *= APInt(Divisor.getBitWidth(), 2) - t;
|
||||
return UseSRA;
|
||||
};
|
||||
|
||||
ConstantSDNode *C = isConstOrConstSplat(Op1);
|
||||
if (!C || C->isNullValue())
|
||||
return SDValue();
|
||||
|
||||
APInt d = C->getAPIntValue();
|
||||
assert(d != 0 && "Division by zero!");
|
||||
APInt FactorVal;
|
||||
unsigned ShiftVal;
|
||||
bool UseSRA = BuildSDIVPattern(C->getAPIntValue(), ShiftVal, FactorVal);
|
||||
SDValue Shift = DAG.getConstant(ShiftVal, dl, ShVT);
|
||||
SDValue Factor = DAG.getConstant(FactorVal, dl, VT);
|
||||
|
||||
SDValue Res = Op0;
|
||||
|
||||
// Shift the value upfront if it is even, so the LSB is one.
|
||||
unsigned ShAmt = d.countTrailingZeros();
|
||||
if (ShAmt) {
|
||||
if (UseSRA) {
|
||||
// TODO: For UDIV use SRL instead of SRA.
|
||||
SDValue Amt = DAG.getConstant(ShAmt, dl, ShVT);
|
||||
SDNodeFlags Flags;
|
||||
Flags.setExact(true);
|
||||
Res = DAG.getNode(ISD::SRA, dl, VT, Res, Amt, Flags);
|
||||
Res = DAG.getNode(ISD::SRA, dl, VT, Res, Shift, Flags);
|
||||
Created.push_back(Res.getNode());
|
||||
d.ashrInPlace(ShAmt);
|
||||
}
|
||||
|
||||
// Calculate the multiplicative inverse, using Newton's method.
|
||||
APInt t, xn = d;
|
||||
while ((t = d*xn) != 1)
|
||||
xn *= APInt(d.getBitWidth(), 2) - t;
|
||||
|
||||
SDValue Mul = DAG.getConstant(xn, dl, VT);
|
||||
return DAG.getNode(ISD::MUL, dl, VT, Res, Mul);
|
||||
return DAG.getNode(ISD::MUL, dl, VT, Res, Factor);
|
||||
}
|
||||
|
||||
SDValue TargetLowering::BuildSDIVPow2(SDNode *N, const APInt &Divisor,
|
||||
|
|
Loading…
Reference in New Issue