Skip to content

Commit a260701

Browse files
committedSep 16, 2015
propagate fast-math-flags on DAG nodes
After D10403, we had FMF in the DAG but disabled by default. Nick reported no crashing errors after some stress testing, so I enabled them at r243687. However, Escha soon notified us of a bug not covered by any in-tree regression tests: if we don't propagate the flags, we may fail to CSE DAG nodes because differing FMF causes them to not match. There is one test case in this patch to prove that point. This patch hopes to fix or leave a 'TODO' for all of the in-tree places where we create nodes that are FMF-capable. I did this by putting an assert in SelectionDAG.getNode() to find any FMF-capable node that was being created without FMF ( D11807 ). I then ran all regression tests and test-suite and confirmed that everything passes. This patch exposes remaining work to get DAG FMF to be fully functional: (1) add the flags to non-binary nodes such as FCMP, FMA and FNEG; (2) add the flags to intrinsics; (3) use the flags as conditions for transforms rather than the current global settings. Differential Revision: http://reviews.llvm.org/D12095 llvm-svn: 247815
1 parent 85dfb68 commit a260701

17 files changed

+344
-205
lines changed
 

‎llvm/include/llvm/CodeGen/SelectionDAG.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ class SelectionDAG {
670670
SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT,
671671
ArrayRef<SDUse> Ops);
672672
SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT,
673-
ArrayRef<SDValue> Ops);
673+
ArrayRef<SDValue> Ops, const SDNodeFlags *Flags = nullptr);
674674
SDValue getNode(unsigned Opcode, SDLoc DL, ArrayRef<EVT> ResultTys,
675675
ArrayRef<SDValue> Ops);
676676
SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs,

‎llvm/include/llvm/CodeGen/SelectionDAGNodes.h

+60-56
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class GlobalValue;
4444
class MachineBasicBlock;
4545
class MachineConstantPoolValue;
4646
class SDNode;
47+
class BinaryWithFlagsSDNode;
4748
class Value;
4849
class MCSymbol;
4950
template <typename T> struct DenseMapInfo;
@@ -319,6 +320,61 @@ template<> struct simplify_type<SDUse> {
319320
}
320321
};
321322

323+
/// These are IR-level optimization flags that may be propagated to SDNodes.
324+
/// TODO: This data structure should be shared by the IR optimizer and the
325+
/// the backend.
326+
struct SDNodeFlags {
327+
private:
328+
bool NoUnsignedWrap : 1;
329+
bool NoSignedWrap : 1;
330+
bool Exact : 1;
331+
bool UnsafeAlgebra : 1;
332+
bool NoNaNs : 1;
333+
bool NoInfs : 1;
334+
bool NoSignedZeros : 1;
335+
bool AllowReciprocal : 1;
336+
337+
public:
338+
/// Default constructor turns off all optimization flags.
339+
SDNodeFlags() {
340+
NoUnsignedWrap = false;
341+
NoSignedWrap = false;
342+
Exact = false;
343+
UnsafeAlgebra = false;
344+
NoNaNs = false;
345+
NoInfs = false;
346+
NoSignedZeros = false;
347+
AllowReciprocal = false;
348+
}
349+
350+
// These are mutators for each flag.
351+
void setNoUnsignedWrap(bool b) { NoUnsignedWrap = b; }
352+
void setNoSignedWrap(bool b) { NoSignedWrap = b; }
353+
void setExact(bool b) { Exact = b; }
354+
void setUnsafeAlgebra(bool b) { UnsafeAlgebra = b; }
355+
void setNoNaNs(bool b) { NoNaNs = b; }
356+
void setNoInfs(bool b) { NoInfs = b; }
357+
void setNoSignedZeros(bool b) { NoSignedZeros = b; }
358+
void setAllowReciprocal(bool b) { AllowReciprocal = b; }
359+
360+
// These are accessors for each flag.
361+
bool hasNoUnsignedWrap() const { return NoUnsignedWrap; }
362+
bool hasNoSignedWrap() const { return NoSignedWrap; }
363+
bool hasExact() const { return Exact; }
364+
bool hasUnsafeAlgebra() const { return UnsafeAlgebra; }
365+
bool hasNoNaNs() const { return NoNaNs; }
366+
bool hasNoInfs() const { return NoInfs; }
367+
bool hasNoSignedZeros() const { return NoSignedZeros; }
368+
bool hasAllowReciprocal() const { return AllowReciprocal; }
369+
370+
/// Return a raw encoding of the flags.
371+
/// This function should only be used to add data to the NodeID value.
372+
unsigned getRawFlags() const {
373+
return (NoUnsignedWrap << 0) | (NoSignedWrap << 1) | (Exact << 2) |
374+
(UnsafeAlgebra << 3) | (NoNaNs << 4) | (NoInfs << 5) |
375+
(NoSignedZeros << 6) | (AllowReciprocal << 7);
376+
}
377+
};
322378

323379
/// Represents one node in the SelectionDAG.
324380
///
@@ -639,6 +695,10 @@ class SDNode : public FoldingSetNode, public ilist_node<SDNode> {
639695
return nullptr;
640696
}
641697

698+
/// This could be defined as a virtual function and implemented more simply
699+
/// and directly, but it is not to avoid creating a vtable for this class.
700+
const SDNodeFlags *getFlags() const;
701+
642702
/// Return the number of values defined/returned by this operator.
643703
unsigned getNumValues() const { return NumValues; }
644704

@@ -950,62 +1010,6 @@ inline void SDUse::setNode(SDNode *N) {
9501010
if (N) N->addUse(*this);
9511011
}
9521012

953-
/// These are IR-level optimization flags that may be propagated to SDNodes.
954-
/// TODO: This data structure should be shared by the IR optimizer and the
955-
/// the backend.
956-
struct SDNodeFlags {
957-
private:
958-
bool NoUnsignedWrap : 1;
959-
bool NoSignedWrap : 1;
960-
bool Exact : 1;
961-
bool UnsafeAlgebra : 1;
962-
bool NoNaNs : 1;
963-
bool NoInfs : 1;
964-
bool NoSignedZeros : 1;
965-
bool AllowReciprocal : 1;
966-
967-
public:
968-
/// Default constructor turns off all optimization flags.
969-
SDNodeFlags() {
970-
NoUnsignedWrap = false;
971-
NoSignedWrap = false;
972-
Exact = false;
973-
UnsafeAlgebra = false;
974-
NoNaNs = false;
975-
NoInfs = false;
976-
NoSignedZeros = false;
977-
AllowReciprocal = false;
978-
}
979-
980-
// These are mutators for each flag.
981-
void setNoUnsignedWrap(bool b) { NoUnsignedWrap = b; }
982-
void setNoSignedWrap(bool b) { NoSignedWrap = b; }
983-
void setExact(bool b) { Exact = b; }
984-
void setUnsafeAlgebra(bool b) { UnsafeAlgebra = b; }
985-
void setNoNaNs(bool b) { NoNaNs = b; }
986-
void setNoInfs(bool b) { NoInfs = b; }
987-
void setNoSignedZeros(bool b) { NoSignedZeros = b; }
988-
void setAllowReciprocal(bool b) { AllowReciprocal = b; }
989-
990-
// These are accessors for each flag.
991-
bool hasNoUnsignedWrap() const { return NoUnsignedWrap; }
992-
bool hasNoSignedWrap() const { return NoSignedWrap; }
993-
bool hasExact() const { return Exact; }
994-
bool hasUnsafeAlgebra() const { return UnsafeAlgebra; }
995-
bool hasNoNaNs() const { return NoNaNs; }
996-
bool hasNoInfs() const { return NoInfs; }
997-
bool hasNoSignedZeros() const { return NoSignedZeros; }
998-
bool hasAllowReciprocal() const { return AllowReciprocal; }
999-
1000-
/// Return a raw encoding of the flags.
1001-
/// This function should only be used to add data to the NodeID value.
1002-
unsigned getRawFlags() const {
1003-
return (NoUnsignedWrap << 0) | (NoSignedWrap << 1) | (Exact << 2) |
1004-
(UnsafeAlgebra << 3) | (NoNaNs << 4) | (NoInfs << 5) |
1005-
(NoSignedZeros << 6) | (AllowReciprocal << 7);
1006-
}
1007-
};
1008-
10091013
/// This class is used for single-operand SDNodes. This is solely
10101014
/// to allow co-allocation of node operands with the node itself.
10111015
class UnarySDNode : public SDNode {

0 commit comments

Comments
 (0)