[llvm] [DAG] Lower frem of power-2 using div/trunc/mul+sub (PR #91148)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Tue May 7 07:06:23 PDT 2024
================
@@ -17264,17 +17264,32 @@ SDValue DAGCombiner::visitFREM(SDNode *N) {
EVT VT = N->getValueType(0);
SDNodeFlags Flags = N->getFlags();
SelectionDAG::FlagInserter FlagsInserter(DAG, N);
+ SDLoc DL(N);
if (SDValue R = DAG.simplifyFPBinop(N->getOpcode(), N0, N1, Flags))
return R;
// fold (frem c1, c2) -> fmod(c1,c2)
- if (SDValue C = DAG.FoldConstantArithmetic(ISD::FREM, SDLoc(N), VT, {N0, N1}))
+ if (SDValue C = DAG.FoldConstantArithmetic(ISD::FREM, DL, VT, {N0, N1}))
return C;
if (SDValue NewSel = foldBinOpIntoSelect(N))
return NewSel;
+ // Lower frem N0, N1 => x - trunc(N0 / N1) * N1, providing N1 is an integer
+ // power of 2.
+ if (DAG.isKnownToBeAPowerOfTwoFP(N1) &&
+ (Flags.hasNoSignedZeros() || DAG.isKnownNonNegativeFP(N0)) &&
+ !TLI.isOperationLegal(ISD::FREM, VT) &&
+ TLI.isOperationLegalOrCustom(ISD::FMUL, VT) &&
+ TLI.isOperationLegalOrCustom(ISD::FDIV, VT) &&
+ TLI.isOperationLegalOrCustom(ISD::FTRUNC, VT)) {
+ SDValue Div = DAG.getNode(ISD::FDIV, DL, VT, N0, N1);
+ SDValue Rnd = DAG.getNode(ISD::FTRUNC, DL, VT, Div);
+ SDValue Mul = DAG.getNode(ISD::FMUL, DL, VT, Rnd, N1);
+ return DAG.getNode(ISD::FSUB, DL, VT, N0, Mul);
----------------
arsenm wrote:
Preserve the flags
https://github.com/llvm/llvm-project/pull/91148
More information about the llvm-commits
mailing list