diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h --- a/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -275,6 +275,7 @@ struct SDNodeExtraInfo { CallSiteInfo CSInfo; MDNode *HeapAllocSite = nullptr; + MDNode *PCSections = nullptr; bool NoMerge = false; }; /// Out-of-line extra information for SDNodes. @@ -336,6 +337,19 @@ virtual void anchor(); }; + struct DAGNodeInsertedListener : public DAGUpdateListener { + std::function Callback; + + DAGNodeInsertedListener(SelectionDAG &DAG, + std::function Callback) + : DAGUpdateListener(DAG), Callback(std::move(Callback)) {} + + void NodeInserted(SDNode *N) override { Callback(N); } + + private: + virtual void anchor(); + }; + /// Help to insert SDNodeFlags automatically in transforming. Use /// RAII to save and resume flags in current scope. class FlagInserter { @@ -2158,6 +2172,15 @@ auto I = SDEI.find(Node); return I != SDEI.end() ? I->second.HeapAllocSite : nullptr; } + /// Set PCSections to be associated with Node. + void addPCSections(const SDNode *Node, MDNode *MD) { + SDEI[Node].PCSections = MD; + } + /// Return PCSections associated with Node, or nullptr if none exists. + MDNode *getPCSections(const SDNode *Node) const { + auto It = SDEI.find(Node); + return It != SDEI.end() ? It->second.PCSections : nullptr; + } /// Set NoMergeSiteInfo to be associated with Node if NoMerge is true. void addNoMergeSiteInfo(const SDNode *Node, bool NoMerge) { if (NoMerge) diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp --- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -890,6 +890,9 @@ MI->setFlag(MachineInstr::MIFlag::NoMerge); } + if (MDNode *MD = DAG->getPCSections(Node)) + MI->setPCSections(MF, MD); + return MI; }; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -92,6 +92,7 @@ void SelectionDAG::DAGUpdateListener::NodeInserted(SDNode *) {} void SelectionDAG::DAGNodeDeletedListener::anchor() {} +void SelectionDAG::DAGNodeInsertedListener::anchor() {} #define DEBUG_TYPE "selectiondag" diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1123,12 +1123,36 @@ CurInst = &I; + // Set inserted listener only if required. + bool NodeInserted = false; + std::unique_ptr InsertedListener; + MDNode *PCSectionsMD = I.getMetadata(LLVMContext::MD_pcsections); + if (PCSectionsMD) { + InsertedListener = std::make_unique( + DAG, [&](SDNode *) { NodeInserted = true; }); + } + visit(I.getOpcode(), I); if (!I.isTerminator() && !HasTailCall && !isa(I)) // statepoints handle their exports internally CopyToExportRegsIfNeeded(&I); + // Handle metadata. + if (PCSectionsMD) { + auto It = NodeMap.find(&I); + if (It != NodeMap.end()) { + DAG.addPCSections(It->second.getNode(), PCSectionsMD); + } else if (NodeInserted) { + // This should not happen; if it does, don't let it go unnoticed so we can + // fix it. Relevant visit*() function is probably missing a setValue(). + errs() << "warning: loosing !pcsections metadata [" + << I.getModule()->getName() << "]\n"; + LLVM_DEBUG(I.dump()); + assert(false); + } + } + CurInst = nullptr; } @@ -2536,6 +2560,8 @@ MVT::Other, getControlRoot(), Cond, DAG.getBasicBlock(CB.TrueBB)); + setValue(CurInst, BrCond); + // Insert the false branch. Do this even if it's a fall through branch, // this makes it easier to do DAG optimizations which require inverting // the branch condition. @@ -4295,6 +4321,7 @@ SDValue StoreNode = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, makeArrayRef(Chains.data(), ChainI)); + setValue(&I, StoreNode); DAG.setRoot(StoreNode); } @@ -4659,7 +4686,9 @@ TLI.getFenceOperandTy(DAG.getDataLayout())); Ops[2] = DAG.getTargetConstant(I.getSyncScopeID(), dl, TLI.getFenceOperandTy(DAG.getDataLayout())); - DAG.setRoot(DAG.getNode(ISD::ATOMIC_FENCE, dl, MVT::Other, Ops)); + SDValue N = DAG.getNode(ISD::ATOMIC_FENCE, dl, MVT::Other, Ops); + setValue(&I, N); + DAG.setRoot(N); } void SelectionDAGBuilder::visitAtomicLoad(const LoadInst &I) { @@ -4745,13 +4774,14 @@ // TODO: Once this is better exercised by tests, it should be merged with // the normal path for stores to prevent future divergence. SDValue S = DAG.getStore(InChain, dl, Val, Ptr, MMO); + setValue(&I, S); DAG.setRoot(S); return; } SDValue OutChain = DAG.getAtomic(ISD::ATOMIC_STORE, dl, MemVT, InChain, Ptr, Val, MMO); - + setValue(&I, OutChain); DAG.setRoot(OutChain); } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -997,6 +997,15 @@ if (ISelPosition == SelectionDAG::allnodes_iterator(N)) ++ISelPosition; } + + /// NodeInserted - Handle new nodes inserted into the graph: propagate + /// metadata from root nodes that also applies to new nodes, in case the root + /// is later deleted. + void NodeInserted(SDNode *N) override { + SDNode *CurNode = &*ISelPosition; + if (MDNode *MD = DAG.getPCSections(CurNode)) + DAG.addPCSections(N, MD); + } }; } // end anonymous namespace @@ -1073,7 +1082,7 @@ ++ISelPosition; // Make sure that ISelPosition gets properly updated when nodes are deleted - // in calls made from this function. + // in calls made from this function. New nodes inherit relevant metadata. ISelUpdater ISU(*CurDAG, ISelPosition); // The AllNodes list is now topological-sorted. Visit the