From e2007c9e7e58f66ad9976e89d83b3ea315b5dc93 Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi Date: Wed, 6 May 2015 14:03:12 +0000 Subject: [PATCH] Revert r236546, "propagate IR-level fast-math-flags to DAG nodes (NFC)" It caused undefined behavior. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236600 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/SelectionDAG.h | 10 ++- include/llvm/CodeGen/SelectionDAGNodes.h | 68 +++++++------- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 9 +- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 89 +++++++++++-------- .../SelectionDAG/SelectionDAGBuilder.cpp | 22 +---- lib/CodeGen/SelectionDAG/TargetLowering.cpp | 5 +- lib/Target/X86/X86ISelLowering.cpp | 5 +- 7 files changed, 99 insertions(+), 109 deletions(-) diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index b7873c0f0ed..10aaecb1de9 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -655,7 +655,7 @@ public: SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, - const SDNodeFlags *Flags = nullptr); + bool nuw = false, bool nsw = false, bool exact = false); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, SDValue N3); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, @@ -978,7 +978,8 @@ public: /// Get the specified node if it's already available, or else return NULL. SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTs, ArrayRef Ops, - const SDNodeFlags *Flags = nullptr); + bool nuw = false, bool nsw = false, + bool exact = false); /// Creates a SDDbgValue node. SDDbgValue *getDbgValue(MDNode *Var, MDNode *Expr, SDNode *N, unsigned R, @@ -1235,8 +1236,9 @@ private: void allnodes_clear(); - SDNode *GetSDNodeWithFlags(unsigned Opcode, SDLoc DL, SDVTList VTs, - ArrayRef Ops, const SDNodeFlags *Flags); + BinarySDNode *GetBinarySDNode(unsigned Opcode, SDLoc DL, SDVTList VTs, + SDValue N1, SDValue N2, bool nuw, bool nsw, + bool exact); /// List of non-single value types. FoldingSet VTListMap; diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 56434bf879a..179c3c03099 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -981,44 +981,6 @@ public: (NoSignedZeros << 6) | (AllowReciprocal << 7); } }; - -/// Returns true if the opcode is an operation with optional optimization flags. -static bool mayHaveOptimizationFlags(unsigned Opcode) { - switch (Opcode) { - case ISD::SDIV: - case ISD::UDIV: - case ISD::SRA: - case ISD::SRL: - case ISD::MUL: - case ISD::ADD: - case ISD::SUB: - case ISD::SHL: - case ISD::FADD: - case ISD::FDIV: - case ISD::FMUL: - case ISD::FREM: - case ISD::FSUB: - return true; - default: - return false; - } -} -/// This class is an extension of SDNode used from instructions that may have -/// associated extra flags. -class SDNodeWithFlags : public SDNode { -public: - SDNodeFlags Flags; - SDNodeWithFlags(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, - ArrayRef Ops, const SDNodeFlags &NodeFlags) - : SDNode(Opc, Order, dl, VTs, Ops) { - Flags = NodeFlags; - } - - // This is used to implement dyn_cast, isa, and other type queries. - static bool classof(const SDNode *N) { - return mayHaveOptimizationFlags(N->getOpcode()); - } -}; /// This class is used for single-operand SDNodes. This is solely /// to allow co-allocation of node operands with the node itself. @@ -1044,6 +1006,36 @@ public: } }; +/// Returns true if the opcode is a binary operation with flags. +static bool isBinOpWithFlags(unsigned Opcode) { + switch (Opcode) { + case ISD::SDIV: + case ISD::UDIV: + case ISD::SRA: + case ISD::SRL: + case ISD::MUL: + case ISD::ADD: + case ISD::SUB: + case ISD::SHL: + return true; + default: + return false; + } +} + +/// This class is an extension of BinarySDNode +/// used from those opcodes that have associated extra flags. +class BinaryWithFlagsSDNode : public BinarySDNode { +public: + SDNodeFlags Flags; + BinaryWithFlagsSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, + SDValue X, SDValue Y) + : BinarySDNode(Opc, Order, dl, VTs, X, Y), Flags() { } + static bool classof(const SDNode *N) { + return isBinOpWithFlags(N->getOpcode()); + } +}; + /// This class is used for three-operand SDNodes. This is solely /// to allow co-allocation of node operands with the node itself. class TernarySDNode : public SDNode { diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index c063d4f9a38..bf42aabeab2 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1452,9 +1452,12 @@ SDValue DAGCombiner::combine(SDNode *N) { if (isa(N0) || !isa(N1)) { SDValue Ops[] = {N1, N0}; SDNode *CSENode; - if (auto *FlagsNode = dyn_cast(N)) { - CSENode = DAG.getNodeIfExists(N->getOpcode(), N->getVTList(), - Ops, &FlagsNode->Flags); + if (const BinaryWithFlagsSDNode *BinNode = + dyn_cast(N)) { + CSENode = DAG.getNodeIfExists(N->getOpcode(), N->getVTList(), Ops, + BinNode->Flags.hasNoUnsignedWrap(), + BinNode->Flags.hasNoSignedWrap(), + BinNode->Flags.hasExact()); } else { CSENode = DAG.getNodeIfExists(N->getOpcode(), N->getVTList(), Ops); } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index d9a85369324..1dbbbaca77f 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -400,22 +400,18 @@ static void AddNodeIDOperands(FoldingSetNodeID &ID, } } -/// Add logical or fast math flag values to FoldingSetNodeID value. -static void AddNodeIDFlags(FoldingSetNodeID &ID, unsigned Opcode, - const SDNodeFlags *Flags) { - if (!Flags || !mayHaveOptimizationFlags(Opcode)) - return; - - unsigned RawFlags = Flags->getRawFlags(); - // If no flags are set, do not alter the ID. This saves time and allows - // a gradual increase in API usage of the optional optimization flags. - if (RawFlags != 0) - ID.AddInteger(RawFlags); +static void AddBinaryNodeIDCustom(FoldingSetNodeID &ID, bool nuw, bool nsw, + bool exact) { + ID.AddBoolean(nuw); + ID.AddBoolean(nsw); + ID.AddBoolean(exact); } -static void AddNodeIDFlags(FoldingSetNodeID &ID, const SDNode *N) { - if (auto *Node = dyn_cast(N)) - AddNodeIDFlags(ID, Node->getOpcode(), &Node->Flags); +/// AddBinaryNodeIDCustom - Add BinarySDNodes special infos +static void AddBinaryNodeIDCustom(FoldingSetNodeID &ID, unsigned Opcode, + bool nuw, bool nsw, bool exact) { + if (isBinOpWithFlags(Opcode)) + AddBinaryNodeIDCustom(ID, nuw, nsw, exact); } static void AddNodeIDNode(FoldingSetNodeID &ID, unsigned short OpC, @@ -510,6 +506,21 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) { ID.AddInteger(ST->getPointerInfo().getAddrSpace()); break; } + case ISD::SDIV: + case ISD::UDIV: + case ISD::SRA: + case ISD::SRL: + case ISD::MUL: + case ISD::ADD: + case ISD::SUB: + case ISD::SHL: { + const BinaryWithFlagsSDNode *BinNode = cast(N); + AddBinaryNodeIDCustom(ID, N->getOpcode(), + BinNode->Flags.hasNoUnsignedWrap(), + BinNode->Flags.hasNoSignedWrap(), + BinNode->Flags.hasExact()); + break; + } case ISD::ATOMIC_CMP_SWAP: case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS: case ISD::ATOMIC_SWAP: @@ -553,8 +564,6 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) { } } // end switch (N->getOpcode()) - AddNodeIDFlags(ID, N); - // Target specific memory nodes could also have address spaces to check. if (N->isTargetMemoryOpcode()) ID.AddInteger(cast(N)->getPointerInfo().getAddrSpace()); @@ -949,22 +958,22 @@ void SelectionDAG::allnodes_clear() { DeallocateNode(AllNodes.begin()); } -SDNode *SelectionDAG::GetSDNodeWithFlags(unsigned Opcode, SDLoc DL, - SDVTList VTs, ArrayRef Ops, - const SDNodeFlags *Flags) { - if (mayHaveOptimizationFlags(Opcode)) { - // If no flags were passed in, use a default flags object. - SDNodeFlags F; - if (Flags == nullptr) - Flags = &F; +BinarySDNode *SelectionDAG::GetBinarySDNode(unsigned Opcode, SDLoc DL, + SDVTList VTs, SDValue N1, + SDValue N2, bool nuw, bool nsw, + bool exact) { + if (isBinOpWithFlags(Opcode)) { + BinaryWithFlagsSDNode *FN = new (NodeAllocator) BinaryWithFlagsSDNode( + Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs, N1, N2); + FN->Flags.setNoUnsignedWrap(nuw); + FN->Flags.setNoSignedWrap(nsw); + FN->Flags.setExact(exact); - SDNodeWithFlags *NodeWithFlags = new (NodeAllocator) SDNodeWithFlags( - Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs, Ops, *Flags); - return NodeWithFlags; + return FN; } - SDNode *N = new (NodeAllocator) SDNode(Opcode, DL.getIROrder(), - DL.getDebugLoc(), VTs, Ops); + BinarySDNode *N = new (NodeAllocator) + BinarySDNode(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs, N1, N2); return N; } @@ -3192,7 +3201,7 @@ SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode, SDLoc DL, EVT VT, } SDValue SelectionDAG::getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, - SDValue N2, const SDNodeFlags *Flags) { + SDValue N2, bool nuw, bool nsw, bool exact) { ConstantSDNode *N1C = dyn_cast(N1.getNode()); ConstantSDNode *N2C = dyn_cast(N2.getNode()); switch (Opcode) { @@ -3654,23 +3663,24 @@ SDValue SelectionDAG::getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, } // Memoize this node if possible. - SDNode *N; + BinarySDNode *N; SDVTList VTs = getVTList(VT); - SDValue Ops[] = { N1, N2 }; + const bool BinOpHasFlags = isBinOpWithFlags(Opcode); if (VT != MVT::Glue) { SDValue Ops[] = {N1, N2}; FoldingSetNodeID ID; AddNodeIDNode(ID, Opcode, VTs, Ops); - AddNodeIDFlags(ID, Opcode, Flags); + if (BinOpHasFlags) + AddBinaryNodeIDCustom(ID, Opcode, nuw, nsw, exact); void *IP = nullptr; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); - N = GetSDNodeWithFlags(Opcode, DL, VTs, Ops, Flags); - + N = GetBinarySDNode(Opcode, DL, VTs, N1, N2, nuw, nsw, exact); + CSEMap.InsertNode(N, IP); } else { - N = GetSDNodeWithFlags(Opcode, DL, VTs, Ops, Flags); + N = GetBinarySDNode(Opcode, DL, VTs, N1, N2, nuw, nsw, exact); } InsertNode(N); @@ -5974,12 +5984,13 @@ SelectionDAG::getTargetInsertSubreg(int SRIdx, SDLoc DL, EVT VT, /// getNodeIfExists - Get the specified node if it's already available, or /// else return NULL. SDNode *SelectionDAG::getNodeIfExists(unsigned Opcode, SDVTList VTList, - ArrayRef Ops, - const SDNodeFlags *Flags) { + ArrayRef Ops, bool nuw, bool nsw, + bool exact) { if (VTList.VTs[VTList.NumVTs - 1] != MVT::Glue) { FoldingSetNodeID ID; AddNodeIDNode(ID, Opcode, VTList, Ops); - AddNodeIDFlags(ID, Opcode, Flags); + if (isBinOpWithFlags(Opcode)) + AddBinaryNodeIDCustom(ID, nuw, nsw, exact); void *IP = nullptr; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return E; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 575f4bd22b4..d0bda11eb05 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2139,8 +2139,6 @@ void SelectionDAGBuilder::visitBinary(const User &I, unsigned OpCode) { bool nuw = false; bool nsw = false; bool exact = false; - FastMathFlags FMF; - if (const OverflowingBinaryOperator *OFBinOp = dyn_cast(&I)) { nuw = OFBinOp->hasNoUnsignedWrap(); @@ -2150,20 +2148,8 @@ void SelectionDAGBuilder::visitBinary(const User &I, unsigned OpCode) { dyn_cast(&I)) exact = ExactOp->isExact(); - if (const FPMathOperator *FPOp = dyn_cast(&I)) - FMF = FPOp->getFastMathFlags(); - - SDNodeFlags Flags; - Flags.setAllowReciprocal(FMF.allowReciprocal()); - Flags.setExact(exact); - Flags.setNoInfs(FMF.noInfs()); - Flags.setNoNaNs(FMF.noNaNs()); - Flags.setNoSignedWrap(nsw); - Flags.setNoSignedZeros(FMF.noSignedZeros()); - Flags.setNoUnsignedWrap(nuw); - Flags.setUnsafeAlgebra(FMF.unsafeAlgebra()); SDValue BinNodeValue = DAG.getNode(OpCode, getCurSDLoc(), Op1.getValueType(), - Op1, Op2, &Flags); + Op1, Op2, nuw, nsw, exact); setValue(&I, BinNodeValue); } @@ -2212,12 +2198,8 @@ void SelectionDAGBuilder::visitShift(const User &I, unsigned Opcode) { exact = ExactOp->isExact(); } - SDNodeFlags Flags; - Flags.setExact(exact); - Flags.setNoSignedWrap(nsw); - Flags.setNoUnsignedWrap(nuw); SDValue Res = DAG.getNode(Opcode, getCurSDLoc(), Op1.getValueType(), Op1, Op2, - &Flags); + nuw, nsw, exact); setValue(&I, Res); } diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 6f22f425449..34ddeb7e9c3 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -2660,9 +2660,8 @@ SDValue TargetLowering::BuildExactSDIV(SDValue Op1, SDValue Op2, SDLoc dl, // TODO: For UDIV use SRL instead of SRA. SDValue Amt = DAG.getConstant(ShAmt, dl, getShiftAmountTy(Op1.getValueType())); - SDNodeFlags Flags; - Flags.setExact(true); - Op1 = DAG.getNode(ISD::SRA, dl, Op1.getValueType(), Op1, Amt, &Flags); + Op1 = DAG.getNode(ISD::SRA, dl, Op1.getValueType(), Op1, Amt, false, false, + true); d = d.ashr(ShAmt); } diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index e2c427d2269..49f0a8a73bf 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -12561,8 +12561,9 @@ SDValue X86TargetLowering::EmitTest(SDValue Op, unsigned X86CC, SDLoc dl, case ISD::SUB: case ISD::MUL: case ISD::SHL: { - const SDNodeWithFlags *Node = cast(Op.getNode()); - if (Node->Flags.hasNoSignedWrap()) + const BinaryWithFlagsSDNode *BinNode = + cast(Op.getNode()); + if (BinNode->Flags.hasNoSignedWrap()) break; } default: -- 2.34.1