Skip to content

Commit 98d51c2

Browse files
committed
[RISCV] Override TargetLowering::BuildSDIVPow2 to generate SELECT
When `Zbt` is enabled, we can generate SELECT for division by power of 2, so that there is no data dependency. Reviewed By: craig.topper Differential Revision: https://reviews.llvm.org/D114856
1 parent 50ec130 commit 98d51c2

File tree

3 files changed

+866
-0
lines changed

3 files changed

+866
-0
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10350,6 +10350,60 @@ SDValue RISCVTargetLowering::joinRegisterPartsIntoValue(
1035010350
return SDValue();
1035110351
}
1035210352

10353+
SDValue
10354+
RISCVTargetLowering::BuildSDIVPow2(SDNode *N, const APInt &Divisor,
10355+
SelectionDAG &DAG,
10356+
SmallVectorImpl<SDNode *> &Created) const {
10357+
AttributeList Attr = DAG.getMachineFunction().getFunction().getAttributes();
10358+
if (isIntDivCheap(N->getValueType(0), Attr))
10359+
return SDValue(N, 0); // Lower SDIV as SDIV
10360+
10361+
assert((Divisor.isPowerOf2() || Divisor.isNegatedPowerOf2()) &&
10362+
"Unexpected divisor!");
10363+
10364+
// Conditional move is needed, so do the transformation iff Zbt is enabled.
10365+
if (!Subtarget.hasStdExtZbt())
10366+
return SDValue();
10367+
10368+
// When |Divisor| >= 2 ^ 12, it isn't profitable to do such transformation.
10369+
// Besides, more critical path instructions will be generated when dividing
10370+
// by 2. So we keep using the original DAGs for these cases.
10371+
unsigned Lg2 = Divisor.countTrailingZeros();
10372+
if (Lg2 == 1 || Lg2 >= 12)
10373+
return SDValue();
10374+
10375+
// fold (sdiv X, pow2)
10376+
EVT VT = N->getValueType(0);
10377+
if (VT != MVT::i32 && !(Subtarget.is64Bit() && VT == MVT::i64))
10378+
return SDValue();
10379+
10380+
SDLoc DL(N);
10381+
SDValue N0 = N->getOperand(0);
10382+
SDValue Zero = DAG.getConstant(0, DL, VT);
10383+
SDValue Pow2MinusOne = DAG.getConstant((1ULL << Lg2) - 1, DL, VT);
10384+
10385+
// Add (N0 < 0) ? Pow2 - 1 : 0;
10386+
SDValue Cmp = DAG.getSetCC(DL, VT, N0, Zero, ISD::SETLT);
10387+
SDValue Add = DAG.getNode(ISD::ADD, DL, VT, N0, Pow2MinusOne);
10388+
SDValue Sel = DAG.getNode(ISD::SELECT, DL, VT, Cmp, Add, N0);
10389+
10390+
Created.push_back(Cmp.getNode());
10391+
Created.push_back(Add.getNode());
10392+
Created.push_back(Sel.getNode());
10393+
10394+
// Divide by pow2.
10395+
SDValue SRA =
10396+
DAG.getNode(ISD::SRA, DL, VT, Sel, DAG.getConstant(Lg2, DL, VT));
10397+
10398+
// If we're dividing by a positive value, we're done. Otherwise, we must
10399+
// negate the result.
10400+
if (Divisor.isNonNegative())
10401+
return SRA;
10402+
10403+
Created.push_back(SRA.getNode());
10404+
return DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), SRA);
10405+
}
10406+
1035310407
#define GET_REGISTER_MATCHER
1035410408
#include "RISCVGenAsmMatcher.inc"
1035510409

llvm/lib/Target/RISCV/RISCVISelLowering.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,9 @@ class RISCVTargetLowering : public TargetLowering {
528528

529529
bool shouldConvertFpToSat(unsigned Op, EVT FPVT, EVT VT) const override;
530530

531+
SDValue BuildSDIVPow2(SDNode *N, const APInt &Divisor, SelectionDAG &DAG,
532+
SmallVectorImpl<SDNode *> &Created) const override;
533+
531534
private:
532535
/// RISCVCCAssignFn - This target-specific function extends the default
533536
/// CCValAssign with additional information used to lower RISC-V calling

0 commit comments

Comments
 (0)