Skip to content

Commit afab680

Browse files
committed
[DAGCombiner] Add generic remainder (rem) CSE optimization
1 parent b9ea93c commit afab680

File tree

1 file changed

+38
-0
lines changed

1 file changed

+38
-0
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,41 @@ namespace {
900900
ISD::NodeType ExtType);
901901
};
902902

903+
/// Generic remainder optimization : Folds a remainder operation (A % B) by reusing the computed quotient (A / B).
904+
static SDValue PerformREMCombineGeneric(SDNode *N, DAGCombiner &DC,
905+
CodeGenOptLevel OptLevel) {
906+
assert(N->getOpcode() == ISD::SREM || N->getOpcode() == ISD::UREM);
907+
908+
// Don't do anything at less than -O2.
909+
if (OptLevel < CodeGenOptLevel::Default)
910+
return SDValue();
911+
912+
SelectionDAG &DAG = DC.getDAG();
913+
SDLoc DL(N);
914+
EVT VT = N->getValueType(0);
915+
bool IsSigned = N->getOpcode() == ISD::SREM;
916+
unsigned DivOpc = IsSigned ? ISD::SDIV : ISD::UDIV;
917+
918+
const SDValue &Num = N->getOperand(0);
919+
const SDValue &Den = N->getOperand(1);
920+
921+
AttributeList Attr = DC.getDAG().getMachineFunction().getFunction().getAttributes();
922+
if (DC.getDAG().getTargetLoweringInfo().isIntDivCheap(N->getValueType(0), Attr))
923+
return SDValue();
924+
925+
for (const SDNode *U : Num->users()) {
926+
if (U->getOpcode() == DivOpc && U->getOperand(0) == Num &&
927+
U->getOperand(1) == Den) {
928+
// Num % Den -> Num - (Num / Den) * Den
929+
return DAG.getNode(ISD::SUB, DL, VT, Num,
930+
DAG.getNode(ISD::MUL, DL, VT,
931+
DAG.getNode(DivOpc, DL, VT, Num, Den),
932+
Den));
933+
}
934+
}
935+
return SDValue();
936+
}
937+
903938
/// This class is a DAGUpdateListener that removes any deleted
904939
/// nodes from the worklist.
905940
class WorklistRemover : public SelectionDAG::DAGUpdateListener {
@@ -5400,6 +5435,9 @@ SDValue DAGCombiner::visitREM(SDNode *N) {
54005435
if (SDValue NewSel = foldBinOpIntoSelect(N))
54015436
return NewSel;
54025437

5438+
if (SDValue V = PerformREMCombineGeneric(N, *this, OptLevel))
5439+
return V;
5440+
54035441
if (isSigned) {
54045442
// If we know the sign bits of both operands are zero, strength reduce to a
54055443
// urem instead. Handles (X & 0x0FFFFFFF) %s 16 -> X&15

0 commit comments

Comments
 (0)