Skip to content

SelectionDAG: Support nofpclass(nan/qnan/snan/nzero) in arguments #130051

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

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions llvm/include/llvm/CodeGen/ISDOpcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ enum NodeType {
/// poisoned the assertion will not be true for that value.
AssertAlign,

/// AssertNoFPClass - These nodes record if a register contains a float
/// value that is known to be not some type.
/// NOTE: In case of the source value (or any vector element value) is
/// poisoned the assertion will not be true for that value.
AssertNoFPClass,

/// Various leaf nodes.
BasicBlock,
VALUETYPE,
Expand Down
26 changes: 19 additions & 7 deletions llvm/include/llvm/CodeGen/SelectionDAGNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ struct SDNodeFlags {
Exact = 1 << 2,
Disjoint = 1 << 3,
NonNeg = 1 << 4,
NoNaNs = 1 << 5,
// 1 << 5 was used as NoNaNs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated change, shouldn't touch the fast math flags

NoInfs = 1 << 6,
NoSignedZeros = 1 << 7,
AllowReciprocal = 1 << 8,
Expand All @@ -416,21 +416,26 @@ struct SDNodeFlags {
// Compare instructions which may carry the samesign flag.
SameSign = 1 << 14,

NoSNaNs = 1 << 15,
NoQNaNs = 1 << 16,

// NOTE: Please update LargestValue in LLVM_DECLARE_ENUM_AS_BITMASK below
// the class definition when adding new flags.

PoisonGeneratingFlags = NoUnsignedWrap | NoSignedWrap | Exact | Disjoint |
NonNeg | NoNaNs | NoInfs | SameSign,
FastMathFlags = NoNaNs | NoInfs | NoSignedZeros | AllowReciprocal |
AllowContract | ApproximateFuncs | AllowReassociation,
NonNeg | NoSNaNs | NoQNaNs | NoInfs | SameSign,
FastMathFlags = NoSNaNs | NoQNaNs | NoInfs | NoSignedZeros |
AllowReciprocal | AllowContract | ApproximateFuncs |
AllowReassociation,
};

/// Default constructor turns off all optimization flags.
SDNodeFlags(unsigned Flags = SDNodeFlags::None) : Flags(Flags) {}

/// Propagate the fast-math-flags from an IR FPMathOperator.
void copyFMF(const FPMathOperator &FPMO) {
setNoNaNs(FPMO.hasNoNaNs());
setNoSNaNs(FPMO.hasNoNaNs());
setNoQNaNs(FPMO.hasNoNaNs());
setNoInfs(FPMO.hasNoInfs());
setNoSignedZeros(FPMO.hasNoSignedZeros());
setAllowReciprocal(FPMO.hasAllowReciprocal());
Expand All @@ -446,7 +451,12 @@ struct SDNodeFlags {
void setDisjoint(bool b) { setFlag<Disjoint>(b); }
void setSameSign(bool b) { setFlag<SameSign>(b); }
void setNonNeg(bool b) { setFlag<NonNeg>(b); }
void setNoNaNs(bool b) { setFlag<NoNaNs>(b); }
void setNoNaNs(bool b) {
setFlag<NoSNaNs>(b);
setFlag<NoQNaNs>(b);
}
void setNoSNaNs(bool b) { setFlag<NoSNaNs>(b); }
void setNoQNaNs(bool b) { setFlag<NoQNaNs>(b); }
void setNoInfs(bool b) { setFlag<NoInfs>(b); }
void setNoSignedZeros(bool b) { setFlag<NoSignedZeros>(b); }
void setAllowReciprocal(bool b) { setFlag<AllowReciprocal>(b); }
Expand All @@ -463,7 +473,9 @@ struct SDNodeFlags {
bool hasDisjoint() const { return Flags & Disjoint; }
bool hasSameSign() const { return Flags & SameSign; }
bool hasNonNeg() const { return Flags & NonNeg; }
bool hasNoNaNs() const { return Flags & NoNaNs; }
bool hasNoNaNs() const { return (Flags & NoSNaNs) && (Flags & NoQNaNs); }
bool hasNoSNaNs() const { return Flags & NoSNaNs; }
bool hasNoQNaNs() const { return Flags & NoQNaNs; }
bool hasNoInfs() const { return Flags & NoInfs; }
bool hasNoSignedZeros() const { return Flags & NoSignedZeros; }
bool hasAllowReciprocal() const { return Flags & AllowReciprocal; }
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/Target/TargetSelectionDAG.td
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,7 @@ def SDT_assert : SDTypeProfile<1, 1,
[SDTCisInt<0>, SDTCisInt<1>, SDTCisSameAs<1, 0>]>;
def assertsext : SDNode<"ISD::AssertSext", SDT_assert>;
def assertzext : SDNode<"ISD::AssertZext", SDT_assert>;
def assernofpclass : SDNode<"ISD::AssertNoFPClass", SDTFPUnaryOp>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo inherited from the other patch

def assertalign : SDNode<"ISD::AssertAlign", SDT_assert>;

def convergencectrl_anchor : SDNode<"ISD::CONVERGENCECTRL_ANCHOR",
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ void DAGTypeLegalizer::SoftenFloatResult(SDNode *N, unsigned ResNo) {
case ISD::POISON:
case ISD::UNDEF: R = SoftenFloatRes_UNDEF(N); break;
case ISD::VAARG: R = SoftenFloatRes_VAARG(N); break;
case ISD::AssertNoFPClass: R = GetSoftenedFloat(N->getOperand(0)); break;
case ISD::VECREDUCE_FADD:
case ISD::VECREDUCE_FMUL:
case ISD::VECREDUCE_FMIN:
Expand Down Expand Up @@ -2576,6 +2577,7 @@ bool DAGTypeLegalizer::PromoteFloatOperand(SDNode *N, unsigned OpNo) {
R = PromoteFloatOp_FAKE_USE(N, OpNo);
break;
case ISD::FCOPYSIGN: R = PromoteFloatOp_FCOPYSIGN(N, OpNo); break;
case ISD::AssertNoFPClass:
case ISD::FP_TO_SINT:
case ISD::FP_TO_UINT:
case ISD::LROUND:
Expand Down Expand Up @@ -2803,6 +2805,7 @@ void DAGTypeLegalizer::PromoteFloatResult(SDNode *N, unsigned ResNo) {
case ISD::FTRUNC:
case ISD::FTAN:
case ISD::FTANH:
case ISD::AssertNoFPClass:
case ISD::FCANONICALIZE: R = PromoteFloatRes_UnaryOp(N); break;

// Binary FP Operations
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
case ISD::UINT_TO_FP:
case ISD::ZERO_EXTEND:
case ISD::FCANONICALIZE:
case ISD::AssertNoFPClass:
R = ScalarizeVecRes_UnaryOp(N);
break;
case ISD::ADDRSPACECAST:
Expand Down Expand Up @@ -1276,6 +1277,7 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
case ISD::UINT_TO_FP:
case ISD::VP_UINT_TO_FP:
case ISD::FCANONICALIZE:
case ISD::AssertNoFPClass:
SplitVecRes_UnaryOp(N, Lo, Hi);
break;
case ISD::ADDRSPACECAST:
Expand Down Expand Up @@ -4844,6 +4846,7 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
case ISD::FREEZE:
case ISD::ARITH_FENCE:
case ISD::FCANONICALIZE:
case ISD::AssertNoFPClass:
Res = WidenVecRes_Unary(N);
break;
case ISD::FMA: case ISD::VP_FMA:
Expand Down
11 changes: 10 additions & 1 deletion llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5603,7 +5603,12 @@ bool SelectionDAG::isBaseWithConstantOffset(SDValue Op) const {

bool SelectionDAG::isKnownNeverNaN(SDValue Op, bool SNaN, unsigned Depth) const {
// If we're told that NaNs won't happen, assume they won't.
if (getTarget().Options.NoNaNsFPMath || Op->getFlags().hasNoNaNs())
if (getTarget().Options.NoNaNsFPMath)
return true;
SDNodeFlags OpFlags = Op->getFlags();
if (SNaN && OpFlags.hasNoSNaNs())
return true;
Comment on lines +5608 to +5610
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't need to touch the flags. This code should be directly inspecting AssertNoFPClass's carried mask

if (OpFlags.hasNoSNaNs() && OpFlags.hasNoQNaNs())
return true;

if (Depth >= MaxRecursionDepth)
Expand Down Expand Up @@ -7370,6 +7375,10 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
N2.getOpcode() == ISD::TargetConstant && "Invalid FP_ROUND!");
if (N1.getValueType() == VT) return N1; // noop conversion.
break;
case ISD::AssertNoFPClass:
assert(N1.getValueType().isFloatingPoint() &&
"AssertNoFPClass is used for a non-floating type");
return N1;
case ISD::AssertSext:
case ISD::AssertZext: {
EVT EVT = cast<VTSDNode>(N2)->getVT();
Expand Down
23 changes: 19 additions & 4 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11827,10 +11827,25 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
AssertOp = ISD::AssertSext;
else if (Arg.hasAttribute(Attribute::ZExt))
AssertOp = ISD::AssertZext;

ArgValues.push_back(getCopyFromParts(DAG, dl, &InVals[i], NumParts,
PartVT, VT, nullptr, NewRoot,
F.getCallingConv(), AssertOp));
SDValue OutVal =
getCopyFromParts(DAG, dl, &InVals[i], NumParts, PartVT, VT, nullptr,
NewRoot, F.getCallingConv(), AssertOp);
if (Arg.hasAttribute(Attribute::NoFPClass) &&
OutVal.getValueType().isFloatingPoint()) {
SDNodeFlags OutValFlags = OutVal->getFlags();
bool NoSNaN = ((Arg.getNoFPClass() & llvm::fcSNan) == llvm::fcSNan);
Comment on lines +11835 to +11836
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AssertNoFPClass should have an explicit integer mask argument that directly copies the value. You shouldn't be trying to re-encode that value as fast math flags

bool NoQNaN = ((Arg.getNoFPClass() & llvm::fcQNan) == llvm::fcQNan);
bool NoInf = ((Arg.getNoFPClass() & llvm::fcInf) == llvm::fcInf);
bool NoNegZero =
((Arg.getNoFPClass() & llvm::fcInf) == llvm::fcNegZero);
OutValFlags.setNoSNaNs(NoSNaN);
OutValFlags.setNoQNaNs(NoQNaN);
OutValFlags.setNoInfs(NoInf);
OutValFlags.setNoSignedZeros(NoNegZero);
Comment on lines +11835 to +11844
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should not be setting any fast math flags. Particularly NSZ, the meaning of the NSZ flag is not that there isn't a -0 value

OutVal =
DAG.getNode(ISD::AssertNoFPClass, dl, VT, OutVal, OutValFlags);
}
ArgValues.push_back(OutVal);
}

i += NumParts;
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::TokenFactor: return "TokenFactor";
case ISD::AssertSext: return "AssertSext";
case ISD::AssertZext: return "AssertZext";
case ISD::AssertNoFPClass: return "AssertNoFPClass";
case ISD::AssertAlign: return "AssertAlign";

case ISD::BasicBlock: return "BasicBlock";
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3265,6 +3265,7 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
return;
case ISD::AssertSext:
case ISD::AssertZext:
case ISD::AssertNoFPClass:
case ISD::AssertAlign:
ReplaceUses(SDValue(NodeToMatch, 0), NodeToMatch->getOperand(0));
CurDAG->RemoveDeadNode(NodeToMatch);
Expand Down
Loading
Loading