Skip to content

Commit 5cafdd6

Browse files
committed
SelectionDAG: Support nofpclass(nan/qnan/snan)
SelectionDAGISel::LowerArguments: Pass NoNaN Flags to InVals. `nofpclass` support values nan, snan, qnan, where nan=snan|qnan. So let's use NoSNaNs and NoQNaNs in SDNodeFlags. Thus, we can use it in isKnownNeverNaN.
1 parent 69527b0 commit 5cafdd6

File tree

6 files changed

+1322
-8
lines changed

6 files changed

+1322
-8
lines changed

llvm/include/llvm/CodeGen/SelectionDAGNodes.h

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ struct SDNodeFlags {
397397
Exact = 1 << 2,
398398
Disjoint = 1 << 3,
399399
NonNeg = 1 << 4,
400-
NoNaNs = 1 << 5,
400+
// 1 << 5 was used as NoNaNs
401401
NoInfs = 1 << 6,
402402
NoSignedZeros = 1 << 7,
403403
AllowReciprocal = 1 << 8,
@@ -416,21 +416,26 @@ struct SDNodeFlags {
416416
// Compare instructions which may carry the samesign flag.
417417
SameSign = 1 << 14,
418418

419+
NoSNaNs = 1 << 15,
420+
NoQNaNs = 1 << 16,
421+
419422
// NOTE: Please update LargestValue in LLVM_DECLARE_ENUM_AS_BITMASK below
420423
// the class definition when adding new flags.
421424

422425
PoisonGeneratingFlags = NoUnsignedWrap | NoSignedWrap | Exact | Disjoint |
423-
NonNeg | NoNaNs | NoInfs | SameSign,
424-
FastMathFlags = NoNaNs | NoInfs | NoSignedZeros | AllowReciprocal |
425-
AllowContract | ApproximateFuncs | AllowReassociation,
426+
NonNeg | NoSNaNs | NoQNaNs | NoInfs | SameSign,
427+
FastMathFlags = NoSNaNs | NoQNaNs | NoInfs | NoSignedZeros |
428+
AllowReciprocal | AllowContract | ApproximateFuncs |
429+
AllowReassociation,
426430
};
427431

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

431435
/// Propagate the fast-math-flags from an IR FPMathOperator.
432436
void copyFMF(const FPMathOperator &FPMO) {
433-
setNoNaNs(FPMO.hasNoNaNs());
437+
setNoSNaNs(FPMO.hasNoNaNs());
438+
setNoQNaNs(FPMO.hasNoNaNs());
434439
setNoInfs(FPMO.hasNoInfs());
435440
setNoSignedZeros(FPMO.hasNoSignedZeros());
436441
setAllowReciprocal(FPMO.hasAllowReciprocal());
@@ -446,7 +451,12 @@ struct SDNodeFlags {
446451
void setDisjoint(bool b) { setFlag<Disjoint>(b); }
447452
void setSameSign(bool b) { setFlag<SameSign>(b); }
448453
void setNonNeg(bool b) { setFlag<NonNeg>(b); }
449-
void setNoNaNs(bool b) { setFlag<NoNaNs>(b); }
454+
void setNoNaNs(bool b) {
455+
setFlag<NoSNaNs>(b);
456+
setFlag<NoQNaNs>(b);
457+
}
458+
void setNoSNaNs(bool b) { setFlag<NoSNaNs>(b); }
459+
void setNoQNaNs(bool b) { setFlag<NoQNaNs>(b); }
450460
void setNoInfs(bool b) { setFlag<NoInfs>(b); }
451461
void setNoSignedZeros(bool b) { setFlag<NoSignedZeros>(b); }
452462
void setAllowReciprocal(bool b) { setFlag<AllowReciprocal>(b); }
@@ -463,7 +473,9 @@ struct SDNodeFlags {
463473
bool hasDisjoint() const { return Flags & Disjoint; }
464474
bool hasSameSign() const { return Flags & SameSign; }
465475
bool hasNonNeg() const { return Flags & NonNeg; }
466-
bool hasNoNaNs() const { return Flags & NoNaNs; }
476+
bool hasNoNaNs() const { return (Flags & NoSNaNs) && (Flags & NoQNaNs); }
477+
bool hasNoSNaNs() const { return Flags & NoSNaNs; }
478+
bool hasNoQNaNs() const { return Flags & NoQNaNs; }
467479
bool hasNoInfs() const { return Flags & NoInfs; }
468480
bool hasNoSignedZeros() const { return Flags & NoSignedZeros; }
469481
bool hasAllowReciprocal() const { return Flags & AllowReciprocal; }

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5613,7 +5613,12 @@ bool SelectionDAG::isBaseWithConstantOffset(SDValue Op) const {
56135613

56145614
bool SelectionDAG::isKnownNeverNaN(SDValue Op, bool SNaN, unsigned Depth) const {
56155615
// If we're told that NaNs won't happen, assume they won't.
5616-
if (getTarget().Options.NoNaNsFPMath || Op->getFlags().hasNoNaNs())
5616+
if (getTarget().Options.NoNaNsFPMath)
5617+
return true;
5618+
SDNodeFlags OpFlags = Op->getFlags();
5619+
if (SNaN && OpFlags.hasNoSNaNs())
5620+
return true;
5621+
if (OpFlags.hasNoSNaNs() && OpFlags.hasNoQNaNs())
56175622
return true;
56185623

56195624
if (Depth >= MaxRecursionDepth)

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11891,6 +11891,16 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
1189111891
AssertOp = ISD::AssertSext;
1189211892
else if (Arg.hasAttribute(Attribute::ZExt))
1189311893
AssertOp = ISD::AssertZext;
11894+
if (Arg.hasAttribute(Attribute::NoFPClass)) {
11895+
SDNodeFlags InValFlags = InVals[i]->getFlags();
11896+
bool NoSNaN = ((Arg.getNoFPClass() & llvm::fcSNan) == llvm::fcSNan);
11897+
bool NoQNaN = ((Arg.getNoFPClass() & llvm::fcQNan) == llvm::fcQNan);
11898+
InValFlags.setNoSNaNs(NoSNaN);
11899+
InValFlags.setNoQNaNs(NoQNaN);
11900+
InValFlags.setNoInfs((Arg.getNoFPClass() & llvm::fcInf) ==
11901+
llvm::fcInf);
11902+
InVals[i]->setFlags(InValFlags);
11903+
}
1189411904

1189511905
ArgValues.push_back(getCopyFromParts(DAG, dl, &InVals[i], NumParts,
1189611906
PartVT, VT, nullptr, NewRoot,

0 commit comments

Comments
 (0)