summaryrefslogtreecommitdiffstats
path: root/llvm/include
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2015-09-16 16:31:21 +0000
committerSanjay Patel <spatel@rotateright.com>2015-09-16 16:31:21 +0000
commita260701bbbf5d6f6f94358b5991dbc34cf6316ef (patch)
tree9b562e1b38204863165172d86d04af4c1cff68c9 /llvm/include
parent85dfb68e5004dd407c5a8cace921c5679ac56a77 (diff)
downloadbcm5719-llvm-a260701bbbf5d6f6f94358b5991dbc34cf6316ef.tar.gz
bcm5719-llvm-a260701bbbf5d6f6f94358b5991dbc34cf6316ef.zip
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
Diffstat (limited to 'llvm/include')
-rw-r--r--llvm/include/llvm/CodeGen/SelectionDAG.h2
-rw-r--r--llvm/include/llvm/CodeGen/SelectionDAGNodes.h116
2 files changed, 61 insertions, 57 deletions
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index 89ef4b8f5a6..9d6753d04d0 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -670,7 +670,7 @@ public:
SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT,
ArrayRef<SDUse> Ops);
SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT,
- ArrayRef<SDValue> Ops);
+ ArrayRef<SDValue> Ops, const SDNodeFlags *Flags = nullptr);
SDValue getNode(unsigned Opcode, SDLoc DL, ArrayRef<EVT> ResultTys,
ArrayRef<SDValue> Ops);
SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs,
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index eefa76d37d6..2a5c32bd0c6 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -44,6 +44,7 @@ class GlobalValue;
class MachineBasicBlock;
class MachineConstantPoolValue;
class SDNode;
+class BinaryWithFlagsSDNode;
class Value;
class MCSymbol;
template <typename T> struct DenseMapInfo;
@@ -319,6 +320,61 @@ template<> struct simplify_type<SDUse> {
}
};
+/// These are IR-level optimization flags that may be propagated to SDNodes.
+/// TODO: This data structure should be shared by the IR optimizer and the
+/// the backend.
+struct SDNodeFlags {
+private:
+ bool NoUnsignedWrap : 1;
+ bool NoSignedWrap : 1;
+ bool Exact : 1;
+ bool UnsafeAlgebra : 1;
+ bool NoNaNs : 1;
+ bool NoInfs : 1;
+ bool NoSignedZeros : 1;
+ bool AllowReciprocal : 1;
+
+public:
+ /// Default constructor turns off all optimization flags.
+ SDNodeFlags() {
+ NoUnsignedWrap = false;
+ NoSignedWrap = false;
+ Exact = false;
+ UnsafeAlgebra = false;
+ NoNaNs = false;
+ NoInfs = false;
+ NoSignedZeros = false;
+ AllowReciprocal = false;
+ }
+
+ // These are mutators for each flag.
+ void setNoUnsignedWrap(bool b) { NoUnsignedWrap = b; }
+ void setNoSignedWrap(bool b) { NoSignedWrap = b; }
+ void setExact(bool b) { Exact = b; }
+ void setUnsafeAlgebra(bool b) { UnsafeAlgebra = b; }
+ void setNoNaNs(bool b) { NoNaNs = b; }
+ void setNoInfs(bool b) { NoInfs = b; }
+ void setNoSignedZeros(bool b) { NoSignedZeros = b; }
+ void setAllowReciprocal(bool b) { AllowReciprocal = b; }
+
+ // These are accessors for each flag.
+ bool hasNoUnsignedWrap() const { return NoUnsignedWrap; }
+ bool hasNoSignedWrap() const { return NoSignedWrap; }
+ bool hasExact() const { return Exact; }
+ bool hasUnsafeAlgebra() const { return UnsafeAlgebra; }
+ bool hasNoNaNs() const { return NoNaNs; }
+ bool hasNoInfs() const { return NoInfs; }
+ bool hasNoSignedZeros() const { return NoSignedZeros; }
+ bool hasAllowReciprocal() const { return AllowReciprocal; }
+
+ /// Return a raw encoding of the flags.
+ /// This function should only be used to add data to the NodeID value.
+ unsigned getRawFlags() const {
+ return (NoUnsignedWrap << 0) | (NoSignedWrap << 1) | (Exact << 2) |
+ (UnsafeAlgebra << 3) | (NoNaNs << 4) | (NoInfs << 5) |
+ (NoSignedZeros << 6) | (AllowReciprocal << 7);
+ }
+};
/// Represents one node in the SelectionDAG.
///
@@ -639,6 +695,10 @@ public:
return nullptr;
}
+ /// This could be defined as a virtual function and implemented more simply
+ /// and directly, but it is not to avoid creating a vtable for this class.
+ const SDNodeFlags *getFlags() const;
+
/// Return the number of values defined/returned by this operator.
unsigned getNumValues() const { return NumValues; }
@@ -950,62 +1010,6 @@ inline void SDUse::setNode(SDNode *N) {
if (N) N->addUse(*this);
}
-/// These are IR-level optimization flags that may be propagated to SDNodes.
-/// TODO: This data structure should be shared by the IR optimizer and the
-/// the backend.
-struct SDNodeFlags {
-private:
- bool NoUnsignedWrap : 1;
- bool NoSignedWrap : 1;
- bool Exact : 1;
- bool UnsafeAlgebra : 1;
- bool NoNaNs : 1;
- bool NoInfs : 1;
- bool NoSignedZeros : 1;
- bool AllowReciprocal : 1;
-
-public:
- /// Default constructor turns off all optimization flags.
- SDNodeFlags() {
- NoUnsignedWrap = false;
- NoSignedWrap = false;
- Exact = false;
- UnsafeAlgebra = false;
- NoNaNs = false;
- NoInfs = false;
- NoSignedZeros = false;
- AllowReciprocal = false;
- }
-
- // These are mutators for each flag.
- void setNoUnsignedWrap(bool b) { NoUnsignedWrap = b; }
- void setNoSignedWrap(bool b) { NoSignedWrap = b; }
- void setExact(bool b) { Exact = b; }
- void setUnsafeAlgebra(bool b) { UnsafeAlgebra = b; }
- void setNoNaNs(bool b) { NoNaNs = b; }
- void setNoInfs(bool b) { NoInfs = b; }
- void setNoSignedZeros(bool b) { NoSignedZeros = b; }
- void setAllowReciprocal(bool b) { AllowReciprocal = b; }
-
- // These are accessors for each flag.
- bool hasNoUnsignedWrap() const { return NoUnsignedWrap; }
- bool hasNoSignedWrap() const { return NoSignedWrap; }
- bool hasExact() const { return Exact; }
- bool hasUnsafeAlgebra() const { return UnsafeAlgebra; }
- bool hasNoNaNs() const { return NoNaNs; }
- bool hasNoInfs() const { return NoInfs; }
- bool hasNoSignedZeros() const { return NoSignedZeros; }
- bool hasAllowReciprocal() const { return AllowReciprocal; }
-
- /// Return a raw encoding of the flags.
- /// This function should only be used to add data to the NodeID value.
- unsigned getRawFlags() const {
- return (NoUnsignedWrap << 0) | (NoSignedWrap << 1) | (Exact << 2) |
- (UnsafeAlgebra << 3) | (NoNaNs << 4) | (NoInfs << 5) |
- (NoSignedZeros << 6) | (AllowReciprocal << 7);
- }
-};
-
/// This class is used for single-operand SDNodes. This is solely
/// to allow co-allocation of node operands with the node itself.
class UnarySDNode : public SDNode {
OpenPOWER on IntegriCloud