diff options
author | Tanya Lattner <tonic@nondot.org> | 2009-02-03 05:07:10 +0000 |
---|---|---|
committer | Tanya Lattner <tonic@nondot.org> | 2009-02-03 05:07:10 +0000 |
commit | 682ae9aa345df80fab3180fd494c99853e7de436 (patch) | |
tree | ff9e30cb68f18ffd4e6a5061fd8c1b64da01a298 /lib/CodeGen/SelectionDAG/SelectionDAG.cpp | |
parent | 254a6e0c63b22de9ddca2fadbeb335abd9735920 (diff) | |
parent | dac5c4b10b387b55c2394cd98a64f3f1394df2e8 (diff) |
Create 2.5 branch.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_25@63604 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/SelectionDAG.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 1298 |
1 files changed, 946 insertions, 352 deletions
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index e3fcc2c216..c34211505a 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -342,8 +342,8 @@ static void AddNodeIDOperands(FoldingSetNodeID &ID, static void AddNodeIDOperands(FoldingSetNodeID &ID, const SDUse *Ops, unsigned NumOps) { for (; NumOps; --NumOps, ++Ops) { - ID.AddPointer(Ops->getVal()); - ID.AddInteger(Ops->getSDValue().getResNo()); + ID.AddPointer(Ops->getNode()); + ID.AddInteger(Ops->getResNo()); } } @@ -429,18 +429,14 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) { } case ISD::LOAD: { const LoadSDNode *LD = cast<LoadSDNode>(N); - ID.AddInteger(LD->getAddressingMode()); - ID.AddInteger(LD->getExtensionType()); ID.AddInteger(LD->getMemoryVT().getRawBits()); - ID.AddInteger(LD->getRawFlags()); + ID.AddInteger(LD->getRawSubclassData()); break; } case ISD::STORE: { const StoreSDNode *ST = cast<StoreSDNode>(N); - ID.AddInteger(ST->getAddressingMode()); - ID.AddInteger(ST->isTruncatingStore()); ID.AddInteger(ST->getMemoryVT().getRawBits()); - ID.AddInteger(ST->getRawFlags()); + ID.AddInteger(ST->getRawSubclassData()); break; } case ISD::ATOMIC_CMP_SWAP: @@ -456,7 +452,8 @@ static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) { case ISD::ATOMIC_LOAD_UMIN: case ISD::ATOMIC_LOAD_UMAX: { const AtomicSDNode *AT = cast<AtomicSDNode>(N); - ID.AddInteger(AT->getRawFlags()); + ID.AddInteger(AT->getMemoryVT().getRawBits()); + ID.AddInteger(AT->getRawSubclassData()); break; } } // end switch (N->getOpcode()) @@ -476,11 +473,20 @@ static void AddNodeIDNode(FoldingSetNodeID &ID, const SDNode *N) { } /// encodeMemSDNodeFlags - Generic routine for computing a value for use in -/// the CSE map that carries both alignment and volatility information. +/// the CSE map that carries alignment, volatility, indexing mode, and +/// extension/truncation information. /// static inline unsigned -encodeMemSDNodeFlags(bool isVolatile, unsigned Alignment) { - return isVolatile | ((Log2_32(Alignment) + 1) << 1); +encodeMemSDNodeFlags(int ConvType, ISD::MemIndexedMode AM, + bool isVolatile, unsigned Alignment) { + assert((ConvType & 3) == ConvType && + "ConvType may not require more than 2 bits!"); + assert((AM & 7) == AM && + "AM may not require more than 3 bits!"); + return ConvType | + (AM << 2) | + (isVolatile << 5) | + ((Log2_32(Alignment) + 1) << 6); } //===----------------------------------------------------------------------===// @@ -538,8 +544,7 @@ void SelectionDAG::RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes, // Process the worklist, deleting the nodes and adding their uses to the // worklist. while (!DeadNodes.empty()) { - SDNode *N = DeadNodes.back(); - DeadNodes.pop_back(); + SDNode *N = DeadNodes.pop_back_val(); if (UpdateListener) UpdateListener->NodeDeleted(N, 0); @@ -549,10 +554,11 @@ void SelectionDAG::RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes, // Next, brutally remove the operand list. This is safe to do, as there are // no cycles in the graph. - for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) { - SDNode *Operand = I->getVal(); - Operand->removeUser(std::distance(N->op_begin(), I), N); - + for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ) { + SDUse &Use = *I++; + SDNode *Operand = Use.getNode(); + Use.set(SDValue()); + // Now that we removed this operand, see if there are no uses of it left. if (Operand->use_empty()) DeadNodes.push_back(Operand); @@ -568,8 +574,6 @@ void SelectionDAG::RemoveDeadNode(SDNode *N, DAGUpdateListener *UpdateListener){ } void SelectionDAG::DeleteNode(SDNode *N) { - assert(N->use_empty() && "Cannot delete a node that is not dead!"); - // First take this out of the appropriate CSE map. RemoveNodeFromCSEMaps(N); @@ -579,11 +583,11 @@ void SelectionDAG::DeleteNode(SDNode *N) { } void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *N) { - assert(N != AllNodes.begin()); + assert(N != AllNodes.begin() && "Cannot delete the entry node!"); + assert(N->use_empty() && "Cannot delete a node that is not dead!"); // Drop all of the operands and decrement used node's use counts. - for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) - I->getVal()->removeUser(std::distance(N->op_begin(), I), N); + N->DropOperands(); DeallocateNode(N); } @@ -652,20 +656,36 @@ bool SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) { return Erased; } -/// AddNonLeafNodeToCSEMaps - Add the specified node back to the CSE maps. It -/// has been taken out and modified in some way. If the specified node already -/// exists in the CSE maps, do not modify the maps, but return the existing node -/// instead. If it doesn't exist, add it and return null. +/// AddModifiedNodeToCSEMaps - The specified node has been removed from the CSE +/// maps and modified in place. Add it back to the CSE maps, unless an identical +/// node already exists, in which case transfer all its users to the existing +/// node. This transfer can potentially trigger recursive merging. /// -SDNode *SelectionDAG::AddNonLeafNodeToCSEMaps(SDNode *N) { - assert(N->getNumOperands() && "This is a leaf node!"); - - if (doNotCSE(N)) - return 0; +void +SelectionDAG::AddModifiedNodeToCSEMaps(SDNode *N, + DAGUpdateListener *UpdateListener) { + // For node types that aren't CSE'd, just act as if no identical node + // already exists. + if (!doNotCSE(N)) { + SDNode *Existing = CSEMap.GetOrInsertNode(N); + if (Existing != N) { + // If there was already an existing matching node, use ReplaceAllUsesWith + // to replace the dead one with the existing one. This can cause + // recursive merging of other unrelated nodes down the line. + ReplaceAllUsesWith(N, Existing, UpdateListener); + + // N is now dead. Inform the listener if it exists and delete it. + if (UpdateListener) + UpdateListener->NodeDeleted(N, Existing); + DeleteNodeNotInCSEMaps(N); + return; + } + } - SDNode *New = CSEMap.GetOrInsertNode(N); - if (New != N) return New; // Node already existed. - return 0; + // If the node doesn't already exist, we updated it. Inform a listener if + // it exists. + if (UpdateListener) + UpdateListener->NodeUpdated(N); } /// FindModifiedNodeSlot - Find a slot for the specified node if its operands @@ -748,7 +768,7 @@ void SelectionDAG::VerifyNode(SDNode *N) { // following checks at least makes it possible to legalize most of the time. // MVT EltVT = N->getValueType(0).getVectorElementType(); // for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) -// assert(I->getSDValue().getValueType() == EltVT && +// assert(I->getValueType() == EltVT && // "Wrong operand type!"); break; } @@ -804,7 +824,7 @@ void SelectionDAG::clear() { std::fill(ValueTypeNodes.begin(), ValueTypeNodes.end(), static_cast<SDNode*>(0)); - EntryNode.Uses = 0; + EntryNode.UseList = 0; AllNodes.push_back(&EntryNode); Root = getEntryNode(); } @@ -817,8 +837,35 @@ SDValue SelectionDAG::getZeroExtendInReg(SDValue Op, MVT VT) { getConstant(Imm, Op.getValueType())); } +SDValue SelectionDAG::getZeroExtendInReg(SDValue Op, DebugLoc DL, MVT VT) { + if (Op.getValueType() == VT) return Op; + APInt Imm = APInt::getLowBitsSet(Op.getValueSizeInBits(), + VT.getSizeInBits()); + return getNode(ISD::AND, DL, Op.getValueType(), Op, + getConstant(Imm, Op.getValueType())); +} + +/// getNOT - Create a bitwise NOT operation as (XOR Val, -1). +/// +SDValue SelectionDAG::getNOT(DebugLoc DL, SDValue Val, MVT VT) { + SDValue NegOne; + if (VT.isVector()) { + MVT EltVT = VT.getVectorElementType(); + SDValue NegOneElt = + getConstant(APInt::getAllOnesValue(EltVT.getSizeInBits()), EltVT); + std::vector<SDValue> NegOnes(VT.getVectorNumElements(), NegOneElt); + NegOne = getNode(ISD::BUILD_VECTOR, DL, VT, &NegOnes[0], NegOnes.size()); + } else { + NegOne = getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), VT); + } + return getNode(ISD::XOR, DL, VT, Val, NegOne); +} + SDValue SelectionDAG::getConstant(uint64_t Val, MVT VT, bool isT) { MVT EltVT = VT.isVector() ? VT.getVectorElementType() : VT; + assert((EltVT.getSizeInBits() >= 64 || + (uint64_t)((int64_t)Val >> EltVT.getSizeInBits()) + 1 < 2) && + "getConstant with a uint64_t value that doesn't fit in the type!"); return getConstant(APInt(EltVT.getSizeInBits(), Val), VT, isT); } @@ -938,7 +985,7 @@ SDValue SelectionDAG::getGlobalAddress(const GlobalValue *GV, ID.AddInteger(Offset); void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) - return SDValue(E, 0); + return SDValue(E, 0); SDNode *N = NodeAllocator.Allocate<GlobalAddressSDNode>(); new (N) GlobalAddressSDNode(isTargetGA, GV, VT, Offset); CSEMap.InsertNode(N, IP); @@ -1036,6 +1083,20 @@ SDValue SelectionDAG::getBasicBlock(MachineBasicBlock *MBB) { return SDValue(N, 0); } +SDValue SelectionDAG::getBasicBlock(MachineBasicBlock *MBB, DebugLoc dl) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::BasicBlock, getVTList(MVT::Other), 0, 0); + ID.AddPointer(MBB); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate<BasicBlockSDNode>(); + new (N) BasicBlockSDNode(MBB, dl); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + SDValue SelectionDAG::getArgFlags(ISD::ArgFlagsTy Flags) { FoldingSetNodeID ID; AddNodeIDNode(ID, ISD::ARG_FLAGS, getVTList(MVT::Other), 0, 0); @@ -1073,6 +1134,15 @@ SDValue SelectionDAG::getExternalSymbol(const char *Sym, MVT VT) { return SDValue(N, 0); } +SDValue SelectionDAG::getExternalSymbol(const char *Sym, DebugLoc dl, MVT VT) { + SDNode *&N = ExternalSymbols[Sym]; + if (N) return SDValue(N, 0); + N = NodeAllocator.Allocate<ExternalSymbolSDNode>(); + new (N) ExternalSymbolSDNode(false, dl, Sym, VT); + AllNodes.push_back(N); + return SDValue(N, 0); +} + SDValue SelectionDAG::getTargetExternalSymbol(const char *Sym, MVT VT) { SDNode *&N = TargetExternalSymbols[Sym]; if (N) return SDValue(N, 0); @@ -1082,6 +1152,16 @@ SDValue SelectionDAG::getTargetExternalSymbol(const char *Sym, MVT VT) { return SDValue(N, 0); } +SDValue SelectionDAG::getTargetExternalSymbol(const char *Sym, DebugLoc dl, + MVT VT) { + SDNode *&N = TargetExternalSymbols[Sym]; + if (N) return SDValue(N, 0); + N = NodeAllocator.Allocate<ExternalSymbolSDNode>(); + new (N) ExternalSymbolSDNode(true, dl, Sym, VT); + AllNodes.push_back(N); + return SDValue(N, 0); +} + SDValue SelectionDAG::getCondCode(ISD::CondCode Cond) { if ((unsigned)Cond >= CondCodeNodes.size()) CondCodeNodes.resize(Cond+1); @@ -1154,6 +1234,23 @@ SDValue SelectionDAG::getLabel(unsigned Opcode, return SDValue(N, 0); } +SDValue SelectionDAG::getLabel(unsigned Opcode, DebugLoc dl, + SDValue Root, + unsigned LabelID) { + FoldingSetNodeID ID; + SDValue Ops[] = { Root }; + AddNodeIDNode(ID, Opcode, getVTList(MVT::Other), &Ops[0], 1); + ID.AddInteger(LabelID); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate<LabelSDNode>(); + new (N) LabelSDNode(Opcode, dl, Root, LabelID); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + SDValue SelectionDAG::getSrcValue(const Value *V) { assert((!V || isa<PointerType>(V->getType())) && "SrcValue is not a pointer?"); @@ -1195,6 +1292,17 @@ SDValue SelectionDAG::getMemOperand(const MachineMemOperand &MO) { return SDValue(N, 0); } +/// getShiftAmountOperand - Return the specified value casted to +/// the target's desired shift amount type. +SDValue SelectionDAG::getShiftAmountOperand(SDValue Op) { + MVT OpTy = Op.getValueType(); + MVT ShTy = TLI.getShiftAmountTy(); + if (OpTy == ShTy || OpTy.isVector()) return Op; + + ISD::NodeType Opcode = OpTy.bitsGT(ShTy) ? ISD::TRUNCATE : ISD::ZERO_EXTEND; + return getNode(Opcode, ShTy, Op); +} + /// CreateStackTemporary - Create a stack temporary, suitable for holding the /// specified value type. SDValue SelectionDAG::CreateStackTemporary(MVT VT, unsigned minAlign) { @@ -1225,7 +1333,7 @@ SDValue SelectionDAG::CreateStackTemporary(MVT VT1, MVT VT2) { } SDValue SelectionDAG::FoldSetCC(MVT VT, SDValue N1, - SDValue N2, ISD::CondCode Cond) { + SDValue N2, ISD::CondCode Cond, DebugLoc dl) { // These setcc operations always fold. switch (Cond) { default: break; @@ -1278,29 +1386,29 @@ SDValue SelectionDAG::FoldSetCC(MVT VT, SDValue N1, switch (Cond) { default: break; case ISD::SETEQ: if (R==APFloat::cmpUnordered) - return getNode(ISD::UNDEF, VT); + return getNode(ISD::UNDEF, dl, VT); // fall through case ISD::SETOEQ: return getConstant(R==APFloat::cmpEqual, VT); case ISD::SETNE: if (R==APFloat::cmpUnordered) - return getNode(ISD::UNDEF, VT); + return getNode(ISD::UNDEF, dl, VT); // fall through case ISD::SETONE: return getConstant(R==APFloat::cmpGreaterThan || R==APFloat::cmpLessThan, VT); case ISD::SETLT: if (R==APFloat::cmpUnordered) - return getNode(ISD::UNDEF, VT); + return getNode(ISD::UNDEF, dl, VT); // fall through case ISD::SETOLT: return getConstant(R==APFloat::cmpLessThan, VT); case ISD::SETGT: if (R==APFloat::cmpUnordered) - return getNode(ISD::UNDEF, VT); + return getNode(ISD::UNDEF, dl, VT); // fall through case ISD::SETOGT: return getConstant(R==APFloat::cmpGreaterThan, VT); case ISD::SETLE: if (R==APFloat::cmpUnordered) - return getNode(ISD::UNDEF, VT); + return getNode(ISD::UNDEF, dl, VT); // fall through case ISD::SETOLE: return getConstant(R==APFloat::cmpLessThan || R==APFloat::cmpEqual, VT); case ISD::SETGE: if (R==APFloat::cmpUnordered) - return getNode(ISD::UNDEF, VT); + return getNode(ISD::UNDEF, dl, VT); // fall through case ISD::SETOGE: return getConstant(R==APFloat::cmpGreaterThan || R==APFloat::cmpEqual, VT); @@ -1318,7 +1426,7 @@ SDValue SelectionDAG::FoldSetCC(MVT VT, SDValue N1, } } else { // Ensure that the constant occurs on the RHS. - return getSetCC(VT, N2, N1, ISD::getSetCCSwappedOperands(Cond)); + return getSetCC(dl, VT, N2, N1, ISD::getSetCCSwappedOperands(Cond)); } } @@ -2041,10 +2149,11 @@ bool SelectionDAG::isVerifiedDebugInfoDesc(SDValue Op) const { /// element of the result of the vector shuffle. SDValue SelectionDAG::getShuffleScalarElt(const SDNode *N, unsigned i) { MVT VT = N->getValueType(0); + DebugLoc dl = N->getDebugLoc(); SDValue PermMask = N->getOperand(2); SDValue Idx = PermMask.getOperand(i); if (Idx.getOpcode() == ISD::UNDEF) - return getNode(ISD::UNDEF, VT.getVectorElementType()); + return getNode(ISD::UNDEF, dl, VT.getVectorElementType()); unsigned Index = cast<ConstantSDNode>(Idx)->getZExtValue(); unsigned NumElems = PermMask.getNumOperands(); SDValue V = (Index < NumElems) ? N->getOperand(0) : N->getOperand(1); @@ -2058,7 +2167,7 @@ SDValue SelectionDAG::getShuffleScalarElt(const SDNode *N, unsigned i) { } if (V.getOpcode() == ISD::SCALAR_TO_VECTOR) return (Index == 0) ? V.getOperand(0) - : getNode(ISD::UNDEF, VT.getVectorElementType()); + : getNode(ISD::UNDEF, dl, VT.getVectorElementType()); if (V.getOpcode() == ISD::BUILD_VECTOR) return V.getOperand(Index); if (V.getOpcode() == ISD::VECTOR_SHUFFLE) @@ -2070,13 +2179,17 @@ SDValue SelectionDAG::getShuffleScalarElt(const SDNode *N, unsigned i) { /// getNode - Gets or creates the specified node. /// SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT) { + return getNode(Opcode, DebugLoc::getUnknownLoc(), VT); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, MVT VT) { FoldingSetNodeID ID; AddNodeIDNode(ID, Opcode, getVTList(VT), 0, 0); void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); SDNode *N = NodeAllocator.Allocate<SDNode>(); - new (N) SDNode(Opcode, SDNode::getSDVTList(VT)); + new (N) SDNode(Opcode, DL, SDNode::getSDVTList(VT)); CSEMap.InsertNode(N, IP); AllNodes.push_back(N); @@ -2087,6 +2200,11 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT) { } SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue Operand) { + return getNode(Opcode, DebugLoc::getUnknownLoc(), VT, Operand); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, + MVT VT, SDValue Operand) { // Constant fold unary operations with an integer constant operand. if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Operand.getNode())) { const APInt &Val = C->getAPIntValue(); @@ -2183,7 +2301,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue Operand) { Operand.getValueType().isFloatingPoint() && "Invalid FP cast!"); if (Operand.getValueType() == VT) return Operand; // noop conversion. if (Operand.getOpcode() == ISD::UNDEF) - return getNode(ISD::UNDEF, VT); + return getNode(ISD::UNDEF, DL, VT); break; case ISD::SIGN_EXTEND: assert(VT.isInteger() && Operand.getValueType().isInteger() && @@ -2192,7 +2310,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue Operand) { assert(Operand.getValueType().bitsLT(VT) && "Invalid sext node, dst < src!"); if (OpOpcode == ISD::SIGN_EXTEND || OpOpcode == ISD::ZERO_EXTEND) - return getNode(OpOpcode, VT, Operand.getNode()->getOperand(0)); + return getNode(OpOpcode, DL, VT, Operand.getNode()->getOperand(0)); break; case ISD::ZERO_EXTEND: assert(VT.isInteger() && Operand.getValueType().isInteger() && @@ -2201,7 +2319,8 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue Operand) { assert(Operand.getValueType().bitsLT(VT) && "Invalid zext node, dst < src!"); if (OpOpcode == ISD::ZERO_EXTEND) // (zext (zext x)) -> (zext x) - return getNode(ISD::ZERO_EXTEND, VT, Operand.getNode()->getOperand(0)); + return getNode(ISD::ZERO_EXTEND, DL, VT, + Operand.getNode()->getOperand(0)); break; case ISD::ANY_EXTEND: assert(VT.isInteger() && Operand.getValueType().isInteger() && @@ -2211,7 +2330,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue Operand) { && "Invalid anyext node, dst < src!"); if (OpOpcode == ISD::ZERO_EXTEND || OpOpcode == ISD::SIGN_EXTEND) // (ext (zext x)) -> (zext x) and (ext (sext x)) -> (sext x) - return getNode(OpOpcode, VT, Operand.getNode()->getOperand(0)); + return getNode(OpOpcode, DL, VT, Operand.getNode()->getOperand(0)); break; case ISD::TRUNCATE: assert(VT.isInteger() && Operand.getValueType().isInteger() && @@ -2220,14 +2339,14 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue Operand) { assert(Operand.getValueType().bitsGT(VT) && "Invalid truncate node, src < dst!"); if (OpOpcode == ISD::TRUNCATE) - return getNode(ISD::TRUNCATE, VT, Operand.getNode()->getOperand(0)); + return getNode(ISD::TRUNCATE, DL, VT, Operand.getNode()->getOperand(0)); else if (OpOpcode == ISD::ZERO_EXTEND || OpOpcode == ISD::SIGN_EXTEND || OpOpcode == ISD::ANY_EXTEND) { // If the source is smaller than the dest, we still need an extend. if (Operand.getNode()->getOperand(0).getValueType().bitsLT(VT)) - return getNode(OpOpcode, VT, Operand.getNode()->getOperand(0)); + return getNode(OpOpcode, DL, VT, Operand.getNode()->getOperand(0)); else if (Operand.getNode()->getOperand(0).getValueType().bitsGT(VT)) - return getNode(ISD::TRUNCATE, VT, Operand.getNode()->getOperand(0)); + return getNode(ISD::TRUNCATE, DL, VT, Operand.getNode()->getOperand(0)); else return Operand.getNode()->getOperand(0); } @@ -2238,16 +2357,16 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue Operand) { && "Cannot BIT_CONVERT between types of different sizes!"); if (VT == Operand.getValueType()) return Operand; // noop conversion. if (OpOpcode == ISD::BIT_CONVERT) // bitconv(bitconv(x)) -> bitconv(x) - return getNode(ISD::BIT_CONVERT, VT, Operand.getOperand(0)); + return getNode(ISD::BIT_CONVERT, DL, VT, Operand.getOperand(0)); if (OpOpcode == ISD::UNDEF) - return getNode(ISD::UNDEF, VT); + return getNode(ISD::UNDEF, DL, VT); break; case ISD::SCALAR_TO_VECTOR: assert(VT.isVector() && !Operand.getValueType().isVector() && VT.getVectorElementType() == Operand.getValueType() && "Illegal SCALAR_TO_VECTOR node!"); if (OpOpcode == ISD::UNDEF) - return getNode(ISD::UNDEF, VT); + return getNode(ISD::UNDEF, DL, VT); // scalar_to_vector(extract_vector_elt V, 0) -> V, top bits are undefined. if (OpOpcode == ISD::EXTRACT_VECTOR_ELT && isa<ConstantSDNode>(Operand.getOperand(1)) && @@ -2256,15 +2375,16 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue Operand) { return Operand.getOperand(0); break; case ISD::FNEG: - if (OpOpcode == ISD::FSUB) // -(X-Y) -> (Y-X) - return getNode(ISD::FSUB, VT, Operand.getNode()->getOperand(1), + // -(X-Y) -> (Y-X) is unsafe because when X==Y, -0.0 != +0.0 + if (UnsafeFPMath && OpOpcode == ISD::FSUB) + return getNode(ISD::FSUB, DL, VT, Operand.getNode()->getOperand(1), Operand.getNode()->getOperand(0)); if (OpOpcode == ISD::FNEG) // --X -> X return Operand.getNode()->getOperand(0); break; case ISD::FABS: if (OpOpcode == ISD::FNEG) // abs(-X) -> abs(X) - return getNode(ISD::FABS, VT, Operand.getNode()->getOperand(0)); + return getNode(ISD::FABS, DL, VT, Operand.getNode()->getOperand(0)); break; } @@ -2278,11 +2398,11 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue Operand) { if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); N = NodeAllocator.Allocate<UnarySDNode>(); - new (N) UnarySDNode(Opcode, VTs, Operand); + new (N) UnarySDNode(Opcode, DL, VTs, Operand); CSEMap.InsertNode(N, IP); } else { N = NodeAllocator.Allocate<UnarySDNode>(); - new (N) UnarySDNode(Opcode, VTs, Operand); + new (N) UnarySDNode(Opcode, DL, VTs, Operand); } AllNodes.push_back(N); @@ -2330,6 +2450,11 @@ SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode, SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue N1, SDValue N2) { + return getNode(Opcode, DebugLoc::getUnknownLoc(), VT, N1, N2); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, MVT VT, + SDValue N1, SDValue N2) { ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.getNode()); ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2.getNode()); switch (Opcode) { @@ -2349,7 +2474,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, N2.getOpcode() == ISD::BUILD_VECTOR) { SmallVector<SDValue, 16> Elts(N1.getNode()->op_begin(), N1.getNode()->op_end()); Elts.insert(Elts.end(), N2.getNode()->op_begin(), N2.getNode()->op_end()); - return getNode(ISD::BUILD_VECTOR, VT, &Elts[0], Elts.size()); + return getNode(ISD::BUILD_VECTOR, DL, VT, &Elts[0], Elts.size()); } break; case ISD::AND: @@ -2422,9 +2547,6 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, "Shift operators return type must be the same as their first arg"); assert(VT.isInteger() && N2.getValueType().isInteger() && "Shifts only work on integers"); - assert((N2.getValueType() == TLI.getShiftAmountTy() || - (N2.getValueType().isVector() && N2.getValueType().isInteger())) && - "Wrong type for shift amount"); // Always fold shifts of i1 values so the code generator doesn't need to // handle them. Since we know the size of the shift has to be less than the @@ -2478,7 +2600,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, case ISD::EXTRACT_VECTOR_ELT: // EXTRACT_VECTOR_ELT of an UNDEF is an UNDEF. if (N1.getOpcode() == ISD::UNDEF) - return getNode(ISD::UNDEF, VT); + return getNode(ISD::UNDEF, DL, VT); // EXTRACT_VECTOR_ELT of CONCAT_VECTORS is often formed while lowering is // expanding copies of large vectors from registers. @@ -2487,7 +2609,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, N1.getNumOperands() > 0) { unsigned Factor = N1.getOperand(0).getValueType().getVectorNumElements(); - return getNode(ISD::EXTRACT_VECTOR_ELT, VT, + return getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, N1.getOperand(N2C->getZExtValue() / Factor), getConstant(N2C->getZExtValue() % Factor, N2.getValueType())); @@ -2501,10 +2623,14 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, // EXTRACT_VECTOR_ELT of INSERT_VECTOR_ELT is often formed when vector // operations are lowered to scalars. if (N1.getOpcode() == ISD::INSERT_VECTOR_ELT) { + // If the indices are the same, return the inserted element. if (N1.getOperand(2) == N2) return N1.getOperand(1); - else - return getNode(ISD::EXTRACT_VECTOR_ELT, VT, N1.getOperand(0), N2); + // If the indices are known different, extract the element from + // the original vector. + else if (isa<ConstantSDNode>(N1.getOperand(2)) && + isa<ConstantSDNode>(N2)) + return getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, N1.getOperand(0), N2); } break; case ISD::EXTRACT_ELEMENT: @@ -2653,7 +2779,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, return N1; case ISD::OR: if (!VT.isVector()) - return getConstant(VT.getIntegerVTBitMask(), VT); + return getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), VT); // For vectors, we can't easily build an all one vector, just return // the LHS. return N1; @@ -2673,11 +2799,11 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); N = NodeAllocator.Allocate<BinarySDNode>(); - new (N) BinarySDNode(Opcode, VTs, N1, N2); + new (N) BinarySDNode(Opcode, DL, VTs, N1, N2); CSEMap.InsertNode(N, IP); } else { N = NodeAllocator.Allocate<BinarySDNode>(); - new (N) BinarySDNode(Opcode, VTs, N1, N2); + new (N) BinarySDNode(Opcode, DL, VTs, N1, N2); } AllNodes.push_back(N); @@ -2689,6 +2815,11 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue N1, SDValue N2, SDValue N3) { + return getNode(Opcode, DebugLoc::getUnknownLoc(), VT, N1, N2, N3); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, MVT VT, + SDValue N1, SDValue N2, SDValue N3) { // Perform various simplifications. ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1.getNode()); ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2.getNode()); @@ -2702,12 +2833,12 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SmallVector<SDValue, 16> Elts(N1.getNode()->op_begin(), N1.getNode()->op_end()); Elts.insert(Elts.end(), N2.getNode()->op_begin(), N2.getNode()->op_end()); Elts.insert(Elts.end(), N3.getNode()->op_begin(), N3.getNode()->op_end()); - return getNode(ISD::BUILD_VECTOR, VT, &Elts[0], Elts.size()); + return getNode(ISD::BUILD_VECTOR, DL, VT, &Elts[0], Elts.size()); } break; case ISD::SETCC: { // Use FoldSetCC to simplify SETCC's. - SDValue Simp = FoldSetCC(VT, N1, N2, cast<CondCodeSDNode>(N3)->get()); + SDValue Simp = FoldSetCC(VT, N1, N2, cast<CondCodeSDNode>(N3)->get(), DL); if (Simp.getNode()) return Simp; break; } @@ -2724,7 +2855,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, case ISD::BRCOND: if (N2C) { if (N2C->getZExtValue()) // Unconditional branch - return getNode(ISD::BR, MVT::Other, N1, N3); + return getNode(ISD::BR, DL, MVT::Other, N1, N3); else return N1; // Never-taken branch } @@ -2755,11 +2886,11 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); N = NodeAllocator.Allocate<TernarySDNode>(); - new (N) TernarySDNode(Opcode, VTs, N1, N2, N3); + new (N) TernarySDNode(Opcode, DL, VTs, N1, N2, N3); CSEMap.InsertNode(N, IP); } else { N = NodeAllocator.Allocate<TernarySDNode>(); - new (N) TernarySDNode(Opcode, VTs, N1, N2, N3); + new (N) TernarySDNode(Opcode, DL, VTs, N1, N2, N3); } AllNodes.push_back(N); #ifndef NDEBUG @@ -2771,15 +2902,27 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue N1, SDValue N2, SDValue N3, SDValue N4) { + return getNode(Opcode, DebugLoc::getUnknownLoc(), VT, N1, N2, N3, N4); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, MVT VT, + SDValue N1, SDValue N2, SDValue N3, + SDValue N4) { SDValue Ops[] = { N1, N2, N3, N4 }; - return getNode(Opcode, VT, Ops, 4); + return getNode(Opcode, DL, VT, Ops, 4); } SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue N1, SDValue N2, SDValue N3, SDValue N4, SDValue N5) { + return getNode(Opcode, DebugLoc::getUnknownLoc(), VT, N1, N2, N3, N4, N5); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, MVT VT, + SDValue N1, SDValue N2, SDValue N3, + SDValue N4, SDValue N5) { SDValue Ops[] = { N1, N2, N3, N4, N5 }; - return getNode(Opcode, VT, Ops, 5); + return getNode(Opcode, DL, VT, Ops, 5); } /// getMemsetValue - Vectorized representation of the memset value @@ -2848,7 +2991,8 @@ static SDValue getMemsetStringVal(MVT VT, SelectionDAG &DAG, static SDValue getMemBasePlusOffset(SDValue Base, unsigned Offset, SelectionDAG &DAG) { MVT VT = Base.getValueType(); - return DAG.getNode(ISD::ADD, VT, Base, DAG.getConstant(Offset, VT)); + return DAG.getNode(ISD::ADD, Base.getNode()->getDebugLoc(), + VT, Base, DAG.getConstant(Offset, VT)); } /// isMemSrcFromString - Returns true if memcpy source is a string constant. @@ -3158,11 +3302,12 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, SDValue Dst, Entry.Node = Dst; Args.push_back(Entry); Entry.Node = Src; Args.push_back(Entry); Entry.Node = Size; Args.push_back(Entry); + // FIXME: pass in DebugLoc std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(Chain, Type::VoidTy, false, false, false, false, CallingConv::C, false, getExternalSymbol("memcpy", TLI.getPointerTy()), - Args, *this); + Args, *this, DebugLoc::getUnknownLoc()); return CallResult.second; } @@ -3203,11 +3348,12 @@ SDValue SelectionDAG::getMemmove(SDValue Chain, SDValue Dst, Entry.Node = Dst; Args.push_back(Entry); Entry.Node = Src; Args.push_back(Entry); Entry.Node = Size; Args.push_back(Entry); + // FIXME: pass in DebugLoc std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(Chain, Type::VoidTy, false, false, false, false, CallingConv::C, false, getExternalSymbol("memmove", TLI.getPointerTy()), - Args, *this); + Args, *this, DebugLoc::getUnknownLoc()); return CallResult.second; } @@ -3254,11 +3400,12 @@ SDValue SelectionDAG::getMemset(SDValue Chain, SDValue Dst, Args.push_back(Entry); Entry.Node = Size; Entry.Ty = IntPtrTy; Entry.isSExt = false; Args.push_back(Entry); + // FIXME: pass in DebugLoc std::pair<SDValue,SDValue> CallResult = TLI.LowerCallTo(Chain, Type::VoidTy, false, false, false, false, CallingConv::C, false, getExternalSymbol("memset", TLI.getPointerTy()), - Args, *this); + Args, *this, DebugLoc::getUnknownLoc()); return CallResult.second; } @@ -3277,6 +3424,7 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, MVT MemVT, SDVTList VTs = getVTList(VT, MVT::Other); FoldingSetNodeID ID; + ID.AddInteger(MemVT.getRawBits()); SDValue Ops[] = {Chain, Ptr, Cmp, Swp}; AddNodeIDNode(ID, Opcode, VTs, Ops, 4); void* IP = 0; @@ -3290,6 +3438,35 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, MVT MemVT, return SDValue(N, 0); } +SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, MVT MemVT, + SDValue Chain, + SDValue Ptr, SDValue Cmp, + SDValue Swp, const Value* PtrVal, + unsigned Alignment) { + assert(Opcode == ISD::ATOMIC_CMP_SWAP && "Invalid Atomic Op"); + assert(Cmp.getValueType() == Swp.getValueType() && "Invalid Atomic Op Types"); + + MVT VT = Cmp.getValueType(); + + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getMVTAlignment(MemVT); + + SDVTList VTs = getVTList(VT, MVT::Other); + FoldingSetNodeID ID; + ID.AddInteger(MemVT.getRawBits()); + SDValue Ops[] = {Chain, Ptr, Cmp, Swp}; + AddNodeIDNode(ID, Opcode, VTs, Ops, 4); + void* IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode* N = NodeAllocator.Allocate<AtomicSDNode>(); + new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, + Chain, Ptr, Cmp, Swp, PtrVal, Alignment); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + SDValue SelectionDAG::getAtomic(unsigned Opcode, MVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, @@ -3315,6 +3492,7 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, MVT MemVT, SDVTList VTs = getVTList(VT, MVT::Other); FoldingSetNodeID ID; + ID.AddInteger(MemVT.getRawBits()); SDValue Ops[] = {Chain, Ptr, Val}; AddNodeIDNode(ID, Opcode, VTs, Ops, 3); void* IP = 0; @@ -3328,6 +3506,45 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, MVT MemVT, return SDValue(N, 0); } +SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, MVT MemVT, + SDValue Chain, + SDValue Ptr, SDValue Val, + const Value* PtrVal, + unsigned Alignment) { + assert((Opcode == ISD::ATOMIC_LOAD_ADD || + Opcode == ISD::ATOMIC_LOAD_SUB || + Opcode == ISD::ATOMIC_LOAD_AND || + Opcode == ISD::ATOMIC_LOAD_OR || + Opcode == ISD::ATOMIC_LOAD_XOR || + Opcode == ISD::ATOMIC_LOAD_NAND || + Opcode == ISD::ATOMIC_LOAD_MIN || + Opcode == ISD::ATOMIC_LOAD_MAX || + Opcode == ISD::ATOMIC_LOAD_UMIN || + Opcode == ISD::ATOMIC_LOAD_UMAX || + Opcode == ISD::ATOMIC_SWAP) && + "Invalid Atomic Op"); + + MVT VT = Val.getValueType(); + + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getMVTAlignment(MemVT); + + SDVTList VTs = getVTList(VT, MVT::Other); + FoldingSetNodeID ID; + ID.AddInteger(MemVT.getRawBits()); + SDValue Ops[] = {Chain, Ptr, Val}; + AddNodeIDNode(ID, Opcode, VTs, Ops, 3); + void* IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode* N = NodeAllocator.Allocate<AtomicSDNode>(); + new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, + Chain, Ptr, Val, PtrVal, Alignment); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + /// getMergeValues - Create a MERGE_VALUES node from the given operands. /// Allowed to return something different (and simpler) if Simplify is true. SDValue SelectionDAG::getMergeValues(const SDValue *Ops, unsigned NumOps) { @@ -3341,6 +3558,20 @@ SDValue SelectionDAG::getMergeValues(const SDValue *Ops, unsigned NumOps) { return getNode(ISD::MERGE_VALUES, getVTList(&VTs[0], NumOps), Ops, NumOps); } +/// DebugLoc-aware version. +SDValue SelectionDAG::getMergeValues(const SDValue *Ops, unsigned NumOps, + DebugLoc dl) { + if (NumOps == 1) + return Ops[0]; + + SmallVector<MVT, 4> VTs; + VTs.reserve(NumOps); + for (unsigned i = 0; i < NumOps; ++i) + VTs.push_back(Ops[i].getValueType()); + return getNode(ISD::MERGE_VALUES, dl, getVTList(&VTs[0], NumOps), + Ops, NumOps); +} + SDValue SelectionDAG::getMemIntrinsicNode(unsigned Opcode, const MVT *VTs, unsigned NumVTs, @@ -3354,6 +3585,18 @@ SelectionDAG::getMemIntrinsicNode(unsigned Opcode, } SDValue +SelectionDAG::getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, + const MVT *VTs, unsigned NumVTs, + const SDValue *Ops, unsigned NumOps, + MVT MemVT, const Value *srcValue, int SVOff, + unsigned Align, bool Vol, + bool ReadMem, bool WriteMem) { + return getMemIntrinsicNode(Opcode, dl, makeVTList(VTs, NumVTs), Ops, NumOps, + MemVT, srcValue, SVOff, Align, Vol, + ReadMem, WriteMem); +} + +SDValue SelectionDAG::getMemIntrinsicNode(unsigned Opcode, SDVTList VTList, const SDValue *Ops, unsigned NumOps, MVT MemVT, const Value *srcValue, int SVOff, @@ -3382,6 +3625,34 @@ SelectionDAG::getMemIntrinsicNode(unsigned Opcode, SDVTList VTList, } SDValue +SelectionDAG::getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList, + const SDValue *Ops, unsigned NumOps, + MVT MemVT, const Value *srcValue, int SVOff, + unsigned Align, bool Vol, + bool ReadMem, bool WriteMem) { + // Memoize the node unless it returns a flag. + MemIntrinsicSDNode *N; + if (VTList.VTs[VTList.NumVTs-1] != MVT::Flag) { + FoldingSetNodeID ID; + AddNodeIDNode(ID, Opcode, VTList, Ops, NumOps); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + + N = NodeAllocator.Allocate<MemIntrinsicSDNode>(); + new (N) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps, MemVT, + srcValue, SVOff, Align, Vol, ReadMem, WriteMem); + CSEMap.InsertNode(N, IP); + } else { + N = NodeAllocator.Allocate<MemIntrinsicSDNode>(); + new (N) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps, MemVT, + srcValue, SVOff, Align, Vol, ReadMem, WriteMem); + } + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getCall(unsigned CallingConv, bool IsVarArgs, bool IsTailCall, bool IsInreg, SDVTList VTs, const SDValue *Operands, unsigned NumOperands) { @@ -3407,6 +3678,31 @@ SelectionDAG::getCall(unsigned CallingConv, bool IsVarArgs, bool IsTailCall, } SDValue +SelectionDAG::getCall(unsigned CallingConv, DebugLoc dl, bool IsVarArgs, + bool IsTailCall, bool IsInreg, SDVTList VTs, + const SDValue *Operands, unsigned NumOperands) { + // Do not include isTailCall in the folding set profile. + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::CALL, VTs, Operands, NumOperands); + ID.AddInteger(CallingConv); + ID.AddInteger(IsVarArgs); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { + // Instead of including isTailCall in the folding set, we just + // set the flag of the existing node. + if (!IsTailCall) + cast<CallSDNode>(E)->setNotTailCall(); + return SDValue(E, 0); + } + SDNode *N = NodeAllocator.Allocate<CallSDNode>(); + new (N) CallSDNode(CallingConv, dl, IsVarArgs, IsTailCall, IsInreg, + VTs, Operands, NumOperands); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + +SDValue SelectionDAG::getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, MVT VT, SDValue Chain, SDValue Ptr, SDValue Offset, @@ -3442,10 +3738,8 @@ SelectionDAG::getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, SDValue Ops[] = { Chain, Ptr, Offset }; FoldingSetNodeID ID; AddNodeIDNode(ID, ISD::LOAD, VTs, Ops, 3); - ID.AddInteger(AM); - ID.AddInteger(ExtType); ID.AddInteger(EVT.getRawBits()); - ID.AddInteger(encodeMemSDNodeFlags(isVolatile, Alignment)); + ID.AddInteger(encodeMemSDNodeFlags(ExtType, AM, isVolatile, Alignment)); void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); @@ -3457,6 +3751,55 @@ SelectionDAG::getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, return SDValue(N, 0); } +SDValue +SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl, + ISD::LoadExtType ExtType, MVT VT, SDValue Chain, + SDValue Ptr, SDValue Offset, + const Value *SV, int SVOffset, MVT EVT, + bool isVolatile, unsigned Alignment) { + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getMVTAlignment(VT); + + if (VT == EVT) { + ExtType = ISD::NON_EXTLOAD; + } else if (ExtType == ISD::NON_EXTLOAD) { + assert(VT == EVT && "Non-extending load from different memory type!"); + } else { + // Extending load. + if (VT.isVector()) + assert(EVT.getVectorNumElements() == VT.getVectorNumElements() && + "Invalid vector extload!"); + else + assert(EVT.bitsLT(VT) && + "Should only be an extending load, not truncating!"); + assert((ExtType == ISD::EXTLOAD || VT.isInteger()) && + "Cannot sign/zero extend a FP/Vector load!"); + assert(VT.isInteger() == EVT.isInteger() && + "Cannot convert from FP to Int or Int -> FP!"); + } + + bool Indexed = AM != ISD::UNINDEXED; + assert((Indexed || Offset.getOpcode() == ISD::UNDEF) && + "Unindexed load with an offset!"); + + SDVTList VTs = Indexed ? + getVTList(VT, Ptr.getValueType(), MVT::Other) : getVTList(VT, MVT::Other); + SDValue Ops[] = { Chain, Ptr, Offset }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::LOAD, VTs, Ops, 3); + ID.AddInteger(EVT.getRawBits()); + ID.AddInteger(encodeMemSDNodeFlags(ExtType, AM, isVolatile, Alignment)); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate<LoadSDNode>(); + new (N) LoadSDNode(Ops, dl, VTs, AM, ExtType, EVT, SV, SVOffset, + Alignment, isVolatile); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + SDValue SelectionDAG::getLoad(MVT VT, SDValue Chain, SDValue Ptr, const Value *SV, int SVOffset, @@ -3466,6 +3809,15 @@ SDValue SelectionDAG::getLoad(MVT VT, SV, SVOffset, VT, isVolatile, Alignment); } +SDValue SelectionDAG::getLoad(MVT VT, DebugLoc dl, + SDValue Chain, SDValue Ptr, + const Value *SV, int SVOffset, + bool isVolatile, unsigned Alignment) { + SDValue Undef = getNode(ISD::UNDEF, Ptr.getValueType()); + return getLoad(ISD::UNINDEXED, dl, ISD::NON_EXTLOAD, VT, Chain, Ptr, Undef, + SV, SVOffset, VT, isVolatile, Alignment); +} + SDValue SelectionDAG::getExtLoad(ISD::LoadExtType ExtType, MVT VT, SDValue Chain, SDValue Ptr, const Value *SV, @@ -3476,6 +3828,16 @@ SDValue SelectionDAG::getExtLoad(ISD::LoadExtType ExtType, MVT VT, SV, SVOffset, EVT, isVolatile, Alignment); } +SDValue SelectionDAG::getExtLoad(ISD::LoadExtType ExtType, DebugLoc dl, MVT VT, + SDValue Chain, SDValue Ptr, + const Value *SV, + int SVOffset, MVT EVT, + bool isVolatile, unsigned Alignment) { + SDValue Undef = getNode(ISD::UNDEF, Ptr.getValueType()); + return getLoad(ISD::UNINDEXED, dl, ExtType, VT, Chain, Ptr, Undef, + SV, SVOffset, EVT, isVolatile, Alignment); +} + SDValue SelectionDAG::getIndexedLoad(SDValue OrigLoad, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM) { @@ -3488,6 +3850,18 @@ SelectionDAG::getIndexedLoad(SDValue OrigLoad, SDValue Base, LD->isVolatile(), LD->getAlignment()); } +SDValue +SelectionDAG::getIndexedLoad(SDValue OrigLoad, DebugLoc dl, SDValue Base, + SDValue Offset, ISD::MemIndexedMode AM) { + LoadSDNode *LD = cast<LoadSDNode>(OrigLoad); + assert(LD->getOffset().getOpcode() == ISD::UNDEF && + "Load is already a indexed load!"); + return getLoad(AM, dl, LD->getExtensionType(), OrigLoad.getValueType(), + LD->getChain(), Base, Offset, LD->getSrcValue(), + LD->getSrcValueOffset(), LD->getMemoryVT(), + LD->isVolatile(), LD->getAlignment()); +} + SDValue SelectionDAG::getStore(SDValue Chain, SDValue Val, SDValue Ptr, const Value *SV, int SVOffset, bool isVolatile, unsigned Alignment) { @@ -3501,10 +3875,9 @@ SDValue SelectionDAG::getStore(SDValue Chain, SDValue Val, SDValue Ops[] = { Chain, Val, Ptr, Undef }; FoldingSetNodeID ID; AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); - ID.AddInteger(ISD::UNINDEXED); - ID.AddInteger(false); ID.AddInteger(VT.getRawBits()); - ID.AddInteger(encodeMemSDNodeFlags(isVolatile, Alignment)); + ID.AddInteger(encodeMemSDNodeFlags(false, ISD::UNINDEXED, + isVolatile, Alignment)); void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); @@ -3516,6 +3889,33 @@ SDValue SelectionDAG::getStore(SDValue Chain, SDValue Val, return SDValue(N, 0); } +SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val, + SDValue Ptr, const Value *SV, int SVOffset, + bool isVolatile, unsigned Alignment) { + MVT VT = Val.getValueType(); + + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getMVTAlignment(VT); + + SDVTList VTs = getVTList(MVT::Other); + SDValue Undef = getNode(ISD::UNDEF, Ptr.getValueType()); + SDValue Ops[] = { Chain, Val, Ptr, Undef }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); + ID.AddInteger(VT.getRawBits()); + ID.AddInteger(encodeMemSDNodeFlags(false, ISD::UNINDEXED, + isVolatile, Alignment)); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate<StoreSDNode>(); + new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, false, + VT, SV, SVOffset, Alignment, isVolatile); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + SDValue SelectionDAG::getTruncStore(SDValue Chain, SDValue Val, SDValue Ptr, const Value *SV, int SVOffset, MVT SVT, @@ -3537,10 +3937,9 @@ SDValue SelectionDAG::getTruncStore(SDValue Chain, SDValue Val, SDValue Ops[] = { Chain, Val, Ptr, Undef }; FoldingSetNodeID ID; AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); - ID.AddInteger(ISD::UNINDEXED); - ID.AddInteger(1); ID.AddInteger(SVT.getRawBits()); - ID.AddInteger(encodeMemSDNodeFlags(isVolatile, Alignment)); + ID.AddInteger(encodeMemSDNodeFlags(true, ISD::UNINDEXED, + isVolatile, Alignment)); void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); @@ -3552,6 +3951,41 @@ SDValue SelectionDAG::getTruncStore(SDValue Chain, SDValue Val, return SDValue(N, 0); } +SDValue SelectionDAG::getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, + SDValue Ptr, const Value *SV, + int SVOffset, MVT SVT, + bool isVolatile, unsigned Alignment) { + MVT VT = Val.getValueType(); + + if (VT == SVT) + return getStore(Chain, dl, Val, Ptr, SV, SVOffset, isVolatile, Alignment); + + assert(VT.bitsGT(SVT) && "Not a truncation?"); + assert(VT.isInteger() == SVT.isInteger() && + "Can't do FP-INT conversion!"); + + if (Alignment == 0) // Ensure that codegen never sees alignment 0 + Alignment = getMVTAlignment(VT); + + SDVTList VTs = getVTList(MVT::Other); + SDValue Undef = getNode(ISD::UNDEF, Ptr.getValueType()); + SDValue Ops[] = { Chain, Val, Ptr, Undef }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); + ID.AddInteger(SVT.getRawBits()); + ID.AddInteger(encodeMemSDNodeFlags(true, ISD::UNINDEXED, + isVolatile, Alignment)); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate<StoreSDNode>(); + new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, true, + SVT, SV, SVOffset, Alignment, isVolatile); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + SDValue SelectionDAG::getIndexedStore(SDValue OrigStore, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM) { @@ -3562,10 +3996,8 @@ SelectionDAG::getIndexedStore(SDValue OrigStore, SDValue Base, SDValue Ops[] = { ST->getChain(), ST->getValue(), Base, Offset }; FoldingSetNodeID ID; AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); - ID.AddInteger(AM); - ID.AddInteger(ST->isTruncatingStore()); ID.AddInteger(ST->getMemoryVT().getRawBits()); - ID.AddInteger(ST->getRawFlags()); + ID.AddInteger(ST->getRawSubclassData()); void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); @@ -3579,6 +4011,31 @@ SelectionDAG::getIndexedStore(SDValue OrigStore, SDValue Base, return SDValue(N, 0); } +SDValue +SelectionDAG::getIndexedStore(SDValue OrigStore, DebugLoc dl, SDValue Base, + SDValue Offset, ISD::MemIndexedMode AM) { + StoreSDNode *ST = cast<StoreSDNode>(OrigStore); + assert(ST->getOffset().getOpcode() == ISD::UNDEF && + "Store is already a indexed store!"); + SDVTList VTs = getVTList(Base.getValueType(), MVT::Other); + SDValue Ops[] = { ST->getChain(), ST->getValue(), Base, Offset }; + FoldingSetNodeID ID; + AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); + ID.AddInteger(ST->getMemoryVT().getRawBits()); + ID.AddInteger(ST->getRawSubclassData()); + void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) + return SDValue(E, 0); + SDNode *N = NodeAllocator.Allocate<StoreSDNode>(); + new (N) StoreSDNode(Ops, dl, VTs, AM, + ST->isTruncatingStore(), ST->getMemoryVT(), + ST->getSrcValue(), ST->getSrcValueOffset(), + ST->getAlignment(), ST->isVolatile()); + CSEMap.InsertNode(N, IP); + AllNodes.push_back(N); + return SDValue(N, 0); +} + SDValue SelectionDAG::getVAArg(MVT VT, SDValue Chain, SDValue Ptr, SDValue SV) { @@ -3588,27 +4045,37 @@ SDValue SelectionDAG::getVAArg(MVT VT, SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, const SDUse *Ops, unsigned NumOps) { + return getNode(Opcode, DebugLoc::getUnknownLoc(), VT, Ops, NumOps); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, MVT VT, + const SDUse *Ops, unsigned NumOps) { switch (NumOps) { - case 0: return getNode(Opcode, VT); - case 1: return getNode(Opcode, VT, Ops[0]); - case 2: return getNode(Opcode, VT, Ops[0], Ops[1]); - case 3: return getNode(Opcode, VT, Ops[0], Ops[1], Ops[2]); + case 0: return getNode(Opcode, DL, VT); + case 1: return getNode(Opcode, DL, VT, Ops[0]); + case 2: return getNode(Opcode, DL, VT, Ops[0], Ops[1]); + case 3: return getNode(Opcode, DL, VT, Ops[0], Ops[1], Ops[2]); default: break; } // Copy from an SDUse array into an SDValue array for use with // the regular getNode logic. SmallVector<SDValue, 8> NewOps(Ops, Ops + NumOps); - return getNode(Opcode, VT, &NewOps[0], NumOps); + return getNode(Opcode, DL, VT, &NewOps[0], NumOps); } SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, const SDValue *Ops, unsigned NumOps) { + return getNode(Opcode, DebugLoc::getUnknownLoc(), VT, Ops, NumOps); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, MVT VT, + const SDValue *Ops, unsigned NumOps) { switch (NumOps) { - case 0: return getNode(Opcode, VT); - case 1: return getNode(Opcode, VT, Ops[0]); - case 2: return getNode(Opcode, VT, Ops[0], Ops[1]); - case 3: return getNode(Opcode, VT, Ops[0], Ops[1], Ops[2]); + case 0: return getNode(Opcode, DL, VT); + case 1: return getNode(Opcode, DL, VT, Ops[0]); + case 2: return getNode(Opcode, DL, VT, Ops[0], Ops[1]); + case 3: return getNode(Opcode, DL, VT, Ops[0], Ops[1], Ops[2]); default: break; } @@ -3635,19 +4102,23 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, // Memoize nodes. SDNode *N; SDVTList VTs = getVTList(VT); + if (VT != MVT::Flag) { FoldingSetNodeID ID; AddNodeIDNode(ID, Opcode, VTs, Ops, NumOps); void *IP = 0; + if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) return SDValue(E, 0); + N = NodeAllocator.Allocate<SDNode>(); - new (N) SDNode(Opcode, VTs, Ops, NumOps); + new (N) SDNode(Opcode, DL, VTs, Ops, NumOps); CSEMap.InsertNode(N, IP); } else { N = NodeAllocator.Allocate<SDNode>(); - new (N) SDNode(Opcode, VTs, Ops, NumOps); + new (N) SDNode(Opcode, DL, VTs, Ops, NumOps); } + AllNodes.push_back(N); #ifndef NDEBUG VerifyNode(N); @@ -3658,22 +4129,39 @@ SDValue SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue SelectionDAG::getNode(unsigned Opcode, const std::vector<MVT> &ResultTys, const SDValue *Ops, unsigned NumOps) { - return getNode(Opcode, getNodeValueTypes(ResultTys), ResultTys.size(), + return getNode(Opcode, DebugLoc::getUnknownLoc(), ResultTys, Ops, NumOps); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, + const std::vector<MVT> &ResultTys, + const SDValue *Ops, unsigned NumOps) { + return getNode(Opcode, DL, getNodeValueTypes(ResultTys), ResultTys.size(), Ops, NumOps); } SDValue SelectionDAG::getNode(unsigned Opcode, const MVT *VTs, unsigned NumVTs, const SDValue *Ops, unsigned NumOps) { + return getNode(Opcode, DebugLoc::getUnknownLoc(), VTs, NumVTs, Ops, NumOps); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, + const MVT *VTs, unsigned NumVTs, + const SDValue *Ops, unsigned NumOps) { if (NumVTs == 1) - return getNode(Opcode, VTs[0], Ops, NumOps); - return getNode(Opcode, makeVTList(VTs, NumVTs), Ops, NumOps); + return getNode(Opcode, DL, VTs[0], Ops, NumOps); + return getNode(Opcode, DL, makeVTList(VTs, NumVTs), Ops, NumOps); } SDValue SelectionDAG::getNode(unsigned Opcode, SDVTList VTList, const SDValue *Ops, unsigned NumOps) { + return getNode(Opcode, DebugLoc::getUnknownLoc(), VTList, Ops, NumOps); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + const SDValue *Ops, unsigned NumOps) { if (VTList.NumVTs == 1) - return getNode(Opcode, VTList.VTs[0], Ops, NumOps); + return getNode(Opcode, DL, VTList.VTs[0], Ops, NumOps); switch (Opcode) { // FIXME: figure out how to safely handle things like @@ -3685,14 +4173,14 @@ SDValue SelectionDAG::getNode(unsigned Opcode, SDVTList VTList, case ISD::SHL_PARTS: if (N3.getOpcode() == ISD::SIGN_EXTEND_INREG && cast<VTSDNode>(N3.getOperand(1))->getVT() != MVT::i1) - return getNode(Opcode, VT, N1, N2, N3.getOperand(0)); + return getNode(Opcode, DL, VT, N1, N2, N3.getOperand(0)); else if (N3.getOpcode() == ISD::AND) if (ConstantSDNode *AndRHS = dyn_cast<ConstantSDNode>(N3.getOperand(1))) { // If the and is only masking out bits that cannot effect the shift, // eliminate the and. unsigned NumBits = VT.getSizeInBits()*2; if ((AndRHS->getValue() & (NumBits-1)) == NumBits-1) - return getNode(Opcode, VT, N1, N2, N3.getOperand(0)); + return getNode(Opcode, DL, VT, N1, N2, N3.getOperand(0)); } break; #endif @@ -3708,31 +4196,31 @@ SDValue SelectionDAG::getNode(unsigned Opcode, SDVTList VTList, return SDValue(E, 0); if (NumOps == 1) { N = NodeAllocator.Allocate<UnarySDNode>(); - new (N) UnarySDNode(Opcode, VTList, Ops[0]); + new (N) UnarySDNode(Opcode, DL, VTList, Ops[0]); } else if (NumOps == 2) { N = NodeAllocator.Allocate<BinarySDNode>(); - new (N) BinarySDNode(Opcode, VTList, Ops[0], Ops[1]); + new (N) BinarySDNode(Opcode, DL, VTList, Ops[0], Ops[1]); } else if (NumOps == 3) { N = NodeAllocator.Allocate<TernarySDNode>(); - new (N) TernarySDNode(Opcode, VTList, Ops[0], Ops[1], Ops[2]); + new (N) TernarySDNode(Opcode, DL, VTList, Ops[0], Ops[1], Ops[2]); } else { N = NodeAllocator.Allocate<SDNode>(); - new (N) SDNode(Opcode, VTList, Ops, NumOps); + new (N) SDNode(Opcode, DL, VTList, Ops, NumOps); } CSEMap.InsertNode(N, IP); } else { if (NumOps == 1) { N = NodeAllocator.Allocate<UnarySDNode>(); - new (N) UnarySDNode(Opcode, VTList, Ops[0]); + new (N) UnarySDNode(Opcode, DL, VTList, Ops[0]); } else if (NumOps == 2) { N = NodeAllocator.Allocate<BinarySDNode>(); - new (N) BinarySDNode(Opcode, VTList, Ops[0], Ops[1]); + new (N) BinarySDNode(Opcode, DL, VTList, Ops[0], Ops[1]); } else if (NumOps == 3) { N = NodeAllocator.Allocate<TernarySDNode>(); - new (N) TernarySDNode(Opcode, VTList, Ops[0], Ops[1], Ops[2]); + new (N) TernarySDNode(Opcode, DL, VTList, Ops[0], Ops[1], Ops[2]); } else { N = NodeAllocator.Allocate<SDNode>(); - new (N) SDNode(Opcode, VTList, Ops, NumOps); + new (N) SDNode(Opcode, DL, VTList, Ops, NumOps); } } AllNodes.push_back(N); @@ -3743,39 +4231,70 @@ SDValue SelectionDAG::getNode(unsigned Opcode, SDVTList VTList, } SDValue SelectionDAG::getNode(unsigned Opcode, SDVTList VTList) { - return getNode(Opcode, VTList, 0, 0); + return getNode(Opcode, DebugLoc::getUnknownLoc(), VTList); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList) { + return getNode(Opcode, DL, VTList, 0, 0); } SDValue SelectionDAG::getNode(unsigned Opcode, SDVTList VTList, - SDValue N1) { + SDValue N1) { + return getNode(Opcode, DebugLoc::getUnknownLoc(), VTList, N1); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + SDValue N1) { SDValue Ops[] = { N1 }; - return getNode(Opcode, VTList, Ops, 1); + return getNode(Opcode, DL, VTList, Ops, 1); } SDValue SelectionDAG::getNode(unsigned Opcode, SDVTList VTList, SDValue N1, SDValue N2) { + return getNode(Opcode, DebugLoc::getUnknownLoc(), VTList, N1, N2); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + SDValue N1, SDValue N2) { SDValue Ops[] = { N1, N2 }; - return getNode(Opcode, VTList, Ops, 2); + return getNode(Opcode, DL, VTList, Ops, 2); } SDValue SelectionDAG::getNode(unsigned Opcode, SDVTList VTList, SDValue N1, SDValue N2, SDValue N3) { + return getNode(Opcode, DebugLoc::getUnknownLoc(), VTList, N1, N2, N3); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + SDValue N1, SDValue N2, SDValue N3) { SDValue Ops[] = { N1, N2, N3 }; - return getNode(Opcode, VTList, Ops, 3); + return getNode(Opcode, DL, VTList, Ops, 3); } SDValue SelectionDAG::getNode(unsigned Opcode, SDVTList VTList, SDValue N1, SDValue N2, SDValue N3, SDValue N4) { + return getNode(Opcode, DebugLoc::getUnknownLoc(), VTList, N1, N2, N3, N4); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + SDValue N1, SDValue N2, SDValue N3, + SDValue N4) { SDValue Ops[] = { N1, N2, N3, N4 }; - return getNode(Opcode, VTList, Ops, 4); + return getNode(Opcode, DL, VTList, Ops, 4); } SDValue SelectionDAG::getNode(unsigned Opcode, SDVTList VTList, SDValue N1, SDValue N2, SDValue N3, SDValue N4, SDValue N5) { + return getNode(Opcode, DebugLoc::getUnknownLoc(), VTList, N1, N2, N3, N4, N5); +} + +SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList, + SDValue N1, SDValue N2, SDValue N3, + SDValue N4, SDValue N5) { SDValue Ops[] = { N1, N2, N3, N4, N5 }; - return getNode(Opcode, VTList, Ops, 5); + return getNode(Opcode, DL, VTList, Ops, 5); } SDVTList SelectionDAG::getVTList(MVT VT) { @@ -3885,10 +4404,7 @@ SDValue SelectionDAG::UpdateNodeOperands(SDValue InN, SDValue Op) { InsertPos = 0; // Now we update the operands. - N->OperandList[0].getVal()->removeUser(0, N); - N->OperandList[0] = Op; - N->OperandList[0].setUser(N); - Op.getNode()->addUser(0, N); + N->OperandList[0].set(Op); // If this gets put into a CSE map, add it. if (InsertPos) CSEMap.InsertNode(N, InsertPos); @@ -3915,18 +4431,10 @@ UpdateNodeOperands(SDValue InN, SDValue Op1, SDValue Op2) { InsertPos = 0; // Now we update the operands. - if (N->OperandList[0] != Op1) { - N->OperandList[0].getVal()->removeUser(0, N); - N->OperandList[0] = Op1; - N->OperandList[0].setUser(N); - Op1.getNode()->addUser(0, N); - } - if (N->OperandList[1] != Op2) { - N->OperandList[1].getVal()->removeUser(1, N); - N->OperandList[1] = Op2; - N->OperandList[1].setUser(N); - Op2.getNode()->addUser(1, N); - } + if (N->OperandList[0] != Op1) + N->OperandList[0].set(Op1); + if (N->OperandList[1] != Op2) + N->OperandList[1].set(Op2); // If this gets put into a CSE map, add it. if (InsertPos) CSEMap.InsertNode(N, InsertPos); @@ -3982,14 +4490,9 @@ UpdateNodeOperands(SDValue InN, const SDValue *Ops, unsigned NumOps) { InsertPos = 0; // Now we update the operands. - for (unsigned i = 0; i != NumOps; ++i) { - if (N->OperandList[i] != Ops[i]) { - N->OperandList[i].getVal()->removeUser(i, N); - N->OperandList[i] = Ops[i]; - N->OperandList[i].setUser(N); - Ops[i].getNode()->addUser(i, N); - } - } + for (unsigned i = 0; i != NumOps; ++i) + if (N->OperandList[i] != Ops[i]) + N->OperandList[i].set(Ops[i]); // If this gets put into a CSE map, add it. if (InsertPos) CSEMap.InsertNode(N, InsertPos); @@ -4001,10 +4504,10 @@ UpdateNodeOperands(SDValue InN, const SDValue *Ops, unsigned NumOps) { void SDNode::DropOperands() { // Unlike the code in MorphNodeTo that does this, we don't need to // watch for dead nodes here. - for (op_iterator I = op_begin(), E = op_end(); I != E; ++I) - I->getVal()->removeUser(std::distance(op_begin(), I), this); - - NumOperands = 0; + for (op_iterator I = op_begin(), E = op_end(); I != E; ) { + SDUse &Use = *I++; + Use.set(SDValue()); + } } /// SelectNodeTo - These are wrappers around MorphNodeTo that accept a @@ -4229,10 +4732,10 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, // Clear the operands list, updating used nodes to remove this from their // use list. Keep track of any operands that become dead as a result. SmallPtrSet<SDNode*, 16> DeadNodeSet; - for (SDNode::op_iterator B = N->op_begin(), I = B, E = N->op_end(); - I != E; ++I) { - SDNode *Used = I->getVal(); - Used->removeUser(std::distance(B, I), N); + for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ) { + SDUse &Use = *I++; + SDNode *Used = Use.getNode(); + Use.set(SDValue()); if (Used->use_empty()) DeadNodeSet.insert(Used); } @@ -4258,10 +4761,8 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, // Assign the new operands. N->NumOperands = NumOps; for (unsigned i = 0, e = NumOps; i != e; ++i) { - N->OperandList[i] = Ops[i]; N->OperandList[i].setUser(N); - SDNode *ToUse = N->OperandList[i].getVal(); - ToUse->addUser(i, N); + N->OperandList[i].setInitial(Ops[i]); } // Delete any nodes that are still dead after adding the uses for the @@ -4288,32 +4789,70 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT) { return getNode(~Opcode, VT).getNode(); } +SDNode *SelectionDAG::getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT) { + return getNode(~Opcode, dl, VT).getNode(); +} + SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT, SDValue Op1) { return getNode(~Opcode, VT, Op1).getNode(); } +SDNode *SelectionDAG::getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT, + SDValue Op1) { + return getNode(~Opcode, dl, VT, Op1).getNode(); +} + SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT, SDValue Op1, SDValue Op2) { return getNode(~Opcode, VT, Op1, Op2).getNode(); } +SDNode *SelectionDAG::getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT, + SDValue Op1, SDValue Op2) { + return getNode(~Opcode, dl, VT, Op1, Op2).getNode(); +} + SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT, SDValue Op1, SDValue Op2, SDValue Op3) { return getNode(~Opcode, VT, Op1, Op2, Op3).getNode(); } +SDNode *SelectionDAG::getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT, + SDValue Op1, SDValue Op2, + SDValue Op3) { + return getNode(~Opcode, dl, VT, Op1, Op2, Op3).getNode(); +} + SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT, const SDValue *Ops, unsigned NumOps) { return getNode(~Opcode, VT, Ops, NumOps).getNode(); } +SDNode *SelectionDAG::getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT, + const SDValue *Ops, unsigned NumOps) { + return getNode(~Opcode, dl, VT, Ops, NumOps).getNode(); +} + SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, MVT VT2) { const MVT *VTs = getNodeValueTypes(VT1, VT2); SDValue Op; return getNode(~Opcode, VTs, 2, &Op, 0).getNode(); } +SDNode *SelectionDAG::getTargetNode(unsigned Opcode, DebugLoc dl, + MVT VT1, MVT VT2) { + const MVT *VTs = getNodeValueTypes(VT1, VT2); + SDValue Op; + return getNode(~Opcode, dl, VTs, 2, &Op, 0).getNode(); +} + SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, MVT VT2, SDValue Op1) { const MVT *VTs = getNodeValueTypes(VT1, VT2); return getNode(~Opcode, VTs, 2, &Op1, 1).getNode(); } +SDNode *SelectionDAG::getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT1, + MVT VT2, SDValue Op1) { + const MVT *VTs = getNodeValueTypes(VT1, VT2); + return getNode(~Opcode, dl, VTs, 2, &Op1, 1).getNode(); +} + SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, MVT VT2, SDValue Op1, SDValue Op2) { @@ -4321,6 +4860,14 @@ SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, SDValue Ops[] = { Op1, Op2 }; return getNode(~Opcode, VTs, 2, Ops, 2).getNode(); } +SDNode *SelectionDAG::getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT1, + MVT VT2, SDValue Op1, + SDValue Op2) { + const MVT *VTs = getNodeValueTypes(VT1, VT2); + SDValue Ops[] = { Op1, Op2 }; + return getNode(~Opcode, dl, VTs, 2, Ops, 2).getNode(); +} + SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, MVT VT2, SDValue Op1, SDValue Op2, SDValue Op3) { @@ -4328,17 +4875,40 @@ SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, SDValue Ops[] = { Op1, Op2, Op3 }; return getNode(~Opcode, VTs, 2, Ops, 3).getNode(); } +SDNode *SelectionDAG::getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT1, + MVT VT2, SDValue Op1, + SDValue Op2, SDValue Op3) { + const MVT *VTs = getNodeValueTypes(VT1, VT2); + SDValue Ops[] = { Op1, Op2, Op3 }; + return getNode(~Opcode, dl, VTs, 2, Ops, 3).getNode(); +} + SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, MVT VT2, const SDValue *Ops, unsigned NumOps) { const MVT *VTs = getNodeValueTypes(VT1, VT2); return getNode(~Opcode, VTs, 2, Ops, NumOps).getNode(); } +SDNode *SelectionDAG::getTargetNode(unsigned Opcode, DebugLoc dl, + MVT VT1, MVT VT2, + const SDValue *Ops, unsigned NumOps) { + const MVT *VTs = getNodeValueTypes(VT1, VT2); + return getNode(~Opcode, dl, VTs, 2, Ops, NumOps).getNode(); +} + SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, MVT VT2, MVT VT3, SDValue Op1, SDValue Op2) { const MVT *VTs = getNodeValueTypes(VT1, VT2, VT3); SDValue Ops[] = { Op1, Op2 }; return getNode(~Opcode, VTs, 3, Ops, 2).getNode(); } +SDNode *SelectionDAG::getTargetNode(unsigned Opcode, DebugLoc dl, + MVT VT1, MVT VT2, MVT VT3, + SDValue Op1, SDValue Op2) { + const MVT *VTs = getNodeValueTypes(VT1, VT2, VT3); + SDValue Ops[] = { Op1, Op2 }; + return getNode(~Opcode, dl, VTs, 3, Ops, 2).getNode(); +} + SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, MVT VT2, MVT VT3, SDValue Op1, SDValue Op2, SDValue Op3) { @@ -4346,11 +4916,27 @@ SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, MVT VT2, MVT VT3, SDValue Ops[] = { Op1, Op2, Op3 }; return getNode(~Opcode, VTs, 3, Ops, 3).getNode(); } +SDNode *SelectionDAG::getTargetNode(unsigned Opcode, DebugLoc dl, + MVT VT1, MVT VT2, MVT VT3, + SDValue Op1, SDValue Op2, + SDValue Op3) { + const MVT *VTs = getNodeValueTypes(VT1, VT2, VT3); + SDValue Ops[] = { Op1, Op2, Op3 }; + return getNode(~Opcode, dl, VTs, 3, Ops, 3).getNode(); +} + SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, MVT VT2, MVT VT3, const SDValue *Ops, unsigned NumOps) { const MVT *VTs = getNodeValueTypes(VT1, VT2, VT3); return getNode(~Opcode, VTs, 3, Ops, NumOps).getNode(); } +SDNode *SelectionDAG::getTargetNode(unsigned Opcode, DebugLoc dl, + MVT VT1, MVT VT2, MVT VT3, + const SDValue *Ops, unsigned NumOps) { + const MVT *VTs = getNodeValueTypes(VT1, VT2, VT3); + return getNode(~Opcode, dl, VTs, 3, Ops, NumOps).getNode(); +} + SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, MVT VT2, MVT VT3, MVT VT4, const SDValue *Ops, unsigned NumOps) { @@ -4362,6 +4948,18 @@ SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, const MVT *VTs = getNodeValueTypes(VTList); return getNode(~Opcode, VTs, 4, Ops, NumOps).getNode(); } +SDNode *SelectionDAG::getTargetNode(unsigned Opcode, DebugLoc dl, MVT VT1, + MVT VT2, MVT VT3, MVT VT4, + const SDValue *Ops, unsigned NumOps) { + std::vector<MVT> VTList; + VTList.push_back(VT1); + VTList.push_back(VT2); + VTList.push_back(VT3); + VTList.push_back(VT4); + const MVT *VTs = getNodeValueTypes(VTList); + return getNode(~Opcode, dl, VTs, 4, Ops, NumOps).getNode(); +} + SDNode *SelectionDAG::getTargetNode(unsigned Opcode, const std::vector<MVT> &ResultTys, const SDValue *Ops, unsigned NumOps) { @@ -4369,6 +4967,13 @@ SDNode *SelectionDAG::getTargetNode(unsigned Opcode, return getNode(~Opcode, VTs, ResultTys.size(), Ops, NumOps).getNode(); } +SDNode *SelectionDAG::getTargetNode(unsigned Opcode, DebugLoc dl, + const std::vector<MVT> &ResultTys, + const SDValue *Ops, unsigned NumOps) { + const MVT *VTs = getNodeValueTypes(ResultTys); + return getNode(~Opcode, dl, VTs, ResultTys.size(), + Ops, NumOps).getNode(); +} /// getNodeIfExists - Get the specified node if it's already available, or /// else return NULL. @@ -4384,7 +4989,6 @@ SDNode *SelectionDAG::getNodeIfExists(unsigned Opcode, SDVTList VTList, return NULL; } - /// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead. /// This can cause recursive merging of nodes in the DAG. /// @@ -4397,43 +5001,33 @@ void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To, "Cannot replace with this method!"); assert(From != To.getNode() && "Cannot replace uses of with self"); - // Iterate over all the existing uses of From. This specifically avoids - // visiting any new uses of From that arrise while the replacement is - // happening, because any such uses would be the result of CSE: If an - // existing node looks like From after one of its operands is replaced - // by To, we don't want to replace of all its users with To too. - // See PR3018 for more info. + // Iterate over all the existing uses of From. New uses will be added + // to the beginning of the use list, which we avoid visiting. + // This specifically avoids visiting uses of From that arise while the + // replacement is happening, because any such uses would be the result + // of CSE: If an existing node looks like From after one of its operands + // is replaced by To, we don't want to replace of all its users with To + // too. See PR3018 for more info. SDNode::use_iterator UI = From->use_begin(), UE = From->use_end(); while (UI != UE) { - SDNode *U = *UI; - do ++UI; while (UI != UE && *UI == U); + SDNode *User = *UI; // This node is about to morph, remove its old self from the CSE maps. - RemoveNodeFromCSEMaps(U); - int operandNum = 0; - for (SDNode::op_iterator I = U->op_begin(), E = U->op_end(); - I != E; ++I, ++operandNum) - if (I->getVal() == From) { - From->removeUser(operandNum, U); - *I = To; - I->setUser(U); - To.getNode()->addUser(operandNum, U); - } - - // Now that we have modified U, add it back to the CSE maps. If it already - // exists there, recursively merge the results together. - if (SDNode *Existing = AddNonLeafNodeToCSEMaps(U)) { - ReplaceAllUsesWith(U, Existing, UpdateListener); - // U is now dead. Inform the listener if it exists and delete it. - if (UpdateListener) - UpdateListener->NodeDeleted(U, Existing); - DeleteNodeNotInCSEMaps(U); - } else { - // If the node doesn't already exist, we updated it. Inform a listener if - // it exists. - if (UpdateListener) - UpdateListener->NodeUpdated(U); - } + RemoveNodeFromCSEMaps(User); + + // A user can appear in a use list multiple times, and when this + // happens the uses are usually next to each other in the list. + // To help reduce the number of CSE recomputations, process all + // the uses of this user that we can find this way. + do { + SDUse &Use = UI.getUse(); + ++UI; + Use.set(To); + } while (UI != UE && *UI == User); + + // Now that we have modified User, add it back to the CSE maps. If it + // already exists there, recursively merge the results together. + AddModifiedNodeToCSEMaps(User, UpdateListener); } } @@ -4457,34 +5051,24 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To, // the ReplaceAllUsesWith above. SDNode::use_iterator UI = From->use_begin(), UE = From->use_end(); while (UI != UE) { - SDNode *U = *UI; - do ++UI; while (UI != UE && *UI == U); + SDNode *User = *UI; // This node is about to morph, remove its old self from the CSE maps. - RemoveNodeFromCSEMaps(U); - int operandNum = 0; - for (SDNode::op_iterator I = U->op_begin(), E = U->op_end(); - I != E; ++I, ++operandNum) - if (I->getVal() == From) { - From->removeUser(operandNum, U); - I->getSDValue().setNode(To); - To->addUser(operandNum, U); - } + RemoveNodeFromCSEMaps(User); - // Now that we have modified U, add it back to the CSE maps. If it already - // exists there, recursively merge the results together. - if (SDNode *Existing = AddNonLeafNodeToCSEMaps(U)) { - ReplaceAllUsesWith(U, Existing, UpdateListener); - // U is now dead. Inform the listener if it exists and delete it. - if (UpdateListener) - UpdateListener->NodeDeleted(U, Existing); - DeleteNodeNotInCSEMaps(U); - } else { - // If the node doesn't already exist, we updated it. Inform a listener if - // it exists. - if (UpdateListener) - UpdateListener->NodeUpdated(U); - } + // A user can appear in a use list multiple times, and when this + // happens the uses are usually next to each other in the list. + // To help reduce the number of CSE recomputations, process all + // the uses of this user that we can find this way. + do { + SDUse &Use = UI.getUse(); + ++UI; + Use.setNode(To); + } while (UI != UE && *UI == User); + + // Now that we have modified User, add it back to the CSE maps. If it + // already exists there, recursively merge the results together. + AddModifiedNodeToCSEMaps(User, UpdateListener); } } @@ -4503,42 +5087,31 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, // the ReplaceAllUsesWith above. SDNode::use_iterator UI = From->use_begin(), UE = From->use_end(); while (UI != UE) { - SDNode *U = *UI; - do ++UI; while (UI != UE && *UI == U); + SDNode *User = *UI; // This node is about to morph, remove its old self from the CSE maps. - RemoveNodeFromCSEMaps(U); - int operandNum = 0; - for (SDNode::op_iterator I = U->op_begin(), E = U->op_end(); - I != E; ++I, ++operandNum) - if (I->getVal() == From) { - const SDValue &ToOp = To[I->getSDValue().getResNo()]; - From->removeUser(operandNum, U); - *I = ToOp; - I->setUser(U); - ToOp.getNode()->addUser(operandNum, U); - } + RemoveNodeFromCSEMaps(User); - // Now that we have modified U, add it back to the CSE maps. If it already - // exists there, recursively merge the results together. - if (SDNode *Existing = AddNonLeafNodeToCSEMaps(U)) { - ReplaceAllUsesWith(U, Existing, UpdateListener); - // U is now dead. Inform the listener if it exists and delete it. - if (UpdateListener) - UpdateListener->NodeDeleted(U, Existing); - DeleteNodeNotInCSEMaps(U); - } else { - // If the node doesn't already exist, we updated it. Inform a listener if - // it exists. - if (UpdateListener) - UpdateListener->NodeUpdated(U); - } + // A user can appear in a use list multiple times, and when this + // happens the uses are usually next to each other in the list. + // To help reduce the number of CSE recomputations, process all + // the uses of this user that we can find this way. + do { + SDUse &Use = UI.getUse(); + const SDValue &ToOp = To[Use.getResNo()]; + ++UI; + Use.set(ToOp); + } while (UI != UE && *UI == User); + + // Now that we have modified User, add it back to the CSE maps. If it + // already exists there, recursively merge the results together. + AddModifiedNodeToCSEMaps(User, UpdateListener); } } /// ReplaceAllUsesOfValueWith - Replace any uses of From with To, leaving -/// uses of other values produced by From.getVal() alone. The Deleted vector is -/// handled the same way as for ReplaceAllUsesWith. +/// uses of other values produced by From.getNode() alone. The Deleted +/// vector is handled the same way as for ReplaceAllUsesWith. void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To, DAGUpdateListener *UpdateListener){ // Handle the really simple, really trivial case efficiently. @@ -4550,60 +5123,67 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To, return; } - // Get all of the users of From.getNode(). We want these in a nice, - // deterministically ordered and uniqued set, so we use a SmallSetVector. - SmallSetVector<SDNode*, 16> Users(From.getNode()->use_begin(), From.getNode()->use_end()); + // Iterate over just the existing users of From. See the comments in + // the ReplaceAllUsesWith above. + SDNode::use_iterator UI = From.getNode()->use_begin(), + UE = From.getNode()->use_end(); + while (UI != UE) { + SDNode *User = *UI; + bool UserRemovedFromCSEMaps = false; + + // A user can appear in a use list multiple times, and when this + // happens the uses are usually next to each other in the list. + // To help reduce the number of CSE recomputations, process all + // the uses of this user that we can find this way. + do { + SDUse &Use = UI.getUse(); + + // Skip uses of different values from the same node. + if (Use.getResNo() != From.getResNo()) { + ++UI; + continue; + } - while (!Users.empty()) { - // We know that this user uses some value of From. If it is the right - // value, update it. - SDNode *User = Users.back(); - Users.pop_back(); - - // Scan for an operand that matches From. - SDNode::op_iterator Op = User->op_begin(), E = User->op_end(); - for (; Op != E; ++Op) - if (*Op == From) break; - - // If there are no matches, the user must use some other result of From. - if (Op == E) continue; - - // Okay, we know this user needs to be updated. Remove its old self - // from the CSE maps. - RemoveNodeFromCSEMaps(User); - - // Update all operands that match "From" in case there are multiple uses. - for (; Op != E; ++Op) { - if (*Op == From) { - From.getNode()->removeUser(Op-User->op_begin(), User); - *Op = To; - Op->setUser(User); - To.getNode()->addUser(Op-User->op_begin(), User); + // If this node hasn't been modified yet, it's still in the CSE maps, + // so remove its old self from the CSE maps. + if (!UserRemovedFromCSEMaps) { + RemoveNodeFromCSEMaps(User); + UserRemovedFromCSEMaps = true; } - } - + + ++UI; + Use.set(To); + } while (UI != UE && *UI == User); + + // We are iterating over all uses of the From node, so if a use + // doesn't use the specific value, no changes are made. + if (!UserRemovedFromCSEMaps) + continue; + // Now that we have modified User, add it back to the CSE maps. If it // already exists there, recursively merge the results together. - SDNode *Existing = AddNonLeafNodeToCSEMaps(User); - if (!Existing) { - if (UpdateListener) UpdateListener->NodeUpdated(User); - continue; // Continue on to next user. - } - - // If there was already an existing matching node, use ReplaceAllUsesWith - // to replace the dead one with the existing one. This can cause - // recursive merging of other unrelated nodes down the line. - ReplaceAllUsesWith(User, Existing, UpdateListener); - - // User is now dead. Notify a listener if present. - if (UpdateListener) UpdateListener->NodeDeleted(User, Existing); - DeleteNodeNotInCSEMaps(User); + AddModifiedNodeToCSEMaps(User, UpdateListener); + } +} + +namespace { + /// UseMemo - This class is used by SelectionDAG::ReplaceAllUsesOfValuesWith + /// to record information about a use. + struct UseMemo { + SDNode *User; + unsigned Index; + SDUse *Use; + }; + + /// operator< - Sort Memos by User. + bool operator<(const UseMemo &L, const UseMemo &R) { + return (intptr_t)L.User < (intptr_t)R.User; } } /// ReplaceAllUsesOfValuesWith - Replace any uses of From with To, leaving -/// uses of other values produced by From.getVal() alone. The same value may -/// appear in both the From and To list. The Deleted vector is +/// uses of other values produced by From.getNode() alone. The same value +/// may appear in both the From and To list. The Deleted vector is /// handled the same way as for ReplaceAllUsesWith. void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From, const SDValue *To, @@ -4613,57 +5193,50 @@ void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From, if (Num == 1) return ReplaceAllUsesOfValueWith(*From, *To, UpdateListener); - SmallVector<std::pair<SDNode *, unsigned>, 16> Users; - for (unsigned i = 0; i != Num; ++i) - for (SDNode::use_iterator UI = From[i].getNode()->use_begin(), - E = From[i].getNode()->use_end(); UI != E; ++UI) - Users.push_back(std::make_pair(*UI, i)); + // Read up all the uses and make records of them. This helps + // processing new uses that are introduced during the + // replacement process. + SmallVector<UseMemo, 4> Uses; + for (unsigned i = 0; i != Num; ++i) { + unsigned FromResNo = From[i].getResNo(); + SDNode *FromNode = From[i].getNode(); + for (SDNode::use_iterator UI = FromNode->use_begin(), + E = FromNode->use_end(); UI != E; ++UI) { + SDUse &Use = UI.getUse(); + if (Use.getResNo() == FromResNo) { + UseMemo Memo = { *UI, i, &Use }; + Uses.push_back(Memo); + } + } + } - while (!Users.empty()) { + // Sort the uses, so that all the uses from a given User are together. + std::sort(Uses.begin(), Uses.end()); + + for (unsigned UseIndex = 0, UseIndexEnd = Uses.size(); + UseIndex != UseIndexEnd; ) { // We know that this user uses some value of From. If it is the right // value, update it. - SDNode *User = Users.back().first; - unsigned i = Users.back().second; - Users.pop_back(); - - // Scan for an operand that matches From. - SDNode::op_iterator Op = User->op_begin(), E = User->op_end(); - for (; Op != E; ++Op) - if (*Op == From[i]) break; - - // If there are no matches, the user must use some other result of From. - if (Op == E) continue; - - // Okay, we know this user needs to be updated. Remove its old self - // from the CSE maps. + SDNode *User = Uses[UseIndex].User; + + // This node is about to morph, remove its old self from the CSE maps. RemoveNodeFromCSEMaps(User); - - // Update all operands that match "From" in case there are multiple uses. - for (; Op != E; ++Op) { - if (*Op == From[i]) { - From[i].getNode()->removeUser(Op-User->op_begin(), User); - *Op = To[i]; - Op->setUser(User); - To[i].getNode()->addUser(Op-User->op_begin(), User); - } - } - + + // The Uses array is sorted, so all the uses for a given User + // are next to each other in the list. + // To help reduce the number of CSE recomputations, process all + // the uses of this user that we can find this way. + do { + unsigned i = Uses[UseIndex].Index; + SDUse &Use = *Uses[UseIndex].Use; + ++UseIndex; + + Use.set(To[i]); + } while (UseIndex != UseIndexEnd && Uses[UseIndex].User == User); + // Now that we have modified User, add it back to the CSE maps. If it // already exists there, recursively merge the results together. - SDNode *Existing = AddNonLeafNodeToCSEMaps(User); - if (!Existing) { - if (UpdateListener) UpdateListener->NodeUpdated(User); - continue; // Continue on to next user. - } - - // If there was already an existing matching node, use ReplaceAllUsesWith - // to replace the dead one with the existing one. This can cause - // recursive merging of other unrelated nodes down the line. - ReplaceAllUsesWith(User, Existing, UpdateListener); - - // User is now dead. Notify a listener if present. - if (UpdateListener) UpdateListener->NodeDeleted(User, Existing); - DeleteNodeNotInCSEMaps(User); + AddModifiedNodeToCSEMaps(User, UpdateListener); } } @@ -4765,9 +5338,8 @@ GlobalAddressSDNode::GlobalAddressSDNode(bool isTarget, const GlobalValue *GA, MemSDNode::MemSDNode(unsigned Opc, SDVTList VTs, MVT memvt, const Value *srcValue, int SVO, unsigned alignment, bool vol) - : SDNode(Opc, VTs), MemoryVT(memvt), SrcValue(srcValue), SVOffset(SVO), - Flags(encodeMemSDNodeFlags(vol, alignment)) { - + : SDNode(Opc, VTs), MemoryVT(memvt), SrcValue(srcValue), SVOffset(SVO) { + SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, vol, alignment); assert(isPowerOf2_32(alignment) && "Alignment is not a power of 2!"); assert(getAlignment() == alignment && "Alignment representation error!"); assert(isVolatile() == vol && "Volatile representation error!"); @@ -4777,8 +5349,30 @@ MemSDNode::MemSDNode(unsigned Opc, SDVTList VTs, const SDValue *Ops, unsigned NumOps, MVT memvt, const Value *srcValue, int SVO, unsigned alignment, bool vol) : SDNode(Opc, VTs, Ops, NumOps), - MemoryVT(memvt), SrcValue(srcValue), SVOffset(SVO), - Flags(vol | ((Log2_32(alignment) + 1) << 1)) { + MemoryVT(memvt), SrcValue(srcValue), SVOffset(SVO) { + SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, vol, alignment); + assert(isPowerOf2_32(alignment) && "Alignment is not a power of 2!"); + assert(getAlignment() == alignment && "Alignment representation error!"); + assert(isVolatile() == vol && "Volatile representation error!"); +} + +MemSDNode::MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, MVT memvt, + const Value *srcValue, int SVO, + unsigned alignment, bool vol) + : SDNode(Opc, dl, VTs), MemoryVT(memvt), SrcValue(srcValue), SVOffset(SVO) { + SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, vol, alignment); + assert(isPowerOf2_32(alignment) && "Alignment is not a power of 2!"); + assert(getAlignment() == alignment && "Alignment representation error!"); + assert(isVolatile() == vol && "Volatile representation error!"); +} + +MemSDNode::MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, + const SDValue *Ops, + unsigned NumOps, MVT memvt, const Value *srcValue, + int SVO, unsigned alignment, bool vol) + : SDNode(Opc, dl, VTs, Ops, NumOps), + MemoryVT(memvt), SrcValue(srcValue), SVOffset(SVO) { + SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, vol, alignment); assert(isPowerOf2_32(alignment) && "Alignment is not a power of 2!"); assert(getAlignment() == alignment && "Alignment representation error!"); assert(isVolatile() == vol && "Volatile representation error!"); @@ -4843,7 +5437,7 @@ bool SDNode::hasNUsesOfValue(unsigned NUses, unsigned Value) const { // TODO: Only iterate over uses of a given value of the node for (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI) { - if (UI.getUse().getSDValue().getResNo() == Value) { + if (UI.getUse().getResNo() == Value) { if (NUses == 0) return false; --NUses; @@ -4861,7 +5455,7 @@ bool SDNode::hasAnyUseOfValue(unsigned Value) const { assert(Value < getNumValues() && "Bad value!"); for (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI) - if (UI.getUse().getSDValue().getResNo() == Value) + if (UI.getUse().getResNo() == Value) return true; return false; @@ -4894,7 +5488,7 @@ bool SDValue::isOperandOf(SDNode *N) const { bool SDNode::isOperandOf(SDNode *N) const { for (unsigned i = 0, e = N->NumOperands; i != e; ++i) - if (this == N->OperandList[i].getVal()) + if (this == N->OperandList[i].getNode()) return true; return false; } |