-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[SelectionDAG] Add initial support for nneg flag on ISD::ZERO_EXTEND. #70872
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
Conversation
This adds the nneg flag to SDNodeFlags and the node printing code. SelectionDAGBuilder will add this flag to the node if the target doesn't prefer sign extend. A future RISC-V patch can remove the sign extend preference from SelectionDAGBuilder. I've also added the flag to the DAG combine that converts ISD::SIGN_EXTEND to ISD::ZERO_EXTEND.
@llvm/pr-subscribers-llvm-selectiondag Author: Craig Topper (topperc) ChangesThis adds the nneg flag to SDNodeFlags and the node printing code. SelectionDAGBuilder will add this flag to the node if the target doesn't prefer sign extend. A future RISC-V patch can remove the sign extend preference from SelectionDAGBuilder. I've also added the flag to the DAG combine that converts ISD::SIGN_EXTEND to ISD::ZERO_EXTEND. Full diff: https://github.com/llvm/llvm-project/pull/70872.diff 4 Files Affected:
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index 59c6feec8bcbfed..4df56aac4aa17ba 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -381,6 +381,7 @@ struct SDNodeFlags {
bool NoUnsignedWrap : 1;
bool NoSignedWrap : 1;
bool Exact : 1;
+ bool NonNeg : 1;
bool NoNaNs : 1;
bool NoInfs : 1;
bool NoSignedZeros : 1;
@@ -401,9 +402,9 @@ struct SDNodeFlags {
public:
/// Default constructor turns off all optimization flags.
SDNodeFlags()
- : NoUnsignedWrap(false), NoSignedWrap(false), Exact(false), NoNaNs(false),
- NoInfs(false), NoSignedZeros(false), AllowReciprocal(false),
- AllowContract(false), ApproximateFuncs(false),
+ : NoUnsignedWrap(false), NoSignedWrap(false), Exact(false), NonNeg(false),
+ NoNaNs(false), NoInfs(false), NoSignedZeros(false),
+ AllowReciprocal(false), AllowContract(false), ApproximateFuncs(false),
AllowReassociation(false), NoFPExcept(false), Unpredictable(false) {}
/// Propagate the fast-math-flags from an IR FPMathOperator.
@@ -421,6 +422,7 @@ struct SDNodeFlags {
void setNoUnsignedWrap(bool b) { NoUnsignedWrap = b; }
void setNoSignedWrap(bool b) { NoSignedWrap = b; }
void setExact(bool b) { Exact = b; }
+ void setNonNeg(bool b) { NonNeg = b; }
void setNoNaNs(bool b) { NoNaNs = b; }
void setNoInfs(bool b) { NoInfs = b; }
void setNoSignedZeros(bool b) { NoSignedZeros = b; }
@@ -435,6 +437,7 @@ struct SDNodeFlags {
bool hasNoUnsignedWrap() const { return NoUnsignedWrap; }
bool hasNoSignedWrap() const { return NoSignedWrap; }
bool hasExact() const { return Exact; }
+ bool hasNonNeg() const { return NonNeg; }
bool hasNoNaNs() const { return NoNaNs; }
bool hasNoInfs() const { return NoInfs; }
bool hasNoSignedZeros() const { return NoSignedZeros; }
@@ -451,6 +454,7 @@ struct SDNodeFlags {
NoUnsignedWrap &= Flags.NoUnsignedWrap;
NoSignedWrap &= Flags.NoSignedWrap;
Exact &= Flags.Exact;
+ NonNeg &= Flags.Exact;
NoNaNs &= Flags.NoNaNs;
NoInfs &= Flags.NoInfs;
NoSignedZeros &= Flags.NoSignedZeros;
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index ca5bd4952866886..8c1282274372088 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -13484,8 +13484,11 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
// fold (sext x) -> (zext x) if the sign bit is known zero.
if (!TLI.isSExtCheaperThanZExt(N0.getValueType(), VT) &&
(!LegalOperations || TLI.isOperationLegal(ISD::ZERO_EXTEND, VT)) &&
- DAG.SignBitIsZero(N0))
- return DAG.getNode(ISD::ZERO_EXTEND, DL, VT, N0);
+ DAG.SignBitIsZero(N0)) {
+ SDNodeFlags Flags;
+ Flags.setNonNeg(true);
+ return DAG.getNode(ISD::ZERO_EXTEND, DL, VT, N0, Flags);
+ }
if (SDValue NewVSel = matchVSelectOpSizesWithSetCC(N))
return NewVSel;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 229f220d8460bda..e4832216850efd9 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3527,18 +3527,20 @@ void SelectionDAGBuilder::visitZExt(const User &I) {
auto &TLI = DAG.getTargetLoweringInfo();
EVT DestVT = TLI.getValueType(DAG.getDataLayout(), I.getType());
- // Since we don't yet have a representation of zext nneg in SDAG or MI,
- // eagerly use the information to canonicalize towards sign_extend if
- // that is the target's preference. TODO: Add nneg support to the
- // SDAG and MI representations.
- if (auto *PNI = dyn_cast<PossiblyNonNegInst>(&I);
- PNI && PNI->hasNonNeg() &&
+ SDNodeFlags Flags;
+ if (auto *PNI = dyn_cast<PossiblyNonNegInst>(&I))
+ Flags.setNonNeg(PNI->hasNonNeg());
+
+ // Eagerly use nonneg information to canonicalize towards sign_extend if
+ // that is the target's preference.
+ // TODO: Let the target do this later.
+ if (Flags.hasNonNeg() &&
TLI.isSExtCheaperThanZExt(N.getValueType(), DestVT)) {
setValue(&I, DAG.getNode(ISD::SIGN_EXTEND, getCurSDLoc(), DestVT, N));
return;
}
- setValue(&I, DAG.getNode(ISD::ZERO_EXTEND, getCurSDLoc(), DestVT, N));
+ setValue(&I, DAG.getNode(ISD::ZERO_EXTEND, getCurSDLoc(), DestVT, N, Flags));
}
void SelectionDAGBuilder::visitSExt(const User &I) {
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
index a92111ca23656eb..78cc60084068a5f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -597,6 +597,9 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
if (getFlags().hasExact())
OS << " exact";
+ if (getFlags().hasNonNeg())
+ OS << " nneg";
+
if (getFlags().hasNoNaNs())
OS << " nnan";
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to update the SDAG canCreateUndefOrPoison() implementation to account for the new flag.
This generally looks ok to me, but I'll leave it to people who do more backend work to decide whether having this flag in SDAG is worthwhile. Given how target-specific SDAG is, I could see the argument for just using SEXT based on target preference and not adding the complexity of additional poison flags.
Do we need to add the flag to the zext_in_reg nodes? This question is complicated by the fact that comments in DAGCombine mention such a node, but it doesn't appear to be in the ISDOpcodes.h list. Can you update the comment for ZERO_EXTEND in ISDOpcodes.h to mention the flag and the implied poison semantics? For context, we're definitely going to need this for RISCV. At the moment, I set us up to prefer SIGN_EXTEND based on the target preference, and I see some cases in benchmarks where this hurt codegen because we missed a zext fold or zeroing bits is easier in a particular case (say, and with smallish constant). |
zext_in_reg is ISD::AND with a trailing ones mask. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should also update SimplifyDemanded to drop that flag.
/// ZERO_EXTEND - Used for integer types, zeroing the new bits. | ||
/// ZERO_EXTEND - Used for integer types, zeroing the new bits. Can carry | ||
/// the NonNeg SDNodeFlag to indicate that the input is known to be | ||
/// non-negative. If the flag is present and the input is negative, the reuslt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// non-negative. If the flag is present and the input is negative, the reuslt | |
/// non-negative. If the flag is present and the input is negative, the result |
There is ZERO_EXTEND_VECTOR_INREG though, so I guess the question applies to that one. |
This adds the nneg flag to SDNodeFlags and the node printing code. SelectionDAGBuilder will add this flag to the node if the target doesn't prefer sign extend.
A future RISC-V patch can remove the sign extend preference from SelectionDAGBuilder.
I've also added the flag to the DAG combine that converts ISD::SIGN_EXTEND to ISD::ZERO_EXTEND.