-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[DAG] Fold add(mul(add(A, CA), CM), CB) -> add(mul(A, CM), CM*CA+CB) #90860
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2838,6 +2838,66 @@ SDValue DAGCombiner::visitADDLike(SDNode *N) { | |
return DAG.getNode(ISD::ADD, DL, VT, Not, N0.getOperand(0)); | ||
} | ||
|
||
// Fold add(mul(add(A, CA), CM), CB) -> add(mul(A, CM), CM*CA+CB). | ||
// This can help if the inner add has multiple uses. | ||
APInt CM, CA; | ||
if (ConstantSDNode *CB = dyn_cast<ConstantSDNode>(N1)) { | ||
if (VT.getScalarSizeInBits() <= 64) { | ||
if (sd_match(N0, m_OneUse(m_Mul(m_Add(m_Value(A), m_ConstInt(CA)), | ||
m_ConstInt(CM)))) && | ||
TLI.isLegalAddImmediate( | ||
(CA * CM + CB->getAPIntValue()).getSExtValue())) { | ||
SDNodeFlags Flags; | ||
// If all the inputs are nuw, the outputs can be nuw. If all the input | ||
// are _also_ nsw the outputs can be too. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can flags be preserved? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to drop flags the flags for general reassociations. I think that would apply here unless you know of a reason why it wouldn't? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean I always just stick it in alive and see if it works There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the generic combine: https://alive2.llvm.org/ce/z/k7Yvo3. In general the flags need removing. In specific cases the flags might be retained, but it feels to me a bit niche and difficult to specify: https://alive2.llvm.org/ce/z/aK5Az3. Let me know what you think. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think using constants in the proof is making this more permissive looking than it should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The first link is the general proof with any values. noundef %CA/%CB/%CM are the constants. In general the flags from the add/mul need to be dropped. It does look like if all the input adds/mul are nsw/nuw then we might be able to keep some flags on the remaining instructions. I'm not sure if it's worth it considering all the other transforms in DAG, but I can try and add that to the patch. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I played around with a bit and I'm not sure what the rule is, probably best to keep that in a separate patch if it's worth it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, seems to just be and on all instructions There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh - sorry. This is the version with all nuw: https://alive2.llvm.org/ce/z/nxaMNR I can remove that patch if you like, it would be just a case of dropping the last patch from this review. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Keep it - as long as some tests actually hit this |
||
if (N->getFlags().hasNoUnsignedWrap() && | ||
N0->getFlags().hasNoUnsignedWrap() && | ||
N0.getOperand(0)->getFlags().hasNoUnsignedWrap()) { | ||
Flags.setNoUnsignedWrap(true); | ||
if (N->getFlags().hasNoSignedWrap() && | ||
N0->getFlags().hasNoSignedWrap() && | ||
N0.getOperand(0)->getFlags().hasNoSignedWrap()) | ||
Flags.setNoSignedWrap(true); | ||
} | ||
SDValue Mul = DAG.getNode(ISD::MUL, SDLoc(N1), VT, A, | ||
DAG.getConstant(CM, DL, VT), Flags); | ||
return DAG.getNode( | ||
ISD::ADD, DL, VT, Mul, | ||
DAG.getConstant(CA * CM + CB->getAPIntValue(), DL, VT), Flags); | ||
} | ||
// Also look in case there is an intermediate add. | ||
if (sd_match(N0, m_OneUse(m_Add( | ||
m_OneUse(m_Mul(m_Add(m_Value(A), m_ConstInt(CA)), | ||
m_ConstInt(CM))), | ||
m_Value(B)))) && | ||
TLI.isLegalAddImmediate( | ||
(CA * CM + CB->getAPIntValue()).getSExtValue())) { | ||
SDNodeFlags Flags; | ||
// If all the inputs are nuw, the outputs can be nuw. If all the input | ||
// are _also_ nsw the outputs can be too. | ||
SDValue OMul = | ||
N0.getOperand(0) == B ? N0.getOperand(1) : N0.getOperand(0); | ||
if (N->getFlags().hasNoUnsignedWrap() && | ||
N0->getFlags().hasNoUnsignedWrap() && | ||
OMul->getFlags().hasNoUnsignedWrap() && | ||
OMul.getOperand(0)->getFlags().hasNoUnsignedWrap()) { | ||
Flags.setNoUnsignedWrap(true); | ||
if (N->getFlags().hasNoSignedWrap() && | ||
N0->getFlags().hasNoSignedWrap() && | ||
OMul->getFlags().hasNoSignedWrap() && | ||
OMul.getOperand(0)->getFlags().hasNoSignedWrap()) | ||
Flags.setNoSignedWrap(true); | ||
} | ||
SDValue Mul = DAG.getNode(ISD::MUL, SDLoc(N1), VT, A, | ||
DAG.getConstant(CM, DL, VT), Flags); | ||
SDValue Add = DAG.getNode(ISD::ADD, SDLoc(N1), VT, Mul, B, Flags); | ||
return DAG.getNode( | ||
ISD::ADD, DL, VT, Add, | ||
DAG.getConstant(CA * CM + CB->getAPIntValue(), DL, VT), Flags); | ||
} | ||
} | ||
} | ||
|
||
if (SDValue Combined = visitADDLikeCommutative(N0, N1, N)) | ||
return Combined; | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.