From 2d389c242a0afc60d1fbc3dd78732f79ac72cb1b Mon Sep 17 00:00:00 2001 From: Zelinskiy Date: Sun, 19 Mar 2023 23:18:21 +0300 Subject: [PATCH 1/9] 0.001 --- include/tsar/Analysis/Clang/SourceCFG.h | 453 ++++++++++++ lib/Analysis/Clang/CMakeLists.txt | 2 +- lib/Analysis/Clang/SourceCFG.cpp | 886 ++++++++++++++++++++++++ 3 files changed, 1340 insertions(+), 1 deletion(-) create mode 100644 include/tsar/Analysis/Clang/SourceCFG.h create mode 100644 lib/Analysis/Clang/SourceCFG.cpp diff --git a/include/tsar/Analysis/Clang/SourceCFG.h b/include/tsar/Analysis/Clang/SourceCFG.h new file mode 100644 index 00000000..1f97dd96 --- /dev/null +++ b/include/tsar/Analysis/Clang/SourceCFG.h @@ -0,0 +1,453 @@ +#ifndef TSAR_CLANG_INCLUDE_SOURCECFG_H +#define TSAR_CLANG_INCLUDE_SOURCECFG_H + +#include "tsar/Analysis/Clang/Passes.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace tsar { + +class SourceCFGNode; +class SourceCFGEdge; +class SourceCFG; +class SourceCFGBuilder; +using SourceCFGNodeBase=llvm::DGNode; +using SourceCFGEdgeBase=llvm::DGEdge; +using SourceCFGBase=llvm::DirectedGraph; +using StmtStringType=std::string; + +struct Op { + union { + clang::Stmt *S; + clang::VarDecl *VD; + }; + bool IsStmt; + Op(clang::VarDecl *_VD) : VD(_VD), IsStmt(false) {} + Op(clang::Stmt *_S) : S(_S), IsStmt(true) {} +}; + +enum NodeOpTypes {NativeNode, WrapperNode, ReferenceNode}; + +struct NodeOp { + bool isReferred; + NodeOp() : isReferred(false) {} + NodeOp(const NodeOp &_N) : isReferred(_N.isReferred) {} + virtual void print(StmtStringType &) = 0; + virtual NodeOpTypes getType() = 0; + virtual std::string getOpAddr() = 0; + void printRefDecl(StmtStringType &ResStr) { + if (isReferred) { + ResStr+=" Leaves; + WrapperNodeOp(tsar::Op _O) : O(_O) {} + void print(StmtStringType &ResStr) override; + NodeOpTypes getType() override { return WrapperNode; } + std::string getOpAddr() override { + return "0x"+(std::stringstream()<isReferred=true; + } + void print(StmtStringType &ResStr) override { + ResStr+="<"+ReferenceName+Referred->getOpAddr()+"_REFERRENCE_>"; + } + NodeOpTypes getType() override { return ReferenceNode; } + std::string getOpAddr() override { + return "0x"+(std::stringstream()<; + using iterator=OpStorageType::iterator; + SourceBasicBlock() = default; + SourceBasicBlock(NodeOp *_Op) : mOps(1, _Op) {} + SourceBasicBlock(std::initializer_list _Ops) : mOps(_Ops) {} + SourceBasicBlock(const llvm::SmallVectorImpl &_Ops) + : mOps(_Ops.begin(), _Ops.end()) {} + SourceBasicBlock(const SourceBasicBlock &_SBB) = delete; + SourceBasicBlock(SourceBasicBlock &&_SBB) = delete; + SourceBasicBlock &operator=(const SourceBasicBlock &_SBB) = delete; + SourceBasicBlock &operator=(SourceBasicBlock &&_SBB) = delete; + iterator addOp(NodeOp *_Op) { mOps.push_back(_Op); return mOps.end()-1; } + void addOpFront(NodeOp *_Op) { mOps.insert(mOps.begin(), _Op); } + template + iterator addOp(It begin, It end) { + for (auto I=begin; I!=end; ++I) mOps.push_back(*I); return mOps.end()-1; + } + void clear() { + for (auto O : mOps) + delete O; + mOps.clear(); + } + unsigned size() const { return mOps.size(); } + iterator begin() { return mOps.begin(); } + iterator end() { return mOps.end(); } + explicit operator std::string() const; + void decrease(int NewSize) { + mOps.resize(NewSize); + } + NodeOp &operator[](int Index) { return *mOps[Index]; } +private: + OpStorageType mOps; +}; + +class SourceCFGEdge : public SourceCFGEdgeBase { +public: + enum class EdgeKind {Default, True, False, Continue, Break, ToCase}; + SourceCFGEdge(SourceCFGNode &_TargetNode, EdgeKind _Kind) + : SourceCFGEdgeBase(_TargetNode), mKind(_Kind) {} + SourceCFGEdge(const SourceCFGEdge &_Edge) + : SourceCFGEdgeBase(_Edge), mKind(_Edge.mKind) {} + SourceCFGEdge(SourceCFGEdge &&_Edge) + : SourceCFGEdgeBase(std::move(_Edge)), mKind(_Edge.mKind) {} + SourceCFGEdge &operator=(const SourceCFGEdge &_Edge) = default; + EdgeKind getKind() const { return mKind; } + explicit operator std::string() const { + switch (mKind) { + case EdgeKind::True: + return "T"; + case EdgeKind::False: + return "F"; + case EdgeKind::Default: + default: + return ""; + } + } +private: + EdgeKind mKind; +}; + +class SourceCFGNode : public SourceCFGNodeBase { + friend class SourceCFG; + friend class SourceCFGBuilder; +public: + enum class NodeKind {Default, GraphStart, GraphStop}; + SourceCFGNode(const NodeKind _Kind) : mKind(_Kind) {} + SourceCFGNode(const SourceCFGNode &_Node) = delete; + SourceCFGNode(SourceCFGNode &&_Node) = delete; + SourceCFGNode &operator=(const SourceCFGNode &_Node) = delete; + SourceCFGNode &operator=(SourceCFGNode &&_Node) = delete; + SourceBasicBlock::iterator addToNode(NodeOp *_Op) { return SBB.addOp(_Op); } + template + SourceBasicBlock::iterator addToNode(It begin, It end) { + return SBB.addOp(begin, end); + } + void addToNodeFront(NodeOp *_Op) { SBB.addOpFront(_Op); } + NodeKind getKind() const { return mKind; } + void setKind(NodeKind _Kind) { mKind=_Kind; } + void merge(SourceCFGNode &NodeToAttach); + unsigned size() { return SBB.size(); } + explicit operator std::string() const { + switch (mKind) { + case NodeKind::GraphStart: + return "START"; + case NodeKind::GraphStop: + return "STOP"; + case NodeKind::Default: + return (std::string)SBB; + } + } + inline SourceCFGEdge *addNewEdge(SourceCFGNode &TargetNode, + SourceCFGEdge::EdgeKind Ekind) { + SourceCFGEdge *ResEdge=new SourceCFGEdge(TargetNode, Ekind); + if (addEdge(*ResEdge)) + return ResEdge; + else { + delete ResEdge; + return nullptr; + } + } + SourceCFG *getParent() { return OwningGraph; } + void printAsOperand(llvm::raw_ostream &OS, bool B) {} + NodeOp &operator[](int Index) { return SBB[Index]; } +private: + SourceCFG *OwningGraph; + SourceBasicBlock SBB; + NodeKind mKind; +}; + +class SourceCFG : public SourceCFGBase { +public: + SourceCFG(const std::string &_mFunctionName) : mFunctionName(_mFunctionName), + mStartNode(&emplaceNode(SourceCFGNode::NodeKind::GraphStart)), + mStopNode(&emplaceNode(SourceCFGNode::NodeKind::GraphStop)) {} + ~SourceCFG() { + for (auto N : Nodes) { + for (auto E : N->getEdges()) + delete E; + delete N; + } + } + inline bool addNode(SourceCFGNode &N) { + return SourceCFGBase::addNode(N)?N.OwningGraph=this, true:false; + } + SourceCFGNode &emplaceNode(SourceCFGNode::NodeKind _Nkind) { + SourceCFGNode *CurrNode=new SourceCFGNode(_Nkind); + addNode(*CurrNode); + return *CurrNode; + } + inline void bindNodes(SourceCFGNode &SourceNode, SourceCFGNode &TargetNode, + SourceCFGEdge::EdgeKind _Ekind) { + connect(SourceNode, TargetNode, *(new SourceCFGEdge(TargetNode, _Ekind))); + } + inline SourceCFGNode *getStartNode() const { return mStartNode; } + inline SourceCFGNode *getStopNode() const { return mStopNode; } + inline llvm::StringRef getName() const { return mFunctionName; } + void mergeNodes(SourceCFGNode &AbsorbNode, SourceCFGNode &OutgoingNode); + void deleteEdge(SourceCFGEdge &_Edge); + bool findParentNodes(const SourceCFGNode &RequestedNode, + llvm::SmallVectorImpl &ParentNodes) { + bool Result=false; + for (auto N : *this) + if (N->hasEdgeTo(RequestedNode)) { + ParentNodes.push_back(N); + Result=true; + } + return Result; + } + void deleteNode(SourceCFGNode &_Node); + void view(const SourceCFGNode &SCFGN, + const llvm::Twine &Name="source cfg") const { + llvm::ViewGraph(this, Name, false, + llvm::DOTGraphTraits::getGraphName(this)); + } + std::string write(const SourceCFGNode &SCFGN, + const llvm::Twine &Name="source cfg") const { + return llvm::WriteGraph(this, Name, false, + llvm::DOTGraphTraits::getGraphName(this)); + } + SourceCFGNode *splitNode(SourceCFGNode &Node, int It); +private: + std::string mFunctionName; + SourceCFGNode *mStartNode, *mStopNode; +}; + +class SourceCFGBuilder { +public: + SourceCFGBuilder() : mSCFG(nullptr), mEntryNode(nullptr), + mNodeToAdd(nullptr), mTreeTopParentPtr(nullptr) {} + SourceCFG *populate(clang::FunctionDecl *Decl); +private: + using MarkedOutsType=llvm::DenseMap; + using OutsType=llvm::SmallPtrSet; + using ParserType=void (SourceCFGBuilder::*)(clang::Stmt*); + struct LabelInfo { + SourceCFGNode *Node; + int LabelIt; + }; + struct GotoInfo { + std::map::iterator GotoNodeIt; + int GotoIt; + }; + static bool compareLabelInfo(const LabelInfo &LI1, const LabelInfo &LI2) { + return LI1.LabelIt mParsers; + SourceCFG *mSCFG; + llvm::DenseMap mLabels; + llvm::DenseMap mCases; + std::map mGotos; + SourceCFGNode *mEntryNode, *mNodeToAdd; + std::stack mDirectOut; + std::stack mContinueOut, mBreakOut; + NodeOp *mTreeTopParentPtr; +}; +} //namespace tsar + +namespace llvm { + +class ClangSourceCFGPass : public FunctionPass, private bcl::Uncopyable { +public: + static char ID; + ClangSourceCFGPass() : FunctionPass(ID), mSCFG(nullptr) { + initializeClangSourceCFGPassPass(*PassRegistry::getPassRegistry()); + } + bool runOnFunction(Function &F) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + void releaseMemory() { + mSCFGBuilder=tsar::SourceCFGBuilder(); + if (mSCFG) { + delete mSCFG; + mSCFG=nullptr; + } + } + inline tsar::SourceCFG &getSourceCFG() { return *mSCFG; } +private: + tsar::SourceCFGBuilder mSCFGBuilder; + tsar::SourceCFG *mSCFG; +}; + +template<> struct GraphTraits { + using NodeRef=tsar::SourceCFGNode*; + static tsar::SourceCFGNode *SCFGGetTargetNode(tsar::SourceCFGEdge *E) { + return &E->getTargetNode(); + } + using ChildIteratorType=mapped_iterator; + using ChildEdgeIteratorType=tsar::SourceCFGNode::iterator; + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { + return ChildIteratorType(N->begin(), &SCFGGetTargetNode); + } + static ChildIteratorType child_end(NodeRef N) { + return ChildIteratorType(N->end(), &SCFGGetTargetNode); + } + static ChildEdgeIteratorType child_edge_begin(NodeRef N) { + return N->begin(); + } + static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } +}; + +template<> struct GraphTraits : + public GraphTraits { + using nodes_iterator=tsar::SourceCFG::iterator; + static NodeRef getEntryNode(tsar::SourceCFG *mSCFG) { + return mSCFG->getStartNode(); + } + static nodes_iterator nodes_begin(tsar::SourceCFG *mSCFG) { + return mSCFG->begin(); + } + static nodes_iterator nodes_end(tsar::SourceCFG *mSCFG) { + return mSCFG->end(); + } + using EdgeRef=tsar::SourceCFGEdge*; + static NodeRef edge_dest(EdgeRef E) { return &E->getTargetNode(); } + static unsigned size(tsar::SourceCFG *mSCFG) { return mSCFG->size(); } +}; + +template<> struct GraphTraits { + using NodeRef=const tsar::SourceCFGNode*; + static const tsar::SourceCFGNode *SCFGGetTargetNode( + const tsar::SourceCFGEdge *E) { return &E->getTargetNode(); } + using ChildIteratorType=mapped_iterator; + using ChildEdgeIteratorType=tsar::SourceCFGNode::const_iterator; + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { + return ChildIteratorType(N->begin(), &SCFGGetTargetNode); + } + static ChildIteratorType child_end(NodeRef N) { + return ChildIteratorType(N->end(), &SCFGGetTargetNode); + } + static ChildEdgeIteratorType child_edge_begin(NodeRef N) { + return N->begin(); + } + static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } +}; + +template<> struct GraphTraits : + public GraphTraits { + using nodes_iterator=tsar::SourceCFG::const_iterator; + static NodeRef getEntryNode(const tsar::SourceCFG *mSCFG) { + return mSCFG->getStartNode(); + } + static nodes_iterator nodes_begin(const tsar::SourceCFG *mSCFG) { + return mSCFG->begin(); + } + static nodes_iterator nodes_end(const tsar::SourceCFG *mSCFG) { + return mSCFG->end(); + } + using EdgeRef=const tsar::SourceCFGEdge*; + static NodeRef edge_dest(EdgeRef E) { return &E->getTargetNode(); } + static unsigned size(const tsar::SourceCFG *mSCFG) { return mSCFG->size(); } +}; + +template<> struct DOTGraphTraits : + public DefaultDOTGraphTraits { + DOTGraphTraits(bool IsSimple=false) : DefaultDOTGraphTraits(IsSimple) {} + static std::string getGraphName(const tsar::SourceCFG *mSCFG) { + return "mSCFG"; + } + std::string getNodeLabel(tsar::SourceCFGNode *Node, tsar::SourceCFG *mSCFG) { + return (std::string)*Node; + } + std::string getEdgeSourceLabel(tsar::SourceCFGNode *Node, + GraphTraits::ChildIteratorType It) { + return (std::string)**It.getCurrent(); + } +}; + +} //namespace llvm +#endif//TSAR_CLANG_INCLUDE_SOURCECFG_H \ No newline at end of file diff --git a/lib/Analysis/Clang/CMakeLists.txt b/lib/Analysis/Clang/CMakeLists.txt index 9f831e92..f26760ff 100644 --- a/lib/Analysis/Clang/CMakeLists.txt +++ b/lib/Analysis/Clang/CMakeLists.txt @@ -2,7 +2,7 @@ set(ANALYSIS_SOURCES Passes.cpp DIMemoryMatcher.cpp NoMacroAssert.cpp MemoryMatcher.cpp LoopMatcher.cpp ExpressionMatcher.cpp CanonicalLoop.cpp PerfectLoop.cpp GlobalInfoExtractor.cpp ControlFlowTraits.cpp RegionDirectiveInfo.cpp VariableCollector.cpp ASTDependenceAnalysis.cpp - IncludeTree.cpp Utils.cpp) + IncludeTree.cpp Utils.cpp SourceCFG.cpp) if(MSVC_IDE) diff --git a/lib/Analysis/Clang/SourceCFG.cpp b/lib/Analysis/Clang/SourceCFG.cpp new file mode 100644 index 00000000..75c49a86 --- /dev/null +++ b/lib/Analysis/Clang/SourceCFG.cpp @@ -0,0 +1,886 @@ +#include "tsar/Analysis/Clang/SourceCFG.h" +#include "tsar/Support/PassGroupRegistry.h" +#include "tsar/Core/Query.h" +#include "tsar/Analysis/Memory/Utils.h" +#include "tsar/Support/MetadataUtils.h" +#include "tsar/Core/TransformationContext.h" +#include "tsar/Frontend/Clang/TransformationContext.h" +#include + +using namespace tsar; +using namespace llvm; +using namespace clang; +using namespace std; + +std::map SourceCFGBuilder:: + mParsers { + {Stmt::StmtClass::CompoundStmtClass,(ParserType)&tsar::SourceCFGBuilder:: + parseCompoundStmt}, + {Stmt::StmtClass::IfStmtClass, (ParserType)&tsar::SourceCFGBuilder:: + parseIfStmt}, + {Stmt::StmtClass::WhileStmtClass, (ParserType)&tsar::SourceCFGBuilder:: + parseWhileStmt}, + {Stmt::StmtClass::DoStmtClass, (ParserType)&tsar::SourceCFGBuilder:: + parseDoStmt}, + {Stmt::StmtClass::ContinueStmtClass, (ParserType)&tsar::SourceCFGBuilder:: + parseContinueStmt}, + {Stmt::StmtClass::BreakStmtClass, (ParserType)&tsar::SourceCFGBuilder:: + parseBreakStmt}, + {Stmt::StmtClass::ReturnStmtClass, (ParserType)&tsar::SourceCFGBuilder:: + parseReturnStmt}, + {Stmt::StmtClass::LabelStmtClass, (ParserType)&tsar::SourceCFGBuilder:: + parseLabelStmt}, + {Stmt::StmtClass::GotoStmtClass, (ParserType)&tsar::SourceCFGBuilder:: + parseGotoStmt}, + {Stmt::StmtClass::DeclStmtClass, (ParserType)&tsar::SourceCFGBuilder:: + parseDeclStmtWrapper}, + {Stmt::StmtClass::ForStmtClass, (ParserType)&tsar::SourceCFGBuilder:: + parseForStmt}, + //{Stmt::StmtClass::SwitchStmtClass, (ParserType)&tsar::SourceCFGBuilder:: + //parseSwitchStmt}, Not working + {Stmt::StmtClass::CaseStmtClass, (ParserType)&tsar::SourceCFGBuilder:: + parseCaseStmt} +}; + +inline void NodeOp::printASTNode(StmtStringType &ResStr, tsar::Op O) { + if (O.IsStmt) + printASTStmtNode(ResStr, O.S); + else + printASTVarDeclNode(ResStr, O.VD); +} + +inline void NodeOp::printASTVarDeclNode(StmtStringType &ResStr, VarDecl *VD) { + ResStr+=VD->getNameAsString()+"="; + printASTStmtNode(ResStr, VD->getInit()); +} + +void NodeOp::printASTStmtNode(StmtStringType &ResStr, Stmt *S) { + switch (S->getStmtClass()) { + case Stmt::StmtClass::UnaryOperatorClass: + if (((clang::UnaryOperator*)S)->isPostfix()) { + printASTNode(ResStr, ((clang::UnaryOperator*)S)->getSubExpr()); + ResStr+=((clang::UnaryOperator*)S)->getOpcodeStr( + ((clang::UnaryOperator*)S)->getOpcode()); + } + else { + ResStr+=((clang::UnaryOperator*)S)->getOpcodeStr( + ((clang::UnaryOperator*)S)->getOpcode()); + printASTNode(ResStr, ((clang::UnaryOperator*)S)->getSubExpr()); + } + break; + case Stmt::StmtClass::BinaryOperatorClass: + case Stmt::StmtClass::CompoundAssignOperatorClass: + printASTNode(ResStr, ((clang::BinaryOperator*)S)->getLHS()); + ResStr+=((clang::BinaryOperator*)S)->getOpcodeStr(); + printASTNode(ResStr, ((clang::BinaryOperator*)S)->getRHS()); + break; + case Stmt::StmtClass::DeclRefExprClass: + ResStr+=((DeclRefExpr*)S)->getNameInfo().getAsString(); + break; + case Stmt::StmtClass::IntegerLiteralClass: + { + SmallString<5> BufferStr; + ((IntegerLiteral*)S)->getValue().toString(BufferStr, 10, false); + ResStr+=BufferStr; + } + break; + case Stmt::StmtClass::CStyleCastExprClass: + ResStr+=((Twine)"("+((CStyleCastExpr*)S)->getCastKindName()+")").str(); + break; + case Stmt::StmtClass::ParenExprClass: + ResStr+="("; + printASTNode(ResStr, ((ParenExpr*)S)->getSubExpr()); + ResStr+=")"; + break; + case Stmt::StmtClass::ImplicitCastExprClass: + printASTNode(ResStr, ((ImplicitCastExpr*)S)->getSubExpr()); + break; + case Stmt::StmtClass::IfStmtClass: + ResStr+="if ("; + printASTNode(ResStr, ((IfStmt*)S)->getCond()); + ResStr+=")"; + break; + case Stmt::StmtClass::DoStmtClass: + case Stmt::StmtClass::WhileStmtClass: + ResStr+="while ("; + printASTNode(ResStr, ((WhileStmt*)S)->getCond()); + ResStr+=")"; + break; + case Stmt::StmtClass::NullStmtClass: + ResStr+=";"; + break; + case Stmt::StmtClass::ReturnStmtClass: + if (((ReturnStmt*)S)->getRetValue()) { + ResStr+="return "; + printASTNode(ResStr, ((ReturnStmt*)S)->getRetValue()); + } + else + ResStr+="return"; + break; + case Stmt::StmtClass::ContinueStmtClass: + ResStr+="continue"; + break; + case Stmt::StmtClass::BreakStmtClass: + ResStr+="break"; + break; + case Stmt::StmtClass::GotoStmtClass: + ResStr+=("goto "+((GotoStmt*)S)->getLabel()->getName()).str(); + break; + case Stmt::StmtClass::LabelStmtClass: + ResStr+=(((LabelStmt*)S)->getDecl()->getName()+":").str(); + break; + case Stmt::StmtClass::CaseStmtClass: + ResStr+="case "; + printASTNode(ResStr, ((CaseStmt*)S)->getLHS()); + ResStr+=":"; + break; + default: + ResStr+=S->getStmtClassName(); + break; + } +} + +void WrapperNodeOp::print(StmtStringType &ResStr) { + printRefDecl(ResStr); + if (O.IsStmt) { + Expr *E=(Expr*)O.S; + switch (E->getStmtClass()) { + case Stmt::StmtClass::UnaryOperatorClass: + if (((clang::UnaryOperator*)E)->isPostfix()) { + if (Leaves[0]) + Leaves[0]->print(ResStr); + ResStr+=((clang::UnaryOperator*)E)->getOpcodeStr( + ((clang::UnaryOperator*)E)->getOpcode()); + } + else { + ResStr+=((clang::UnaryOperator*)E)->getOpcodeStr( + ((clang::UnaryOperator*)E)->getOpcode()); + if (Leaves[0]) + Leaves[0]->print(ResStr); + } + break; + case Stmt::StmtClass::CompoundAssignOperatorClass: + case Stmt::StmtClass::BinaryOperatorClass: + if (((clang::BinaryOperator*)E)->isCompoundAssignmentOp() || + !((clang::BinaryOperator*)E)->isAssignmentOp()) { + if (Leaves[0]) + Leaves[0]->print(ResStr); + ResStr+=((clang::BinaryOperator*)E)->getOpcodeStr(); + if (Leaves[1]) + Leaves[1]->print(ResStr); + } + else { + if (Leaves[1]) + Leaves[1]->print(ResStr); + ResStr+=((clang::BinaryOperator*)E)->getOpcodeStr(); + if (Leaves[0]) + Leaves[0]->print(ResStr); + } + break; + case Stmt::StmtClass::DeclRefExprClass: + ResStr+=((DeclRefExpr*)E)->getNameInfo().getAsString(); + break; + case Stmt::StmtClass::IntegerLiteralClass: + { + SmallString<5> BufferStr; + ((IntegerLiteral*)E)->getValue().toString(BufferStr, 10, false); + ResStr+=BufferStr; + } + break; + case Stmt::StmtClass::CStyleCastExprClass: + ResStr+=((Twine)"("+((CStyleCastExpr*)E)->getCastKindName()+")").str(); + break; + case Stmt::StmtClass::ParenExprClass: + ResStr+="("; + if (Leaves[0]) + Leaves[0]->print(ResStr); + ResStr+=")"; + break; + case Stmt::StmtClass::ImplicitCastExprClass: + if (Leaves[0]) + Leaves[0]->print(ResStr); + break; + case Stmt::StmtClass::ConditionalOperatorClass: + ResStr+=" - "; + if (Leaves[0]) + Leaves[0]->print(ResStr); + break; + case Stmt::StmtClass::IfStmtClass: + ResStr+="if ("; + if (Leaves[0]) + Leaves[0]->print(ResStr); + ResStr+=")"; + break; + case Stmt::StmtClass::WhileStmtClass: + case Stmt::StmtClass::DoStmtClass: + ResStr+="while ("; + if (Leaves[0]) + Leaves[0]->print(ResStr); + ResStr+=")"; + break; + case Stmt::StmtClass::ForStmtClass: + ResStr+=" - "; + if (Leaves[0]) + Leaves[0]->print(ResStr); + break; + case Stmt::StmtClass::SwitchStmtClass: + ResStr+="switch ("; + if (Leaves[0]) + Leaves[0]->print(ResStr); + ResStr+=")"; + break; + default: + ResStr+=O.S->getStmtClassName(); + break; + } + } + else { + ResStr+=O.VD->getNameAsString()+"="; + if (Leaves[0]) + Leaves[0]->print(ResStr); + } +} + +SourceBasicBlock::operator string() const { + string ResStr; + for (auto NO : mOps) { + NO->print(ResStr); + ResStr+="\n"; + } + return ResStr; +} + +void SourceCFG::deleteNode(SourceCFGNode &_Node) { + EdgeListTy EdgesToDelete; + findIncomingEdgesToNode(_Node, EdgesToDelete); + llvm::append_range(EdgesToDelete, _Node.getEdges()); + SourceCFGBase::removeNode(_Node); + for (auto E : EdgesToDelete) + delete E; + if (mStartNode==&_Node) + mStartNode=nullptr; + if (mStopNode==&_Node) + mStopNode==nullptr; + delete &_Node; +} + +void SourceCFG::deleteEdge(SourceCFGEdge &_Edge) { + for (auto N : Nodes) + for (auto E : N->getEdges()) + if (E==&_Edge) + N->removeEdge(_Edge); + delete &_Edge; +} + +void SourceCFGNode::merge(SourceCFGNode &NodeToAttach) { + for (auto E : NodeToAttach.getEdges()) { + SourceCFGNodeBase::addEdge(*E); + NodeToAttach.removeEdge(*E); + } + SBB.addOp(NodeToAttach.SBB.begin(), NodeToAttach.SBB.end()); +} + +SourceCFGNode *SourceCFG::splitNode(SourceCFGNode &Node, int It) { + if (It==0) + return &Node; + SourceCFGNode *NewNode=&emplaceNode(SourceCFGNode::NodeKind::Default); + for (auto E : Node.getEdges()) + NewNode->addEdge(*E); + Node.clear(); + bindNodes(Node, *NewNode, SourceCFGEdge::EdgeKind::Default); + NewNode->addToNode(Node.SBB.begin()+It, Node.SBB.end()); + Node.SBB.decrease(It); + return NewNode; +} + +void SourceCFG::mergeNodes(SourceCFGNode &AbsorbNode, + SourceCFGNode &OutgoingNode) { + EdgeListTy CommonEdges; + if (AbsorbNode.findEdgesTo(OutgoingNode, CommonEdges)) { + for (auto E : CommonEdges) { + AbsorbNode.removeEdge(*E); + delete E; + } + CommonEdges.clear(); + } + if (OutgoingNode.findEdgesTo(AbsorbNode, CommonEdges)) + for (auto E : CommonEdges) { + AbsorbNode.addEdge(*(new SourceCFGEdge(*E))); + OutgoingNode.removeEdge(*E); + delete E; + } + AbsorbNode.merge(OutgoingNode); + SourceCFGBase::removeNode(OutgoingNode); + delete &OutgoingNode; +} + +void markReached(SourceCFGNode *Node, + std::map *NodesList) { + (*NodesList)[Node]=true; + for (auto E : *Node) + if (!(*NodesList)[&E->getTargetNode()]) + markReached(&E->getTargetNode(), NodesList); +} + +void SourceCFGBuilder::eliminateUnreached() { + std::map ReachedNodes; + for (auto N : *mSCFG) + ReachedNodes.insert({N, false}); + markReached(mSCFG->getStartNode(), &ReachedNodes); + for (auto It : ReachedNodes) + if (!It.second) + mSCFG->deleteNode(*It.first); +} + +void SourceCFGBuilder::processLabels() { + std::map> OrderingMap; + for (auto GotoIt=mGotos.begin(); GotoIt!=mGotos.end(); ++GotoIt) + if (OrderingMap.find(mLabels[GotoIt->first].Node)!=OrderingMap.end()) + OrderingMap[mLabels[GotoIt->first].Node].push_back({GotoIt, + mLabels[GotoIt->first].LabelIt}); + else + OrderingMap.insert({mLabels[GotoIt->first].Node, + {{GotoIt, mLabels[GotoIt->first].LabelIt}}}); + for (auto OMIt=OrderingMap.begin(); OMIt!=OrderingMap.end(); ++OMIt) { + auto &GIVector=OMIt->second; + std::sort(GIVector.begin(), GIVector.end(), compareGotoInfo); + auto GIIt=GIVector.rbegin(); + while (GIIt!=GIVector.rend()) { + while (GIIt+1!=GIVector.rend() && (GIIt+1)->GotoIt-GIIt->GotoIt==1) + ++GIIt; + auto NewNode=mSCFG->splitNode(*OMIt->first, GIIt->GotoIt); + for (auto UpdateIt=mGotos.begin(); UpdateIt!=mGotos.end(); ++UpdateIt) + if (UpdateIt->second==OMIt->first) { + UpdateIt->second=NewNode; + break; + } + mSCFG->bindNodes(*GIIt->GotoNodeIt->second, *NewNode, + SourceCFGEdge::EdgeKind::Default); + ++GIIt; + } + } +} + +SourceCFG *SourceCFGBuilder::populate(FunctionDecl *Decl) { + if (Decl->hasBody()) { + DeclarationNameInfo Info=Decl->getNameInfo(); + mSCFG=new SourceCFG(Info.getAsString()); + mDirectOut.push(MarkedOutsType()); + parseStmt(Decl->getBody()); + if (mEntryNode) { + mSCFG->bindNodes(*mSCFG->getStartNode(), *mEntryNode, + SourceCFGEdge::EdgeKind::Default); + for (auto It : mDirectOut.top()) + mSCFG->bindNodes(*It.first, *mSCFG->getStopNode(), It.second); + processLabels(); + } + else + mSCFG->bindNodes(*mSCFG->getStartNode(), *mSCFG->getStopNode(), + SourceCFGEdge::EdgeKind::Default); + mDirectOut.pop(); + eliminateUnreached(); + } + return mSCFG; +} + +void SourceCFGBuilder::parseStmt(Stmt *Root) { + Stmt::StmtClass Type=Root->getStmtClass(); + if ((!mEntryNode || !mNodeToAdd) && + Type!=Stmt::StmtClass::CompoundStmtClass) { + mNodeToAdd=&mSCFG->emplaceNode(SourceCFGNode::NodeKind::Default); + if (!mEntryNode) + mEntryNode=mNodeToAdd; + for (auto Outs : mDirectOut.top()) + mSCFG->bindNodes(*Outs.first, *mNodeToAdd, Outs.second); + mDirectOut.top().clear(); + mDirectOut.top().insert({mNodeToAdd, SourceCFGEdge::EdgeKind::Default}); + } + auto ParserIt=mParsers.find(Type); + if (ParserIt!=mParsers.end()) + (this->*(ParserIt->second))(Root); + else { + if (isa(Root)) + parseExpr((Expr*)Root, nullptr, true); + else { + mNodeToAdd->addToNode(new NativeNodeOp(Root)); + mDirectOut.top().insert({mNodeToAdd, SourceCFGEdge::EdgeKind::Default}); + } + } +} + +void SourceCFGBuilder::continueFlow(NodeOp *Op) { + if (!mNodeToAdd) { + mNodeToAdd=&mSCFG->emplaceNode(SourceCFGNode::NodeKind::Default); + mNodeToAdd->addToNode(Op); + for (auto Outs : mDirectOut.top()) + mSCFG->bindNodes(*Outs.first, *mNodeToAdd, Outs.second); + mDirectOut.top().clear(); + } + else + mNodeToAdd->addToNode(Op); + mDirectOut.top().insert({mNodeToAdd, SourceCFGEdge::EdgeKind::Default}); +} + +void SourceCFGBuilder::processIndirect(SourceCFGNode *CondStartNode) { + if (CondStartNode) + for (auto Out : mContinueOut.top()) + mSCFG->bindNodes(*Out, *CondStartNode, + SourceCFGEdge::EdgeKind::Continue); + for (auto Out : mBreakOut.top()) + mDirectOut.top().insert({Out, SourceCFGEdge::EdgeKind::Break}); +} + +void SourceCFGBuilder::parseExpr(tsar::Op O, NodeOp *ParentOp, + bool isFirstCall) { + SourceCFGNode *OldNodeToAdd; + WrapperNodeOp *NewNodeOp; + if (O.IsStmt) { + Stmt::StmtClass Type=O.S->getStmtClass(); + if (isa(*O.S)) { + MarkedOutsType UpperOuts; + SourceCFGNode *ConditionNode, *TrueNode, *FalseNode; + ConditionalOperator &CO=*(ConditionalOperator*)O.S; + auto OldEntryNode=mEntryNode; + auto OldTreeTopParentPtr=mTreeTopParentPtr; + NodeOp *CondOp=new WrapperNodeOp(&CO); + if (ParentOp) + ((WrapperNodeOp*)ParentOp)->Leaves.push_back(new ReferenceNodeOp( + CondOp, "cond_res")); + if (mTreeTopParentPtr && ((WrapperNodeOp*)mTreeTopParentPtr)-> + Leaves.size()>0) { + continueFlow(((WrapperNodeOp*)mTreeTopParentPtr)->Leaves[0]); + ((WrapperNodeOp*)mTreeTopParentPtr)->Leaves[0]=new ReferenceNodeOp( + ((WrapperNodeOp*)mTreeTopParentPtr)->Leaves[0], ""); + } + parseExpr(CO.getCond(), CondOp, true); + ConditionNode=mNodeToAdd; + mEntryNode=mNodeToAdd=nullptr; + mDirectOut.push(MarkedOutsType()); + parseStmt(CO.getTrueExpr()); + TrueNode=mEntryNode; + mSCFG->bindNodes(*ConditionNode, *TrueNode, + SourceCFGEdge::EdgeKind::True); + UpperOuts=mDirectOut.top(); + mDirectOut.pop(); + for (auto It : UpperOuts) + mDirectOut.top().insert(It); + mEntryNode=mNodeToAdd=nullptr; + mDirectOut.push(MarkedOutsType()); + parseStmt(CO.getFalseExpr()); + FalseNode=mEntryNode; + mSCFG->bindNodes(*ConditionNode, *FalseNode, + SourceCFGEdge::EdgeKind::False); + UpperOuts=mDirectOut.top(); + mDirectOut.pop(); + for (auto It : UpperOuts) + mDirectOut.top().insert(It); + mDirectOut.top().erase(ConditionNode); + mNodeToAdd=nullptr; + mEntryNode=OldEntryNode; + mTreeTopParentPtr=OldTreeTopParentPtr; + if (isFirstCall && ParentOp && + !isa(*((WrapperNodeOp*)ParentOp)->O.S)) + continueFlow(ParentOp); + return; + } + else { + OldNodeToAdd=mNodeToAdd; + if (isFirstCall) + mTreeTopParentPtr=nullptr; + NewNodeOp=new WrapperNodeOp(O.S); + switch (Type) { + case Stmt::StmtClass::CompoundAssignOperatorClass: + parseExpr(((clang::BinaryOperator*)O.S)->getLHS(), NewNodeOp, false); + parseExpr(((clang::BinaryOperator*)O.S)->getRHS(), NewNodeOp, false); + break; + case Stmt::StmtClass::BinaryOperatorClass: + if (((clang::BinaryOperator*)O.S)->isAssignmentOp()) { + parseExpr(((clang::BinaryOperator*)O.S)->getRHS(), NewNodeOp, + false); + parseExpr(((clang::BinaryOperator*)O.S)->getLHS(), NewNodeOp, + false); + } + else { + parseExpr(((clang::BinaryOperator*)O.S)->getLHS(), NewNodeOp, + false); + parseExpr(((clang::BinaryOperator*)O.S)->getRHS(), NewNodeOp, + false); + } + break; + default: + for (auto SubExpr : O.S->children()) + parseExpr((clang::Expr*)SubExpr, NewNodeOp, false); + break; + } + } + } + else { + OldNodeToAdd=mNodeToAdd; + if (isFirstCall) + mTreeTopParentPtr=nullptr; + NewNodeOp=new WrapperNodeOp(O.VD); + parseExpr(O.VD->getInit(), NewNodeOp, false); + } + NodeOp *OpToAdd; + if (mNodeToAdd && OldNodeToAdd==mNodeToAdd) { + OpToAdd=new NativeNodeOp(*NewNodeOp); + delete NewNodeOp; + } + else + OpToAdd=NewNodeOp; + if (isFirstCall) { + if (ParentOp) { + ((WrapperNodeOp*)ParentOp)->Leaves.push_back(OpToAdd); + continueFlow(ParentOp); + } + else + continueFlow(OpToAdd); + mTreeTopParentPtr=nullptr; + } + else { + ((WrapperNodeOp*)ParentOp)->Leaves.push_back(OpToAdd); + mTreeTopParentPtr=ParentOp; + } +} + +void SourceCFGBuilder::parseCompoundStmt(CompoundStmt *Root) { + MarkedOutsType UpperOuts; + SourceCFGNode *ResultEntryNode=mEntryNode; + mDirectOut.push(MarkedOutsType()); + for (auto S : Root->body()) { + parseStmt(S); + if (!ResultEntryNode && mEntryNode) + ResultEntryNode=mEntryNode; + } + mEntryNode=ResultEntryNode; + UpperOuts=mDirectOut.top(); + mDirectOut.pop(); + for (auto Outs : UpperOuts) + mDirectOut.top().insert(Outs); +} + +void SourceCFGBuilder::parseDoStmt(DoStmt *Root) { + SourceCFGNode *mStartNode=mNodeToAdd, *CondStartNode, *CondEndNode, *Body; + mContinueOut.push(OutsType()); + mBreakOut.push(OutsType()); + mDirectOut.push(MarkedOutsType()); + if (mStartNode->size()==0) + Body=mStartNode; + else { + Body=mEntryNode=mNodeToAdd=&mSCFG->emplaceNode( + SourceCFGNode::NodeKind::Default); + mSCFG->bindNodes(*mStartNode, *Body, SourceCFGEdge::EdgeKind::Default); + } + parseStmt(Root->getBody()); + if (!mContinueOut.top().empty() || !mNodeToAdd) { + CondStartNode=mNodeToAdd=&mSCFG->emplaceNode( + SourceCFGNode::NodeKind::Default); + for (auto Outs : mDirectOut.top()) + mSCFG->bindNodes(*Outs.first, *CondStartNode, Outs.second); + mDirectOut.top().clear(); + } + else + CondStartNode=mNodeToAdd; + parseExpr(Root->getCond(), new WrapperNodeOp(Root), true); + CondEndNode=mNodeToAdd; + mSCFG->bindNodes(*CondEndNode, *Body, SourceCFGEdge::EdgeKind::True); + mDirectOut.pop(); + mDirectOut.top().erase(mStartNode); + mDirectOut.top().insert({CondEndNode, SourceCFGEdge::EdgeKind::False}); + mNodeToAdd=nullptr; + mEntryNode=mStartNode; + processIndirect(CondStartNode); + mContinueOut.pop(); + mBreakOut.pop(); +} + +void SourceCFGBuilder::parseForStmt(ForStmt *Root) { + SourceCFGNode *mStartNode=mNodeToAdd, *CondStartNode=nullptr, + *CondEndNode=nullptr, *Body=nullptr, *IncStartNode=nullptr, *LoopNode; + MarkedOutsType AfterInitOuts; + mContinueOut.push(OutsType()); + mBreakOut.push(OutsType()); + if (Root->getInit()) + if (isa(*Root->getInit())) + parseDeclStmt((DeclStmt*)Root->getInit(), nullptr); + else + parseExpr(Root->getInit(), nullptr, true); + AfterInitOuts=mDirectOut.top(); + if (Root->getCond()) { + if (mNodeToAdd && mNodeToAdd->size()==0) + CondStartNode=mNodeToAdd; + else { + CondStartNode=mNodeToAdd=&mSCFG->emplaceNode( + SourceCFGNode::NodeKind::Default); + for (auto Out : mDirectOut.top()) + mSCFG->bindNodes(*Out.first, *CondStartNode, Out.second); + mDirectOut.top().clear(); + } + parseExpr(Root->getCond(), new WrapperNodeOp(Root), true); + CondEndNode=mNodeToAdd; + } + mDirectOut.top().clear(); + mEntryNode=mNodeToAdd=nullptr; + parseStmt(Root->getBody()); + Body=mEntryNode; + if (CondEndNode) + mSCFG->bindNodes(*CondEndNode, *Body, SourceCFGEdge::EdgeKind::True); + else + for (auto Out : AfterInitOuts) + mSCFG->bindNodes(*Out.first, *Body, Out.second); + if (Root->getInc()) { + if (!mContinueOut.top().empty()) + mEntryNode=mNodeToAdd=nullptr; + parseStmt(Root->getInc()); + IncStartNode=mEntryNode; + } + LoopNode=CondStartNode?CondStartNode:Body; + for (auto Out : mDirectOut.top()) + mSCFG->bindNodes(*Out.first, *LoopNode, Out.second); + mDirectOut.top().clear(); + if (CondEndNode) + mDirectOut.top().insert({CondEndNode, SourceCFGEdge::EdgeKind::False}); + mNodeToAdd=nullptr; + mEntryNode=mStartNode; + if (IncStartNode) + processIndirect(IncStartNode); + else + if (CondStartNode) + processIndirect(CondStartNode); + else + processIndirect(Body); + mContinueOut.pop(); + mBreakOut.pop(); +} + +void SourceCFGBuilder::parseSwitchStmt(SwitchStmt *Root) { + mBreakOut.push(OutsType()); + SourceCFGNode *CondStartNode=mNodeToAdd, *CondEndNode; + parseExpr(Root->getCond(), new WrapperNodeOp(Root), true); + CondEndNode=mNodeToAdd; + mEntryNode=mNodeToAdd=nullptr; + parseStmt(Root->getBody()); + processIndirect(nullptr); + std::map> OrderingMap; + for (auto CaseIt : mCases) + if (OrderingMap.find(CaseIt.second.Node)!=OrderingMap.end()) + OrderingMap[CaseIt.second.Node].push_back(CaseIt.second.LabelIt); + else + OrderingMap.insert({CaseIt.second.Node, {CaseIt.second.LabelIt}}); + for (auto OMIt=OrderingMap.begin(); OMIt!=OrderingMap.end(); ++OMIt) { + auto &IVector=OMIt->second; + std::sort(IVector.begin(), IVector.end()); + auto It=IVector.rbegin(); + while (It!=IVector.rend()) { + while (It+1!=IVector.rend() && *(It+1)-*It==1) + ++It; + auto NewNode=mSCFG->splitNode(*OMIt->first, *It); + mSCFG->bindNodes(*CondEndNode, *NewNode, + SourceCFGEdge::EdgeKind::ToCase); + ++It; + } + } + //mDirectOut.top().clear(); + mBreakOut.pop(); +} + +void SourceCFGBuilder::parseCaseStmt(CaseStmt *Root) { + mNodeToAdd->addToNode(new NativeNodeOp(Root)); + mCases.insert({Root, {mNodeToAdd, (int)mNodeToAdd->size()-1}}); + parseStmt(Root->getSubStmt()); +} + +void SourceCFGBuilder::parseWhileStmt(WhileStmt *Root) { + mContinueOut.push(OutsType()); + mBreakOut.push(OutsType()); + mDirectOut.push(MarkedOutsType()); + SourceCFGNode *mStartNode=mNodeToAdd, *CondStartNode, *CondEndNode; + if (mStartNode->size()==0) { + CondStartNode=mStartNode; + parseExpr(Root->getCond(), new WrapperNodeOp(Root), true); + } + else { + CondStartNode=mNodeToAdd=&mSCFG->emplaceNode( + SourceCFGNode::NodeKind::Default); + mSCFG->bindNodes(*mStartNode, *CondStartNode, + SourceCFGEdge::EdgeKind::Default); + parseExpr(Root->getCond(), new WrapperNodeOp(Root), true); + } + CondEndNode=mNodeToAdd; + mDirectOut.top().erase(CondEndNode); + mEntryNode=mNodeToAdd=nullptr; + parseStmt(Root->getBody()); + mSCFG->bindNodes(*CondEndNode, *mEntryNode, SourceCFGEdge::EdgeKind::True); + for (auto Outs : mDirectOut.top()) + mSCFG->bindNodes(*Outs.first, *CondStartNode, Outs.second); + mDirectOut.pop(); + mDirectOut.top().erase(mStartNode); + mDirectOut.top().insert({CondEndNode, SourceCFGEdge::EdgeKind::False}); + mEntryNode=mStartNode; + mNodeToAdd=nullptr; + processIndirect(CondStartNode); + mContinueOut.pop(); + mBreakOut.pop(); +} + +void SourceCFGBuilder::parseIfStmt(IfStmt *Root) { + MarkedOutsType UpperOuts; + SourceCFGNode *CondStartNode=mNodeToAdd, *CondEndNode; + Stmt *ActionStmt; + parseExpr(Root->getCond(), new WrapperNodeOp(Root), true); + CondEndNode=mNodeToAdd; + mDirectOut.push(MarkedOutsType()); + mEntryNode=mNodeToAdd=nullptr; + parseStmt(Root->getThen()); + mSCFG->bindNodes(*CondEndNode, *mEntryNode, SourceCFGEdge::EdgeKind::True); + if ((ActionStmt=Root->getElse())) { + mDirectOut.push(MarkedOutsType()); + mEntryNode=mNodeToAdd=nullptr; + parseStmt(ActionStmt); + mSCFG->bindNodes(*CondEndNode, *mEntryNode, + SourceCFGEdge::EdgeKind::False); + UpperOuts=mDirectOut.top(); + mDirectOut.pop(); + for (auto Out : UpperOuts) + mDirectOut.top().insert(Out); + } + else + mDirectOut.top().insert({CondEndNode, SourceCFGEdge::EdgeKind::False}); + UpperOuts=mDirectOut.top(); + mDirectOut.pop(); + mDirectOut.top().erase(CondEndNode); + for (auto Outs : UpperOuts) + mDirectOut.top().insert(Outs); + mEntryNode=CondStartNode; + mNodeToAdd=nullptr; +} + +void SourceCFGBuilder::parseBreakStmt(BreakStmt *Root) { + mNodeToAdd->addToNode(new NativeNodeOp(Root)); + mDirectOut.top().erase(mNodeToAdd); + mBreakOut.top().insert(mNodeToAdd); + mNodeToAdd=nullptr; +} + +void SourceCFGBuilder::parseContinueStmt(ContinueStmt *Root) { + mNodeToAdd->addToNode(new NativeNodeOp(Root)); + mDirectOut.top().erase(mNodeToAdd); + mContinueOut.top().insert(mNodeToAdd); + mNodeToAdd=nullptr; +} + +void SourceCFGBuilder::parseGotoStmt(GotoStmt *Root) { + mNodeToAdd->addToNode(new NativeNodeOp(Root)); + mGotos.insert({Root->getLabel()->getStmt(), mNodeToAdd}); + mDirectOut.top().erase(mNodeToAdd); + mNodeToAdd=nullptr; +} + +void SourceCFGBuilder::parseLabelStmt(LabelStmt *Root) { + mNodeToAdd->addToNode(new NativeNodeOp(Root)); + mLabels.insert({Root, {mNodeToAdd, (int)mNodeToAdd->size()-1}}); + parseStmt(Root->getSubStmt()); +} + +void SourceCFGBuilder::parseReturnStmt(ReturnStmt *Root) { + if (Root->getRetValue()) + parseExpr(Root->getRetValue(), new WrapperNodeOp(Root), true); + else + mNodeToAdd->addToNode(new NativeNodeOp(Root)); + mSCFG->bindNodes(*mNodeToAdd, *mSCFG->getStopNode(), + SourceCFGEdge::EdgeKind::Default); + mDirectOut.top().erase(mNodeToAdd); + mNodeToAdd=nullptr; +} + +void SourceCFGBuilder::parseDeclStmt(DeclStmt *Root, NodeOp *ParentOp) { + for (auto D : Root->decls()) + if ((D->getKind()==Decl::Kind::Var) && ((VarDecl*)D)->getInit()) + parseExpr((VarDecl*)D, ParentOp, true); +} + +void SourceCFGBuilder::parseDeclStmtWrapper(DeclStmt *Root) { + parseDeclStmt(Root, nullptr); +} + +char ClangSourceCFGPass::ID=0; + +INITIALIZE_PASS_BEGIN(ClangSourceCFGPass, "clang-source-cfg", + "Source Control Flow Graph (Clang)", false, true) +INITIALIZE_PASS_DEPENDENCY(TransformationEnginePass) +INITIALIZE_PASS_END(ClangSourceCFGPass, "clang-source-cfg", + "Source Control Flow Graph (Clang)", false, true) + +FunctionPass *createClangSourceCFGPass() { return new ClangSourceCFGPass; } + +void ClangSourceCFGPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.setPreservesAll(); +} + +bool ClangSourceCFGPass::runOnFunction(Function &F) { + releaseMemory(); + auto *DISub(findMetadata(&F)); + if (!DISub) + return false; + auto *CU{DISub->getUnit()}; + if (!CU) + return false; + if (!isC(CU->getSourceLanguage())) + return false; + auto &TfmInfo{getAnalysis()}; + auto *TfmCtx{TfmInfo ? dyn_cast_or_null< + ClangTransformationContext>(TfmInfo->getContext(*CU)) : nullptr}; + if (!TfmCtx || !TfmCtx->hasInstance()) + return false; + auto FuncDecl=TfmCtx->getDeclForMangledName(F.getName()); + mSCFG=mSCFGBuilder.populate((FunctionDecl*)FuncDecl); + return false; +} + +namespace { +struct ClangSourceCFGPassGraphTraits { + static tsar::SourceCFG *getGraph(ClangSourceCFGPass *P) { + return &P->getSourceCFG(); + } +}; + +struct ClangSourceCFGPrinter : public DOTGraphTraitsPrinterWrapperPass< + ClangSourceCFGPass, false, tsar::SourceCFG*, + ClangSourceCFGPassGraphTraits> { + static char ID; + ClangSourceCFGPrinter() : DOTGraphTraitsPrinterWrapperPass("scfg", ID) { + initializeClangSourceCFGPrinterPass(*PassRegistry::getPassRegistry()); + } +}; +char ClangSourceCFGPrinter::ID = 0; + +struct ClangSourceCFGViewer : public DOTGraphTraitsViewerWrapperPass< + ClangSourceCFGPass, false, tsar::SourceCFG*, + ClangSourceCFGPassGraphTraits> { + static char ID; + ClangSourceCFGViewer() : DOTGraphTraitsViewerWrapperPass("scfg", ID) { + initializeClangSourceCFGViewerPass(*PassRegistry::getPassRegistry()); + } +}; +char ClangSourceCFGViewer::ID = 0; +} //anonymous namespace + +INITIALIZE_PASS_IN_GROUP(ClangSourceCFGViewer, "clang-view-source-cfg", + "View Source Control FLow Graph (Clang)", true, true, + DefaultQueryManager::OutputPassGroup::getPassRegistry()) + +INITIALIZE_PASS_IN_GROUP(ClangSourceCFGPrinter, "clang-print-source-cfg", + "Print Source Control FLow Graph(Clang)", true, true, + DefaultQueryManager::OutputPassGroup::getPassRegistry()) + +FunctionPass *llvm::createClangSourceCFGPrinter() { + return new ClangSourceCFGPrinter; +} + +FunctionPass *llvm::createClangSourceCFGViewer() { + return new ClangSourceCFGViewer; +} + From 7d0253da3e5350704f245702e18a7b56fba66d47 Mon Sep 17 00:00:00 2001 From: a_zel Date: Fri, 21 Apr 2023 06:58:06 +0300 Subject: [PATCH 2/9] 1. Performed refactoring of code 2. Added processing of switch statement 3. Added construction of control dependence subgraph (without region-nodes) --- include/tsar/Analysis/Clang/Passes.h | 18 + include/tsar/Analysis/Clang/SourceCFG.h | 883 +++++++------ include/tsar/Analysis/PDG.h | 234 ++++ include/tsar/Analysis/Passes.h | 18 + lib/Analysis/CMakeLists.txt | 2 +- lib/Analysis/Clang/Passes.cpp | 3 + lib/Analysis/Clang/SourceCFG.cpp | 1556 ++++++++++++----------- lib/Analysis/PDG.cpp | 144 +++ lib/Analysis/Passes.cpp | 3 + 9 files changed, 1728 insertions(+), 1133 deletions(-) create mode 100644 include/tsar/Analysis/PDG.h create mode 100644 lib/Analysis/PDG.cpp diff --git a/include/tsar/Analysis/Clang/Passes.h b/include/tsar/Analysis/Clang/Passes.h index 50d9bac4..2d3de0f8 100644 --- a/include/tsar/Analysis/Clang/Passes.h +++ b/include/tsar/Analysis/Clang/Passes.h @@ -149,5 +149,23 @@ void initializeClangIncludeTreeOnlyViewerPass(PassRegistry &Registry); /// Create a pass to display source file tree (filenames instead of /// full paths). ModulePass *createClangIncludeTreeOnlyViewer(); + +/// Initialize a pass to build source control flow graph. +void initializeClangSourceCFGPassPass(PassRegistry &Registry); + +/// Create a pass to build source control flow graph. +FunctionPass *createClangSourceCFGPass(); + +/// Initialize a pass to print source control flow graph to 'dot' file. +void initializeClangSourceCFGPrinterPass(PassRegistry &Registry); + +/// Create a pass to print source control flow graph to 'dot' file. +FunctionPass *createClangSourceCFGPrinter(); + +/// Initialize a pass to display source control flow graph. +void initializeClangSourceCFGViewerPass(PassRegistry &Registry); + +/// Create a pass to display source control flow graph. +FunctionPass *createClangSourceCFGViewer(); } #endif//TSAR_CLANG_ANALYSIS_PASSES_H diff --git a/include/tsar/Analysis/Clang/SourceCFG.h b/include/tsar/Analysis/Clang/SourceCFG.h index 1f97dd96..9c8e6071 100644 --- a/include/tsar/Analysis/Clang/SourceCFG.h +++ b/include/tsar/Analysis/Clang/SourceCFG.h @@ -3,7 +3,9 @@ #include "tsar/Analysis/Clang/Passes.h" #include -#include +#include +#include +#include #include #include #include @@ -11,11 +13,13 @@ #include #include #include -#include #include #include +#include #include +#include #include +#include //For Inverse namespace tsar { @@ -27,312 +31,430 @@ using SourceCFGNodeBase=llvm::DGNode; using SourceCFGEdgeBase=llvm::DGEdge; using SourceCFGBase=llvm::DirectedGraph; using StmtStringType=std::string; +class ReferenceNodeOp; +class NativeNodeOp; + +class NodeOp { + friend class ReferenceNodeOp; + friend class NativeNodeOp; + friend class SourceCFGBuilder; +public: + enum class NodeOpKind {Native, Wrapper, Reference}; + NodeOp(NodeOpKind _mKind) : mKind(_mKind), mIsReferred(false) {} + NodeOp(const NodeOp &_N) = default; + NodeOpKind getKind() const { return mKind; }; + void print(StmtStringType &ResStr) const; + std::string getOpAddr() const; -struct Op { - union { - clang::Stmt *S; - clang::VarDecl *VD; - }; - bool IsStmt; - Op(clang::VarDecl *_VD) : VD(_VD), IsStmt(false) {} - Op(clang::Stmt *_S) : S(_S), IsStmt(true) {} + void printRefDecl(StmtStringType &ResStr) const { + if (mIsReferred) { + ResStr+="getKind()==NodeOpKind::Wrapper; } - inline void printASTNode(StmtStringType &ResStr, tsar::Op O); - inline void printASTVarDeclNode(StmtStringType &ResStr, clang::VarDecl *VD); - void printASTStmtNode(StmtStringType &ResStr, clang::Stmt *S); + + std::string getOpAddr() const { + return "0x"+(std::stringstream()<()).str(); + } + + ~WrapperNodeOp() { + for (auto L : Leaves) + L->destroy(); + } +private: + clang::DynTypedNode Op; + std::vector Leaves; }; -struct WrapperNodeOp : NodeOp { - Op O; - std::vector Leaves; - WrapperNodeOp(tsar::Op _O) : O(_O) {} - void print(StmtStringType &ResStr) override; - NodeOpTypes getType() override { return WrapperNode; } - std::string getOpAddr() override { - return "0x"+(std::stringstream()<getKind()==NodeOpKind::Native; + } + + void print(StmtStringType &ResStr) const { + llvm::raw_string_ostream StrStream(ResStr); + printRefDecl(ResStr); + if (Op.get()) { + Op.getUnchecked().printPretty(StrStream, nullptr, + clang::PrintingPolicy(clang::LangOptions())); + } + else + Op.getUnchecked().print(StrStream); + } + + std::string getOpAddr() const { + return "0x"+(std::stringstream()<()).str(); + } + ~NativeNodeOp() = default; +private: + clang::DynTypedNode Op; }; -struct NativeNodeOp : NodeOp { - Op O; - NativeNodeOp(tsar::Op _O) : O(_O) {} - NativeNodeOp(const WrapperNodeOp &WNO) : NodeOp(WNO), O(WNO.O) {} - void print(StmtStringType &ResStr) override { - printRefDecl(ResStr); - printASTNode(ResStr, O.S); - } - NodeOpTypes getType() override { return NativeNode; } - std::string getOpAddr() override { - return "0x"+(std::stringstream()<mIsReferred=true; + } + static bool classof(const NodeOp *Node) { + return Node->getKind()==NodeOpKind::Reference; + } + void print(StmtStringType &ResStr) const { + ResStr+="<"+mReferenceName+mReferredNode->getOpAddr()+"_REFERRENCE_>"; + } + std::string getOpAddr() const { + return "0x"+(std::stringstream()<isReferred=true; - } - void print(StmtStringType &ResStr) override { - ResStr+="<"+ReferenceName+Referred->getOpAddr()+"_REFERRENCE_>"; - } - NodeOpTypes getType() override { return ReferenceNode; } - std::string getOpAddr() override { - return "0x"+(std::stringstream()<; - using iterator=OpStorageType::iterator; - SourceBasicBlock() = default; - SourceBasicBlock(NodeOp *_Op) : mOps(1, _Op) {} - SourceBasicBlock(std::initializer_list _Ops) : mOps(_Ops) {} - SourceBasicBlock(const llvm::SmallVectorImpl &_Ops) - : mOps(_Ops.begin(), _Ops.end()) {} - SourceBasicBlock(const SourceBasicBlock &_SBB) = delete; - SourceBasicBlock(SourceBasicBlock &&_SBB) = delete; - SourceBasicBlock &operator=(const SourceBasicBlock &_SBB) = delete; - SourceBasicBlock &operator=(SourceBasicBlock &&_SBB) = delete; - iterator addOp(NodeOp *_Op) { mOps.push_back(_Op); return mOps.end()-1; } - void addOpFront(NodeOp *_Op) { mOps.insert(mOps.begin(), _Op); } - template - iterator addOp(It begin, It end) { - for (auto I=begin; I!=end; ++I) mOps.push_back(*I); return mOps.end()-1; - } - void clear() { - for (auto O : mOps) - delete O; - mOps.clear(); - } - unsigned size() const { return mOps.size(); } - iterator begin() { return mOps.begin(); } - iterator end() { return mOps.end(); } - explicit operator std::string() const; - void decrease(int NewSize) { - mOps.resize(NewSize); - } - NodeOp &operator[](int Index) { return *mOps[Index]; } + enum class EdgeType {Default, True, False, ImplicitDefault}; + DefaultSCFGEdge(SourceCFGNode &_TargetNode, EdgeType _mType) + : SourceCFGEdge(_TargetNode, EdgeKind::Default), mType(_mType) {} + + explicit operator std::string() const { + switch (mType) { + case EdgeType::Default: + return ""; + case EdgeType::True: + return "T"; + case EdgeType::False: + return "F"; + case EdgeType::ImplicitDefault: + return "default"; + } + } + + ~DefaultSCFGEdge() = default; private: - OpStorageType mOps; + EdgeType mType; }; -class SourceCFGEdge : public SourceCFGEdgeBase { +class LabeledSCFGEdge : public SourceCFGEdge { public: - enum class EdgeKind {Default, True, False, Continue, Break, ToCase}; - SourceCFGEdge(SourceCFGNode &_TargetNode, EdgeKind _Kind) - : SourceCFGEdgeBase(_TargetNode), mKind(_Kind) {} - SourceCFGEdge(const SourceCFGEdge &_Edge) - : SourceCFGEdgeBase(_Edge), mKind(_Edge.mKind) {} - SourceCFGEdge(SourceCFGEdge &&_Edge) - : SourceCFGEdgeBase(std::move(_Edge)), mKind(_Edge.mKind) {} - SourceCFGEdge &operator=(const SourceCFGEdge &_Edge) = default; - EdgeKind getKind() const { return mKind; } - explicit operator std::string() const { - switch (mKind) { - case EdgeKind::True: - return "T"; - case EdgeKind::False: - return "F"; - case EdgeKind::Default: - default: - return ""; - } - } + LabeledSCFGEdge(SourceCFGNode &_TargetNode, clang::SwitchCase *_mLabel) + : SourceCFGEdge(_TargetNode, EdgeKind::Labeled), mLabel(_mLabel) {} + + explicit operator std::string() const { + std::string ResStr; + llvm::raw_string_ostream StrStream(ResStr); + if (llvm::isa(*mLabel)) + ResStr="default"; + else + ((clang::CaseStmt*)mLabel)->getLHS()->printPretty(StrStream, nullptr, + clang::PrintingPolicy(clang::LangOptions())); + return ResStr; + } + + ~LabeledSCFGEdge() = default; private: - EdgeKind mKind; + clang::SwitchCase *mLabel; }; class SourceCFGNode : public SourceCFGNodeBase { - friend class SourceCFG; - friend class SourceCFGBuilder; + friend class SourceCFG; public: - enum class NodeKind {Default, GraphStart, GraphStop}; - SourceCFGNode(const NodeKind _Kind) : mKind(_Kind) {} - SourceCFGNode(const SourceCFGNode &_Node) = delete; - SourceCFGNode(SourceCFGNode &&_Node) = delete; - SourceCFGNode &operator=(const SourceCFGNode &_Node) = delete; - SourceCFGNode &operator=(SourceCFGNode &&_Node) = delete; - SourceBasicBlock::iterator addToNode(NodeOp *_Op) { return SBB.addOp(_Op); } - template - SourceBasicBlock::iterator addToNode(It begin, It end) { - return SBB.addOp(begin, end); - } - void addToNodeFront(NodeOp *_Op) { SBB.addOpFront(_Op); } - NodeKind getKind() const { return mKind; } - void setKind(NodeKind _Kind) { mKind=_Kind; } - void merge(SourceCFGNode &NodeToAttach); - unsigned size() { return SBB.size(); } - explicit operator std::string() const { - switch (mKind) { - case NodeKind::GraphStart: - return "START"; - case NodeKind::GraphStop: - return "STOP"; - case NodeKind::Default: - return (std::string)SBB; - } - } - inline SourceCFGEdge *addNewEdge(SourceCFGNode &TargetNode, - SourceCFGEdge::EdgeKind Ekind) { - SourceCFGEdge *ResEdge=new SourceCFGEdge(TargetNode, Ekind); - if (addEdge(*ResEdge)) - return ResEdge; - else { - delete ResEdge; - return nullptr; - } - } - SourceCFG *getParent() { return OwningGraph; } - void printAsOperand(llvm::raw_ostream &OS, bool B) {} - NodeOp &operator[](int Index) { return SBB[Index]; } + enum class NodeKind {Default, Service}; + SourceCFGNode(NodeKind _mKind) : mKind(_mKind) {} + NodeKind getKind() const { return mKind; } + + inline SourceCFGEdge *addNewEdge(SourceCFGNode &TargetNode, + SourceCFGEdge::EdgeKind Ekind) { + SourceCFGEdge *ResEdge=new SourceCFGEdge(TargetNode, Ekind); + if (addEdge(*ResEdge)) + return ResEdge; + else { + delete ResEdge; + return nullptr; + } + } + + void merge(SourceCFGNode &NodeToAttach); + SourceCFG *getParent() { return OwningGraph; } + explicit operator std::string() const; + void printAsOperand(llvm::raw_ostream &OS, bool B) { + OS<getEdges()) - delete E; - delete N; - } - } - inline bool addNode(SourceCFGNode &N) { - return SourceCFGBase::addNode(N)?N.OwningGraph=this, true:false; - } - SourceCFGNode &emplaceNode(SourceCFGNode::NodeKind _Nkind) { - SourceCFGNode *CurrNode=new SourceCFGNode(_Nkind); - addNode(*CurrNode); - return *CurrNode; - } - inline void bindNodes(SourceCFGNode &SourceNode, SourceCFGNode &TargetNode, - SourceCFGEdge::EdgeKind _Ekind) { - connect(SourceNode, TargetNode, *(new SourceCFGEdge(TargetNode, _Ekind))); - } - inline SourceCFGNode *getStartNode() const { return mStartNode; } - inline SourceCFGNode *getStopNode() const { return mStopNode; } - inline llvm::StringRef getName() const { return mFunctionName; } - void mergeNodes(SourceCFGNode &AbsorbNode, SourceCFGNode &OutgoingNode); - void deleteEdge(SourceCFGEdge &_Edge); - bool findParentNodes(const SourceCFGNode &RequestedNode, - llvm::SmallVectorImpl &ParentNodes) { - bool Result=false; - for (auto N : *this) - if (N->hasEdgeTo(RequestedNode)) { - ParentNodes.push_back(N); - Result=true; - } - return Result; - } - void deleteNode(SourceCFGNode &_Node); - void view(const SourceCFGNode &SCFGN, - const llvm::Twine &Name="source cfg") const { - llvm::ViewGraph(this, Name, false, - llvm::DOTGraphTraits::getGraphName(this)); - } - std::string write(const SourceCFGNode &SCFGN, - const llvm::Twine &Name="source cfg") const { - return llvm::WriteGraph(this, Name, false, - llvm::DOTGraphTraits::getGraphName(this)); + enum class NodeType {GraphStart, GraphStop, GraphEntry}; + ServiceSCFGNode(NodeType _mType) : SourceCFGNode(NodeKind::Service), + mType(_mType) {} + NodeType getType() const { return mType; } + static bool classof(const SourceCFGNode *Node) { + return Node->getKind()==NodeKind::Service; + } + explicit operator std::string() const { + switch (mType) { + case NodeType::GraphStart: + return "START"; + case NodeType::GraphStop: + return "STOP"; + case NodeType::GraphEntry: + return "ENTRY"; + } + } +private: + NodeType mType; +}; + +class DefaultSCFGNode : public SourceCFGNode { + friend class SourceCFG; + friend class SourceCFGBuilder; +public: + using OpStorageType=std::vector; + DefaultSCFGNode() : SourceCFGNode(NodeKind::Default) {} + std::size_t size() const { return mBlock.size(); } + static bool classof(const SourceCFGNode *Node) { + return Node->getKind()==NodeKind::Default; + } + NodeOp &operator[](int Index) { return *mBlock[Index]; } + explicit operator std::string() const; + + void clearBlock() { + for (auto Op : mBlock) + Op->destroy(); + mBlock.clear(); + } + + ~DefaultSCFGNode() { + clearBlock(); + } + +private: + inline OpStorageType::iterator addOp(NodeOp *_Op) { + mBlock.push_back(_Op); + return mBlock.end()-1; } - SourceCFGNode *splitNode(SourceCFGNode &Node, int It); + + template + OpStorageType::iterator addOp(It begin, It end) { + for (auto I=begin; I!=end; ++I) + mBlock.push_back(*I); + return mBlock.end()-1; + } + + OpStorageType mBlock; +}; + +class SourceCFG : public SourceCFGBase { +public: + SourceCFG(const std::string &_mFunctionName) : mFunctionName(_mFunctionName), + mStartNode(&emplaceNode(ServiceSCFGNode::NodeType::GraphStart)), + mStopNode(&emplaceNode(ServiceSCFGNode::NodeType::GraphStop)), + mEntryNode(nullptr) {} + + + inline bool addNode(SourceCFGNode &N) { + return SourceCFGBase::addNode(N)?N.OwningGraph=this, true:false; + } + + DefaultSCFGNode &emplaceNode() { + DefaultSCFGNode *CurrNode=new DefaultSCFGNode(); + addNode(*CurrNode); + return *CurrNode; + } + + ServiceSCFGNode &emplaceNode(ServiceSCFGNode::NodeType Type) { + ServiceSCFGNode *CurrNode=new ServiceSCFGNode(Type); + addNode(*CurrNode); + return *CurrNode; + } + + ServiceSCFGNode &emplaceEntryNode() { + mEntryNode=new ServiceSCFGNode(ServiceSCFGNode::NodeType::GraphEntry); + addNode(*mEntryNode); + bindNodes(*mEntryNode, *mStartNode, DefaultSCFGEdge::EdgeType::True); + bindNodes(*mEntryNode, *mStopNode, DefaultSCFGEdge::EdgeType::False); + return *mEntryNode; + } + + inline void bindNodes(SourceCFGNode &SourceNode, + SourceCFGNode &TargetNode ) { + connect(SourceNode, TargetNode, *(new DefaultSCFGEdge(TargetNode, + DefaultSCFGEdge::EdgeType::Default))); + } + + inline void bindNodes(SourceCFGNode &SourceNode, SourceCFGNode &TargetNode, + DefaultSCFGEdge::EdgeType EdgeType) { + connect(SourceNode, TargetNode, *(new DefaultSCFGEdge(TargetNode, + EdgeType))); + } + + inline void bindNodes(SourceCFGNode &SourceNode, SourceCFGNode &TargetNode, + clang::SwitchCase *Label) { + connect(SourceNode, TargetNode, *(new LabeledSCFGEdge(TargetNode, Label))); + } + + inline ServiceSCFGNode *getStartNode() const { return mStartNode; } + inline ServiceSCFGNode *getStopNode() const { return mStopNode; } + inline ServiceSCFGNode *getEntryNode() const { + return mEntryNode?mEntryNode:mStartNode; + } + inline llvm::StringRef getName() const { return mFunctionName; } + void mergeNodes(SourceCFGNode &AbsorbNode, SourceCFGNode &OutgoingNode); + void deleteNode(SourceCFGNode &_Node); + void deleteEdge(SourceCFGEdge &_Edge); + DefaultSCFGNode *splitNode(DefaultSCFGNode &Node, int It); + void recalculatePredMap(); + + std::set &getPredMap(SourceCFGNode *Node) { + return mPredecessorsMap[Node]; + } + + bool findParentNodes(const SourceCFGNode &RequestedNode, + llvm::SmallVectorImpl &ParentNodes) { + bool Result=false; + for (auto N : *this) + if (N->hasEdgeTo(RequestedNode)) { + ParentNodes.push_back(N); + Result=true; + } + return Result; + } + + void view(const SourceCFGNode &SCFGN, + const llvm::Twine &Name="source cfg") const { + llvm::ViewGraph(this, Name, false, + llvm::DOTGraphTraits::getGraphName(this)); + } + + std::string write(const SourceCFGNode &SCFGN, + const llvm::Twine &Name="source cfg") const { + return llvm::WriteGraph(this, Name, false, + llvm::DOTGraphTraits::getGraphName(this)); + } + + ~SourceCFG() { + for (auto N : Nodes) { + for (auto E : N->getEdges()) + E->destroy(); + N->destroy(); + } + } private: - std::string mFunctionName; - SourceCFGNode *mStartNode, *mStopNode; + std::string mFunctionName; + ServiceSCFGNode *mStartNode, *mStopNode, *mEntryNode; + std::map> mPredecessorsMap; }; class SourceCFGBuilder { public: - SourceCFGBuilder() : mSCFG(nullptr), mEntryNode(nullptr), - mNodeToAdd(nullptr), mTreeTopParentPtr(nullptr) {} - SourceCFG *populate(clang::FunctionDecl *Decl); + SourceCFGBuilder() : mSCFG(nullptr), mEntryNode(nullptr), + mNodeToAdd(nullptr), mTreeTopParentPtr(nullptr), + mPrevFirstLabel({nullptr, 0}) {} + SourceCFG *populate(clang::FunctionDecl *Decl); private: - using MarkedOutsType=llvm::DenseMap; - using OutsType=llvm::SmallPtrSet; - using ParserType=void (SourceCFGBuilder::*)(clang::Stmt*); - struct LabelInfo { - SourceCFGNode *Node; - int LabelIt; - }; - struct GotoInfo { - std::map::iterator GotoNodeIt; - int GotoIt; - }; - static bool compareLabelInfo(const LabelInfo &LI1, const LabelInfo &LI2) { - return LI1.LabelIt mParsers; - SourceCFG *mSCFG; - llvm::DenseMap mLabels; - llvm::DenseMap mCases; - std::map mGotos; - SourceCFGNode *mEntryNode, *mNodeToAdd; - std::stack mDirectOut; - std::stack mContinueOut, mBreakOut; - NodeOp *mTreeTopParentPtr; + using MarkedOutsType=llvm::DenseMap; + using OutsType=llvm::SmallPtrSet; + + struct LabelInfo { + DefaultSCFGNode *Node; + size_t LabelIt; + }; + + friend bool operator<(const LabelInfo&, const LabelInfo&); + void parseCompoundStmt(clang::CompoundStmt *Root); + void parseIfStmt(clang::IfStmt *Root); + void parseStmt(clang::Stmt *Root); + void parseDoStmt(clang::DoStmt *Root); + void parseExpr(clang::DynTypedNode Op, NodeOp *ParentOp, bool isFirstCall); + void parseWhileStmt(clang::WhileStmt *Root); + void parseBreakStmt(clang::BreakStmt *Root); + void parseContinueStmt(clang::ContinueStmt *Root); + void parseReturnStmt(clang::ReturnStmt *Root); + void parseLabelStmt(clang::Stmt *Root); + void parseGotoStmt(clang::GotoStmt *Root); + void parseDeclStmt(clang::DeclStmt *Root, NodeOp *ParentOp); + void parseForStmt(clang::ForStmt *Root); + void parseSwitchStmt(clang::SwitchStmt *Root); + void processIndirect(SourceCFGNode *CondStartNode); + void eliminateUnreached(); + void continueFlow(tsar::NodeOp *Op); + void processLabels(); + bool hasConditionalOperator(clang::Stmt *Root); + SourceCFG *mSCFG; + llvm::SmallDenseMap mLabels; + llvm::SmallVector> mGotos; + llvm::SmallVector> mSwitchGotos; + LabelInfo mPrevFirstLabel; + size_t mLastLabelIt; + DefaultSCFGNode *mEntryNode, *mNodeToAdd; + std::vector mDirectOut; + std::stack mContinueOut, mBreakOut; + std::stack mSwitchNodes; + NodeOp *mTreeTopParentPtr; }; } //namespace tsar @@ -340,113 +462,142 @@ namespace llvm { class ClangSourceCFGPass : public FunctionPass, private bcl::Uncopyable { public: - static char ID; - ClangSourceCFGPass() : FunctionPass(ID), mSCFG(nullptr) { - initializeClangSourceCFGPassPass(*PassRegistry::getPassRegistry()); - } - bool runOnFunction(Function &F) override; - void getAnalysisUsage(AnalysisUsage &AU) const override; - void releaseMemory() { - mSCFGBuilder=tsar::SourceCFGBuilder(); - if (mSCFG) { - delete mSCFG; - mSCFG=nullptr; - } - } - inline tsar::SourceCFG &getSourceCFG() { return *mSCFG; } + static char ID; + ClangSourceCFGPass() : FunctionPass(ID), mSCFG(nullptr) { + initializeClangSourceCFGPassPass(*PassRegistry::getPassRegistry()); + } + bool runOnFunction(Function &F) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + void releaseMemory() { + mSCFGBuilder=tsar::SourceCFGBuilder(); + if (mSCFG) { + delete mSCFG; + mSCFG=nullptr; + } + } + inline tsar::SourceCFG &getSourceCFG() { return *mSCFG; } private: - tsar::SourceCFGBuilder mSCFGBuilder; - tsar::SourceCFG *mSCFG; + tsar::SourceCFGBuilder mSCFGBuilder; + tsar::SourceCFG *mSCFG; }; template<> struct GraphTraits { - using NodeRef=tsar::SourceCFGNode*; - static tsar::SourceCFGNode *SCFGGetTargetNode(tsar::SourceCFGEdge *E) { - return &E->getTargetNode(); - } - using ChildIteratorType=mapped_iterator; - using ChildEdgeIteratorType=tsar::SourceCFGNode::iterator; - static NodeRef getEntryNode(NodeRef N) { return N; } - static ChildIteratorType child_begin(NodeRef N) { - return ChildIteratorType(N->begin(), &SCFGGetTargetNode); - } - static ChildIteratorType child_end(NodeRef N) { - return ChildIteratorType(N->end(), &SCFGGetTargetNode); - } - static ChildEdgeIteratorType child_edge_begin(NodeRef N) { - return N->begin(); - } - static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } + using NodeRef=tsar::SourceCFGNode*; + static tsar::SourceCFGNode *SCFGGetTargetNode(tsar::SourceCFGEdge *E) { + return &E->getTargetNode(); + } + using ChildIteratorType=mapped_iterator; + using ChildEdgeIteratorType=tsar::SourceCFGNode::iterator; + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { + return ChildIteratorType(N->begin(), &SCFGGetTargetNode); + } + static ChildIteratorType child_end(NodeRef N) { + return ChildIteratorType(N->end(), &SCFGGetTargetNode); + } + static ChildEdgeIteratorType child_edge_begin(NodeRef N) { + return N->begin(); + } + static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } }; template<> struct GraphTraits : - public GraphTraits { - using nodes_iterator=tsar::SourceCFG::iterator; - static NodeRef getEntryNode(tsar::SourceCFG *mSCFG) { - return mSCFG->getStartNode(); - } - static nodes_iterator nodes_begin(tsar::SourceCFG *mSCFG) { - return mSCFG->begin(); - } - static nodes_iterator nodes_end(tsar::SourceCFG *mSCFG) { - return mSCFG->end(); - } - using EdgeRef=tsar::SourceCFGEdge*; - static NodeRef edge_dest(EdgeRef E) { return &E->getTargetNode(); } - static unsigned size(tsar::SourceCFG *mSCFG) { return mSCFG->size(); } + public GraphTraits { + using nodes_iterator=tsar::SourceCFG::iterator; + static NodeRef getEntryNode(tsar::SourceCFG *mSCFG) { + return mSCFG->getEntryNode(); + } + static nodes_iterator nodes_begin(tsar::SourceCFG *mSCFG) { + return mSCFG->begin(); + } + static nodes_iterator nodes_end(tsar::SourceCFG *mSCFG) { + return mSCFG->end(); + } + using EdgeRef=tsar::SourceCFGEdge*; + static NodeRef edge_dest(EdgeRef E) { return &E->getTargetNode(); } + static unsigned size(tsar::SourceCFG *mSCFG) { return mSCFG->size(); } }; template<> struct GraphTraits { - using NodeRef=const tsar::SourceCFGNode*; - static const tsar::SourceCFGNode *SCFGGetTargetNode( - const tsar::SourceCFGEdge *E) { return &E->getTargetNode(); } - using ChildIteratorType=mapped_iterator; - using ChildEdgeIteratorType=tsar::SourceCFGNode::const_iterator; - static NodeRef getEntryNode(NodeRef N) { return N; } - static ChildIteratorType child_begin(NodeRef N) { - return ChildIteratorType(N->begin(), &SCFGGetTargetNode); - } - static ChildIteratorType child_end(NodeRef N) { - return ChildIteratorType(N->end(), &SCFGGetTargetNode); - } - static ChildEdgeIteratorType child_edge_begin(NodeRef N) { - return N->begin(); - } - static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } + using NodeRef=const tsar::SourceCFGNode*; + static const tsar::SourceCFGNode *SCFGGetTargetNode( + const tsar::SourceCFGEdge *E) { return &E->getTargetNode(); } + using ChildIteratorType=mapped_iterator; + using ChildEdgeIteratorType=tsar::SourceCFGNode::const_iterator; + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { + return ChildIteratorType(N->begin(), &SCFGGetTargetNode); + } + static ChildIteratorType child_end(NodeRef N) { + return ChildIteratorType(N->end(), &SCFGGetTargetNode); + } + static ChildEdgeIteratorType child_edge_begin(NodeRef N) { + return N->begin(); + } + static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } }; template<> struct GraphTraits : - public GraphTraits { - using nodes_iterator=tsar::SourceCFG::const_iterator; - static NodeRef getEntryNode(const tsar::SourceCFG *mSCFG) { - return mSCFG->getStartNode(); - } - static nodes_iterator nodes_begin(const tsar::SourceCFG *mSCFG) { - return mSCFG->begin(); - } - static nodes_iterator nodes_end(const tsar::SourceCFG *mSCFG) { - return mSCFG->end(); - } - using EdgeRef=const tsar::SourceCFGEdge*; - static NodeRef edge_dest(EdgeRef E) { return &E->getTargetNode(); } - static unsigned size(const tsar::SourceCFG *mSCFG) { return mSCFG->size(); } + public GraphTraits { + using nodes_iterator=tsar::SourceCFG::const_iterator; + static NodeRef getEntryNode(const tsar::SourceCFG *mSCFG) { + return mSCFG->getEntryNode(); + } + static nodes_iterator nodes_begin(const tsar::SourceCFG *mSCFG) { + return mSCFG->begin(); + } + static nodes_iterator nodes_end(const tsar::SourceCFG *mSCFG) { + return mSCFG->end(); + } + using EdgeRef=const tsar::SourceCFGEdge*; + static NodeRef edge_dest(EdgeRef E) { return &E->getTargetNode(); } + static unsigned size(const tsar::SourceCFG *mSCFG) { return mSCFG->size(); } +}; + +template<> struct GraphTraits> { + using NodeRef=tsar::SourceCFGNode*; + using ChildIteratorType=std::set::iterator; + static ChildIteratorType child_begin(NodeRef N) { + return N->getParent()->getPredMap(N).begin(); + } + static ChildIteratorType child_end(NodeRef N) { + return N->getParent()->getPredMap(N).end(); + } + static NodeRef getEntryNode(NodeRef N) { return N; } +}; + +template<> struct GraphTraits> : + public GraphTraits> { + using nodes_iterator=tsar::SourceCFG::iterator; + static NodeRef getEntryNode(tsar::SourceCFG *SCFG) { + return SCFG->getEntryNode(); + } + static nodes_iterator nodes_begin(Inverse *ISCFG) { + return ISCFG->Graph->begin(); + } + static nodes_iterator nodes_end(Inverse *ISCFG) { + return ISCFG->Graph->end(); + } + unsigned size(Inverse *ISCFG) { + return ISCFG->Graph->size(); + } }; template<> struct DOTGraphTraits : - public DefaultDOTGraphTraits { - DOTGraphTraits(bool IsSimple=false) : DefaultDOTGraphTraits(IsSimple) {} - static std::string getGraphName(const tsar::SourceCFG *mSCFG) { - return "mSCFG"; - } - std::string getNodeLabel(tsar::SourceCFGNode *Node, tsar::SourceCFG *mSCFG) { - return (std::string)*Node; - } - std::string getEdgeSourceLabel(tsar::SourceCFGNode *Node, - GraphTraits::ChildIteratorType It) { - return (std::string)**It.getCurrent(); - } + public DefaultDOTGraphTraits { + DOTGraphTraits(bool IsSimple=false) : DefaultDOTGraphTraits(IsSimple) {} + static std::string getGraphName(const tsar::SourceCFG *SCFG) { + return "Source Control Flow Graph"; + } + std::string getNodeLabel(tsar::SourceCFGNode *Node, tsar::SourceCFG *SCFG) { + return (std::string)*Node; + } + std::string getEdgeSourceLabel(tsar::SourceCFGNode *Node, + GraphTraits::ChildIteratorType It) { + return (std::string)**It.getCurrent(); + } }; } //namespace llvm diff --git a/include/tsar/Analysis/PDG.h b/include/tsar/Analysis/PDG.h new file mode 100644 index 00000000..14738f9b --- /dev/null +++ b/include/tsar/Analysis/PDG.h @@ -0,0 +1,234 @@ +#ifndef TSAR_INCLUDE_BUILDPDG_H +#define TSAR_INCLUDE_BUILDPDG_H + +#include "tsar/Analysis/Passes.h" +#include "tsar/Analysis/Clang/SourceCFG.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace tsar { + +class PDGNode; +class PDGEdge; +class PDG; +class PDGBuilder; +using PDGNodeBase=llvm::DGNode; +using PDGEdgeBase=llvm::DGEdge; +using PDGBase=llvm::DirectedGraph; + +class PDGEdge : public PDGEdgeBase { +public: + enum class EdgeKind {ControlDependence, DataDependence}; + PDGEdge(PDGNode &_TargetNode, EdgeKind _Kind) + : PDGEdgeBase(_TargetNode), Kind(_Kind) {} + inline EdgeKind getKind() const { return Kind; } +private: + EdgeKind Kind; +}; + +class PDGNode : public PDGNodeBase { +public: + enum class NodeKind {Default, Region}; + PDGNode(SourceCFGNode *_mBlock) + : mBlock(_mBlock), mKind(NodeKind::Default) {} + inline NodeKind getKind() const { return mKind; } + SourceCFGNode *getBlock() const { return mBlock; } +private: + SourceCFGNode *mBlock; + NodeKind mKind; +}; + +class PDG : public PDGBase { + friend class PDGBuilder; +public: + PDG(const std::string &_FunctionName, SourceCFG *_mSCFG) + : FunctionName(_FunctionName), mSCFG(_mSCFG) {} + + inline bool addNode(PDGNode &N) { + if (PDGBase::addNode(N)) { + BlockToNodeMap.insert({N.getBlock(), &N}); + return true; + } + else + return false; + } + + PDGNode &emplaceNode(SourceCFGNode *Block) { + PDGNode *NewNode=new PDGNode(Block); + addNode(*NewNode); + return *NewNode; + } + + inline void bindNodes(PDGNode &SourceNode, PDGNode &TargetNode, + PDGEdge::EdgeKind _Ekind) { + connect(SourceNode, TargetNode, *(new PDGEdge(TargetNode, _Ekind))); + } + + inline PDGNode *getNode(SourceCFGNode *Block) { + return BlockToNodeMap[Block]; + } + + inline PDGNode *getEntryNode() { + return getNode(mSCFG->getEntryNode()); + } + + ~PDG() { + for (auto N : Nodes) { + for (auto E : N->getEdges()) + delete E; + delete N; + } + } +private: + std::string FunctionName; + std::map BlockToNodeMap; + SourceCFG *mSCFG; +}; + +class PDGBuilder { +public: + PDGBuilder() : mPDG(nullptr) {} + PDG *populate(SourceCFG &_SCFG); +private: + inline void processControlDependence(); + inline llvm::DomTreeNodeBase *getRealRoot() { + return *mSPDT.getRootNode()->begin(); + } + PDG *mPDG; + SourceCFG *mSCFG; + llvm::PostDomTreeBase mSPDT; +}; + +}//namespace tsar + +namespace llvm { + +class PDGPass : public FunctionPass, private bcl::Uncopyable { +public: + static char ID; + PDGPass() : FunctionPass(ID), mPDG(nullptr) { + initializePDGPassPass(*PassRegistry::getPassRegistry()); + } + bool runOnFunction(Function &F) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + void releaseMemory() { + mPDGBuilder=tsar::PDGBuilder(); + if (mPDG) { + delete mPDG; + mPDG=nullptr; + } + } + inline tsar::PDG &getPDG() { return *mPDG; } +private: + tsar::PDGBuilder mPDGBuilder; + tsar::PDG *mPDG; +}; + +template<> struct GraphTraits*> { + using NodeRef=DomTreeNodeBase*; + using ChildIteratorType=DomTreeNodeBase::iterator; + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { + return N->begin(); + } + static ChildIteratorType child_end(NodeRef N) { + return N->end(); + } +}; + +template struct GraphTraits*> + : public GraphTraits*> { + static NodeRef getEntryNode(DominatorTreeBase *Tree) { + return Tree->getRootNode(); + } + using nodes_iterator=df_iterator*>; + static nodes_iterator nodes_begin(DominatorTreeBase *Tree) { + return df_begin(Tree->getRootNode()); + } + static nodes_iterator nodes_end(DominatorTreeBase *Tree) { + return df_end(Tree->getRootNode()); + } + static unsigned size(DominatorTreeBase *Tree) { + return Tree->root_size(); + } +}; + +template struct DOTGraphTraits*> : public DefaultDOTGraphTraits { + DOTGraphTraits(bool IsSimple=false) : DefaultDOTGraphTraits(IsSimple) {} + static std::string getGraphName(const DominatorTreeBase *Tree) { + return IsPostDom?"Post-Dominator Tree":"Dominator Tree"; + } + std::string getNodeLabel(DomTreeNodeBase *Node, + DominatorTreeBase *Tree) { + return (std::string)*Node->getBlock(); + } + static bool isNodeHidden(DomTreeNodeBase *Node, + DominatorTreeBase *Tree) { + Tree->isVirtualRoot(Node)?true:false; + } +}; + +template<> struct GraphTraits { + using NodeRef=tsar::PDGNode*; + static tsar::PDGNode *PDGGetTargetNode(tsar::PDGEdge *E) { + return &E->getTargetNode(); + } + using ChildIteratorType=mapped_iterator; + using ChildEdgeIteratorType=tsar::PDGNode::iterator; + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { + return ChildIteratorType(N->begin(), &PDGGetTargetNode); + } + static ChildIteratorType child_end(NodeRef N) { + return ChildIteratorType(N->end(), &PDGGetTargetNode); + } + static ChildEdgeIteratorType child_edge_begin(NodeRef N) { + return N->begin(); + } + static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } +}; + +template<> struct GraphTraits : + public GraphTraits { + using nodes_iterator=tsar::PDG::iterator; + static NodeRef getEntryNode(tsar::PDG *Graph) { + return Graph->getEntryNode(); + } + static nodes_iterator nodes_begin(tsar::PDG *Graph) { + return Graph->begin(); + } + static nodes_iterator nodes_end(tsar::PDG *Graph) { + return Graph->end(); + } + using EdgeRef=tsar::PDGEdge*; + static NodeRef edge_dest(EdgeRef E) { return &E->getTargetNode(); } + static unsigned size(tsar::PDG *Graph) { return Graph->size(); } +}; + +template<> struct DOTGraphTraits : public DefaultDOTGraphTraits { + DOTGraphTraits(bool IsSimple=false) : DefaultDOTGraphTraits(IsSimple) {} + static std::string getGraphName(const tsar::PDG *Graph) { + return "Control Dependence Graph"; + } + std::string getNodeLabel(const tsar::PDGNode *Node, const tsar::PDG *Graph) { + return (std::string)*Node->getBlock(); + } +}; + +}//namespace llvm + +#endif//TSAR_INCLUDE_BUILDPDG_H \ No newline at end of file diff --git a/include/tsar/Analysis/Passes.h b/include/tsar/Analysis/Passes.h index e73be0f5..4ab50623 100644 --- a/include/tsar/Analysis/Passes.h +++ b/include/tsar/Analysis/Passes.h @@ -117,5 +117,23 @@ ModulePass *createAnalysisCloseConnectionPass(bool ActiveOnly = false); /// Close connection with server (it should be run on client). Client will /// be blocked until server confirms that connection can be closed. ModulePass *createAnalysisCloseConnectionPass(const void * ServerID); + +/// Initialize a pass to build program dependency graph. +void initializePDGPassPass(PassRegistry &Registry); + +/// Create a pass to build program dependency graph. +FunctionPass *createPDGPass(); + +/// Initialize a pass to print program dependency graph to 'dot' file. +void initializePDGPrinterPass(PassRegistry &Registry); + +/// Create a pass to print program dependency to 'dot' file. +FunctionPass *createPDGPrinter(); + +/// Initialize a pass to display program dependency graph. +void initializePDGViewerPass(PassRegistry &Registry); + +/// Create a pass to display program dependency graph. +FunctionPass *createPDGViewer(); } #endif//TSAR_ANALYSIS_PASSES_H diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt index 1bc0ff68..520abe09 100644 --- a/lib/Analysis/CMakeLists.txt +++ b/lib/Analysis/CMakeLists.txt @@ -1,5 +1,5 @@ set(ANALYSIS_SOURCES Passes.cpp PrintUtils.cpp DFRegionInfo.cpp Attributes.cpp - Intrinsics.cpp AnalysisSocket.cpp AnalysisServer.cpp) + Intrinsics.cpp AnalysisSocket.cpp AnalysisServer.cpp PDG.cpp) if(MSVC_IDE) file(GLOB ANALYSIS_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} diff --git a/lib/Analysis/Clang/Passes.cpp b/lib/Analysis/Clang/Passes.cpp index 146f656b..4d9d7234 100644 --- a/lib/Analysis/Clang/Passes.cpp +++ b/lib/Analysis/Clang/Passes.cpp @@ -42,6 +42,9 @@ void llvm::initializeClangAnalysis(PassRegistry &Registry) { initializeClangIncludeTreeOnlyPrinterPass(Registry); initializeClangIncludeTreeViewerPass(Registry); initializeClangIncludeTreeOnlyViewerPass(Registry); + initializeClangSourceCFGPassPass(Registry); + initializeClangSourceCFGPrinterPass(Registry); + initializeClangSourceCFGViewerPass(Registry); // Initialize checkers. initializeClangNoMacroAssertPass(Registry); } diff --git a/lib/Analysis/Clang/SourceCFG.cpp b/lib/Analysis/Clang/SourceCFG.cpp index 75c49a86..df352277 100644 --- a/lib/Analysis/Clang/SourceCFG.cpp +++ b/lib/Analysis/Clang/SourceCFG.cpp @@ -5,882 +5,906 @@ #include "tsar/Support/MetadataUtils.h" #include "tsar/Core/TransformationContext.h" #include "tsar/Frontend/Clang/TransformationContext.h" -#include +#include + +namespace tsar { +bool operator<(const SourceCFGBuilder::LabelInfo &LI1, + const SourceCFGBuilder::LabelInfo &LI2) { + return LI1.NodeLI2.LabelIt); +} +}; using namespace tsar; using namespace llvm; using namespace clang; using namespace std; -std::map SourceCFGBuilder:: - mParsers { - {Stmt::StmtClass::CompoundStmtClass,(ParserType)&tsar::SourceCFGBuilder:: - parseCompoundStmt}, - {Stmt::StmtClass::IfStmtClass, (ParserType)&tsar::SourceCFGBuilder:: - parseIfStmt}, - {Stmt::StmtClass::WhileStmtClass, (ParserType)&tsar::SourceCFGBuilder:: - parseWhileStmt}, - {Stmt::StmtClass::DoStmtClass, (ParserType)&tsar::SourceCFGBuilder:: - parseDoStmt}, - {Stmt::StmtClass::ContinueStmtClass, (ParserType)&tsar::SourceCFGBuilder:: - parseContinueStmt}, - {Stmt::StmtClass::BreakStmtClass, (ParserType)&tsar::SourceCFGBuilder:: - parseBreakStmt}, - {Stmt::StmtClass::ReturnStmtClass, (ParserType)&tsar::SourceCFGBuilder:: - parseReturnStmt}, - {Stmt::StmtClass::LabelStmtClass, (ParserType)&tsar::SourceCFGBuilder:: - parseLabelStmt}, - {Stmt::StmtClass::GotoStmtClass, (ParserType)&tsar::SourceCFGBuilder:: - parseGotoStmt}, - {Stmt::StmtClass::DeclStmtClass, (ParserType)&tsar::SourceCFGBuilder:: - parseDeclStmtWrapper}, - {Stmt::StmtClass::ForStmtClass, (ParserType)&tsar::SourceCFGBuilder:: - parseForStmt}, - //{Stmt::StmtClass::SwitchStmtClass, (ParserType)&tsar::SourceCFGBuilder:: - //parseSwitchStmt}, Not working - {Stmt::StmtClass::CaseStmtClass, (ParserType)&tsar::SourceCFGBuilder:: - parseCaseStmt} -}; - -inline void NodeOp::printASTNode(StmtStringType &ResStr, tsar::Op O) { - if (O.IsStmt) - printASTStmtNode(ResStr, O.S); - else - printASTVarDeclNode(ResStr, O.VD); -} - -inline void NodeOp::printASTVarDeclNode(StmtStringType &ResStr, VarDecl *VD) { - ResStr+=VD->getNameAsString()+"="; - printASTStmtNode(ResStr, VD->getInit()); -} - -void NodeOp::printASTStmtNode(StmtStringType &ResStr, Stmt *S) { - switch (S->getStmtClass()) { - case Stmt::StmtClass::UnaryOperatorClass: - if (((clang::UnaryOperator*)S)->isPostfix()) { - printASTNode(ResStr, ((clang::UnaryOperator*)S)->getSubExpr()); - ResStr+=((clang::UnaryOperator*)S)->getOpcodeStr( - ((clang::UnaryOperator*)S)->getOpcode()); - } - else { - ResStr+=((clang::UnaryOperator*)S)->getOpcodeStr( - ((clang::UnaryOperator*)S)->getOpcode()); - printASTNode(ResStr, ((clang::UnaryOperator*)S)->getSubExpr()); - } - break; - case Stmt::StmtClass::BinaryOperatorClass: - case Stmt::StmtClass::CompoundAssignOperatorClass: - printASTNode(ResStr, ((clang::BinaryOperator*)S)->getLHS()); - ResStr+=((clang::BinaryOperator*)S)->getOpcodeStr(); - printASTNode(ResStr, ((clang::BinaryOperator*)S)->getRHS()); - break; - case Stmt::StmtClass::DeclRefExprClass: - ResStr+=((DeclRefExpr*)S)->getNameInfo().getAsString(); - break; - case Stmt::StmtClass::IntegerLiteralClass: - { - SmallString<5> BufferStr; - ((IntegerLiteral*)S)->getValue().toString(BufferStr, 10, false); - ResStr+=BufferStr; - } - break; - case Stmt::StmtClass::CStyleCastExprClass: - ResStr+=((Twine)"("+((CStyleCastExpr*)S)->getCastKindName()+")").str(); - break; - case Stmt::StmtClass::ParenExprClass: - ResStr+="("; - printASTNode(ResStr, ((ParenExpr*)S)->getSubExpr()); - ResStr+=")"; - break; - case Stmt::StmtClass::ImplicitCastExprClass: - printASTNode(ResStr, ((ImplicitCastExpr*)S)->getSubExpr()); - break; - case Stmt::StmtClass::IfStmtClass: - ResStr+="if ("; - printASTNode(ResStr, ((IfStmt*)S)->getCond()); - ResStr+=")"; - break; - case Stmt::StmtClass::DoStmtClass: - case Stmt::StmtClass::WhileStmtClass: - ResStr+="while ("; - printASTNode(ResStr, ((WhileStmt*)S)->getCond()); - ResStr+=")"; - break; - case Stmt::StmtClass::NullStmtClass: - ResStr+=";"; - break; - case Stmt::StmtClass::ReturnStmtClass: - if (((ReturnStmt*)S)->getRetValue()) { - ResStr+="return "; - printASTNode(ResStr, ((ReturnStmt*)S)->getRetValue()); - } - else - ResStr+="return"; - break; - case Stmt::StmtClass::ContinueStmtClass: - ResStr+="continue"; - break; - case Stmt::StmtClass::BreakStmtClass: - ResStr+="break"; - break; - case Stmt::StmtClass::GotoStmtClass: - ResStr+=("goto "+((GotoStmt*)S)->getLabel()->getName()).str(); - break; - case Stmt::StmtClass::LabelStmtClass: - ResStr+=(((LabelStmt*)S)->getDecl()->getName()+":").str(); - break; - case Stmt::StmtClass::CaseStmtClass: - ResStr+="case "; - printASTNode(ResStr, ((CaseStmt*)S)->getLHS()); - ResStr+=":"; - break; - default: - ResStr+=S->getStmtClassName(); - break; - } -} - -void WrapperNodeOp::print(StmtStringType &ResStr) { - printRefDecl(ResStr); - if (O.IsStmt) { - Expr *E=(Expr*)O.S; - switch (E->getStmtClass()) { - case Stmt::StmtClass::UnaryOperatorClass: - if (((clang::UnaryOperator*)E)->isPostfix()) { - if (Leaves[0]) - Leaves[0]->print(ResStr); - ResStr+=((clang::UnaryOperator*)E)->getOpcodeStr( - ((clang::UnaryOperator*)E)->getOpcode()); - } - else { - ResStr+=((clang::UnaryOperator*)E)->getOpcodeStr( - ((clang::UnaryOperator*)E)->getOpcode()); - if (Leaves[0]) - Leaves[0]->print(ResStr); - } - break; - case Stmt::StmtClass::CompoundAssignOperatorClass: - case Stmt::StmtClass::BinaryOperatorClass: - if (((clang::BinaryOperator*)E)->isCompoundAssignmentOp() || - !((clang::BinaryOperator*)E)->isAssignmentOp()) { - if (Leaves[0]) - Leaves[0]->print(ResStr); - ResStr+=((clang::BinaryOperator*)E)->getOpcodeStr(); - if (Leaves[1]) - Leaves[1]->print(ResStr); - } - else { - if (Leaves[1]) - Leaves[1]->print(ResStr); - ResStr+=((clang::BinaryOperator*)E)->getOpcodeStr(); - if (Leaves[0]) - Leaves[0]->print(ResStr); - } - break; - case Stmt::StmtClass::DeclRefExprClass: - ResStr+=((DeclRefExpr*)E)->getNameInfo().getAsString(); - break; - case Stmt::StmtClass::IntegerLiteralClass: - { - SmallString<5> BufferStr; - ((IntegerLiteral*)E)->getValue().toString(BufferStr, 10, false); - ResStr+=BufferStr; - } - break; - case Stmt::StmtClass::CStyleCastExprClass: - ResStr+=((Twine)"("+((CStyleCastExpr*)E)->getCastKindName()+")").str(); - break; - case Stmt::StmtClass::ParenExprClass: - ResStr+="("; - if (Leaves[0]) - Leaves[0]->print(ResStr); - ResStr+=")"; - break; - case Stmt::StmtClass::ImplicitCastExprClass: - if (Leaves[0]) - Leaves[0]->print(ResStr); - break; - case Stmt::StmtClass::ConditionalOperatorClass: - ResStr+=" - "; - if (Leaves[0]) - Leaves[0]->print(ResStr); - break; - case Stmt::StmtClass::IfStmtClass: - ResStr+="if ("; - if (Leaves[0]) - Leaves[0]->print(ResStr); - ResStr+=")"; - break; - case Stmt::StmtClass::WhileStmtClass: - case Stmt::StmtClass::DoStmtClass: - ResStr+="while ("; - if (Leaves[0]) - Leaves[0]->print(ResStr); - ResStr+=")"; - break; - case Stmt::StmtClass::ForStmtClass: - ResStr+=" - "; - if (Leaves[0]) - Leaves[0]->print(ResStr); - break; - case Stmt::StmtClass::SwitchStmtClass: - ResStr+="switch ("; - if (Leaves[0]) - Leaves[0]->print(ResStr); - ResStr+=")"; - break; - default: - ResStr+=O.S->getStmtClassName(); - break; - } - } - else { - ResStr+=O.VD->getNameAsString()+"="; - if (Leaves[0]) - Leaves[0]->print(ResStr); - } -} - -SourceBasicBlock::operator string() const { - string ResStr; - for (auto NO : mOps) { - NO->print(ResStr); - ResStr+="\n"; - } - return ResStr; +template +void addToMap(MapT &Map, KeyT Key, ValueT Value) { + auto It=Map.find(Key); + if (It!=Map.end()) + Map[Key].push_back(Value); + else + Map.insert({Key, {Value}}); +} + +void NodeOp::print(StmtStringType &ResStr) const { + switch (mKind) { + case NodeOpKind::Native: + ((NativeNodeOp*)this)->print(ResStr); + break; + case NodeOpKind::Wrapper: + ((WrapperNodeOp*)this)->print(ResStr); + break; + case NodeOpKind::Reference: + ((ReferenceNodeOp*)this)->print(ResStr); + break; + } +} + +std::string NodeOp::getOpAddr() const { + switch (mKind) { + case NodeOpKind::Native: + return ((NativeNodeOp*)this)->getOpAddr(); + case NodeOpKind::Wrapper: + return ((WrapperNodeOp*)this)->getOpAddr(); + case NodeOpKind::Reference: + return ((ReferenceNodeOp*)this)->getOpAddr(); + } +} + +void NodeOp::destroy() { + switch (mKind) { + case NodeOpKind::Native: + delete (NativeNodeOp*)this; + break; + case NodeOpKind::Wrapper: + delete (WrapperNodeOp*)this; + break; + case NodeOpKind::Reference: + delete (ReferenceNodeOp*)this; + break; + } +} + +void WrapperNodeOp::print(StmtStringType &ResStr) const { + printRefDecl(ResStr); + if (Op.get()) { + Expr *E=(Expr*)&Op.getUnchecked(); + switch (E->getStmtClass()) { + case Stmt::StmtClass::UnaryOperatorClass: + if (((clang::UnaryOperator*)E)->isPostfix()) { + if (Leaves[0]) + Leaves[0]->print(ResStr); + ResStr+=((clang::UnaryOperator*)E)->getOpcodeStr( + ((clang::UnaryOperator*)E)->getOpcode()); + } + else { + ResStr+=((clang::UnaryOperator*)E)->getOpcodeStr( + ((clang::UnaryOperator*)E)->getOpcode()); + if (Leaves[0]) + Leaves[0]->print(ResStr); + } + break; + case Stmt::StmtClass::CompoundAssignOperatorClass: + case Stmt::StmtClass::BinaryOperatorClass: + if (((clang::BinaryOperator*)E)->isCompoundAssignmentOp() || + !((clang::BinaryOperator*)E)->isAssignmentOp()) { + if (Leaves[0]) + Leaves[0]->print(ResStr); + ResStr+=((clang::BinaryOperator*)E)->getOpcodeStr(); + if (Leaves[1]) + Leaves[1]->print(ResStr); + } + else { + if (Leaves[1]) + Leaves[1]->print(ResStr); + ResStr+=((clang::BinaryOperator*)E)->getOpcodeStr(); + if (Leaves[0]) + Leaves[0]->print(ResStr); + } + break; + case Stmt::StmtClass::DeclRefExprClass: + ResStr+=((DeclRefExpr*)E)->getNameInfo().getAsString(); + break; + case Stmt::StmtClass::IntegerLiteralClass: + { + SmallString<5> BufferStr; + ((IntegerLiteral*)E)->getValue().toString(BufferStr, 10, false); + ResStr+=BufferStr; + } + break; + case Stmt::StmtClass::CStyleCastExprClass: + ResStr+=((Twine)"("+((CStyleCastExpr*)E)->getCastKindName()+")").str(); + break; + case Stmt::StmtClass::ParenExprClass: + ResStr+="("; + if (Leaves[0]) + Leaves[0]->print(ResStr); + ResStr+=")"; + break; + case Stmt::StmtClass::ImplicitCastExprClass: + if (Leaves[0]) + Leaves[0]->print(ResStr); + break; + case Stmt::StmtClass::ConditionalOperatorClass: + ResStr+=" - "; + if (Leaves[0]) + Leaves[0]->print(ResStr); + break; + case Stmt::StmtClass::IfStmtClass: + ResStr+="if ("; + if (Leaves[0]) + Leaves[0]->print(ResStr); + ResStr+=")"; + break; + case Stmt::StmtClass::WhileStmtClass: + case Stmt::StmtClass::DoStmtClass: + ResStr+="while ("; + if (Leaves[0]) + Leaves[0]->print(ResStr); + ResStr+=")"; + break; + case Stmt::StmtClass::ForStmtClass: + ResStr+=" - "; + if (Leaves[0]) + Leaves[0]->print(ResStr); + break; + case Stmt::StmtClass::SwitchStmtClass: + ResStr+="switch ("; + if (Leaves[0]) + Leaves[0]->print(ResStr); + ResStr+=")"; + break; + case Stmt::StmtClass::LabelStmtClass: + ResStr+=((Twine)Op.getUnchecked().getName()+":").str(); + break; + case Stmt::StmtClass::CaseStmtClass: + { + ResStr+="case "; + llvm::raw_string_ostream StrStream(ResStr); + Op.getUnchecked().getLHS()->printPretty(StrStream, nullptr, + clang::PrintingPolicy(clang::LangOptions())); + ResStr+=":"; + } + break; + case Stmt::StmtClass::DefaultStmtClass: + ResStr+="default:"; + break; + default: + ResStr+=Op.get()->getStmtClassName(); + break; + } + } + else { + ResStr+=Op.get()->getNameAsString()+"="; + if (Leaves[0]) + Leaves[0]->print(ResStr); + } +} + +void SourceCFGNode::destroy() { + switch (mKind) { + case NodeKind::Default: + delete (DefaultSCFGNode*)this; + break; + case NodeKind::Service: + delete (ServiceSCFGNode*)this; + break; + } +} + +SourceCFGNode::operator std::string() const { + switch (mKind) { + case NodeKind::Default: + return (string)(*(DefaultSCFGNode*)this); + case NodeKind::Service: + return (string)(*(ServiceSCFGNode*)this); + } +} + +DefaultSCFGNode::operator string() const { + string ResStr; + for (NodeOp *NO : mBlock) { + NO->print(ResStr); + ResStr+="\n"; + } + return ResStr; } void SourceCFG::deleteNode(SourceCFGNode &_Node) { - EdgeListTy EdgesToDelete; - findIncomingEdgesToNode(_Node, EdgesToDelete); - llvm::append_range(EdgesToDelete, _Node.getEdges()); - SourceCFGBase::removeNode(_Node); - for (auto E : EdgesToDelete) - delete E; - if (mStartNode==&_Node) - mStartNode=nullptr; - if (mStopNode==&_Node) - mStopNode==nullptr; - delete &_Node; + EdgeListTy EdgesToDelete; + findIncomingEdgesToNode(_Node, EdgesToDelete); + llvm::append_range(EdgesToDelete, _Node.getEdges()); + SourceCFGBase::removeNode(_Node); + for (auto E : EdgesToDelete) + E->destroy(); + if (mStartNode==&_Node) + mStartNode=nullptr; + if (mStopNode==&_Node) + mStopNode==nullptr; + _Node.destroy(); } void SourceCFG::deleteEdge(SourceCFGEdge &_Edge) { - for (auto N : Nodes) - for (auto E : N->getEdges()) - if (E==&_Edge) - N->removeEdge(_Edge); - delete &_Edge; + for (auto N : Nodes) + for (auto E : N->getEdges()) + if (E==&_Edge) + N->removeEdge(_Edge); + _Edge.destroy(); } +/* - Not working void SourceCFGNode::merge(SourceCFGNode &NodeToAttach) { - for (auto E : NodeToAttach.getEdges()) { - SourceCFGNodeBase::addEdge(*E); - NodeToAttach.removeEdge(*E); - } - SBB.addOp(NodeToAttach.SBB.begin(), NodeToAttach.SBB.end()); -} - -SourceCFGNode *SourceCFG::splitNode(SourceCFGNode &Node, int It) { - if (It==0) - return &Node; - SourceCFGNode *NewNode=&emplaceNode(SourceCFGNode::NodeKind::Default); - for (auto E : Node.getEdges()) - NewNode->addEdge(*E); - Node.clear(); - bindNodes(Node, *NewNode, SourceCFGEdge::EdgeKind::Default); - NewNode->addToNode(Node.SBB.begin()+It, Node.SBB.end()); - Node.SBB.decrease(It); - return NewNode; + for (auto E : NodeToAttach.getEdges()) { + SourceCFGNodeBase::addEdge(*E); + NodeToAttach.removeEdge(*E); + } + SBB.addOp(NodeToAttach.SBB.begin(), NodeToAttach.SBB.end()); +} +*/ + +DefaultSCFGNode *SourceCFG::splitNode(DefaultSCFGNode &Node, int It) { + if (It==0) + return &Node; + DefaultSCFGNode *NewNode=&emplaceNode(); + for (auto E : Node.getEdges()) + NewNode->addEdge(*E); + Node.clear(); + bindNodes(Node, *NewNode); + NewNode->addOp(Node.mBlock.begin()+It, Node.mBlock.end()); + Node.mBlock.resize(It); + return NewNode; +} + +void SourceCFGEdge::destroy() { + switch (mKind) { + case EdgeKind::Default: + delete (DefaultSCFGEdge*)this; + break; + case EdgeKind::Labeled: + delete (LabeledSCFGEdge*)this; + break; + } +} + +SourceCFGEdge::operator std::string() const { + switch (mKind) { + case EdgeKind::Default: + return (string)(*(DefaultSCFGEdge*)this); + case EdgeKind::Labeled: + return (string)(*(LabeledSCFGEdge*)this); + } } void SourceCFG::mergeNodes(SourceCFGNode &AbsorbNode, - SourceCFGNode &OutgoingNode) { - EdgeListTy CommonEdges; - if (AbsorbNode.findEdgesTo(OutgoingNode, CommonEdges)) { - for (auto E : CommonEdges) { - AbsorbNode.removeEdge(*E); - delete E; - } - CommonEdges.clear(); - } - if (OutgoingNode.findEdgesTo(AbsorbNode, CommonEdges)) - for (auto E : CommonEdges) { - AbsorbNode.addEdge(*(new SourceCFGEdge(*E))); - OutgoingNode.removeEdge(*E); - delete E; - } - AbsorbNode.merge(OutgoingNode); - SourceCFGBase::removeNode(OutgoingNode); - delete &OutgoingNode; + SourceCFGNode &OutgoingNode) { + EdgeListTy CommonEdges; + if (AbsorbNode.findEdgesTo(OutgoingNode, CommonEdges)) { + for (auto E : CommonEdges) { + AbsorbNode.removeEdge(*E); + E->destroy(); + } + CommonEdges.clear(); + } + if (OutgoingNode.findEdgesTo(AbsorbNode, CommonEdges)) + for (auto E : CommonEdges) { + AbsorbNode.addEdge(*(new SourceCFGEdge(*E))); + OutgoingNode.removeEdge(*E); + E->destroy(); + } + //AbsorbNode.merge(OutgoingNode); - Not working + SourceCFGBase::removeNode(OutgoingNode); + OutgoingNode.destroy(); } void markReached(SourceCFGNode *Node, - std::map *NodesList) { - (*NodesList)[Node]=true; - for (auto E : *Node) - if (!(*NodesList)[&E->getTargetNode()]) - markReached(&E->getTargetNode(), NodesList); + std::map *NodesList) { + (*NodesList)[Node]=true; + for (auto E : *Node) + if (!(*NodesList)[&E->getTargetNode()]) + markReached(&E->getTargetNode(), NodesList); +} + +void SourceCFG::recalculatePredMap() { + mPredecessorsMap.clear(); + for (auto N : Nodes) { + mPredecessorsMap.insert({N, {}}); + auto OutcomingEdges=N->getEdges(); + for (auto E : OutcomingEdges) { + auto It=mPredecessorsMap.find(&E->getTargetNode()); + if (It!=mPredecessorsMap.end()) + It->second.insert(N); + else + mPredecessorsMap.insert({&E->getTargetNode(), {N}}); + } + } } void SourceCFGBuilder::eliminateUnreached() { - std::map ReachedNodes; - for (auto N : *mSCFG) - ReachedNodes.insert({N, false}); - markReached(mSCFG->getStartNode(), &ReachedNodes); - for (auto It : ReachedNodes) - if (!It.second) - mSCFG->deleteNode(*It.first); + std::map ReachedNodes; + for (auto N : *mSCFG) + ReachedNodes.insert({N, false}); + markReached(mSCFG->getStartNode(), &ReachedNodes); + for (auto It : ReachedNodes) + if (!It.second) + mSCFG->deleteNode(*It.first); } void SourceCFGBuilder::processLabels() { - std::map> OrderingMap; - for (auto GotoIt=mGotos.begin(); GotoIt!=mGotos.end(); ++GotoIt) - if (OrderingMap.find(mLabels[GotoIt->first].Node)!=OrderingMap.end()) - OrderingMap[mLabels[GotoIt->first].Node].push_back({GotoIt, - mLabels[GotoIt->first].LabelIt}); - else - OrderingMap.insert({mLabels[GotoIt->first].Node, - {{GotoIt, mLabels[GotoIt->first].LabelIt}}}); - for (auto OMIt=OrderingMap.begin(); OMIt!=OrderingMap.end(); ++OMIt) { - auto &GIVector=OMIt->second; - std::sort(GIVector.begin(), GIVector.end(), compareGotoInfo); - auto GIIt=GIVector.rbegin(); - while (GIIt!=GIVector.rend()) { - while (GIIt+1!=GIVector.rend() && (GIIt+1)->GotoIt-GIIt->GotoIt==1) - ++GIIt; - auto NewNode=mSCFG->splitNode(*OMIt->first, GIIt->GotoIt); - for (auto UpdateIt=mGotos.begin(); UpdateIt!=mGotos.end(); ++UpdateIt) - if (UpdateIt->second==OMIt->first) { - UpdateIt->second=NewNode; - break; - } - mSCFG->bindNodes(*GIIt->GotoNodeIt->second, *NewNode, - SourceCFGEdge::EdgeKind::Default); - ++GIIt; - } - } + std::map>> OrderingMap; + for (auto GotoIt : mGotos) + addToMap(OrderingMap, mLabels[GotoIt.first], pair{GotoIt.second, nullptr}); + for (auto SwitchIt : mSwitchGotos) + addToMap(OrderingMap, mLabels[SwitchIt.first], pair{SwitchIt.second, + SwitchIt.first}); + for (auto It : OrderingMap) { + auto NewNode=mSCFG->splitNode(*It.first.Node, It.first.LabelIt); + for (auto GotoNode : It.second) + if (GotoNode.second) + mSCFG->bindNodes(*GotoNode.first, *NewNode, GotoNode.second); + else + mSCFG->bindNodes(*GotoNode.first, *NewNode); + } } SourceCFG *SourceCFGBuilder::populate(FunctionDecl *Decl) { - if (Decl->hasBody()) { - DeclarationNameInfo Info=Decl->getNameInfo(); - mSCFG=new SourceCFG(Info.getAsString()); - mDirectOut.push(MarkedOutsType()); - parseStmt(Decl->getBody()); - if (mEntryNode) { - mSCFG->bindNodes(*mSCFG->getStartNode(), *mEntryNode, - SourceCFGEdge::EdgeKind::Default); - for (auto It : mDirectOut.top()) - mSCFG->bindNodes(*It.first, *mSCFG->getStopNode(), It.second); - processLabels(); - } - else - mSCFG->bindNodes(*mSCFG->getStartNode(), *mSCFG->getStopNode(), - SourceCFGEdge::EdgeKind::Default); - mDirectOut.pop(); - eliminateUnreached(); - } - return mSCFG; + if (Decl->hasBody()) { + DeclarationNameInfo Info=Decl->getNameInfo(); + mSCFG=new SourceCFG(Info.getAsString()); + mDirectOut.push_back(MarkedOutsType()); + parseStmt(Decl->getBody()); + if (mEntryNode) { + mSCFG->bindNodes(*mSCFG->getStartNode(), *mEntryNode); + for (auto It : mDirectOut.back()) + mSCFG->bindNodes(*It.first, *mSCFG->getStopNode(), It.second); + processLabels(); + } + else + mSCFG->bindNodes(*mSCFG->getStartNode(), *mSCFG->getStopNode()); + mDirectOut.pop_back(); + eliminateUnreached(); + } + return mSCFG; +} + +bool SourceCFGBuilder::hasConditionalOperator(clang::Stmt *Root) { + if (isa(*Root)) + return true; + else { + for (auto SubExpr : Root->children()) + if (hasConditionalOperator(SubExpr)) + return true; + return false; + } } void SourceCFGBuilder::parseStmt(Stmt *Root) { - Stmt::StmtClass Type=Root->getStmtClass(); - if ((!mEntryNode || !mNodeToAdd) && - Type!=Stmt::StmtClass::CompoundStmtClass) { - mNodeToAdd=&mSCFG->emplaceNode(SourceCFGNode::NodeKind::Default); - if (!mEntryNode) - mEntryNode=mNodeToAdd; - for (auto Outs : mDirectOut.top()) - mSCFG->bindNodes(*Outs.first, *mNodeToAdd, Outs.second); - mDirectOut.top().clear(); - mDirectOut.top().insert({mNodeToAdd, SourceCFGEdge::EdgeKind::Default}); - } - auto ParserIt=mParsers.find(Type); - if (ParserIt!=mParsers.end()) - (this->*(ParserIt->second))(Root); - else { - if (isa(Root)) - parseExpr((Expr*)Root, nullptr, true); - else { - mNodeToAdd->addToNode(new NativeNodeOp(Root)); - mDirectOut.top().insert({mNodeToAdd, SourceCFGEdge::EdgeKind::Default}); - } - } + Stmt::StmtClass Type=Root->getStmtClass(); + if ((!mEntryNode || !mNodeToAdd) && + Type!=Stmt::StmtClass::CompoundStmtClass) { + mNodeToAdd=&mSCFG->emplaceNode(); + if (!mEntryNode) + mEntryNode=mNodeToAdd; + for (auto Outs : mDirectOut.back()) + mSCFG->bindNodes(*Outs.first, *mNodeToAdd, Outs.second); + mDirectOut.back().clear(); + mDirectOut.back().insert({mNodeToAdd, DefaultSCFGEdge::EdgeType::Default}); + } + switch (Type) { + case Stmt::StmtClass::CompoundStmtClass: + parseCompoundStmt((CompoundStmt*)Root); + break; + case Stmt::StmtClass::IfStmtClass: + parseIfStmt((IfStmt*)Root); + break; + case Stmt::StmtClass::WhileStmtClass: + parseWhileStmt((WhileStmt*)Root); + break; + case Stmt::StmtClass::DoStmtClass: + parseDoStmt((DoStmt*)Root); + break; + case Stmt::StmtClass::ContinueStmtClass: + parseContinueStmt((ContinueStmt*)Root); + break; + case Stmt::StmtClass::BreakStmtClass: + parseBreakStmt((BreakStmt*)Root); + break; + case Stmt::StmtClass::ReturnStmtClass: + parseReturnStmt((ReturnStmt*)Root); + break; + case Stmt::StmtClass::LabelStmtClass: + parseLabelStmt((LabelStmt*)Root); + break; + case Stmt::StmtClass::GotoStmtClass: + parseGotoStmt((GotoStmt*)Root); + break; + case Stmt::StmtClass::DeclStmtClass: + parseDeclStmt((DeclStmt*)Root, nullptr); + break; + case Stmt::StmtClass::ForStmtClass: + parseForStmt((ForStmt*)Root); + break; + case Stmt::StmtClass::SwitchStmtClass: + parseSwitchStmt((SwitchStmt*)Root); + break; + case Stmt::StmtClass::DefaultStmtClass: + mDirectOut[mDirectOut.size()-2].erase(mSwitchNodes.top()); + case Stmt::StmtClass::CaseStmtClass: + parseLabelStmt((LabelStmt*)Root); + mSwitchGotos.push_back({(SwitchCase*)Root, mSwitchNodes.top()}); + break; + default: + if (isa(*Root) && hasConditionalOperator(Root)) + parseExpr(DynTypedNode::create(*Root), nullptr, true); + else { + mNodeToAdd->addOp(new NativeNodeOp(Root)); + mDirectOut.back().insert({mNodeToAdd, + DefaultSCFGEdge::EdgeType::Default}); + } + } } void SourceCFGBuilder::continueFlow(NodeOp *Op) { - if (!mNodeToAdd) { - mNodeToAdd=&mSCFG->emplaceNode(SourceCFGNode::NodeKind::Default); - mNodeToAdd->addToNode(Op); - for (auto Outs : mDirectOut.top()) - mSCFG->bindNodes(*Outs.first, *mNodeToAdd, Outs.second); - mDirectOut.top().clear(); - } - else - mNodeToAdd->addToNode(Op); - mDirectOut.top().insert({mNodeToAdd, SourceCFGEdge::EdgeKind::Default}); + if (!mNodeToAdd) { + mNodeToAdd=&mSCFG->emplaceNode(); + mNodeToAdd->addOp(Op); + for (auto Outs : mDirectOut.back()) + mSCFG->bindNodes(*Outs.first, *mNodeToAdd, Outs.second); + mDirectOut.back().clear(); + } + else + mNodeToAdd->addOp(Op); + mDirectOut.back().insert({mNodeToAdd, DefaultSCFGEdge::EdgeType::Default}); } void SourceCFGBuilder::processIndirect(SourceCFGNode *CondStartNode) { - if (CondStartNode) - for (auto Out : mContinueOut.top()) - mSCFG->bindNodes(*Out, *CondStartNode, - SourceCFGEdge::EdgeKind::Continue); - for (auto Out : mBreakOut.top()) - mDirectOut.top().insert({Out, SourceCFGEdge::EdgeKind::Break}); -} - -void SourceCFGBuilder::parseExpr(tsar::Op O, NodeOp *ParentOp, - bool isFirstCall) { - SourceCFGNode *OldNodeToAdd; - WrapperNodeOp *NewNodeOp; - if (O.IsStmt) { - Stmt::StmtClass Type=O.S->getStmtClass(); - if (isa(*O.S)) { - MarkedOutsType UpperOuts; - SourceCFGNode *ConditionNode, *TrueNode, *FalseNode; - ConditionalOperator &CO=*(ConditionalOperator*)O.S; - auto OldEntryNode=mEntryNode; - auto OldTreeTopParentPtr=mTreeTopParentPtr; - NodeOp *CondOp=new WrapperNodeOp(&CO); - if (ParentOp) - ((WrapperNodeOp*)ParentOp)->Leaves.push_back(new ReferenceNodeOp( - CondOp, "cond_res")); - if (mTreeTopParentPtr && ((WrapperNodeOp*)mTreeTopParentPtr)-> - Leaves.size()>0) { - continueFlow(((WrapperNodeOp*)mTreeTopParentPtr)->Leaves[0]); - ((WrapperNodeOp*)mTreeTopParentPtr)->Leaves[0]=new ReferenceNodeOp( - ((WrapperNodeOp*)mTreeTopParentPtr)->Leaves[0], ""); - } - parseExpr(CO.getCond(), CondOp, true); - ConditionNode=mNodeToAdd; - mEntryNode=mNodeToAdd=nullptr; - mDirectOut.push(MarkedOutsType()); - parseStmt(CO.getTrueExpr()); - TrueNode=mEntryNode; - mSCFG->bindNodes(*ConditionNode, *TrueNode, - SourceCFGEdge::EdgeKind::True); - UpperOuts=mDirectOut.top(); - mDirectOut.pop(); - for (auto It : UpperOuts) - mDirectOut.top().insert(It); - mEntryNode=mNodeToAdd=nullptr; - mDirectOut.push(MarkedOutsType()); - parseStmt(CO.getFalseExpr()); - FalseNode=mEntryNode; - mSCFG->bindNodes(*ConditionNode, *FalseNode, - SourceCFGEdge::EdgeKind::False); - UpperOuts=mDirectOut.top(); - mDirectOut.pop(); - for (auto It : UpperOuts) - mDirectOut.top().insert(It); - mDirectOut.top().erase(ConditionNode); - mNodeToAdd=nullptr; - mEntryNode=OldEntryNode; - mTreeTopParentPtr=OldTreeTopParentPtr; - if (isFirstCall && ParentOp && - !isa(*((WrapperNodeOp*)ParentOp)->O.S)) - continueFlow(ParentOp); - return; - } - else { - OldNodeToAdd=mNodeToAdd; - if (isFirstCall) - mTreeTopParentPtr=nullptr; - NewNodeOp=new WrapperNodeOp(O.S); - switch (Type) { - case Stmt::StmtClass::CompoundAssignOperatorClass: - parseExpr(((clang::BinaryOperator*)O.S)->getLHS(), NewNodeOp, false); - parseExpr(((clang::BinaryOperator*)O.S)->getRHS(), NewNodeOp, false); - break; - case Stmt::StmtClass::BinaryOperatorClass: - if (((clang::BinaryOperator*)O.S)->isAssignmentOp()) { - parseExpr(((clang::BinaryOperator*)O.S)->getRHS(), NewNodeOp, - false); - parseExpr(((clang::BinaryOperator*)O.S)->getLHS(), NewNodeOp, - false); - } - else { - parseExpr(((clang::BinaryOperator*)O.S)->getLHS(), NewNodeOp, - false); - parseExpr(((clang::BinaryOperator*)O.S)->getRHS(), NewNodeOp, - false); - } - break; - default: - for (auto SubExpr : O.S->children()) - parseExpr((clang::Expr*)SubExpr, NewNodeOp, false); - break; - } - } - } - else { - OldNodeToAdd=mNodeToAdd; - if (isFirstCall) - mTreeTopParentPtr=nullptr; - NewNodeOp=new WrapperNodeOp(O.VD); - parseExpr(O.VD->getInit(), NewNodeOp, false); - } - NodeOp *OpToAdd; - if (mNodeToAdd && OldNodeToAdd==mNodeToAdd) { - OpToAdd=new NativeNodeOp(*NewNodeOp); - delete NewNodeOp; - } - else - OpToAdd=NewNodeOp; - if (isFirstCall) { - if (ParentOp) { - ((WrapperNodeOp*)ParentOp)->Leaves.push_back(OpToAdd); - continueFlow(ParentOp); - } - else - continueFlow(OpToAdd); - mTreeTopParentPtr=nullptr; - } - else { - ((WrapperNodeOp*)ParentOp)->Leaves.push_back(OpToAdd); - mTreeTopParentPtr=ParentOp; - } + // Processing of continue statements + if (CondStartNode) + for (auto Out : mContinueOut.top()) + mSCFG->bindNodes(*Out, *CondStartNode); + // Processing of break statements + for (auto Out : mBreakOut.top()) + mDirectOut.back().insert({Out, DefaultSCFGEdge::EdgeType::Default}); +} + +void SourceCFGBuilder::parseExpr(clang::DynTypedNode Op, NodeOp *ParentOp, + bool isFirstCall) { + DefaultSCFGNode *OldNodeToAdd; + WrapperNodeOp *NewNodeOp; + if (Op.get()) { + Stmt::StmtClass Type=Op.getUnchecked().getStmtClass(); + if (Op.get()) { + MarkedOutsType UpperOuts; + DefaultSCFGNode *ConditionNode, *TrueNode, *FalseNode; + const ConditionalOperator &CO=Op.getUnchecked(); + auto OldEntryNode=mEntryNode; + auto OldTreeTopParentPtr=mTreeTopParentPtr; + NodeOp *CondOp=new WrapperNodeOp(&CO); + if (ParentOp) + ((WrapperNodeOp*)ParentOp)->Leaves.push_back(new ReferenceNodeOp( + CondOp, "cond_res")); + if (mTreeTopParentPtr && ((WrapperNodeOp*)mTreeTopParentPtr)-> + Leaves.size()>0) { + continueFlow(((WrapperNodeOp*)mTreeTopParentPtr)->Leaves[0]); + ((WrapperNodeOp*)mTreeTopParentPtr)->Leaves[0]=new ReferenceNodeOp( + ((WrapperNodeOp*)mTreeTopParentPtr)->Leaves[0], ""); + } + parseExpr(DynTypedNode::create(*CO.getCond()), CondOp, true); + ConditionNode=mNodeToAdd; + mEntryNode=mNodeToAdd=nullptr; + mDirectOut.push_back(MarkedOutsType()); + parseStmt(CO.getTrueExpr()); + TrueNode=mEntryNode; + mSCFG->bindNodes(*ConditionNode, *TrueNode, + DefaultSCFGEdge::EdgeType::True); + UpperOuts=mDirectOut.back(); + mDirectOut.pop_back(); + for (auto It : UpperOuts) + mDirectOut.back().insert(It); + mEntryNode=mNodeToAdd=nullptr; + mDirectOut.push_back(MarkedOutsType()); + parseStmt(CO.getFalseExpr()); + FalseNode=mEntryNode; + mSCFG->bindNodes(*ConditionNode, *FalseNode, + DefaultSCFGEdge::EdgeType::False); + UpperOuts=mDirectOut.back(); + mDirectOut.pop_back(); + for (auto It : UpperOuts) + mDirectOut.back().insert(It); + mDirectOut.back().erase(ConditionNode); + mNodeToAdd=nullptr; + mEntryNode=OldEntryNode; + mTreeTopParentPtr=OldTreeTopParentPtr; + if (isFirstCall && ParentOp && + !((WrapperNodeOp*)ParentOp)->Op.get()) + continueFlow(ParentOp); + return; + } + else { + OldNodeToAdd=mNodeToAdd; + if (isFirstCall) + mTreeTopParentPtr=nullptr; + NewNodeOp=new WrapperNodeOp(&Op.getUnchecked()); + switch (Type) { + case Stmt::StmtClass::CompoundAssignOperatorClass: + parseExpr(DynTypedNode::create(*Op.getUnchecked().getLHS()), NewNodeOp, false); + parseExpr(DynTypedNode::create(*Op.getUnchecked().getRHS()), NewNodeOp, false); + break; + case Stmt::StmtClass::BinaryOperatorClass: + if (Op.getUnchecked().isAssignmentOp()) { + parseExpr(DynTypedNode::create(*Op.getUnchecked().getRHS()), NewNodeOp, false); + parseExpr(DynTypedNode::create(*Op.getUnchecked().getLHS()), NewNodeOp, false); + } + else { + parseExpr(DynTypedNode::create(*Op.getUnchecked().getLHS()), NewNodeOp, false); + parseExpr(DynTypedNode::create(*Op.getUnchecked().getRHS()), NewNodeOp, false); + } + break; + default: + for (auto SubExpr : Op.getUnchecked().children()) + parseExpr(DynTypedNode::create(*SubExpr), NewNodeOp, false); + break; + } + } + } + else { + OldNodeToAdd=mNodeToAdd; + if (isFirstCall) + mTreeTopParentPtr=nullptr; + NewNodeOp=new WrapperNodeOp(&Op.getUnchecked()); + parseExpr(DynTypedNode::create(*Op.getUnchecked().getInit()), + NewNodeOp, false); + } + NodeOp *OpToAdd; + if (mNodeToAdd && OldNodeToAdd==mNodeToAdd) { + OpToAdd=new NativeNodeOp(*NewNodeOp); + delete NewNodeOp; + } + else + OpToAdd=NewNodeOp; + if (isFirstCall) { + if (ParentOp) { + ((WrapperNodeOp*)ParentOp)->Leaves.push_back(OpToAdd); + continueFlow(ParentOp); + } + else + continueFlow(OpToAdd); + mTreeTopParentPtr=nullptr; + } + else { + ((WrapperNodeOp*)ParentOp)->Leaves.push_back(OpToAdd); + mTreeTopParentPtr=ParentOp; + } } void SourceCFGBuilder::parseCompoundStmt(CompoundStmt *Root) { - MarkedOutsType UpperOuts; - SourceCFGNode *ResultEntryNode=mEntryNode; - mDirectOut.push(MarkedOutsType()); - for (auto S : Root->body()) { - parseStmt(S); - if (!ResultEntryNode && mEntryNode) - ResultEntryNode=mEntryNode; - } - mEntryNode=ResultEntryNode; - UpperOuts=mDirectOut.top(); - mDirectOut.pop(); - for (auto Outs : UpperOuts) - mDirectOut.top().insert(Outs); + MarkedOutsType UpperOuts; + DefaultSCFGNode *ResultEntryNode=mEntryNode; + mDirectOut.push_back(MarkedOutsType()); + for (auto S : Root->body()) { + parseStmt(S); + if (!ResultEntryNode && mEntryNode) + ResultEntryNode=mEntryNode; + } + mEntryNode=ResultEntryNode; + UpperOuts=mDirectOut.back(); + mDirectOut.pop_back(); + for (auto Outs : UpperOuts) + mDirectOut.back().insert(Outs); } void SourceCFGBuilder::parseDoStmt(DoStmt *Root) { - SourceCFGNode *mStartNode=mNodeToAdd, *CondStartNode, *CondEndNode, *Body; - mContinueOut.push(OutsType()); - mBreakOut.push(OutsType()); - mDirectOut.push(MarkedOutsType()); - if (mStartNode->size()==0) - Body=mStartNode; - else { - Body=mEntryNode=mNodeToAdd=&mSCFG->emplaceNode( - SourceCFGNode::NodeKind::Default); - mSCFG->bindNodes(*mStartNode, *Body, SourceCFGEdge::EdgeKind::Default); - } - parseStmt(Root->getBody()); - if (!mContinueOut.top().empty() || !mNodeToAdd) { - CondStartNode=mNodeToAdd=&mSCFG->emplaceNode( - SourceCFGNode::NodeKind::Default); - for (auto Outs : mDirectOut.top()) - mSCFG->bindNodes(*Outs.first, *CondStartNode, Outs.second); - mDirectOut.top().clear(); - } - else - CondStartNode=mNodeToAdd; - parseExpr(Root->getCond(), new WrapperNodeOp(Root), true); - CondEndNode=mNodeToAdd; - mSCFG->bindNodes(*CondEndNode, *Body, SourceCFGEdge::EdgeKind::True); - mDirectOut.pop(); - mDirectOut.top().erase(mStartNode); - mDirectOut.top().insert({CondEndNode, SourceCFGEdge::EdgeKind::False}); - mNodeToAdd=nullptr; - mEntryNode=mStartNode; - processIndirect(CondStartNode); - mContinueOut.pop(); - mBreakOut.pop(); + DefaultSCFGNode *mStartNode=mNodeToAdd, *CondStartNode, *CondEndNode, *Body; + mContinueOut.push(OutsType()); + mBreakOut.push(OutsType()); + mDirectOut.push_back(MarkedOutsType()); + if (mStartNode->size()==0) + Body=mStartNode; + else { + Body=mEntryNode=mNodeToAdd=&mSCFG->emplaceNode(); + mSCFG->bindNodes(*mStartNode, *Body); + } + parseStmt(Root->getBody()); + if (!mContinueOut.top().empty() || !mNodeToAdd) { + CondStartNode=mNodeToAdd=&mSCFG->emplaceNode(); + for (auto Outs : mDirectOut.back()) + mSCFG->bindNodes(*Outs.first, *CondStartNode, Outs.second); + mDirectOut.back().clear(); + } + else + CondStartNode=mNodeToAdd; + parseExpr(DynTypedNode::create(*Root->getCond()), new WrapperNodeOp(Root), + true); + CondEndNode=mNodeToAdd; + mSCFG->bindNodes(*CondEndNode, *Body, DefaultSCFGEdge::EdgeType::True); + mDirectOut.pop_back(); + mDirectOut.back().erase(mStartNode); + mDirectOut.back().insert({CondEndNode, DefaultSCFGEdge::EdgeType::False}); + mNodeToAdd=nullptr; + mEntryNode=mStartNode; + processIndirect(CondStartNode); + mContinueOut.pop(); + mBreakOut.pop(); } void SourceCFGBuilder::parseForStmt(ForStmt *Root) { - SourceCFGNode *mStartNode=mNodeToAdd, *CondStartNode=nullptr, - *CondEndNode=nullptr, *Body=nullptr, *IncStartNode=nullptr, *LoopNode; - MarkedOutsType AfterInitOuts; - mContinueOut.push(OutsType()); - mBreakOut.push(OutsType()); - if (Root->getInit()) - if (isa(*Root->getInit())) - parseDeclStmt((DeclStmt*)Root->getInit(), nullptr); - else - parseExpr(Root->getInit(), nullptr, true); - AfterInitOuts=mDirectOut.top(); - if (Root->getCond()) { - if (mNodeToAdd && mNodeToAdd->size()==0) - CondStartNode=mNodeToAdd; - else { - CondStartNode=mNodeToAdd=&mSCFG->emplaceNode( - SourceCFGNode::NodeKind::Default); - for (auto Out : mDirectOut.top()) - mSCFG->bindNodes(*Out.first, *CondStartNode, Out.second); - mDirectOut.top().clear(); - } - parseExpr(Root->getCond(), new WrapperNodeOp(Root), true); - CondEndNode=mNodeToAdd; - } - mDirectOut.top().clear(); - mEntryNode=mNodeToAdd=nullptr; - parseStmt(Root->getBody()); - Body=mEntryNode; - if (CondEndNode) - mSCFG->bindNodes(*CondEndNode, *Body, SourceCFGEdge::EdgeKind::True); - else - for (auto Out : AfterInitOuts) - mSCFG->bindNodes(*Out.first, *Body, Out.second); - if (Root->getInc()) { - if (!mContinueOut.top().empty()) - mEntryNode=mNodeToAdd=nullptr; - parseStmt(Root->getInc()); - IncStartNode=mEntryNode; - } - LoopNode=CondStartNode?CondStartNode:Body; - for (auto Out : mDirectOut.top()) - mSCFG->bindNodes(*Out.first, *LoopNode, Out.second); - mDirectOut.top().clear(); - if (CondEndNode) - mDirectOut.top().insert({CondEndNode, SourceCFGEdge::EdgeKind::False}); - mNodeToAdd=nullptr; - mEntryNode=mStartNode; - if (IncStartNode) - processIndirect(IncStartNode); - else - if (CondStartNode) - processIndirect(CondStartNode); - else - processIndirect(Body); - mContinueOut.pop(); - mBreakOut.pop(); + DefaultSCFGNode *mStartNode=mNodeToAdd, *CondStartNode=nullptr, + *CondEndNode=nullptr, *Body=nullptr, *IncStartNode=nullptr, *LoopNode; + MarkedOutsType AfterInitOuts; + mContinueOut.push(OutsType()); + mBreakOut.push(OutsType()); + if (Root->getInit()) + if (isa(*Root->getInit())) + parseDeclStmt((DeclStmt*)Root->getInit(), nullptr); + else + parseExpr(DynTypedNode::create(*Root->getInit()), nullptr, true); + AfterInitOuts=mDirectOut.back(); + if (Root->getCond()) { + if (mNodeToAdd && mNodeToAdd->size()==0) + CondStartNode=mNodeToAdd; + else { + CondStartNode=mNodeToAdd=&mSCFG->emplaceNode(); + for (auto Out : mDirectOut.back()) + mSCFG->bindNodes(*Out.first, *CondStartNode, Out.second); + mDirectOut.back().clear(); + } + parseExpr(DynTypedNode::create(*Root->getCond()), new WrapperNodeOp(Root), + true); + CondEndNode=mNodeToAdd; + } + mDirectOut.back().clear(); + mEntryNode=mNodeToAdd=nullptr; + parseStmt(Root->getBody()); + Body=mEntryNode; + if (CondEndNode) + mSCFG->bindNodes(*CondEndNode, *Body, DefaultSCFGEdge::EdgeType::True); + else + for (auto Out : AfterInitOuts) + mSCFG->bindNodes(*Out.first, *Body, Out.second); + if (Root->getInc()) { + if (!mContinueOut.top().empty()) + mEntryNode=mNodeToAdd=nullptr; + parseStmt(Root->getInc()); + IncStartNode=mEntryNode; + } + LoopNode=CondStartNode?CondStartNode:Body; + for (auto Out : mDirectOut.back()) + mSCFG->bindNodes(*Out.first, *LoopNode, Out.second); + mDirectOut.back().clear(); + if (CondEndNode) + mDirectOut.back().insert({CondEndNode, DefaultSCFGEdge::EdgeType::False}); + mNodeToAdd=nullptr; + mEntryNode=mStartNode; + if (IncStartNode) + processIndirect(IncStartNode); + else + if (CondStartNode) + processIndirect(CondStartNode); + else + processIndirect(Body); + mContinueOut.pop(); + mBreakOut.pop(); } void SourceCFGBuilder::parseSwitchStmt(SwitchStmt *Root) { - mBreakOut.push(OutsType()); - SourceCFGNode *CondStartNode=mNodeToAdd, *CondEndNode; - parseExpr(Root->getCond(), new WrapperNodeOp(Root), true); - CondEndNode=mNodeToAdd; - mEntryNode=mNodeToAdd=nullptr; - parseStmt(Root->getBody()); - processIndirect(nullptr); - std::map> OrderingMap; - for (auto CaseIt : mCases) - if (OrderingMap.find(CaseIt.second.Node)!=OrderingMap.end()) - OrderingMap[CaseIt.second.Node].push_back(CaseIt.second.LabelIt); - else - OrderingMap.insert({CaseIt.second.Node, {CaseIt.second.LabelIt}}); - for (auto OMIt=OrderingMap.begin(); OMIt!=OrderingMap.end(); ++OMIt) { - auto &IVector=OMIt->second; - std::sort(IVector.begin(), IVector.end()); - auto It=IVector.rbegin(); - while (It!=IVector.rend()) { - while (It+1!=IVector.rend() && *(It+1)-*It==1) - ++It; - auto NewNode=mSCFG->splitNode(*OMIt->first, *It); - mSCFG->bindNodes(*CondEndNode, *NewNode, - SourceCFGEdge::EdgeKind::ToCase); - ++It; - } - } - //mDirectOut.top().clear(); - mBreakOut.pop(); -} - -void SourceCFGBuilder::parseCaseStmt(CaseStmt *Root) { - mNodeToAdd->addToNode(new NativeNodeOp(Root)); - mCases.insert({Root, {mNodeToAdd, (int)mNodeToAdd->size()-1}}); - parseStmt(Root->getSubStmt()); + mBreakOut.push(OutsType()); + DefaultSCFGNode *CondStartNode=mNodeToAdd, *CondEndNode; + parseExpr(DynTypedNode::create(*Root->getCond()), new WrapperNodeOp(Root), + true); + CondEndNode=mNodeToAdd; + mSwitchNodes.push(CondEndNode); + mDirectOut.back()[CondEndNode]=DefaultSCFGEdge::EdgeType::ImplicitDefault; + mEntryNode=mNodeToAdd=nullptr; + parseStmt(Root->getBody()); + processIndirect(nullptr); + mSwitchNodes.pop(); + mBreakOut.pop(); } void SourceCFGBuilder::parseWhileStmt(WhileStmt *Root) { - mContinueOut.push(OutsType()); - mBreakOut.push(OutsType()); - mDirectOut.push(MarkedOutsType()); - SourceCFGNode *mStartNode=mNodeToAdd, *CondStartNode, *CondEndNode; - if (mStartNode->size()==0) { - CondStartNode=mStartNode; - parseExpr(Root->getCond(), new WrapperNodeOp(Root), true); - } - else { - CondStartNode=mNodeToAdd=&mSCFG->emplaceNode( - SourceCFGNode::NodeKind::Default); - mSCFG->bindNodes(*mStartNode, *CondStartNode, - SourceCFGEdge::EdgeKind::Default); - parseExpr(Root->getCond(), new WrapperNodeOp(Root), true); - } - CondEndNode=mNodeToAdd; - mDirectOut.top().erase(CondEndNode); - mEntryNode=mNodeToAdd=nullptr; - parseStmt(Root->getBody()); - mSCFG->bindNodes(*CondEndNode, *mEntryNode, SourceCFGEdge::EdgeKind::True); - for (auto Outs : mDirectOut.top()) - mSCFG->bindNodes(*Outs.first, *CondStartNode, Outs.second); - mDirectOut.pop(); - mDirectOut.top().erase(mStartNode); - mDirectOut.top().insert({CondEndNode, SourceCFGEdge::EdgeKind::False}); - mEntryNode=mStartNode; - mNodeToAdd=nullptr; - processIndirect(CondStartNode); - mContinueOut.pop(); - mBreakOut.pop(); + mContinueOut.push(OutsType()); + mBreakOut.push(OutsType()); + mDirectOut.push_back(MarkedOutsType()); + DefaultSCFGNode *mStartNode=mNodeToAdd, *CondStartNode, *CondEndNode; + if (mStartNode->size()==0) { + CondStartNode=mStartNode; + parseExpr(DynTypedNode::create(*Root->getCond()), new WrapperNodeOp(Root), + true); + } + else { + CondStartNode=mNodeToAdd=&mSCFG->emplaceNode(); + mSCFG->bindNodes(*mStartNode, *CondStartNode); + parseExpr(DynTypedNode::create(*Root->getCond()), new WrapperNodeOp(Root), + true); + } + CondEndNode=mNodeToAdd; + mDirectOut.back().erase(CondEndNode); + mEntryNode=mNodeToAdd=nullptr; + parseStmt(Root->getBody()); + mSCFG->bindNodes(*CondEndNode, *mEntryNode, DefaultSCFGEdge::EdgeType::True); + for (auto Outs : mDirectOut.back()) + mSCFG->bindNodes(*Outs.first, *CondStartNode, Outs.second); + mDirectOut.pop_back(); + mDirectOut.back().erase(mStartNode); + mDirectOut.back().insert({CondEndNode, DefaultSCFGEdge::EdgeType::False}); + mEntryNode=mStartNode; + mNodeToAdd=nullptr; + processIndirect(CondStartNode); + mContinueOut.pop(); + mBreakOut.pop(); } void SourceCFGBuilder::parseIfStmt(IfStmt *Root) { - MarkedOutsType UpperOuts; - SourceCFGNode *CondStartNode=mNodeToAdd, *CondEndNode; - Stmt *ActionStmt; - parseExpr(Root->getCond(), new WrapperNodeOp(Root), true); - CondEndNode=mNodeToAdd; - mDirectOut.push(MarkedOutsType()); - mEntryNode=mNodeToAdd=nullptr; - parseStmt(Root->getThen()); - mSCFG->bindNodes(*CondEndNode, *mEntryNode, SourceCFGEdge::EdgeKind::True); - if ((ActionStmt=Root->getElse())) { - mDirectOut.push(MarkedOutsType()); - mEntryNode=mNodeToAdd=nullptr; - parseStmt(ActionStmt); - mSCFG->bindNodes(*CondEndNode, *mEntryNode, - SourceCFGEdge::EdgeKind::False); - UpperOuts=mDirectOut.top(); - mDirectOut.pop(); - for (auto Out : UpperOuts) - mDirectOut.top().insert(Out); - } - else - mDirectOut.top().insert({CondEndNode, SourceCFGEdge::EdgeKind::False}); - UpperOuts=mDirectOut.top(); - mDirectOut.pop(); - mDirectOut.top().erase(CondEndNode); - for (auto Outs : UpperOuts) - mDirectOut.top().insert(Outs); - mEntryNode=CondStartNode; - mNodeToAdd=nullptr; + MarkedOutsType UpperOuts; + DefaultSCFGNode *CondStartNode=mNodeToAdd, *CondEndNode; + Stmt *ActionStmt; + parseExpr(DynTypedNode::create(*Root->getCond()), new WrapperNodeOp(Root), + true); + CondEndNode=mNodeToAdd; + mDirectOut.push_back(MarkedOutsType()); + mEntryNode=mNodeToAdd=nullptr; + parseStmt(Root->getThen()); + mSCFG->bindNodes(*CondEndNode, *mEntryNode, DefaultSCFGEdge::EdgeType::True); + if ((ActionStmt=Root->getElse())) { + mDirectOut.push_back(MarkedOutsType()); + mEntryNode=mNodeToAdd=nullptr; + parseStmt(ActionStmt); + mSCFG->bindNodes(*CondEndNode, *mEntryNode, + DefaultSCFGEdge::EdgeType::False); + UpperOuts=mDirectOut.back(); + mDirectOut.pop_back(); + for (auto Out : UpperOuts) + mDirectOut.back().insert(Out); + } + else + mDirectOut.back().insert({CondEndNode, DefaultSCFGEdge::EdgeType::False}); + UpperOuts=mDirectOut.back(); + mDirectOut.pop_back(); + mDirectOut.back().erase(CondEndNode); + for (auto Outs : UpperOuts) + mDirectOut.back().insert(Outs); + mEntryNode=CondStartNode; + mNodeToAdd=nullptr; } void SourceCFGBuilder::parseBreakStmt(BreakStmt *Root) { - mNodeToAdd->addToNode(new NativeNodeOp(Root)); - mDirectOut.top().erase(mNodeToAdd); - mBreakOut.top().insert(mNodeToAdd); - mNodeToAdd=nullptr; + mNodeToAdd->addOp(new NativeNodeOp(Root)); + mDirectOut.back().erase(mNodeToAdd); + mBreakOut.top().insert(mNodeToAdd); + mNodeToAdd=nullptr; } void SourceCFGBuilder::parseContinueStmt(ContinueStmt *Root) { - mNodeToAdd->addToNode(new NativeNodeOp(Root)); - mDirectOut.top().erase(mNodeToAdd); - mContinueOut.top().insert(mNodeToAdd); - mNodeToAdd=nullptr; + mNodeToAdd->addOp(new NativeNodeOp(Root)); + mDirectOut.back().erase(mNodeToAdd); + mContinueOut.top().insert(mNodeToAdd); + mNodeToAdd=nullptr; } void SourceCFGBuilder::parseGotoStmt(GotoStmt *Root) { - mNodeToAdd->addToNode(new NativeNodeOp(Root)); - mGotos.insert({Root->getLabel()->getStmt(), mNodeToAdd}); - mDirectOut.top().erase(mNodeToAdd); - mNodeToAdd=nullptr; + mNodeToAdd->addOp(new NativeNodeOp(Root)); + mGotos.push_back({Root->getLabel()->getStmt(), mNodeToAdd}); + mDirectOut.back().erase(mNodeToAdd); + mNodeToAdd=nullptr; } -void SourceCFGBuilder::parseLabelStmt(LabelStmt *Root) { - mNodeToAdd->addToNode(new NativeNodeOp(Root)); - mLabels.insert({Root, {mNodeToAdd, (int)mNodeToAdd->size()-1}}); - parseStmt(Root->getSubStmt()); +void SourceCFGBuilder::parseLabelStmt(Stmt *Root) { + mNodeToAdd->addOp(new WrapperNodeOp(Root)); + if (!mPrevFirstLabel.Node || mPrevFirstLabel.Node!=mNodeToAdd || + mLastLabelItsize()-2) + mPrevFirstLabel={mNodeToAdd, mNodeToAdd->size()-1}; + mLastLabelIt=mNodeToAdd->size()-1; + mLabels.insert({Root, mPrevFirstLabel}); + if (isa(*Root)) + parseStmt(((LabelStmt*)Root)->getSubStmt()); + else + parseStmt(((SwitchCase*)Root)->getSubStmt()); } void SourceCFGBuilder::parseReturnStmt(ReturnStmt *Root) { - if (Root->getRetValue()) - parseExpr(Root->getRetValue(), new WrapperNodeOp(Root), true); - else - mNodeToAdd->addToNode(new NativeNodeOp(Root)); - mSCFG->bindNodes(*mNodeToAdd, *mSCFG->getStopNode(), - SourceCFGEdge::EdgeKind::Default); - mDirectOut.top().erase(mNodeToAdd); - mNodeToAdd=nullptr; + if (Root->getRetValue()) + parseExpr(DynTypedNode::create(*Root->getRetValue()), + new WrapperNodeOp(Root), true); + else + mNodeToAdd->addOp(new NativeNodeOp(Root)); + mSCFG->bindNodes(*mNodeToAdd, *mSCFG->getStopNode()); + mDirectOut.back().erase(mNodeToAdd); + mNodeToAdd=nullptr; } void SourceCFGBuilder::parseDeclStmt(DeclStmt *Root, NodeOp *ParentOp) { - for (auto D : Root->decls()) - if ((D->getKind()==Decl::Kind::Var) && ((VarDecl*)D)->getInit()) - parseExpr((VarDecl*)D, ParentOp, true); -} - -void SourceCFGBuilder::parseDeclStmtWrapper(DeclStmt *Root) { - parseDeclStmt(Root, nullptr); + for (auto D : Root->decls()) + if ((D->getKind()==Decl::Kind::Var) && ((VarDecl*)D)->getInit()) + parseExpr(DynTypedNode::create(*D), ParentOp, true); } char ClangSourceCFGPass::ID=0; INITIALIZE_PASS_BEGIN(ClangSourceCFGPass, "clang-source-cfg", - "Source Control Flow Graph (Clang)", false, true) + "Source Control Flow Graph (Clang)", false, true) INITIALIZE_PASS_DEPENDENCY(TransformationEnginePass) INITIALIZE_PASS_END(ClangSourceCFGPass, "clang-source-cfg", - "Source Control Flow Graph (Clang)", false, true) + "Source Control Flow Graph (Clang)", false, true) FunctionPass *createClangSourceCFGPass() { return new ClangSourceCFGPass; } void ClangSourceCFGPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); - AU.setPreservesAll(); + AU.addRequired(); + AU.setPreservesAll(); } bool ClangSourceCFGPass::runOnFunction(Function &F) { - releaseMemory(); - auto *DISub(findMetadata(&F)); - if (!DISub) - return false; - auto *CU{DISub->getUnit()}; - if (!CU) - return false; - if (!isC(CU->getSourceLanguage())) - return false; - auto &TfmInfo{getAnalysis()}; - auto *TfmCtx{TfmInfo ? dyn_cast_or_null< - ClangTransformationContext>(TfmInfo->getContext(*CU)) : nullptr}; - if (!TfmCtx || !TfmCtx->hasInstance()) - return false; - auto FuncDecl=TfmCtx->getDeclForMangledName(F.getName()); - mSCFG=mSCFGBuilder.populate((FunctionDecl*)FuncDecl); - return false; + releaseMemory(); + auto *DISub(findMetadata(&F)); + if (!DISub) + return false; + auto *CU{DISub->getUnit()}; + if (!CU) + return false; + if (!isC(CU->getSourceLanguage())) + return false; + auto &TfmInfo{getAnalysis()}; + auto *TfmCtx{TfmInfo ? dyn_cast_or_null< + ClangTransformationContext>(TfmInfo->getContext(*CU)) : nullptr}; + if (!TfmCtx || !TfmCtx->hasInstance()) + return false; + auto FuncDecl=TfmCtx->getDeclForMangledName(F.getName()); + mSCFG=mSCFGBuilder.populate((FunctionDecl*)FuncDecl); + return false; } namespace { struct ClangSourceCFGPassGraphTraits { - static tsar::SourceCFG *getGraph(ClangSourceCFGPass *P) { - return &P->getSourceCFG(); - } + static tsar::SourceCFG *getGraph(ClangSourceCFGPass *P) { + return &P->getSourceCFG(); + } }; struct ClangSourceCFGPrinter : public DOTGraphTraitsPrinterWrapperPass< - ClangSourceCFGPass, false, tsar::SourceCFG*, - ClangSourceCFGPassGraphTraits> { - static char ID; - ClangSourceCFGPrinter() : DOTGraphTraitsPrinterWrapperPass("scfg", ID) { - initializeClangSourceCFGPrinterPass(*PassRegistry::getPassRegistry()); - } + ClangSourceCFGPass, false, tsar::SourceCFG*, + ClangSourceCFGPassGraphTraits> { + static char ID; + ClangSourceCFGPrinter() : DOTGraphTraitsPrinterWrapperPass< + ClangSourceCFGPass, false, tsar::SourceCFG*, + ClangSourceCFGPassGraphTraits>("scfg", ID) { + initializeClangSourceCFGPrinterPass(*PassRegistry::getPassRegistry()); + } }; char ClangSourceCFGPrinter::ID = 0; struct ClangSourceCFGViewer : public DOTGraphTraitsViewerWrapperPass< - ClangSourceCFGPass, false, tsar::SourceCFG*, - ClangSourceCFGPassGraphTraits> { - static char ID; - ClangSourceCFGViewer() : DOTGraphTraitsViewerWrapperPass("scfg", ID) { - initializeClangSourceCFGViewerPass(*PassRegistry::getPassRegistry()); - } + ClangSourceCFGPass, false, tsar::SourceCFG*, + ClangSourceCFGPassGraphTraits> { + static char ID; + ClangSourceCFGViewer() : DOTGraphTraitsViewerWrapperPass("scfg", ID) { + initializeClangSourceCFGViewerPass(*PassRegistry::getPassRegistry()); + } }; char ClangSourceCFGViewer::ID = 0; } //anonymous namespace INITIALIZE_PASS_IN_GROUP(ClangSourceCFGViewer, "clang-view-source-cfg", - "View Source Control FLow Graph (Clang)", true, true, - DefaultQueryManager::OutputPassGroup::getPassRegistry()) + "View Source Control FLow Graph (Clang)", true, true, + DefaultQueryManager::OutputPassGroup::getPassRegistry()) INITIALIZE_PASS_IN_GROUP(ClangSourceCFGPrinter, "clang-print-source-cfg", - "Print Source Control FLow Graph(Clang)", true, true, - DefaultQueryManager::OutputPassGroup::getPassRegistry()) + "Print Source Control FLow Graph(Clang)", true, true, + DefaultQueryManager::OutputPassGroup::getPassRegistry()) FunctionPass *llvm::createClangSourceCFGPrinter() { - return new ClangSourceCFGPrinter; + return new ClangSourceCFGPrinter; } FunctionPass *llvm::createClangSourceCFGViewer() { - return new ClangSourceCFGViewer; + return new ClangSourceCFGViewer; } diff --git a/lib/Analysis/PDG.cpp b/lib/Analysis/PDG.cpp new file mode 100644 index 00000000..c5c4516f --- /dev/null +++ b/lib/Analysis/PDG.cpp @@ -0,0 +1,144 @@ +#include "tsar/Analysis/PDG.h" +#include "tsar/Support/PassGroupRegistry.h" +#include "tsar/Core/Query.h" +#include +#include +#include +#include + +using namespace tsar; +using namespace llvm; +using namespace clang; +using namespace std; + +template +void addToMap(map &Map, KeyT Key, ValueT Value) { + auto It=Map.find(Key); + if (It!=Map.end()) + Map[Key].insert(Value); + else + Map.insert({Key, {Value}}); +} + +inline void PDGBuilder::processControlDependence() { + map> DependenceInfo; + for (auto SourceNodeIt=++df_begin(getRealRoot()); + SourceNodeIt!=df_end(getRealRoot()); ++SourceNodeIt) + for (auto TargetNodeIt=++df_begin(SourceNodeIt->getIDom()); + TargetNodeIt!=df_end(SourceNodeIt->getIDom()); ++TargetNodeIt) + if (SourceNodeIt->getBlock()->hasEdgeTo(*TargetNodeIt->getBlock()) + /* + && !( (SourceNodeIt->getBlock()->getKind()== + SourceCFGNode::NodeKind::Service + && ((ServiceNode*)SourceNodeIt->getBlock())->getType()!= + ServiceNode::NodeType::GraphEntry) + || (TargetNodeIt->getBlock()->getKind()== + SourceCFGNode::NodeKind::Service + && ((ServiceNode*)TargetNodeIt->getBlock())->getType()!= + ServiceNode::NodeType::GraphEntry) ) + */ + ) + for (unsigned I=TargetNodeIt.getPathLength()-1; I>0; --I) + addToMap(DependenceInfo, SourceNodeIt->getBlock(), + TargetNodeIt.getPath(I)->getBlock()); + for (auto N : *mSCFG) + if (!(N->getKind()==SourceCFGNode::NodeKind::Service && + ((ServiceSCFGNode*)N)->getType()!=ServiceSCFGNode::NodeType::GraphEntry)) + mPDG->emplaceNode(N); + for (auto DIIt : DependenceInfo) + for (auto TargetNodeIt : DIIt.second) { + if (DIIt.first->getKind()==SourceCFGNode::NodeKind::Service + && ((ServiceSCFGNode*)DIIt.first)->getType()!= + ServiceSCFGNode::NodeType::GraphEntry) + break; + if (!(TargetNodeIt->getKind()==SourceCFGNode::NodeKind::Service + && ((ServiceSCFGNode*)TargetNodeIt)->getType()!= + ServiceSCFGNode::NodeType::GraphEntry)) + mPDG->bindNodes(*mPDG->getNode(DIIt.first), + *mPDG->getNode(TargetNodeIt), + PDGEdge::EdgeKind::ControlDependence); + } +} + +PDG *PDGBuilder::populate(SourceCFG &_SCFG) { + ServiceSCFGNode *EntryNode; + if (!_SCFG.getStopNode()) + return nullptr; + mPDG=new tsar::PDG(string(_SCFG.getName()), &_SCFG); + mSCFG=&_SCFG; + mSCFG->emplaceEntryNode(); + mSCFG->recalculatePredMap(); + mSPDT=PostDomTreeBase(); + mSPDT.recalculate(*mSCFG); + /*May be useful + dumpDotGraphToFile(mSPDT, "post-dom-tree.dot", "post-dom-tree"); + */ + processControlDependence(); + return mPDG; +} + +char PDGPass::ID=0; + +INITIALIZE_PASS_BEGIN(PDGPass, "pdg", + "Program Dependency Graph", false, true) +INITIALIZE_PASS_DEPENDENCY(ClangSourceCFGPass) +INITIALIZE_PASS_END(PDGPass, "pdg", + "Program Dependency Graph", false, true) + +FunctionPass *createPDGPass() { return new PDGPass; } + +void PDGPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + AU.setPreservesAll(); +} + +bool PDGPass::runOnFunction(Function &F) { + releaseMemory(); + auto &SCFGPass=getAnalysis(); + mPDG=mPDGBuilder.populate(SCFGPass.getSourceCFG()); + return false; +} + +namespace { +struct PDGPassGraphTraits { + static tsar::PDG *getGraph(PDGPass *P) { return &P->getPDG(); } +}; + +struct PDGPrinter : public DOTGraphTraitsPrinterWrapperPass< + PDGPass, false, tsar::PDG*, + PDGPassGraphTraits> { + static char ID; + PDGPrinter() : DOTGraphTraitsPrinterWrapperPass("pdg", ID) { + initializePDGPrinterPass(*PassRegistry::getPassRegistry()); + } +}; +char PDGPrinter::ID = 0; + +struct PDGViewer : public DOTGraphTraitsViewerWrapperPass< + PDGPass, false, tsar::PDG*, + PDGPassGraphTraits> { + static char ID; + PDGViewer() : DOTGraphTraitsViewerWrapperPass("pdg", ID) { + initializePDGViewerPass(*PassRegistry::getPassRegistry()); + } +}; +char PDGViewer::ID = 0; +} //anonymous namespace + +INITIALIZE_PASS_IN_GROUP(PDGViewer, "view-pdg", + "View Program Dependency Graph", true, true, + DefaultQueryManager::OutputPassGroup::getPassRegistry()) + +INITIALIZE_PASS_IN_GROUP(PDGPrinter, "print-pdg", + "Print Program Dependency Graph", true, true, + DefaultQueryManager::OutputPassGroup::getPassRegistry()) + +FunctionPass *llvm::createPDGPrinter() { + return new PDGPrinter; +} + +FunctionPass *llvm::createPDGViewer() { + return new PDGViewer; +} diff --git a/lib/Analysis/Passes.cpp b/lib/Analysis/Passes.cpp index 047c04c1..22684f56 100644 --- a/lib/Analysis/Passes.cpp +++ b/lib/Analysis/Passes.cpp @@ -29,4 +29,7 @@ using namespace llvm; void llvm::initializeAnalysisBase(PassRegistry &Registry) { initializeDFRegionInfoPassPass(Registry); initializeAnalysisConnectionImmutableWrapperPass(Registry); + initializePDGPassPass(Registry); + initializePDGPrinterPass(Registry); + initializePDGViewerPass(Registry); } From 5927be19d78f6efbeeba1745784e18d4767d88a0 Mon Sep 17 00:00:00 2001 From: a_zel Date: Sun, 8 Oct 2023 01:30:09 +0300 Subject: [PATCH 3/9] Added generalization of control dependence graph construction --- include/tsar/Analysis/Clang/SourceCFG.h | 151 ++++------- include/tsar/Analysis/PDG.h | 342 ++++++++++++++---------- include/tsar/Analysis/Passes.h | 42 ++- lib/Analysis/Clang/SourceCFG.cpp | 61 ++--- lib/Analysis/PDG.cpp | 310 +++++++++++++++------ lib/Analysis/Passes.cpp | 9 +- 6 files changed, 520 insertions(+), 395 deletions(-) diff --git a/include/tsar/Analysis/Clang/SourceCFG.h b/include/tsar/Analysis/Clang/SourceCFG.h index 9c8e6071..0c1b7ef4 100644 --- a/include/tsar/Analysis/Clang/SourceCFG.h +++ b/include/tsar/Analysis/Clang/SourceCFG.h @@ -79,12 +79,12 @@ class WrapperNodeOp : public NodeOp { Op(clang::DynTypedNode::create(*_Op)) {} void print(StmtStringType &ResStr) const; static bool classof(const NodeOp *Node) { - return Node->getKind()==NodeOpKind::Wrapper; - } + return Node->getKind()==NodeOpKind::Wrapper; + } std::string getOpAddr() const { return "0x"+(std::stringstream()<()).str(); + (long unsigned)&Op.getUnchecked()).str(); } ~WrapperNodeOp() { @@ -104,8 +104,8 @@ class NativeNodeOp : public NodeOp { NativeNodeOp(clang::VarDecl *_Op) : NodeOp(NodeOpKind::Native), Op(clang::DynTypedNode::create(*_Op)) {} NativeNodeOp(const WrapperNodeOp &WNO) : NodeOp(WNO), Op(WNO.Op) { - mKind=NodeOpKind::Native; - } + mKind=NodeOpKind::Native; + } static bool classof(const NodeOp *Node) { return Node->getKind()==NodeOpKind::Native; } @@ -115,7 +115,7 @@ class NativeNodeOp : public NodeOp { printRefDecl(ResStr); if (Op.get()) { Op.getUnchecked().printPretty(StrStream, nullptr, - clang::PrintingPolicy(clang::LangOptions())); + clang::PrintingPolicy(clang::LangOptions())); } else Op.getUnchecked().print(StrStream); @@ -123,7 +123,7 @@ class NativeNodeOp : public NodeOp { std::string getOpAddr() const { return "0x"+(std::stringstream()<()).str(); + (long unsigned)&Op.getUnchecked()).str(); } ~NativeNodeOp() = default; private: @@ -135,12 +135,12 @@ class ReferenceNodeOp : public NodeOp { public: ReferenceNodeOp(NodeOp *_mReferredNode, std::string _mReferenceName) : NodeOp(NodeOpKind::Reference), mReferredNode(_mReferredNode), - mReferenceName(_mReferenceName) { + mReferenceName(_mReferenceName) { mReferredNode->mIsReferred=true; } static bool classof(const NodeOp *Node) { - return Node->getKind()==NodeOpKind::Reference; - } + return Node->getKind()==NodeOpKind::Reference; + } void print(StmtStringType &ResStr) const { ResStr+="<"+mReferenceName+mReferredNode->getOpAddr()+"_REFERRENCE_>"; } @@ -215,10 +215,21 @@ class LabeledSCFGEdge : public SourceCFGEdge { class SourceCFGNode : public SourceCFGNodeBase { friend class SourceCFG; + friend class SourceCFGBuilder; public: - enum class NodeKind {Default, Service}; - SourceCFGNode(NodeKind _mKind) : mKind(_mKind) {} - NodeKind getKind() const { return mKind; } + using OpStorageType=std::vector; + SourceCFGNode() = default; + std::size_t size() const { return mBlock.size(); } + NodeOp &operator[](int Index) { return *mBlock[Index]; } + void clearBlock() { + for (auto Op : mBlock) + Op->destroy(); + mBlock.clear(); + } + + ~SourceCFGNode() { + clearBlock(); + } inline SourceCFGEdge *addNewEdge(SourceCFGNode &TargetNode, SourceCFGEdge::EdgeKind Ekind) { @@ -235,111 +246,43 @@ class SourceCFGNode : public SourceCFGNodeBase { SourceCFG *getParent() { return OwningGraph; } explicit operator std::string() const; void printAsOperand(llvm::raw_ostream &OS, bool B) { - OS<getKind()==NodeKind::Service; - } - explicit operator std::string() const { - switch (mType) { - case NodeType::GraphStart: - return "START"; - case NodeType::GraphStop: - return "STOP"; - case NodeType::GraphEntry: - return "ENTRY"; - } - } -private: - NodeType mType; -}; - -class DefaultSCFGNode : public SourceCFGNode { - friend class SourceCFG; - friend class SourceCFGBuilder; -public: - using OpStorageType=std::vector; - DefaultSCFGNode() : SourceCFGNode(NodeKind::Default) {} - std::size_t size() const { return mBlock.size(); } - static bool classof(const SourceCFGNode *Node) { - return Node->getKind()==NodeKind::Default; - } - NodeOp &operator[](int Index) { return *mBlock[Index]; } - explicit operator std::string() const; - - void clearBlock() { - for (auto Op : mBlock) - Op->destroy(); - mBlock.clear(); - } - - ~DefaultSCFGNode() { - clearBlock(); - } - -private: inline OpStorageType::iterator addOp(NodeOp *_Op) { mBlock.push_back(_Op); - return mBlock.end()-1; - } + return mBlock.end()-1; + } template OpStorageType::iterator addOp(It begin, It end) { for (auto I=begin; I!=end; ++I) - mBlock.push_back(*I); - return mBlock.end()-1; + mBlock.push_back(*I); + return mBlock.end()-1; } - OpStorageType mBlock; }; class SourceCFG : public SourceCFGBase { + friend class SourceCFGBuilder; public: SourceCFG(const std::string &_mFunctionName) : mFunctionName(_mFunctionName), - mStartNode(&emplaceNode(ServiceSCFGNode::NodeType::GraphStart)), - mStopNode(&emplaceNode(ServiceSCFGNode::NodeType::GraphStop)), - mEntryNode(nullptr) {} + mStartNode(nullptr) {} inline bool addNode(SourceCFGNode &N) { return SourceCFGBase::addNode(N)?N.OwningGraph=this, true:false; } - DefaultSCFGNode &emplaceNode() { - DefaultSCFGNode *CurrNode=new DefaultSCFGNode(); + SourceCFGNode &emplaceNode() { + SourceCFGNode *CurrNode=new SourceCFGNode(); addNode(*CurrNode); return *CurrNode; } - ServiceSCFGNode &emplaceNode(ServiceSCFGNode::NodeType Type) { - ServiceSCFGNode *CurrNode=new ServiceSCFGNode(Type); - addNode(*CurrNode); - return *CurrNode; - } - - ServiceSCFGNode &emplaceEntryNode() { - mEntryNode=new ServiceSCFGNode(ServiceSCFGNode::NodeType::GraphEntry); - addNode(*mEntryNode); - bindNodes(*mEntryNode, *mStartNode, DefaultSCFGEdge::EdgeType::True); - bindNodes(*mEntryNode, *mStopNode, DefaultSCFGEdge::EdgeType::False); - return *mEntryNode; - } - inline void bindNodes(SourceCFGNode &SourceNode, - SourceCFGNode &TargetNode ) { + SourceCFGNode &TargetNode ) { connect(SourceNode, TargetNode, *(new DefaultSCFGEdge(TargetNode, DefaultSCFGEdge::EdgeType::Default))); } @@ -354,17 +297,13 @@ class SourceCFG : public SourceCFGBase { clang::SwitchCase *Label) { connect(SourceNode, TargetNode, *(new LabeledSCFGEdge(TargetNode, Label))); } - - inline ServiceSCFGNode *getStartNode() const { return mStartNode; } - inline ServiceSCFGNode *getStopNode() const { return mStopNode; } - inline ServiceSCFGNode *getEntryNode() const { - return mEntryNode?mEntryNode:mStartNode; - } + // Needed for GraphTraits + inline SourceCFGNode *getEntryNode() const { return mStartNode; } inline llvm::StringRef getName() const { return mFunctionName; } void mergeNodes(SourceCFGNode &AbsorbNode, SourceCFGNode &OutgoingNode); void deleteNode(SourceCFGNode &_Node); void deleteEdge(SourceCFGEdge &_Edge); - DefaultSCFGNode *splitNode(DefaultSCFGNode &Node, int It); + SourceCFGNode *splitNode(SourceCFGNode &Node, int It); void recalculatePredMap(); std::set &getPredMap(SourceCFGNode *Node) { @@ -398,12 +337,12 @@ class SourceCFG : public SourceCFGBase { for (auto N : Nodes) { for (auto E : N->getEdges()) E->destroy(); - N->destroy(); + delete N; } } private: std::string mFunctionName; - ServiceSCFGNode *mStartNode, *mStopNode, *mEntryNode; + SourceCFGNode *mStartNode; std::map> mPredecessorsMap; }; @@ -419,7 +358,7 @@ class SourceCFGBuilder { using OutsType=llvm::SmallPtrSet; struct LabelInfo { - DefaultSCFGNode *Node; + SourceCFGNode *Node; size_t LabelIt; }; @@ -445,15 +384,15 @@ class SourceCFGBuilder { bool hasConditionalOperator(clang::Stmt *Root); SourceCFG *mSCFG; llvm::SmallDenseMap mLabels; - llvm::SmallVector> mGotos; + llvm::SmallVector> mGotos; llvm::SmallVector> mSwitchGotos; + SourceCFGNode*>> mSwitchGotos; LabelInfo mPrevFirstLabel; size_t mLastLabelIt; - DefaultSCFGNode *mEntryNode, *mNodeToAdd; + SourceCFGNode *mEntryNode, *mNodeToAdd; std::vector mDirectOut; std::stack mContinueOut, mBreakOut; - std::stack mSwitchNodes; + std::stack mSwitchNodes; NodeOp *mTreeTopParentPtr; }; } //namespace tsar diff --git a/include/tsar/Analysis/PDG.h b/include/tsar/Analysis/PDG.h index 14738f9b..12d6333a 100644 --- a/include/tsar/Analysis/PDG.h +++ b/include/tsar/Analysis/PDG.h @@ -4,54 +4,96 @@ #include "tsar/Analysis/Passes.h" #include "tsar/Analysis/Clang/SourceCFG.h" #include +#include #include #include #include #include +#include +#include #include +#include #include #include +#include namespace tsar { -class PDGNode; -class PDGEdge; -class PDG; -class PDGBuilder; -using PDGNodeBase=llvm::DGNode; -using PDGEdgeBase=llvm::DGEdge; -using PDGBase=llvm::DirectedGraph; +template +class CDGNode; +template +class CDGEdge; +template +class CDGBuilder; -class PDGEdge : public PDGEdgeBase { +template +using CDGNodeBase=llvm::DGNode, CDGEdge>; +template +using CDGEdgeBase=llvm::DGEdge, CDGEdge>; +template +using CDGBase=llvm::DirectedGraph, CDGEdge>; + +template +class CDGEdge : public CDGEdgeBase { public: - enum class EdgeKind {ControlDependence, DataDependence}; - PDGEdge(PDGNode &_TargetNode, EdgeKind _Kind) - : PDGEdgeBase(_TargetNode), Kind(_Kind) {} - inline EdgeKind getKind() const { return Kind; } -private: - EdgeKind Kind; + using NodeType=CDGNode; + CDGEdge(NodeType &_TargetNode) : CDGEdgeBase(_TargetNode){} }; -class PDGNode : public PDGNodeBase { +template +class CDGNode : public CDGNodeBase { public: - enum class NodeKind {Default, Region}; - PDGNode(SourceCFGNode *_mBlock) - : mBlock(_mBlock), mKind(NodeKind::Default) {} + enum class NodeKind {Entry, Default, Region}; + CDGNode(NodeKind _mKind) : mKind(_mKind) {} inline NodeKind getKind() const { return mKind; } - SourceCFGNode *getBlock() const { return mBlock; } + void destroy(); private: - SourceCFGNode *mBlock; NodeKind mKind; }; -class PDG : public PDGBase { - friend class PDGBuilder; +template +class EntryCDGNode : public CDGNode { +private: + using Base=CDGNode; public: - PDG(const std::string &_FunctionName, SourceCFG *_mSCFG) - : FunctionName(_FunctionName), mSCFG(_mSCFG) {} + EntryCDGNode() : Base(Base::NodeKind::Entry) {} + static bool classof(const Base *Node) { return Node->getKind()==Base::NodeKind::Entry; } +}; - inline bool addNode(PDGNode &N) { - if (PDGBase::addNode(N)) { +template +class DefaultCDGNode : public CDGNode { +private: + using Base=CDGNode; +public: + using NodeValueType=CFGNodeType*; + DefaultCDGNode(NodeValueType _mBlock) : Base(Base::NodeKind::Default), mBlock(_mBlock) {} + static bool classof(const Base *Node) { return Node->getKind()==Base::NodeKind::Default; } + inline NodeValueType getBlock() const { return mBlock; } +private: + NodeValueType mBlock; +}; + +template +class ControlDependenceGraph : public CDGBase { +private: + using DefaultNode=DefaultCDGNode; + using EntryNode=EntryCDGNode; +public: + using CFGT=CFGType; + using CFGNodeT=CFGNodeType; + using NodeType=CDGNode; + using EdgeType=CDGEdge; + // TODO: NodeValueType must be declared once for all DirectedGraph classes + using NodeValueType=CFGNodeType*; + using CFGNodeMapType=llvm::DenseMap; + + ControlDependenceGraph(const std::string &_FunctionName, CFGType *_mCFG) + : FunctionName(_FunctionName), mCFG(_mCFG), mEntryNode(new EntryNode()) { + CDGBase::addNode(*mEntryNode); + } + + inline bool addNode(DefaultNode &N) { + if (CDGBase::addNode(N)) { BlockToNodeMap.insert({N.getBlock(), &N}); return true; } @@ -59,142 +101,61 @@ class PDG : public PDGBase { return false; } - PDGNode &emplaceNode(SourceCFGNode *Block) { - PDGNode *NewNode=new PDGNode(Block); + NodeType &emplaceNode(NodeValueType Block) { + DefaultNode *NewNode=new DefaultNode(Block); addNode(*NewNode); return *NewNode; } - inline void bindNodes(PDGNode &SourceNode, PDGNode &TargetNode, - PDGEdge::EdgeKind _Ekind) { - connect(SourceNode, TargetNode, *(new PDGEdge(TargetNode, _Ekind))); + inline void bindNodes(NodeType &SourceNode, NodeType &TargetNode) { + CDGBase::connect(SourceNode, TargetNode, *(new CDGEdge(TargetNode))); } - inline PDGNode *getNode(SourceCFGNode *Block) { + inline NodeType *getNode(NodeValueType Block) { return BlockToNodeMap[Block]; } - inline PDGNode *getEntryNode() { - return getNode(mSCFG->getEntryNode()); + inline NodeType *getEntryNode() { + return mEntryNode; + } + + inline CFGType *getCFG() const { + return mCFG; } - ~PDG() { - for (auto N : Nodes) { + ~ControlDependenceGraph() { + for (auto N : CDGBase::Nodes) { for (auto E : N->getEdges()) delete E; delete N; } } private: + EntryNode *mEntryNode; std::string FunctionName; - std::map BlockToNodeMap; - SourceCFG *mSCFG; -}; - -class PDGBuilder { -public: - PDGBuilder() : mPDG(nullptr) {} - PDG *populate(SourceCFG &_SCFG); -private: - inline void processControlDependence(); - inline llvm::DomTreeNodeBase *getRealRoot() { - return *mSPDT.getRootNode()->begin(); - } - PDG *mPDG; - SourceCFG *mSCFG; - llvm::PostDomTreeBase mSPDT; + CFGNodeMapType BlockToNodeMap; + CFGType *mCFG; }; }//namespace tsar namespace llvm { -class PDGPass : public FunctionPass, private bcl::Uncopyable { -public: - static char ID; - PDGPass() : FunctionPass(ID), mPDG(nullptr) { - initializePDGPassPass(*PassRegistry::getPassRegistry()); - } - bool runOnFunction(Function &F) override; - void getAnalysisUsage(AnalysisUsage &AU) const override; - void releaseMemory() { - mPDGBuilder=tsar::PDGBuilder(); - if (mPDG) { - delete mPDG; - mPDG=nullptr; - } - } - inline tsar::PDG &getPDG() { return *mPDG; } -private: - tsar::PDGBuilder mPDGBuilder; - tsar::PDG *mPDG; -}; - -template<> struct GraphTraits*> { - using NodeRef=DomTreeNodeBase*; - using ChildIteratorType=DomTreeNodeBase::iterator; - static NodeRef getEntryNode(NodeRef N) { return N; } - static ChildIteratorType child_begin(NodeRef N) { - return N->begin(); - } - static ChildIteratorType child_end(NodeRef N) { - return N->end(); - } -}; - -template struct GraphTraits*> - : public GraphTraits*> { - static NodeRef getEntryNode(DominatorTreeBase *Tree) { - return Tree->getRootNode(); - } - using nodes_iterator=df_iterator*>; - static nodes_iterator nodes_begin(DominatorTreeBase *Tree) { - return df_begin(Tree->getRootNode()); - } - static nodes_iterator nodes_end(DominatorTreeBase *Tree) { - return df_end(Tree->getRootNode()); - } - static unsigned size(DominatorTreeBase *Tree) { - return Tree->root_size(); - } -}; - -template struct DOTGraphTraits*> : public DefaultDOTGraphTraits { - DOTGraphTraits(bool IsSimple=false) : DefaultDOTGraphTraits(IsSimple) {} - static std::string getGraphName(const DominatorTreeBase *Tree) { - return IsPostDom?"Post-Dominator Tree":"Dominator Tree"; - } - std::string getNodeLabel(DomTreeNodeBase *Node, - DominatorTreeBase *Tree) { - return (std::string)*Node->getBlock(); - } - static bool isNodeHidden(DomTreeNodeBase *Node, - DominatorTreeBase *Tree) { - Tree->isVirtualRoot(Node)?true:false; - } -}; - -template<> struct GraphTraits { - using NodeRef=tsar::PDGNode*; - static tsar::PDGNode *PDGGetTargetNode(tsar::PDGEdge *E) { +template +struct GraphTraits*> { + using NodeRef=tsar::CDGNode*; + static tsar::CDGNode *CDGGetTargetNode(tsar::CDGEdge *E) { return &E->getTargetNode(); } - using ChildIteratorType=mapped_iterator; - using ChildEdgeIteratorType=tsar::PDGNode::iterator; + using ChildIteratorType=mapped_iterator::iterator, + decltype(&CDGGetTargetNode)>; + using ChildEdgeIteratorType=typename tsar::CDGNode::iterator; static NodeRef getEntryNode(NodeRef N) { return N; } static ChildIteratorType child_begin(NodeRef N) { - return ChildIteratorType(N->begin(), &PDGGetTargetNode); + return ChildIteratorType(N->begin(), &CDGGetTargetNode); } static ChildIteratorType child_end(NodeRef N) { - return ChildIteratorType(N->end(), &PDGGetTargetNode); + return ChildIteratorType(N->end(), &CDGGetTargetNode); } static ChildEdgeIteratorType child_edge_begin(NodeRef N) { return N->begin(); @@ -202,33 +163,122 @@ template<> struct GraphTraits { static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } }; -template<> struct GraphTraits : - public GraphTraits { - using nodes_iterator=tsar::PDG::iterator; - static NodeRef getEntryNode(tsar::PDG *Graph) { +template +struct GraphTraits*> : + public GraphTraits*> { + using nodes_iterator=typename tsar::ControlDependenceGraph::iterator; + static typename llvm::GraphTraits*>::NodeRef getEntryNode(tsar::ControlDependenceGraph *Graph) { return Graph->getEntryNode(); } - static nodes_iterator nodes_begin(tsar::PDG *Graph) { + static nodes_iterator nodes_begin(tsar::ControlDependenceGraph *Graph) { return Graph->begin(); } - static nodes_iterator nodes_end(tsar::PDG *Graph) { + static nodes_iterator nodes_end(tsar::ControlDependenceGraph *Graph) { return Graph->end(); } - using EdgeRef=tsar::PDGEdge*; - static NodeRef edge_dest(EdgeRef E) { return &E->getTargetNode(); } - static unsigned size(tsar::PDG *Graph) { return Graph->size(); } + using EdgeRef=tsar::CDGEdge*; + static typename llvm::GraphTraits*>::NodeRef edge_dest(EdgeRef E) { return &E->getTargetNode(); } + static unsigned size(tsar::ControlDependenceGraph *Graph) { return Graph->size(); } }; -template<> struct DOTGraphTraits : public DefaultDOTGraphTraits { - DOTGraphTraits(bool IsSimple=false) : DefaultDOTGraphTraits(IsSimple) {} - static std::string getGraphName(const tsar::PDG *Graph) { +template +struct DOTGraphTraits*> : + public DOTGraphTraits { +private: + using GTInstanced=GraphTraits*>; +public: + DOTGraphTraits(bool IsSimple=false) : DOTGraphTraits(IsSimple) {} + static std::string getGraphName(const tsar::ControlDependenceGraph *Graph) { return "Control Dependence Graph"; } - std::string getNodeLabel(const tsar::PDGNode *Node, const tsar::PDG *Graph) { - return (std::string)*Node->getBlock(); + std::string getNodeLabel(const tsar::CDGNode *Node, + const tsar::ControlDependenceGraph *Graph) { + if (auto *DefNode=dyn_cast>(Node)) + return DOTGraphTraits::getNodeLabel(DefNode->getBlock(), Graph->getCFG()); + else + return "Entry"; + } + std::string getNodeAttributes(const tsar::CDGNode *Node, + tsar::ControlDependenceGraph *Graph) { + if (auto *DefNode=dyn_cast>(Node)) + return DOTGraphTraits::getNodeAttributes(DefNode->getBlock(), Graph->getCFG()); + else + return ""; + } + std::string getEdgeSourceLabel(const tsar::CDGNode *Node, + typename GraphTraits*>::ChildIteratorType It) { return ""; } + std::string getEdgeAttributes(const tsar::CDGNode *Node, + typename GTInstanced::ChildIteratorType EdgeIt, + tsar::ControlDependenceGraph *Graph) { + //return DOTGraphTraits::getEdgeAttributes(Node->getBlock(), EdgeIt, Graph->getCFG()); + return ""; + } + bool isNodeHidden(const tsar::CDGNode *Node, + tsar::ControlDependenceGraph*) { + return false; } }; }//namespace llvm +namespace tsar { +template +class CDGBuilder { +private: + using CFGType=typename CDGType::CFGT; + using CFGNodeType=typename CDGType::CFGNodeT; +public: + // TODO: NodeValueType must be declared once for all DirectedGraph classes + using NodeValueType=typename llvm::GraphTraits::NodeRef; + + CDGBuilder() : mCDG(nullptr) {} + CDGType *populate(CFGType &_CFG); +private: + inline void processControlDependence(); + CFGType *mCFG; + CDGType *mCDG; + llvm::PostDomTreeBase mPDT; +}; +}; //namespace tsar + +namespace llvm { + +template +class CDGPass : public FunctionPass, private bcl::Uncopyable { +private: + using CFGType=typename CDGType::CFGT; + using CFGNodeType=typename CDGType::CFGNodeT; +public: + static char ID; + CDGPass(); + bool runOnFunction(Function &F) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + void releaseMemory() { + mCDGBuilder=tsar::CDGBuilder(); + if (mCDG) { + delete mCDG; + mCDG=nullptr; + } + } + inline tsar::ControlDependenceGraph &getCDG() { return *mCDG; } +private: + tsar::CDGBuilder mCDGBuilder; + tsar::ControlDependenceGraph *mCDG; +}; + +template<> +CDGPass>::CDGPass() : FunctionPass(ID), mCDG(nullptr) { + initializeSourceCDGPassPass(*PassRegistry::getPassRegistry()); +} + +template<> +CDGPass>::CDGPass() : FunctionPass(ID), mCDG(nullptr) { + initializeIRCDGPassPass(*PassRegistry::getPassRegistry()); +} + +using SourceCDGPass=CDGPass>; +using IRCDGPass=CDGPass>; + +};//namespace llvm + #endif//TSAR_INCLUDE_BUILDPDG_H \ No newline at end of file diff --git a/include/tsar/Analysis/Passes.h b/include/tsar/Analysis/Passes.h index 4ab50623..4016b435 100644 --- a/include/tsar/Analysis/Passes.h +++ b/include/tsar/Analysis/Passes.h @@ -118,22 +118,40 @@ ModulePass *createAnalysisCloseConnectionPass(bool ActiveOnly = false); /// be blocked until server confirms that connection can be closed. ModulePass *createAnalysisCloseConnectionPass(const void * ServerID); -/// Initialize a pass to build program dependency graph. -void initializePDGPassPass(PassRegistry &Registry); +/// Initialize a pass to build control dependence graph from source code. +void initializeSourceCDGPassPass(PassRegistry &Registry); -/// Create a pass to build program dependency graph. -FunctionPass *createPDGPass(); +/// Create a pass to build control dependence graph from source code. +FunctionPass *createSourceCDGPass(); -/// Initialize a pass to print program dependency graph to 'dot' file. -void initializePDGPrinterPass(PassRegistry &Registry); +/// Initialize a pass to print control dependence graph from source code to 'dot' file. +void initializeSourceCDGPrinterPass(PassRegistry &Registry); -/// Create a pass to print program dependency to 'dot' file. -FunctionPass *createPDGPrinter(); +/// Create a pass to print control dependence graph from source code to 'dot' file. +FunctionPass *createSourceCDGPrinter(); -/// Initialize a pass to display program dependency graph. -void initializePDGViewerPass(PassRegistry &Registry); +/// Initialize a pass to display control dependence graph from source code. +void initializeSourceCDGViewerPass(PassRegistry &Registry); -/// Create a pass to display program dependency graph. -FunctionPass *createPDGViewer(); +/// Create a pass to display control dependence graph from source code. +FunctionPass *createSourceCDGViewer(); + +/// Initialize a pass to build control dependence graph from LLVM IR. +void initializeIRCDGPassPass(PassRegistry &Registry); + +/// Create a pass to build control dependence graph from LLVM IR. +FunctionPass *createIRCDGPass(); + +/// Initialize a pass to print control dependence graph from LLVM IR to 'dot' file. +void initializeIRCDGPrinterPass(PassRegistry &Registry); + +/// Create a pass to print controld dependence graph from LLVM IR to 'dot' file. +FunctionPass *createIRCDGPrinter(); + +/// Initialize a pass to display control dependence graph from LLVM IR. +void initializeIRCDGViewerPass(PassRegistry &Registry); + +/// Create a pass to display control dependence graph from LLVM IR. +FunctionPass *createIRCDGViewer(); } #endif//TSAR_ANALYSIS_PASSES_H diff --git a/lib/Analysis/Clang/SourceCFG.cpp b/lib/Analysis/Clang/SourceCFG.cpp index df352277..554336f6 100644 --- a/lib/Analysis/Clang/SourceCFG.cpp +++ b/lib/Analysis/Clang/SourceCFG.cpp @@ -183,27 +183,7 @@ void WrapperNodeOp::print(StmtStringType &ResStr) const { } } -void SourceCFGNode::destroy() { - switch (mKind) { - case NodeKind::Default: - delete (DefaultSCFGNode*)this; - break; - case NodeKind::Service: - delete (ServiceSCFGNode*)this; - break; - } -} - SourceCFGNode::operator std::string() const { - switch (mKind) { - case NodeKind::Default: - return (string)(*(DefaultSCFGNode*)this); - case NodeKind::Service: - return (string)(*(ServiceSCFGNode*)this); - } -} - -DefaultSCFGNode::operator string() const { string ResStr; for (NodeOp *NO : mBlock) { NO->print(ResStr); @@ -221,9 +201,7 @@ void SourceCFG::deleteNode(SourceCFGNode &_Node) { E->destroy(); if (mStartNode==&_Node) mStartNode=nullptr; - if (mStopNode==&_Node) - mStopNode==nullptr; - _Node.destroy(); + delete &_Node; } void SourceCFG::deleteEdge(SourceCFGEdge &_Edge) { @@ -244,10 +222,10 @@ void SourceCFGNode::merge(SourceCFGNode &NodeToAttach) { } */ -DefaultSCFGNode *SourceCFG::splitNode(DefaultSCFGNode &Node, int It) { +SourceCFGNode *SourceCFG::splitNode(SourceCFGNode &Node, int It) { if (It==0) return &Node; - DefaultSCFGNode *NewNode=&emplaceNode(); + SourceCFGNode *NewNode=&emplaceNode(); for (auto E : Node.getEdges()) NewNode->addEdge(*E); Node.clear(); @@ -295,7 +273,7 @@ void SourceCFG::mergeNodes(SourceCFGNode &AbsorbNode, } //AbsorbNode.merge(OutgoingNode); - Not working SourceCFGBase::removeNode(OutgoingNode); - OutgoingNode.destroy(); + delete &OutgoingNode; } void markReached(SourceCFGNode *Node, @@ -325,14 +303,14 @@ void SourceCFGBuilder::eliminateUnreached() { std::map ReachedNodes; for (auto N : *mSCFG) ReachedNodes.insert({N, false}); - markReached(mSCFG->getStartNode(), &ReachedNodes); + markReached(mSCFG->getEntryNode(), &ReachedNodes); for (auto It : ReachedNodes) if (!It.second) mSCFG->deleteNode(*It.first); } void SourceCFGBuilder::processLabels() { - std::map>> OrderingMap; for (auto GotoIt : mGotos) addToMap(OrderingMap, mLabels[GotoIt.first], pair{GotoIt.second, nullptr}); @@ -355,14 +333,9 @@ SourceCFG *SourceCFGBuilder::populate(FunctionDecl *Decl) { mSCFG=new SourceCFG(Info.getAsString()); mDirectOut.push_back(MarkedOutsType()); parseStmt(Decl->getBody()); - if (mEntryNode) { - mSCFG->bindNodes(*mSCFG->getStartNode(), *mEntryNode); - for (auto It : mDirectOut.back()) - mSCFG->bindNodes(*It.first, *mSCFG->getStopNode(), It.second); + mSCFG->mStartNode=mEntryNode; + if (mEntryNode) processLabels(); - } - else - mSCFG->bindNodes(*mSCFG->getStartNode(), *mSCFG->getStopNode()); mDirectOut.pop_back(); eliminateUnreached(); } @@ -471,13 +444,13 @@ void SourceCFGBuilder::processIndirect(SourceCFGNode *CondStartNode) { void SourceCFGBuilder::parseExpr(clang::DynTypedNode Op, NodeOp *ParentOp, bool isFirstCall) { - DefaultSCFGNode *OldNodeToAdd; + SourceCFGNode *OldNodeToAdd; WrapperNodeOp *NewNodeOp; if (Op.get()) { Stmt::StmtClass Type=Op.getUnchecked().getStmtClass(); if (Op.get()) { MarkedOutsType UpperOuts; - DefaultSCFGNode *ConditionNode, *TrueNode, *FalseNode; + SourceCFGNode *ConditionNode, *TrueNode, *FalseNode; const ConditionalOperator &CO=Op.getUnchecked(); auto OldEntryNode=mEntryNode; auto OldTreeTopParentPtr=mTreeTopParentPtr; @@ -587,7 +560,7 @@ void SourceCFGBuilder::parseExpr(clang::DynTypedNode Op, NodeOp *ParentOp, void SourceCFGBuilder::parseCompoundStmt(CompoundStmt *Root) { MarkedOutsType UpperOuts; - DefaultSCFGNode *ResultEntryNode=mEntryNode; + SourceCFGNode *ResultEntryNode=mEntryNode; mDirectOut.push_back(MarkedOutsType()); for (auto S : Root->body()) { parseStmt(S); @@ -602,7 +575,7 @@ void SourceCFGBuilder::parseCompoundStmt(CompoundStmt *Root) { } void SourceCFGBuilder::parseDoStmt(DoStmt *Root) { - DefaultSCFGNode *mStartNode=mNodeToAdd, *CondStartNode, *CondEndNode, *Body; + SourceCFGNode *mStartNode=mNodeToAdd, *CondStartNode, *CondEndNode, *Body; mContinueOut.push(OutsType()); mBreakOut.push(OutsType()); mDirectOut.push_back(MarkedOutsType()); @@ -636,7 +609,7 @@ void SourceCFGBuilder::parseDoStmt(DoStmt *Root) { } void SourceCFGBuilder::parseForStmt(ForStmt *Root) { - DefaultSCFGNode *mStartNode=mNodeToAdd, *CondStartNode=nullptr, + SourceCFGNode *mStartNode=mNodeToAdd, *CondStartNode=nullptr, *CondEndNode=nullptr, *Body=nullptr, *IncStartNode=nullptr, *LoopNode; MarkedOutsType AfterInitOuts; mContinueOut.push(OutsType()); @@ -696,7 +669,7 @@ void SourceCFGBuilder::parseForStmt(ForStmt *Root) { void SourceCFGBuilder::parseSwitchStmt(SwitchStmt *Root) { mBreakOut.push(OutsType()); - DefaultSCFGNode *CondStartNode=mNodeToAdd, *CondEndNode; + SourceCFGNode *CondStartNode=mNodeToAdd, *CondEndNode; parseExpr(DynTypedNode::create(*Root->getCond()), new WrapperNodeOp(Root), true); CondEndNode=mNodeToAdd; @@ -713,7 +686,7 @@ void SourceCFGBuilder::parseWhileStmt(WhileStmt *Root) { mContinueOut.push(OutsType()); mBreakOut.push(OutsType()); mDirectOut.push_back(MarkedOutsType()); - DefaultSCFGNode *mStartNode=mNodeToAdd, *CondStartNode, *CondEndNode; + SourceCFGNode *mStartNode=mNodeToAdd, *CondStartNode, *CondEndNode; if (mStartNode->size()==0) { CondStartNode=mStartNode; parseExpr(DynTypedNode::create(*Root->getCond()), new WrapperNodeOp(Root), @@ -744,7 +717,7 @@ void SourceCFGBuilder::parseWhileStmt(WhileStmt *Root) { void SourceCFGBuilder::parseIfStmt(IfStmt *Root) { MarkedOutsType UpperOuts; - DefaultSCFGNode *CondStartNode=mNodeToAdd, *CondEndNode; + SourceCFGNode *CondStartNode=mNodeToAdd, *CondEndNode; Stmt *ActionStmt; parseExpr(DynTypedNode::create(*Root->getCond()), new WrapperNodeOp(Root), true); @@ -815,7 +788,7 @@ void SourceCFGBuilder::parseReturnStmt(ReturnStmt *Root) { new WrapperNodeOp(Root), true); else mNodeToAdd->addOp(new NativeNodeOp(Root)); - mSCFG->bindNodes(*mNodeToAdd, *mSCFG->getStopNode()); + //mSCFG->bindNodes(*mNodeToAdd, *mSCFG->getStopNode()); mDirectOut.back().erase(mNodeToAdd); mNodeToAdd=nullptr; } diff --git a/lib/Analysis/PDG.cpp b/lib/Analysis/PDG.cpp index c5c4516f..0f71724b 100644 --- a/lib/Analysis/PDG.cpp +++ b/lib/Analysis/PDG.cpp @@ -1,6 +1,10 @@ #include "tsar/Analysis/PDG.h" #include "tsar/Support/PassGroupRegistry.h" #include "tsar/Core/Query.h" +#include +#include +#include +#include #include #include #include @@ -11,6 +15,94 @@ using namespace llvm; using namespace clang; using namespace std; +namespace llvm { +template<> +struct DOTGraphTraits + : public DOTGraphTraits { + DOTGraphTraits(bool isSimple=false) : DOTGraphTraits(isSimple) {} + string getNodeLabel(const BasicBlock *Node, Function*) { + return DOTGraphTraits::getNodeLabel(Node, nullptr); + } + string getNodeAttributes(const BasicBlock *Node, Function *F) { + DOTFuncInfo DOTInfo(F); + return DOTGraphTraits::getNodeAttributes(Node, &DOTInfo); + } + string getEdgeAttributes(const BasicBlock *Node, + const_succ_iterator EdgeIt, Function *F) { + DOTFuncInfo DOTInfo(F); + return DOTGraphTraits::getEdgeAttributes(Node, EdgeIt, &DOTInfo); + } + bool isNodeHidden(const BasicBlock *Node, const Function *F) { + DOTFuncInfo DOTInfo(F); + return DOTGraphTraits::isNodeHidden(Node, &DOTInfo); + } +}; + +template<> struct GraphTraits*> + : public DomTreeGraphTraitsBase, + DomTreeNodeBase::const_iterator> {}; + +template<> struct GraphTraits*> + : public DomTreeGraphTraitsBase, + DomTreeNodeBase::const_iterator> {}; + +template +struct GraphTraits*> + : public GraphTraits*> { +private: + using BaseGT=GraphTraits*>; +public: + static typename BaseGT::NodeRef getEntryNode(PostDomTreeBase *PDT) { + PDT->getRootNode(); + } + static typename BaseGT::nodes_iterator nodes_begin(PostDomTreeBase *PDT) { + return df_begin(getEntryNode(PDT)); + } + static typename BaseGT::nodes_iterator nodes_end(PostDomTreeBase *PDT) { + return df_end(getEntryNode(PDT)); + } +}; + +template +struct DOTGraphTraits*> + : public DOTGraphTraits::ParentPtr> { +private: + using BaseDOTGT=DOTGraphTraits::ParentPtr>; +public: + DOTGraphTraits(bool IsSimple=false) : BaseDOTGT(IsSimple) {} + static std::string getGraphName(const PostDomTreeBase *Tree) { + return "Post-Dominator Tree"; + } + std::string getNodeLabel(DomTreeNodeBase *Node, + PostDomTreeBase *Tree) { + if (Tree->isVirtualRoot(Node)) + return "Virtual Root"; + else + return BaseDOTGT::getNodeLabel(Node->getBlock(), Node->getBlock()->getParent()); + + } + std::string getEdgeSourceLabel(DomTreeNodeBase *Node, + typename GraphTraits*>::ChildIteratorType It) { return ""; } + static bool isNodeHidden(DomTreeNodeBase *Node, + PostDomTreeBase *Tree) { + return false; + } + std::string getNodeAttributes(DomTreeNodeBase *Node, + PostDomTreeBase *Tree) { + if (Tree->isVirtualRoot(Node)) + return ""; + else + return BaseDOTGT::getNodeAttributes(Node->getBlock(), Node->getBlock()->getParent()); + } + std::string getEdgeAttributes(DomTreeNodeBase*, + typename GraphTraits*>::ChildIteratorType, + PostDomTreeBase*) { + return ""; + } +}; +}; //namespace llvm + +namespace { template void addToMap(map &Map, KeyT Key, ValueT Value) { auto It=Map.find(Key); @@ -20,125 +112,175 @@ void addToMap(map &Map, KeyT Key, ValueT Value) { Map.insert({Key, {Value}}); } -inline void PDGBuilder::processControlDependence() { - map> DependenceInfo; - for (auto SourceNodeIt=++df_begin(getRealRoot()); - SourceNodeIt!=df_end(getRealRoot()); ++SourceNodeIt) - for (auto TargetNodeIt=++df_begin(SourceNodeIt->getIDom()); - TargetNodeIt!=df_end(SourceNodeIt->getIDom()); ++TargetNodeIt) - if (SourceNodeIt->getBlock()->hasEdgeTo(*TargetNodeIt->getBlock()) - /* - && !( (SourceNodeIt->getBlock()->getKind()== - SourceCFGNode::NodeKind::Service - && ((ServiceNode*)SourceNodeIt->getBlock())->getType()!= - ServiceNode::NodeType::GraphEntry) - || (TargetNodeIt->getBlock()->getKind()== - SourceCFGNode::NodeKind::Service - && ((ServiceNode*)TargetNodeIt->getBlock())->getType()!= - ServiceNode::NodeType::GraphEntry) ) - */ - ) +template +bool hasEdgesTo(NodeType *SourceN, NodeType *TargetN) { + for (auto ChildNodeIt=GraphTraits::child_begin(SourceN); + ChildNodeIt!=GraphTraits::child_end(SourceN); ++ChildNodeIt) + if (*ChildNodeIt==TargetN) + return true; + return false; +} +}; //anonymous namespace + +template +inline void CDGBuilder::processControlDependence() { + map> DependenceInfo; + for (auto NIt=GraphTraits::nodes_begin(mCFG); NIt!=GraphTraits::nodes_end(mCFG); ++NIt) + mCDG->emplaceNode(*NIt); + for (auto SourceNodeIt=++df_begin(mPDT.getRootNode()); SourceNodeIt!=df_end(mPDT.getRootNode()); ++SourceNodeIt) { + if (SourceNodeIt->getBlock()==GraphTraits::getEntryNode(mCFG)) + for (unsigned I=SourceNodeIt.getPathLength()-1; I>0; --I) + addToMap(DependenceInfo, mCDG->getEntryNode(), SourceNodeIt.getPath(I)->getBlock()); + for (auto TargetNodeIt=++df_begin(SourceNodeIt->getIDom()); TargetNodeIt!=df_end(SourceNodeIt->getIDom()); ++TargetNodeIt) + if (hasEdgesTo(SourceNodeIt->getBlock(), TargetNodeIt->getBlock())) for (unsigned I=TargetNodeIt.getPathLength()-1; I>0; --I) - addToMap(DependenceInfo, SourceNodeIt->getBlock(), - TargetNodeIt.getPath(I)->getBlock()); - for (auto N : *mSCFG) - if (!(N->getKind()==SourceCFGNode::NodeKind::Service && - ((ServiceSCFGNode*)N)->getType()!=ServiceSCFGNode::NodeType::GraphEntry)) - mPDG->emplaceNode(N); + addToMap(DependenceInfo, mCDG->getNode(SourceNodeIt->getBlock()), TargetNodeIt.getPath(I)->getBlock()); + } for (auto DIIt : DependenceInfo) - for (auto TargetNodeIt : DIIt.second) { - if (DIIt.first->getKind()==SourceCFGNode::NodeKind::Service - && ((ServiceSCFGNode*)DIIt.first)->getType()!= - ServiceSCFGNode::NodeType::GraphEntry) - break; - if (!(TargetNodeIt->getKind()==SourceCFGNode::NodeKind::Service - && ((ServiceSCFGNode*)TargetNodeIt)->getType()!= - ServiceSCFGNode::NodeType::GraphEntry)) - mPDG->bindNodes(*mPDG->getNode(DIIt.first), - *mPDG->getNode(TargetNodeIt), - PDGEdge::EdgeKind::ControlDependence); - } + for (auto TargetNodeIt : DIIt.second) + mCDG->bindNodes(*DIIt.first, *mCDG->getNode(TargetNodeIt)); } -PDG *PDGBuilder::populate(SourceCFG &_SCFG) { - ServiceSCFGNode *EntryNode; - if (!_SCFG.getStopNode()) - return nullptr; - mPDG=new tsar::PDG(string(_SCFG.getName()), &_SCFG); - mSCFG=&_SCFG; - mSCFG->emplaceEntryNode(); - mSCFG->recalculatePredMap(); - mSPDT=PostDomTreeBase(); - mSPDT.recalculate(*mSCFG); - /*May be useful - dumpDotGraphToFile(mSPDT, "post-dom-tree.dot", "post-dom-tree"); - */ +template +CDGType *CDGBuilder::populate(CFGType &CFG) { + mCFG=&CFG; + mCDG=new CDGType(string(CFG.getName()), &CFG); + mPDT=PostDomTreeBase(); + mPDT.recalculate(*mCFG); + /*May be useful*/ + dumpDotGraphToFile(&mPDT, "post-dom-tree.dot", "post-dom-tree"); + /**/ processControlDependence(); - return mPDG; + return mCDG; } -char PDGPass::ID=0; +template<> char SourceCDGPass::ID=0; -INITIALIZE_PASS_BEGIN(PDGPass, "pdg", - "Program Dependency Graph", false, true) +INITIALIZE_PASS_BEGIN(SourceCDGPass, "source-cdg", + "Control Dependence Graph from source code", false, true) INITIALIZE_PASS_DEPENDENCY(ClangSourceCFGPass) -INITIALIZE_PASS_END(PDGPass, "pdg", - "Program Dependency Graph", false, true) +INITIALIZE_PASS_END(SourceCDGPass, "source-cdg", + "Control Dependence Graph from source code", false, true) -FunctionPass *createPDGPass() { return new PDGPass; } +FunctionPass *createSourceCDGPass() { return new SourceCDGPass; } -void PDGPass::getAnalysisUsage(AnalysisUsage &AU) const { +template<> +void SourceCDGPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); AU.setPreservesAll(); } -bool PDGPass::runOnFunction(Function &F) { +template<> +bool SourceCDGPass::runOnFunction(Function &F) { releaseMemory(); - auto &SCFGPass=getAnalysis(); - mPDG=mPDGBuilder.populate(SCFGPass.getSourceCFG()); + ClangSourceCFGPass &SCFGPass=getAnalysis(); + SCFGPass.getSourceCFG().recalculatePredMap(); + mCDG=mCDGBuilder.populate(SCFGPass.getSourceCFG()); + return false; +} + +template<> char IRCDGPass::ID=0; + +INITIALIZE_PASS_BEGIN(IRCDGPass, "llvm-ir-cdg", + "Control Dependence Graph from IR", false, true) +INITIALIZE_PASS_END(IRCDGPass, "llvm-ir-cdg", + "Control Dependence Graph from IR", false, true) + +FunctionPass *createIRCDGPass() { return new IRCDGPass; } + +template<> +void IRCDGPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); +} + +template<> +bool IRCDGPass::runOnFunction(Function &F) { + releaseMemory(); + mCDG=mCDGBuilder.populate(F); return false; } namespace { -struct PDGPassGraphTraits { - static tsar::PDG *getGraph(PDGPass *P) { return &P->getPDG(); } +template +struct CDGPassGraphTraits { + static CDGType *getGraph(CDGPass *P) { return &P->getCDG(); } +}; + +struct SourceCDGPrinter : public DOTGraphTraitsPrinterWrapperPass< + SourceCDGPass, false, ControlDependenceGraph*, + CDGPassGraphTraits>> { + static char ID; + SourceCDGPrinter() : DOTGraphTraitsPrinterWrapperPass*, + CDGPassGraphTraits>>("source-cdg", ID) { + initializeSourceCDGPrinterPass(*PassRegistry::getPassRegistry()); + } +}; +char SourceCDGPrinter::ID = 0; + +struct SourceCDGViewer : public DOTGraphTraitsViewerWrapperPass< + SourceCDGPass, false, ControlDependenceGraph*, + CDGPassGraphTraits>> { + static char ID; + SourceCDGViewer() : DOTGraphTraitsViewerWrapperPass*, + CDGPassGraphTraits>>("source-cdg", ID) { + initializeSourceCDGViewerPass(*PassRegistry::getPassRegistry()); + } }; +char SourceCDGViewer::ID = 0; -struct PDGPrinter : public DOTGraphTraitsPrinterWrapperPass< - PDGPass, false, tsar::PDG*, - PDGPassGraphTraits> { +struct IRCDGPrinter : public DOTGraphTraitsPrinterWrapperPass< + IRCDGPass, false, ControlDependenceGraph*, + CDGPassGraphTraits>> { static char ID; - PDGPrinter() : DOTGraphTraitsPrinterWrapperPass("pdg", ID) { - initializePDGPrinterPass(*PassRegistry::getPassRegistry()); + IRCDGPrinter() : DOTGraphTraitsPrinterWrapperPass*, + CDGPassGraphTraits>>("ir-cdg", ID) { + initializeIRCDGPrinterPass(*PassRegistry::getPassRegistry()); } }; -char PDGPrinter::ID = 0; +char IRCDGPrinter::ID = 0; -struct PDGViewer : public DOTGraphTraitsViewerWrapperPass< - PDGPass, false, tsar::PDG*, - PDGPassGraphTraits> { +struct IRCDGViewer : public DOTGraphTraitsViewerWrapperPass< + IRCDGPass, false, ControlDependenceGraph*, + CDGPassGraphTraits>> { static char ID; - PDGViewer() : DOTGraphTraitsViewerWrapperPass("pdg", ID) { - initializePDGViewerPass(*PassRegistry::getPassRegistry()); + IRCDGViewer() : DOTGraphTraitsViewerWrapperPass*, + CDGPassGraphTraits>>("ir-cdg", ID) { + initializeIRCDGViewerPass(*PassRegistry::getPassRegistry()); } }; -char PDGViewer::ID = 0; +char IRCDGViewer::ID = 0; } //anonymous namespace -INITIALIZE_PASS_IN_GROUP(PDGViewer, "view-pdg", - "View Program Dependency Graph", true, true, +INITIALIZE_PASS_IN_GROUP(SourceCDGViewer, "view-source-cdg", + "View Control Dependence Graph from source code", true, true, + DefaultQueryManager::OutputPassGroup::getPassRegistry()) +INITIALIZE_PASS_IN_GROUP(SourceCDGPrinter, "print-source-cdg", + "Print Control Dependence Graph from source code", true, true, DefaultQueryManager::OutputPassGroup::getPassRegistry()) -INITIALIZE_PASS_IN_GROUP(PDGPrinter, "print-pdg", - "Print Program Dependency Graph", true, true, +INITIALIZE_PASS_IN_GROUP(IRCDGViewer, "view-ir-cdg", + "View Control Dependence Graph from LLVM IR", true, true, + DefaultQueryManager::OutputPassGroup::getPassRegistry()) +INITIALIZE_PASS_IN_GROUP(IRCDGPrinter, "print-ir-cdg", + "Print Control Dependence Graph from LLVM IR", true, true, DefaultQueryManager::OutputPassGroup::getPassRegistry()) -FunctionPass *llvm::createPDGPrinter() { - return new PDGPrinter; +FunctionPass *llvm::createSourceCDGPrinter() { + return new SourceCDGPrinter; +} + +FunctionPass *llvm::createSourceCDGViewer() { + return new SourceCDGViewer; +} + +FunctionPass *llvm::createIRCDGPrinter() { + return new IRCDGPrinter; } -FunctionPass *llvm::createPDGViewer() { - return new PDGViewer; +FunctionPass *llvm::createIRCDGViewer() { + return new IRCDGViewer; } diff --git a/lib/Analysis/Passes.cpp b/lib/Analysis/Passes.cpp index 22684f56..421f7acd 100644 --- a/lib/Analysis/Passes.cpp +++ b/lib/Analysis/Passes.cpp @@ -29,7 +29,10 @@ using namespace llvm; void llvm::initializeAnalysisBase(PassRegistry &Registry) { initializeDFRegionInfoPassPass(Registry); initializeAnalysisConnectionImmutableWrapperPass(Registry); - initializePDGPassPass(Registry); - initializePDGPrinterPass(Registry); - initializePDGViewerPass(Registry); + initializeSourceCDGPassPass(Registry); + initializeSourceCDGPrinterPass(Registry); + initializeSourceCDGViewerPass(Registry); + initializeIRCDGPassPass(Registry); + initializeIRCDGPrinterPass(Registry); + initializeIRCDGViewerPass(Registry); } From 81195c47fb9c7b203c470bbb63e301ebf2b50cd1 Mon Sep 17 00:00:00 2001 From: a_zel Date: Fri, 20 Oct 2023 16:33:25 +0300 Subject: [PATCH 4/9] Merge branch 'ddg_observ' --- include/tsar/Analysis/PDG.h | 94 +++++++++++++++++++++++++++++++++++++ lib/Analysis/PDG.cpp | 26 ++++++++++ 2 files changed, 120 insertions(+) diff --git a/include/tsar/Analysis/PDG.h b/include/tsar/Analysis/PDG.h index 12d6333a..cddff6b0 100644 --- a/include/tsar/Analysis/PDG.h +++ b/include/tsar/Analysis/PDG.h @@ -17,6 +17,9 @@ #include #include +#include +#include + namespace tsar { template @@ -137,6 +140,13 @@ class ControlDependenceGraph : public CDGBase { CFGType *mCFG; }; +using SourceCDG=ControlDependenceGraph; +using IRCDGNode=CDGNode; +using DefaultIRCDGNode=DefaultCDGNode; +using EntryIRCDGNode=EntryCDGNode; +using IRCDGEdge=CDGEdge; +using IRCDG=ControlDependenceGraph; + }//namespace tsar namespace llvm { @@ -281,4 +291,88 @@ using IRCDGPass=CDGPass>; };//namespace llvm +namespace tsar { +class ControlPDGEdge : public llvm::DDGEdge { +public: + ControlPDGEdge(llvm::DDGNode &TargetNode) : llvm::DDGEdge(TargetNode, EdgeKind::Unknown) {} +}; + +class ProgramDependencyGraph : public llvm::DataDependenceGraph { +private: + using Base=llvm::DataDependenceGraph; + void construct(llvm::Function &F) { + // + for (auto INode : *this) + for (auto Edge : INode->getEdges()) + assert(Edge->getKind()!=llvm::DDGEdge::EdgeKind::Unknown); + // + IRCDG *CDG=CDGBuilder().populate(F); + std::map InstrMap; + for (auto INode : *this) + if (llvm::isa(INode)) + for (auto I : llvm::dyn_cast(INode)->getInstructions()) + InstrMap[I]=INode; + for (auto It : InstrMap) + if (It.first->isTerminator()) { + IRCDGNode *CDGNode=CDG->getNode(It.first->getParent()); + for (auto CDGEdge : *CDGNode) { + //llvm::BasicBlock *TargetBB=(llvm::dyn_cast(CDGEdge->getTargetNode())).getBlock(); + llvm::BasicBlock *TargetBB=((DefaultIRCDGNode*)(&CDGEdge->getTargetNode()))->getBlock(); + for (auto IIt=TargetBB->begin(); IIt!=TargetBB->end(); ++IIt) + connect(*InstrMap[It.first], *InstrMap[&(*IIt)], *(new ControlPDGEdge(*InstrMap[&(*IIt)]))); + } + } + for (auto RootEdge : getRoot().getEdges()) + delete RootEdge; + getRoot().clear(); + for (auto CDGEdge : *(CDG->getEntryNode())) + //for (auto IIt=llvm::dyn_cast(CDGEdge->getTargetNode()).getBlock()->begin(); + for (auto IIt=((DefaultIRCDGNode*)(&CDGEdge->getTargetNode()))->getBlock()->begin(); + //IIt!=llvm::dyn_cast(&CDGEdge->getTargetNode())->getBlock()->end(); ++IIt) + IIt!=((DefaultIRCDGNode*)(&CDGEdge->getTargetNode()))->getBlock()->end(); ++IIt) + connect(getRoot(), *InstrMap[&(*IIt)], *(new ControlPDGEdge(*InstrMap[&(*IIt)]))); + delete CDG; + } +public: + ProgramDependencyGraph(llvm::Function &F, llvm::DependenceInfo &DI) + : Base(F, DI) { + construct(F); + } +}; +} + +namespace llvm { +template <> +struct GraphTraits : public GraphTraits {}; + +template <> +struct GraphTraits : public GraphTraits {}; + +template <> +struct DOTGraphTraits : public DOTGraphTraits { +private: + using GT=GraphTraits; + using BaseDOTGT=DOTGraphTraits; +public: + DOTGraphTraits(bool isSimple=false) : BaseDOTGT(isSimple) {} + + std::string getNodeLabel(const DDGNode *Node, const tsar::ProgramDependencyGraph *PDG) { + return BaseDOTGT::getNodeLabel(Node, PDG); + } + + std::string getEdgeAttributes(const DDGNode *Node, typename GT::ChildIteratorType ChildNodeIt, const tsar::ProgramDependencyGraph *PDG) { + assert((*ChildNodeIt.getCurrent())->getKind()!=DDGEdge::EdgeKind::Rooted); + switch ((*ChildNodeIt.getCurrent())->getKind()) { + case DDGEdge::EdgeKind::Unknown: + return "style=\"dashed\""; + case DDGEdge::EdgeKind::RegisterDefUse: + return "style=\"solid\" color=\"blue\" "+BaseDOTGT::getEdgeAttributes(Node, ChildNodeIt, PDG); + case DDGEdge::EdgeKind::MemoryDependence: + return "style=\"solid\" color=\"green\" "+BaseDOTGT::getEdgeAttributes(Node, ChildNodeIt, PDG); + } + } +}; + +}; + #endif//TSAR_INCLUDE_BUILDPDG_H \ No newline at end of file diff --git a/lib/Analysis/PDG.cpp b/lib/Analysis/PDG.cpp index 0f71724b..a37a557c 100644 --- a/lib/Analysis/PDG.cpp +++ b/lib/Analysis/PDG.cpp @@ -10,6 +10,12 @@ #include #include +// +#include "tsar/Analysis/Memory/DependenceAnalysis.h" +#include +// +#include + using namespace tsar; using namespace llvm; using namespace clang; @@ -183,6 +189,7 @@ template<> char IRCDGPass::ID=0; INITIALIZE_PASS_BEGIN(IRCDGPass, "llvm-ir-cdg", "Control Dependence Graph from IR", false, true) +INITIALIZE_PASS_DEPENDENCY(DependenceAnalysisWrapperPass) INITIALIZE_PASS_END(IRCDGPass, "llvm-ir-cdg", "Control Dependence Graph from IR", false, true) @@ -190,6 +197,7 @@ FunctionPass *createIRCDGPass() { return new IRCDGPass; } template<> void IRCDGPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); AU.setPreservesAll(); } @@ -197,6 +205,24 @@ template<> bool IRCDGPass::runOnFunction(Function &F) { releaseMemory(); mCDG=mCDGBuilder.populate(F); + { + auto &DIPass=getAnalysis(); + /*May be useful*/ + StringMap &OpMap=cl::getRegisteredOptions(); + bool OldDDGSimplifyOpt=((cl::opt*)OpMap["ddg-simplify"])->getValue(), + OldDDGPiBlocksOpt=((cl::opt*)OpMap["ddg-pi-blocks"])->getValue(); + ((cl::opt*)OpMap["ddg-simplify"])->setValue(false); + ((cl::opt*)OpMap["ddg-pi-blocks"])->setValue(false); + ProgramDependencyGraph PDG(F, DIPass.getDI()); + dumpDotGraphToFile((const ProgramDependencyGraph*)&PDG, "pdg.dot", "program dependency graph"); + DataDependenceGraph DDG(F, DIPass.getDI()); + dumpDotGraphToFile((const DataDependenceGraph*)&DDG, "data-dependence-graph.dot", "data dependence graph", false); + ((cl::opt*)OpMap["ddg-simplify"])->setValue(OldDDGSimplifyOpt); + ((cl::opt*)OpMap["ddg-pi-blocks"])->setValue(OldDDGPiBlocksOpt); + DOTFuncInfo DOTCFGInfo(&F); + dumpDotGraphToFile(&DOTCFGInfo, "ircfg.dot", "control flow graph"); + } + /**/ return false; } From ffa94f22769197f3887365d51e4d34eefe6f5482 Mon Sep 17 00:00:00 2001 From: a_zel Date: Thu, 21 Dec 2023 20:49:29 +0300 Subject: [PATCH 5/9] Merge commit '8410cf703f871da05d5f209e8a453f290e437897' --- include/tsar/Analysis/PDG.h | 217 +++++++++++++++++++++++++++++++----- lib/Analysis/PDG.cpp | 13 ++- 2 files changed, 203 insertions(+), 27 deletions(-) diff --git a/include/tsar/Analysis/PDG.h b/include/tsar/Analysis/PDG.h index cddff6b0..ff2a2214 100644 --- a/include/tsar/Analysis/PDG.h +++ b/include/tsar/Analysis/PDG.h @@ -19,6 +19,24 @@ #include #include +#include "tsar/Analysis/Memory/EstimateMemory.h" +#include "tsar/Analysis/Memory/DIEstimateMemory.h" +#include +#include + +#include "tsar/Analysis/Memory/DIClientServerInfo.h" +#include "tsar/Analysis/Memory/MemoryAccessUtils.h" + +// DEBUG: +#include +#include +#include "tsar/ADT/SpanningTreeRelation.h" +#include "tsar/Analysis/Memory/EstimateMemory.h" +#include "tsar/Core/Query.h" +#include "tsar/Unparse/Utils.h" +#include +#include + namespace tsar { @@ -40,14 +58,14 @@ template class CDGEdge : public CDGEdgeBase { public: using NodeType=CDGNode; - CDGEdge(NodeType &_TargetNode) : CDGEdgeBase(_TargetNode){} + CDGEdge(NodeType &TargetNode) : CDGEdgeBase(TargetNode){} }; template class CDGNode : public CDGNodeBase { public: enum class NodeKind {Entry, Default, Region}; - CDGNode(NodeKind _mKind) : mKind(_mKind) {} + CDGNode(NodeKind Kind) : mKind(Kind) {} inline NodeKind getKind() const { return mKind; } void destroy(); private: @@ -69,7 +87,7 @@ class DefaultCDGNode : public CDGNode { using Base=CDGNode; public: using NodeValueType=CFGNodeType*; - DefaultCDGNode(NodeValueType _mBlock) : Base(Base::NodeKind::Default), mBlock(_mBlock) {} + DefaultCDGNode(NodeValueType Block) : Base(Base::NodeKind::Default), mBlock(Block) {} static bool classof(const Base *Node) { return Node->getKind()==Base::NodeKind::Default; } inline NodeValueType getBlock() const { return mBlock; } private: @@ -90,14 +108,14 @@ class ControlDependenceGraph : public CDGBase { using NodeValueType=CFGNodeType*; using CFGNodeMapType=llvm::DenseMap; - ControlDependenceGraph(const std::string &_FunctionName, CFGType *_mCFG) - : FunctionName(_FunctionName), mCFG(_mCFG), mEntryNode(new EntryNode()) { + ControlDependenceGraph(const std::string &FunctionName, CFGType *CFG) + : mFunctionName(FunctionName), mCFG(CFG), mEntryNode(new EntryNode()) { CDGBase::addNode(*mEntryNode); } inline bool addNode(DefaultNode &N) { if (CDGBase::addNode(N)) { - BlockToNodeMap.insert({N.getBlock(), &N}); + mBlockToNodeMap.insert({N.getBlock(), &N}); return true; } else @@ -115,7 +133,7 @@ class ControlDependenceGraph : public CDGBase { } inline NodeType *getNode(NodeValueType Block) { - return BlockToNodeMap[Block]; + return mBlockToNodeMap[Block]; } inline NodeType *getEntryNode() { @@ -135,8 +153,8 @@ class ControlDependenceGraph : public CDGBase { } private: EntryNode *mEntryNode; - std::string FunctionName; - CFGNodeMapType BlockToNodeMap; + std::string mFunctionName; + CFGNodeMapType mBlockToNodeMap; CFGType *mCFG; }; @@ -288,7 +306,6 @@ CDGPass>::CDGPass() : Functio using SourceCDGPass=CDGPass>; using IRCDGPass=CDGPass>; - };//namespace llvm namespace tsar { @@ -298,15 +315,56 @@ class ControlPDGEdge : public llvm::DDGEdge { }; class ProgramDependencyGraph : public llvm::DataDependenceGraph { -private: - using Base=llvm::DataDependenceGraph; - void construct(llvm::Function &F) { +public: + ProgramDependencyGraph(llvm::IRCDGPass &P, llvm::Function &F, llvm::DependenceInfo &DI, const AliasTree &AT, + const DIAliasTree &DIAT, const llvm::TargetLibraryInfo &TLI, bool ShouldSolveReachability=true) + : Base(F, DI), mF(F), mAT(AT), mDIAT(DIAT), mDIATRel(&const_cast(DIAT)), mTLI(TLI), + mSolvedReachability(ShouldSolveReachability), mDIMInfo(const_cast(DIAT), P, F) { + if (mDIMInfo.isValid()) + mServerDIATRel=SpanningTreeRelation(mDIMInfo.DIAT); + if (ShouldSolveReachability) + solveReachability(); + std::vector NodesToRemove; + std::vector> EdgesToDelete; // - for (auto INode : *this) - for (auto Edge : INode->getEdges()) + int RemovedEdges=0; + // + for (auto INode : *this) { + if (INode->getKind()==llvm::DDGNode::NodeKind::SingleInstruction && + shouldShadow(*llvm::dyn_cast(INode)->getFirstInstruction())) { + NodesToRemove.push_back(INode); + continue; + } + for (auto Edge : INode->getEdges()) { assert(Edge->getKind()!=llvm::DDGEdge::EdgeKind::Unknown); + const llvm::Instruction &TargetInst=*llvm::dyn_cast(&Edge->getTargetNode())->getFirstInstruction(); + if (shouldShadow(TargetInst)) { + EdgesToDelete.push_back({INode, Edge}); + continue; + } + // Try to exclude some memory dependence edges + if (Edge->getKind()==llvm::DDGEdge::EdgeKind::MemoryDependence && + specifyMemoryDependence(*llvm::dyn_cast(INode), + Edge->getTargetNode())) { + EdgesToDelete.push_back({INode, Edge}); + ++RemovedEdges; + } + } + } + // DEBUG: + std::cerr<<"Removed Edges Count - "<().populate(F); + for (auto &RQ : EdgesToDelete) { + RQ.first->removeEdge(*RQ.second); + delete RQ.second; + } + for (auto INode : NodesToRemove) { + for (auto Edge : *INode) + delete Edge; + Nodes.erase(findNode(*INode)); + delete INode; + } + IRCDG *CDG=CDGBuilder().populate(mF); std::map InstrMap; for (auto INode : *this) if (llvm::isa(INode)) @@ -316,28 +374,135 @@ class ProgramDependencyGraph : public llvm::DataDependenceGraph { if (It.first->isTerminator()) { IRCDGNode *CDGNode=CDG->getNode(It.first->getParent()); for (auto CDGEdge : *CDGNode) { - //llvm::BasicBlock *TargetBB=(llvm::dyn_cast(CDGEdge->getTargetNode())).getBlock(); llvm::BasicBlock *TargetBB=((DefaultIRCDGNode*)(&CDGEdge->getTargetNode()))->getBlock(); for (auto IIt=TargetBB->begin(); IIt!=TargetBB->end(); ++IIt) - connect(*InstrMap[It.first], *InstrMap[&(*IIt)], *(new ControlPDGEdge(*InstrMap[&(*IIt)]))); + if (!shouldShadow(*IIt)) + connect(*InstrMap[It.first], *InstrMap[&(*IIt)], *(new ControlPDGEdge(*InstrMap[&(*IIt)]))); } } for (auto RootEdge : getRoot().getEdges()) delete RootEdge; getRoot().clear(); for (auto CDGEdge : *(CDG->getEntryNode())) - //for (auto IIt=llvm::dyn_cast(CDGEdge->getTargetNode()).getBlock()->begin(); for (auto IIt=((DefaultIRCDGNode*)(&CDGEdge->getTargetNode()))->getBlock()->begin(); - //IIt!=llvm::dyn_cast(&CDGEdge->getTargetNode())->getBlock()->end(); ++IIt) - IIt!=((DefaultIRCDGNode*)(&CDGEdge->getTargetNode()))->getBlock()->end(); ++IIt) - connect(getRoot(), *InstrMap[&(*IIt)], *(new ControlPDGEdge(*InstrMap[&(*IIt)]))); + IIt!=((DefaultIRCDGNode*)(&CDGEdge->getTargetNode()))->getBlock()->end(); ++IIt) + if (!shouldShadow(*IIt)) + connect(getRoot(), *InstrMap[&(*IIt)], *(new ControlPDGEdge(*InstrMap[&(*IIt)]))); delete CDG; } -public: - ProgramDependencyGraph(llvm::Function &F, llvm::DependenceInfo &DI) - : Base(F, DI) { - construct(F); +private: + using Base=llvm::DataDependenceGraph; + using MemoryLocationSet=llvm::SmallDenseSet; + + struct ReachabilityMatrix : public std::vector { + size_t NodesCount; + ReachabilityMatrix() = default; + ReachabilityMatrix(size_t _NodesCount) : std::vector(_NodesCount*_NodesCount, false), NodesCount(_NodesCount) {} + std::vector::reference operator()(size_t I, size_t J) { + return this->operator[](I*NodesCount+J); + } + std::vector::const_reference operator()(size_t I, size_t J) const { + return this->operator[](I*NodesCount+J); + } + }; + + bool shouldShadow(const llvm::Instruction &I) { + return I.isDebugOrPseudoInst() || I.isLifetimeStartOrEnd(); + } + + bool isReachable(const llvm::BasicBlock &From, const llvm::BasicBlock &To) { + return mReachabilityMatrix(mBBToInd[&From], mBBToInd[&To]); + } + + void solveReachability() { + mReachabilityMatrix=ReachabilityMatrix(mF.size()); + size_t Ind=0; + mBBToInd.init(mF.size()); + for (auto &BB : mF) { + mReachabilityMatrix(Ind, Ind)=true; + mBBToInd[&BB]=Ind++; + } + for (auto &BB : mF) + for (auto SuccBB : llvm::successors(&BB)) + mReachabilityMatrix(mBBToInd[&BB], mBBToInd[SuccBB])=true; + for (size_t K=0; K(&Src)->getFirstInstruction(), + &DstInst=*llvm::dyn_cast(&Dst)->getFirstInstruction(); + if (!isReachable(*SrcInst.getParent(), *DstInst.getParent())) + return true; + bool SrcUnknownMemory=false, DstUnknownMemory=false, *CurrMarker=&SrcUnknownMemory; + MemoryLocationSet SrcMemLocs, DstMemLocs, *CurrSet=&SrcMemLocs; + auto CollectMemory=[&CurrSet](Instruction &I, MemoryLocation &&MemLoc, unsigned OpInd, + AccessInfo IsRead, AccessInfo IsWrite) { + CurrSet->insert(MemLoc); + }; + auto EvaluateUnknown=[&CurrMarker](Instruction&, AccessInfo, AccessInfo) { + *CurrMarker=true; + }; + for_each_memory(const_cast(SrcInst), const_cast(mTLI), + CollectMemory, EvaluateUnknown); + CurrSet=&DstMemLocs; + CurrMarker=&DstUnknownMemory; + for_each_memory(const_cast(DstInst), const_cast(mTLI), + CollectMemory, EvaluateUnknown); + if (SrcMemLocs.empty() || DstMemLocs.empty()) + return SrcMemLocs.empty() && !SrcUnknownMemory || DstMemLocs.empty() && !DstUnknownMemory; + SmallVector SrcDIMems, SrcServerDIMems, DstDIMems, DstServerDIMems; + auto FillDIMemories=[&](const MemoryLocationSet &MemoryLocations, SmallVectorImpl &DIMemories, + SmallVectorImpl &ServerDIMemories) { + for (auto &MemLoc : MemoryLocations) { + const EstimateMemory *EstMem=mAT.find(MemLoc); + const MDNode *MDNode; + while (!(MDNode=getRawDIMemoryIfExists(*EstMem, mF.getContext(), + mF.getParent()->getDataLayout(), mAT.getDomTree()))) + EstMem=EstMem->getParent(); + DIMemories.push_back(&*mDIAT.find(*MDNode)); + ServerDIMemories.push_back(mDIMInfo.findFromClient(*EstMem, SrcInst.getModule()->getDataLayout(), + const_cast(mAT.getDomTree())).get()); + } + }; + FillDIMemories(SrcMemLocs, SrcDIMems, SrcServerDIMems); + FillDIMemories(DstMemLocs, DstDIMems, DstServerDIMems); + bool ShouldDelete=true; + for (int SrcI=0; SrcIhasAliasNode() && DstDIMems[DstI]->hasAliasNode() && + mDIATRel.compare(SrcDINode=SrcDIMems[SrcI]->getAliasNode(), DstDINode=DstDIMems[DstI]->getAliasNode())!= + TreeRelation::TR_UNREACHABLE && (!mServerDIATRel || mServerDIATRel.value().compare(SrcServerDINode= + SrcServerDIMems[SrcI]->getAliasNode(), DstServerDINode=DstServerDIMems[DstI]->getAliasNode())!= + TreeRelation::TR_UNREACHABLE)) + ShouldDelete=false; + } + } + if (ShouldDelete) + return true; + else { + // At this point we have dependence confirmed by AliasTrees + return false; + } } + + llvm::Function &mF; + const AliasTree &mAT; + const DIAliasTree &mDIAT; + SpanningTreeRelation mDIATRel; + const llvm::TargetLibraryInfo &mTLI; + bool mSolvedReachability; + ReachabilityMatrix mReachabilityMatrix; + llvm::DenseMap mBBToInd; + DIMemoryClientServerInfo mDIMInfo; + std::optional> mServerDIATRel; }; } diff --git a/lib/Analysis/PDG.cpp b/lib/Analysis/PDG.cpp index a37a557c..a8363fb2 100644 --- a/lib/Analysis/PDG.cpp +++ b/lib/Analysis/PDG.cpp @@ -190,6 +190,9 @@ template<> char IRCDGPass::ID=0; INITIALIZE_PASS_BEGIN(IRCDGPass, "llvm-ir-cdg", "Control Dependence Graph from IR", false, true) INITIALIZE_PASS_DEPENDENCY(DependenceAnalysisWrapperPass) +INITIALIZE_PASS_DEPENDENCY(EstimateMemoryPass) +INITIALIZE_PASS_DEPENDENCY(DIEstimateMemoryPass) +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) INITIALIZE_PASS_END(IRCDGPass, "llvm-ir-cdg", "Control Dependence Graph from IR", false, true) @@ -198,6 +201,9 @@ FunctionPass *createIRCDGPass() { return new IRCDGPass; } template<> void IRCDGPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); AU.setPreservesAll(); } @@ -213,7 +219,12 @@ bool IRCDGPass::runOnFunction(Function &F) { OldDDGPiBlocksOpt=((cl::opt*)OpMap["ddg-pi-blocks"])->getValue(); ((cl::opt*)OpMap["ddg-simplify"])->setValue(false); ((cl::opt*)OpMap["ddg-pi-blocks"])->setValue(false); - ProgramDependencyGraph PDG(F, DIPass.getDI()); + // + auto &EMPass=getAnalysis(); + auto &DIEMPass=getAnalysis(); + auto &mTLIPass=getAnalysis(); + // + ProgramDependencyGraph PDG(*this, F, DIPass.getDI(), EMPass.getAliasTree(), DIEMPass.getAliasTree(), mTLIPass.getTLI(F)); dumpDotGraphToFile((const ProgramDependencyGraph*)&PDG, "pdg.dot", "program dependency graph"); DataDependenceGraph DDG(F, DIPass.getDI()); dumpDotGraphToFile((const DataDependenceGraph*)&DDG, "data-dependence-graph.dot", "data dependence graph", false); From a66d6a2f73c2be4ae32ec4f0e133eae0562df693 Mon Sep 17 00:00:00 2001 From: a_zel Date: Fri, 23 Feb 2024 04:53:07 +0300 Subject: [PATCH 6/9] refactored by copying code from abstract dependence graph builder --- include/tsar/Analysis/PDG.h | 809 +++++++++++++++++------------ include/tsar/Analysis/Passes.h | 32 +- lib/Analysis/PDG.cpp | 918 ++++++++++++++++++++++++++++----- lib/Analysis/Passes.cpp | 9 +- 4 files changed, 1282 insertions(+), 486 deletions(-) diff --git a/include/tsar/Analysis/PDG.h b/include/tsar/Analysis/PDG.h index ff2a2214..0345fe36 100644 --- a/include/tsar/Analysis/PDG.h +++ b/include/tsar/Analysis/PDG.h @@ -1,42 +1,20 @@ #ifndef TSAR_INCLUDE_BUILDPDG_H #define TSAR_INCLUDE_BUILDPDG_H -#include "tsar/Analysis/Passes.h" -#include "tsar/Analysis/Clang/SourceCFG.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include +#include "tsar/ADT/SpanningTreeRelation.h" + #include "tsar/Analysis/Memory/DependenceAnalysis.h" #include "tsar/Analysis/Memory/EstimateMemory.h" #include "tsar/Analysis/Memory/DIEstimateMemory.h" -#include -#include - #include "tsar/Analysis/Memory/DIClientServerInfo.h" #include "tsar/Analysis/Memory/MemoryAccessUtils.h" - -// DEBUG: -#include -#include -#include "tsar/ADT/SpanningTreeRelation.h" -#include "tsar/Analysis/Memory/EstimateMemory.h" -#include "tsar/Core/Query.h" -#include "tsar/Unparse/Utils.h" -#include -#include - +#include "tsar/Analysis/Clang/SourceCFG.h" +#include "tsar/Analysis/Passes.h" +#include +#include +#include +#include +#include +#include namespace tsar { @@ -136,13 +114,9 @@ class ControlDependenceGraph : public CDGBase { return mBlockToNodeMap[Block]; } - inline NodeType *getEntryNode() { - return mEntryNode; - } + inline NodeType *getEntryNode() { return mEntryNode; } - inline CFGType *getCFG() const { - return mCFG; - } + inline CFGType *getCFG() const { return mCFG; } ~ControlDependenceGraph() { for (auto N : CDGBase::Nodes) { @@ -165,10 +139,403 @@ using EntryIRCDGNode=EntryCDGNode; using IRCDGEdge=CDGEdge; using IRCDG=ControlDependenceGraph; -}//namespace tsar +template +class CDGBuilder { +private: + using CFGType=typename CDGType::CFGT; + using CFGNodeType=typename CDGType::CFGNodeT; +public: + // TODO: NodeValueType must be declared once for all DirectedGraph classes + using NodeValueType=typename llvm::GraphTraits::NodeRef; + + CDGBuilder() : mCDG(nullptr) {} + CDGType *populate(CFGType &_CFG); +private: + inline void processControlDependence(); + CFGType *mCFG; + CDGType *mCDG; + llvm::PostDomTreeBase mPDT; +}; + +class PDGNode; +class PDGEdge; +class ProgramDependencyGraph; +using PDGNodeBase=llvm::DGNode; +using PDGEdgeBase=llvm::DGEdge; +using PDGBase=llvm::DirectedGraph; + +class PDGNode : public PDGNodeBase { +public: + enum class NodeKind { + SingleInstruction, + MultiInstruction, + PiBlock, + Entry, + }; + PDGNode() : mKind(NodeKind::Entry) {} + NodeKind getKind() const { return mKind; } + bool collectInstructions(llvm::function_ref const &Pred, llvm::SmallVectorImpl &IList) const; + bool collectEdges(llvm::function_ref const &Pred, llvm::SmallVectorImpl &IList) const; + using PDGNodeBase::findEdgeTo; + void destroy(); + ~PDGNode() = default; +protected: + PDGNode(NodeKind Kind) : mKind(Kind) {} + NodeKind mKind; +}; + +class SimplePDGNode : public PDGNode { + friend class PDGBuilder; +public: + SimplePDGNode(llvm::Instruction &Inst) : PDGNode(NodeKind::SingleInstruction), mInstructions({&Inst}) {} + template + SimplePDGNode(InputIt First, InputIt Last) : PDGNode(NodeKind::SingleInstruction), mInstructions(First, Last) { + if (mInstructions.size()>0) + mKind=NodeKind::MultiInstruction; + } + static bool classof(const PDGNode *Node) { return Node->getKind()==NodeKind::SingleInstruction || + Node->getKind()==NodeKind::MultiInstruction; } + const llvm::SmallVectorImpl &getInstructions() const { + assert(!mInstructions.empty() && "Instruction List is empty."); + return mInstructions; + } + llvm::SmallVectorImpl &getInstructions() { + return const_cast&>(static_cast(this)->getInstructions()); + } + llvm::Instruction *getFirstInstruction() const { return getInstructions().front(); } + llvm::Instruction *getLastInstruction() const { return getInstructions().back(); } + ~SimplePDGNode() = default; +private: + /// Append the list of instructions in \p Input to this node. + void appendInstructions(const llvm::SmallVectorImpl &Input) { + mKind=mInstructions.size()+Input.size()>1?NodeKind::MultiInstruction:NodeKind::SingleInstruction; + llvm::append_range(mInstructions, Input); + } + void appendInstructions(const SimplePDGNode &Input) { + appendInstructions(Input.getInstructions()); + } + /// List of instructions associated with a single or multi-instruction node. + llvm::SmallVector mInstructions; +}; + +class PiBlockPDGNode : public PDGNode { +public: + template + PiBlockPDGNode(InputIt First, InputIt Last) : PDGNode(NodeKind::PiBlock), mInlinedNodes(First, Last) {} + llvm::SmallVectorImpl &getInlinedNodes() { return mInlinedNodes; } + const llvm::SmallVectorImpl &getInlinedNodes() const { return mInlinedNodes; } + static bool classof(const PDGNode *Node) { return Node->getKind()==NodeKind::PiBlock; } + ~PiBlockPDGNode(); +private: + llvm::SmallVector mInlinedNodes; +}; + +class PDGEdge : public PDGEdgeBase { +public: + enum class DependenceType { + Data, + Control, + Last=Control + }; + enum class EdgeKind { + RegisterDefUse, + Memory, + MixedData, + Control, + ComplexData, + ComplexControl + }; + PDGEdge(PDGNode &TargetNode, DependenceType DT) : PDGEdgeBase(TargetNode), + mKind(DT==DependenceType::Data?EdgeKind::RegisterDefUse:EdgeKind::Control) {} + EdgeKind getKind() const { return mKind; } + DependenceType getDependenceType() const { return (mKind==EdgeKind::Control || + mKind==EdgeKind::ComplexControl)?DependenceType::Control:DependenceType::Data; } + bool isControl() const { return getDependenceType()==DependenceType::Control; } + bool isData() const { return getDependenceType()==DependenceType::Data; } + void destroy(); + ~PDGEdge() = default; +protected: + PDGEdge(PDGNode &TargetNode, EdgeKind Kind) : PDGEdgeBase(TargetNode), mKind(Kind) {} +private: + EdgeKind mKind; +}; + +class MemoryPDGEdge : public PDGEdge { +public: + MemoryPDGEdge(PDGNode &TargetNode, llvm::Dependence &Dep, bool HasDefUse) + : PDGEdge(TargetNode, HasDefUse?EdgeKind::MixedData:EdgeKind::Memory), mMemoryDep(Dep) {} + ~MemoryPDGEdge() { delete &mMemoryDep; } + static bool classof(const PDGEdge *Edge) { return Edge->getKind()==EdgeKind::Memory || + Edge->getKind()==EdgeKind::MixedData; } + const llvm::Dependence &getMemoryDep() const { return mMemoryDep; } +private: + llvm::Dependence &mMemoryDep; +}; + +class ComplexPDGEdge : public PDGEdge { +public: + enum Direction { + Incoming, // Incoming edges to the SCC + Outgoing, // Edges going ot of the SCC + DirectionCount // To make the enum usable as an array index. + }; + struct EdgeHandler { + size_t SrcNOrdinal, TgtNordinal; + PDGEdge &E; + }; + ComplexPDGEdge(PDGNode &Dst, PDGEdge &EToInline, size_t SCCOrdinal, const Direction Dir) + : PDGEdge(Dst, EToInline.getDependenceType()==DependenceType::Control?EdgeKind::ComplexControl:EdgeKind::ComplexData) { + absorbEdge(EToInline, SCCOrdinal, Dir); + } + void absorbEdge(PDGEdge &E, size_t SCCOrdinal, const Direction Dir) { + if (E.getKind()==PDGEdge::EdgeKind::ComplexControl || + E.getKind()==PDGEdge::EdgeKind::ComplexData) { + ComplexPDGEdge &ComplexE=llvm::cast(E); + if (Dir==Incoming) + for (EdgeHandler &EH : ComplexE.mInlinedEdges) + mInlinedEdges.push_back({EH.SrcNOrdinal, SCCOrdinal, EH.E}); + else + for (EdgeHandler &EH : ComplexE.mInlinedEdges) + mInlinedEdges.push_back({SCCOrdinal, EH.TgtNordinal, EH.E}); + ComplexE.mInlinedEdges.clear(); + E.destroy(); + } + else + if (Dir==Incoming) + mInlinedEdges.push_back({0, SCCOrdinal, E}); + else + mInlinedEdges.push_back({SCCOrdinal, 0, E}); + } + static bool classof(const PDGEdge *Edge) { return Edge->getKind()==EdgeKind::ComplexControl || + Edge->getKind()==EdgeKind::ComplexData; } + llvm::SmallVectorImpl &getInlinedEdges() { return mInlinedEdges; } + const llvm::SmallVectorImpl &getInlinedEdges() const { return mInlinedEdges; } + ~ComplexPDGEdge() { + for (EdgeHandler &EH : mInlinedEdges) + EH.E.destroy(); + } +private: + llvm::SmallVector mInlinedEdges; +}; + +class ProgramDependencyGraph : public PDGBase { + friend class PDGBuilder; +public: + using NodeType=PDGNode; + using EdgeType=PDGEdge; + ProgramDependencyGraph(const llvm::Function &F) : PDGBase(), mF(F), mEntryNode(nullptr) {} + llvm::StringRef getName() const { return mF.getName(); } + PDGNode &getEntryNode() { + assert(mEntryNode); + return *mEntryNode; + } + const PDGNode &getEntryNode() const { + assert(mEntryNode); + return *mEntryNode; + } + bool addEntryNode(PDGNode &EntryNode) { + if (addNode(EntryNode)) { + mEntryNode=&EntryNode; + return true; + } + return false; + } + ~ProgramDependencyGraph() { + for (PDGNode *N : Nodes) { + for (PDGEdge *E : N->getEdges()) + E->destroy(); + N->destroy(); + } + + } +private: + const llvm::Function &mF; + PDGNode *mEntryNode; +}; + +llvm::raw_ostream &operator<<(llvm::raw_ostream&, const PDGNode&); +llvm::raw_ostream &operator<<(llvm::raw_ostream&, const PDGNode::NodeKind); +llvm::raw_ostream &operator<<(llvm::raw_ostream&, const PDGEdge&); +llvm::raw_ostream &operator<<(llvm::raw_ostream&, const PDGEdge::EdgeKind); +llvm::raw_ostream &operator<<(llvm::raw_ostream&, const ProgramDependencyGraph&); + +class PDGBuilder { + using MemoryLocationSet=llvm::SmallDenseSet; +public: + PDGBuilder(ProgramDependencyGraph &G, llvm::DependenceInfo &DI, const llvm::Function &F, const AliasTree &AT, + const DIAliasTree &DIAT, const llvm::TargetLibraryInfo &TLI, DIMemoryClientServerInfo &DIMInfo, + bool ShouldSolveReachability=true, bool ShouldSimplify=false, bool ShouldCreatePiBlocks=false) + : mGraph(G), mDI(DI), mF(F), mAT(AT), mDIAT(DIAT), mDIATRel(&const_cast(DIAT)), + mTLI(TLI), mDIMInfo(DIMInfo), mSolvedReachability(ShouldSolveReachability), mSimplified(ShouldSimplify), + mCreatedPiBlocks(ShouldCreatePiBlocks), mBBList(F.size()) { + { + size_t BBIdx=F.size(); + for (auto It=llvm::po_begin(&F); It!=llvm::po_end(&F); ++It) + mBBList[--BBIdx]=*It; + } + if (mDIMInfo.isValid()) + mServerDIATRel=SpanningTreeRelation(mDIMInfo.DIAT); + if (ShouldSolveReachability) + solveReachability(); + } + ~PDGBuilder() = default; + void populate() { + computeInstructionOrdinals(); + createFineGrainedNodes(); + createDefUseEdges(); + createMemoryDependenceEdges(); + createControlDependenceEdges(); + // Operation of this function results in memory leak + // simplify(); + createPiBlocks(); + } + static bool shouldShadow(const llvm::Instruction &I) { + return I.isDebugOrPseudoInst() || I.isLifetimeStartOrEnd(); + } +private: + struct ReachabilityMatrix : public std::vector { + size_t NodesCount; + ReachabilityMatrix() = default; + ReachabilityMatrix(size_t _NodesCount) : std::vector(_NodesCount*_NodesCount, false), NodesCount(_NodesCount) {} + std::vector::reference operator()(size_t I, size_t J) { + return this->operator[](I*NodesCount+J); + } + std::vector::const_reference operator()(size_t I, size_t J) const { + return this->operator[](I*NodesCount+J); + } + }; + + bool isReachable(const llvm::BasicBlock &From, const llvm::BasicBlock &To) { + return mReachabilityMatrix(mBBToInd[&From], mBBToInd[&To]); + } + + void solveReachability() { + mReachabilityMatrix=ReachabilityMatrix(mF.size()); + size_t Ind=0; + mBBToInd.init(mF.size()); + for (auto &BB : mF) { + // mReachabilityMatrix(Ind, Ind)=true; + mBBToInd[&BB]=Ind++; + } + for (auto &BB : mF) + for (auto SuccBB : llvm::successors(&BB)) + mReachabilityMatrix(mBBToInd[&BB], mBBToInd[SuccBB])=true; + for (size_t K=0; K(I)); + mGraph.addNode(*NewNode); + return *NewNode; + } + PDGEdge &createDefUseEdge(PDGNode &Src, PDGNode &Tgt) { + PDGEdge *NewEdge=new PDGEdge(Tgt, PDGEdge::DependenceType::Data); + mGraph.connect(Src, Tgt, *NewEdge); + return *NewEdge; + } + bool areNodesMergeable(const PDGNode &Src, const PDGNode &Tgt) const { + using namespace llvm; + // Only merge two nodes if they are both simple nodes and the consecutive + // instructions after merging belong to the same BB. + const SimplePDGNode *SimpleSrc=dyn_cast(&Src); + const SimplePDGNode *SimpleTgt=dyn_cast(&Tgt); + if (!SimpleSrc || !SimpleTgt) + return false; + return true; + //return SimpleSrc->getLastInstruction()->getParent()==SimpleTgt->getFirstInstruction()->getParent(); + } + void mergeNodes(PDGNode &AbsorbN, PDGNode &OutgoingN) { + using namespace llvm; + PDGEdge &EdgeToFold=AbsorbN.back(); + assert(AbsorbN.getEdges().size()==1 && EdgeToFold.getTargetNode()==OutgoingN && "Expected A to have a single edge to B."); + assert(isa(&AbsorbN) && isa(&OutgoingN) && "Expected simple nodes"); + // Copy instructions from B to the end of A. + cast(&AbsorbN)->appendInstructions(*cast(&OutgoingN)); + // Move to A any outgoing edges from B. + for (PDGEdge *OutgoingE : OutgoingN) + mGraph.connect(AbsorbN, OutgoingE->getTargetNode(), *OutgoingE); + AbsorbN.removeEdge(EdgeToFold); + EdgeToFold.destroy(); + mGraph.removeNode(OutgoingN); + OutgoingN.destroy(); + } + PiBlockPDGNode &createPiBlock(const llvm::SmallVectorImpl &NodeList) { + PiBlockPDGNode *Res=new PiBlockPDGNode(NodeList.begin(), NodeList.end()); + mGraph.addNode(*Res); + return *Res; + } + size_t getOrdinal(const llvm::Instruction &I) { + assert(mInstOrdinalMap.find(&I) != mInstOrdinalMap.end() && + "No ordinal computed for this instruction."); + return mInstOrdinalMap[&I]; + } + size_t getOrdinal(PDGNode &N) { + assert(mNodeOrdinalMap.find(&N)!=mNodeOrdinalMap.end() && + "No ordinal computed for this node."); + return mNodeOrdinalMap[&N]; + } + llvm::DenseMap mIMap; + llvm::DenseMap mInstOrdinalMap; + llvm::DenseMap mNodeOrdinalMap; + llvm::DependenceInfo &mDI; + llvm::SmallVector mBBList; + // + + ProgramDependencyGraph &mGraph; + const llvm::Function &mF; + const AliasTree &mAT; + const DIAliasTree &mDIAT; + SpanningTreeRelation mDIATRel; + const llvm::TargetLibraryInfo &mTLI; + bool mSolvedReachability, mSimplified, mCreatedPiBlocks; + ReachabilityMatrix mReachabilityMatrix; + llvm::DenseMap mBBToInd; + DIMemoryClientServerInfo &mDIMInfo; + std::optional> mServerDIATRel; +}; +} //namespace tsar namespace llvm { +class ProgramDependencyGraphPass : public FunctionPass, private bcl::Uncopyable { +public: + static char ID; + ProgramDependencyGraphPass() : FunctionPass(ID), mPDGBuilder(nullptr), mPDG(nullptr) { + initializeProgramDependencyGraphPassPass(*PassRegistry::getPassRegistry()); + } + bool runOnFunction(Function &F) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + void releaseMemory() override { + if (mPDGBuilder) { + delete mPDGBuilder; + mPDGBuilder=nullptr; + } + if (mPDG) { + delete mPDG; + mPDG=nullptr; + } + } + inline tsar::ProgramDependencyGraph &getPDG() { return *mPDG; } + inline const tsar::ProgramDependencyGraph &getPDG() const { return *mPDG; } +private: + tsar::PDGBuilder *mPDGBuilder; + tsar::ProgramDependencyGraph *mPDG; +}; + template struct GraphTraits*> { using NodeRef=tsar::CDGNode*; @@ -247,297 +614,101 @@ struct DOTGraphTraits*> : } }; -}//namespace llvm - -namespace tsar { -template -class CDGBuilder { -private: - using CFGType=typename CDGType::CFGT; - using CFGNodeType=typename CDGType::CFGNodeT; -public: - // TODO: NodeValueType must be declared once for all DirectedGraph classes - using NodeValueType=typename llvm::GraphTraits::NodeRef; - - CDGBuilder() : mCDG(nullptr) {} - CDGType *populate(CFGType &_CFG); -private: - inline void processControlDependence(); - CFGType *mCFG; - CDGType *mCDG; - llvm::PostDomTreeBase mPDT; +template <> struct GraphTraits { + using NodeRef=tsar::PDGNode *; + static tsar::PDGNode *PDGGetTargetNode(DGEdge *P) { + return &P->getTargetNode(); + } + // Provide a mapped iterator so that the GraphTrait-based implementations can + // find the target nodes without having to explicitly go through the edges. + using ChildIteratorType = + mapped_iterator; + using ChildEdgeIteratorType=tsar::PDGNode::iterator; + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { + return ChildIteratorType(N->begin(), &PDGGetTargetNode); + } + static ChildIteratorType child_end(NodeRef N) { + return ChildIteratorType(N->end(), &PDGGetTargetNode); + } + static ChildEdgeIteratorType child_edge_begin(NodeRef N) { + return N->begin(); + } + static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } }; -}; //namespace tsar - -namespace llvm { -template -class CDGPass : public FunctionPass, private bcl::Uncopyable { -private: - using CFGType=typename CDGType::CFGT; - using CFGNodeType=typename CDGType::CFGNodeT; -public: - static char ID; - CDGPass(); - bool runOnFunction(Function &F) override; - void getAnalysisUsage(AnalysisUsage &AU) const override; - void releaseMemory() { - mCDGBuilder=tsar::CDGBuilder(); - if (mCDG) { - delete mCDG; - mCDG=nullptr; - } - } - inline tsar::ControlDependenceGraph &getCDG() { return *mCDG; } -private: - tsar::CDGBuilder mCDGBuilder; - tsar::ControlDependenceGraph *mCDG; +template <> +struct GraphTraits : public GraphTraits { + using nodes_iterator = tsar::ProgramDependencyGraph::iterator; + static NodeRef getEntryNode(tsar::ProgramDependencyGraph *DG) { + return &DG->getEntryNode(); + } + static nodes_iterator nodes_begin(tsar::ProgramDependencyGraph *DG) { + return DG->begin(); + } + static nodes_iterator nodes_end(tsar::ProgramDependencyGraph *DG) { return DG->end(); } }; -template<> -CDGPass>::CDGPass() : FunctionPass(ID), mCDG(nullptr) { - initializeSourceCDGPassPass(*PassRegistry::getPassRegistry()); -} - -template<> -CDGPass>::CDGPass() : FunctionPass(ID), mCDG(nullptr) { - initializeIRCDGPassPass(*PassRegistry::getPassRegistry()); -} - -using SourceCDGPass=CDGPass>; -using IRCDGPass=CDGPass>; -};//namespace llvm - -namespace tsar { -class ControlPDGEdge : public llvm::DDGEdge { -public: - ControlPDGEdge(llvm::DDGNode &TargetNode) : llvm::DDGEdge(TargetNode, EdgeKind::Unknown) {} +template <> struct GraphTraits { + using NodeRef=const tsar::PDGNode *; + static const tsar::PDGNode *PDGGetTargetNode(const DGEdge *P) { + return &P->getTargetNode(); + } + using ChildIteratorType = + mapped_iterator; + using ChildEdgeIteratorType = tsar::PDGNode::const_iterator; + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { + return ChildIteratorType(N->begin(), &PDGGetTargetNode); + } + static ChildIteratorType child_end(NodeRef N) { + return ChildIteratorType(N->end(), &PDGGetTargetNode); + } + static ChildEdgeIteratorType child_edge_begin(NodeRef N) { + return N->begin(); + } + static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } }; -class ProgramDependencyGraph : public llvm::DataDependenceGraph { -public: - ProgramDependencyGraph(llvm::IRCDGPass &P, llvm::Function &F, llvm::DependenceInfo &DI, const AliasTree &AT, - const DIAliasTree &DIAT, const llvm::TargetLibraryInfo &TLI, bool ShouldSolveReachability=true) - : Base(F, DI), mF(F), mAT(AT), mDIAT(DIAT), mDIATRel(&const_cast(DIAT)), mTLI(TLI), - mSolvedReachability(ShouldSolveReachability), mDIMInfo(const_cast(DIAT), P, F) { - if (mDIMInfo.isValid()) - mServerDIATRel=SpanningTreeRelation(mDIMInfo.DIAT); - if (ShouldSolveReachability) - solveReachability(); - std::vector NodesToRemove; - std::vector> EdgesToDelete; - // - int RemovedEdges=0; - // - for (auto INode : *this) { - if (INode->getKind()==llvm::DDGNode::NodeKind::SingleInstruction && - shouldShadow(*llvm::dyn_cast(INode)->getFirstInstruction())) { - NodesToRemove.push_back(INode); - continue; - } - for (auto Edge : INode->getEdges()) { - assert(Edge->getKind()!=llvm::DDGEdge::EdgeKind::Unknown); - const llvm::Instruction &TargetInst=*llvm::dyn_cast(&Edge->getTargetNode())->getFirstInstruction(); - if (shouldShadow(TargetInst)) { - EdgesToDelete.push_back({INode, Edge}); - continue; - } - // Try to exclude some memory dependence edges - if (Edge->getKind()==llvm::DDGEdge::EdgeKind::MemoryDependence && - specifyMemoryDependence(*llvm::dyn_cast(INode), - Edge->getTargetNode())) { - EdgesToDelete.push_back({INode, Edge}); - ++RemovedEdges; - } - } - } - // DEBUG: - std::cerr<<"Removed Edges Count - "<removeEdge(*RQ.second); - delete RQ.second; - } - for (auto INode : NodesToRemove) { - for (auto Edge : *INode) - delete Edge; - Nodes.erase(findNode(*INode)); - delete INode; - } - IRCDG *CDG=CDGBuilder().populate(mF); - std::map InstrMap; - for (auto INode : *this) - if (llvm::isa(INode)) - for (auto I : llvm::dyn_cast(INode)->getInstructions()) - InstrMap[I]=INode; - for (auto It : InstrMap) - if (It.first->isTerminator()) { - IRCDGNode *CDGNode=CDG->getNode(It.first->getParent()); - for (auto CDGEdge : *CDGNode) { - llvm::BasicBlock *TargetBB=((DefaultIRCDGNode*)(&CDGEdge->getTargetNode()))->getBlock(); - for (auto IIt=TargetBB->begin(); IIt!=TargetBB->end(); ++IIt) - if (!shouldShadow(*IIt)) - connect(*InstrMap[It.first], *InstrMap[&(*IIt)], *(new ControlPDGEdge(*InstrMap[&(*IIt)]))); - } - } - for (auto RootEdge : getRoot().getEdges()) - delete RootEdge; - getRoot().clear(); - for (auto CDGEdge : *(CDG->getEntryNode())) - for (auto IIt=((DefaultIRCDGNode*)(&CDGEdge->getTargetNode()))->getBlock()->begin(); - IIt!=((DefaultIRCDGNode*)(&CDGEdge->getTargetNode()))->getBlock()->end(); ++IIt) - if (!shouldShadow(*IIt)) - connect(getRoot(), *InstrMap[&(*IIt)], *(new ControlPDGEdge(*InstrMap[&(*IIt)]))); - delete CDG; - } -private: - using Base=llvm::DataDependenceGraph; - using MemoryLocationSet=llvm::SmallDenseSet; - - struct ReachabilityMatrix : public std::vector { - size_t NodesCount; - ReachabilityMatrix() = default; - ReachabilityMatrix(size_t _NodesCount) : std::vector(_NodesCount*_NodesCount, false), NodesCount(_NodesCount) {} - std::vector::reference operator()(size_t I, size_t J) { - return this->operator[](I*NodesCount+J); - } - std::vector::const_reference operator()(size_t I, size_t J) const { - return this->operator[](I*NodesCount+J); - } - }; - - bool shouldShadow(const llvm::Instruction &I) { - return I.isDebugOrPseudoInst() || I.isLifetimeStartOrEnd(); - } - - bool isReachable(const llvm::BasicBlock &From, const llvm::BasicBlock &To) { - return mReachabilityMatrix(mBBToInd[&From], mBBToInd[&To]); - } - - void solveReachability() { - mReachabilityMatrix=ReachabilityMatrix(mF.size()); - size_t Ind=0; - mBBToInd.init(mF.size()); - for (auto &BB : mF) { - mReachabilityMatrix(Ind, Ind)=true; - mBBToInd[&BB]=Ind++; - } - for (auto &BB : mF) - for (auto SuccBB : llvm::successors(&BB)) - mReachabilityMatrix(mBBToInd[&BB], mBBToInd[SuccBB])=true; - for (size_t K=0; K(&Src)->getFirstInstruction(), - &DstInst=*llvm::dyn_cast(&Dst)->getFirstInstruction(); - if (!isReachable(*SrcInst.getParent(), *DstInst.getParent())) - return true; - bool SrcUnknownMemory=false, DstUnknownMemory=false, *CurrMarker=&SrcUnknownMemory; - MemoryLocationSet SrcMemLocs, DstMemLocs, *CurrSet=&SrcMemLocs; - auto CollectMemory=[&CurrSet](Instruction &I, MemoryLocation &&MemLoc, unsigned OpInd, - AccessInfo IsRead, AccessInfo IsWrite) { - CurrSet->insert(MemLoc); - }; - auto EvaluateUnknown=[&CurrMarker](Instruction&, AccessInfo, AccessInfo) { - *CurrMarker=true; - }; - for_each_memory(const_cast(SrcInst), const_cast(mTLI), - CollectMemory, EvaluateUnknown); - CurrSet=&DstMemLocs; - CurrMarker=&DstUnknownMemory; - for_each_memory(const_cast(DstInst), const_cast(mTLI), - CollectMemory, EvaluateUnknown); - if (SrcMemLocs.empty() || DstMemLocs.empty()) - return SrcMemLocs.empty() && !SrcUnknownMemory || DstMemLocs.empty() && !DstUnknownMemory; - SmallVector SrcDIMems, SrcServerDIMems, DstDIMems, DstServerDIMems; - auto FillDIMemories=[&](const MemoryLocationSet &MemoryLocations, SmallVectorImpl &DIMemories, - SmallVectorImpl &ServerDIMemories) { - for (auto &MemLoc : MemoryLocations) { - const EstimateMemory *EstMem=mAT.find(MemLoc); - const MDNode *MDNode; - while (!(MDNode=getRawDIMemoryIfExists(*EstMem, mF.getContext(), - mF.getParent()->getDataLayout(), mAT.getDomTree()))) - EstMem=EstMem->getParent(); - DIMemories.push_back(&*mDIAT.find(*MDNode)); - ServerDIMemories.push_back(mDIMInfo.findFromClient(*EstMem, SrcInst.getModule()->getDataLayout(), - const_cast(mAT.getDomTree())).get()); - } - }; - FillDIMemories(SrcMemLocs, SrcDIMems, SrcServerDIMems); - FillDIMemories(DstMemLocs, DstDIMems, DstServerDIMems); - bool ShouldDelete=true; - for (int SrcI=0; SrcIhasAliasNode() && DstDIMems[DstI]->hasAliasNode() && - mDIATRel.compare(SrcDINode=SrcDIMems[SrcI]->getAliasNode(), DstDINode=DstDIMems[DstI]->getAliasNode())!= - TreeRelation::TR_UNREACHABLE && (!mServerDIATRel || mServerDIATRel.value().compare(SrcServerDINode= - SrcServerDIMems[SrcI]->getAliasNode(), DstServerDINode=DstServerDIMems[DstI]->getAliasNode())!= - TreeRelation::TR_UNREACHABLE)) - ShouldDelete=false; - } - } - if (ShouldDelete) - return true; - else { - // At this point we have dependence confirmed by AliasTrees - return false; - } - } - - llvm::Function &mF; - const AliasTree &mAT; - const DIAliasTree &mDIAT; - SpanningTreeRelation mDIATRel; - const llvm::TargetLibraryInfo &mTLI; - bool mSolvedReachability; - ReachabilityMatrix mReachabilityMatrix; - llvm::DenseMap mBBToInd; - DIMemoryClientServerInfo mDIMInfo; - std::optional> mServerDIATRel; -}; -} - -namespace llvm { template <> -struct GraphTraits : public GraphTraits {}; - -template <> -struct GraphTraits : public GraphTraits {}; +struct GraphTraits + : public GraphTraits { + using nodes_iterator=tsar::ProgramDependencyGraph::const_iterator; + static NodeRef getEntryNode(const tsar::ProgramDependencyGraph *DG) { + return &DG->getEntryNode(); + } + static nodes_iterator nodes_begin(const tsar::ProgramDependencyGraph *DG) { + return DG->begin(); + } + static nodes_iterator nodes_end(const tsar::ProgramDependencyGraph *DG) { + return DG->end(); + } +}; template <> -struct DOTGraphTraits : public DOTGraphTraits { +struct DOTGraphTraits + : public DefaultDOTGraphTraits { + DOTGraphTraits(bool IsSimple=false) : DefaultDOTGraphTraits(IsSimple) {} + static std::string getGraphName(const tsar::ProgramDependencyGraph *G) { + assert(G && "expected a valid pointer to the graph."); + return "PDG for '"+std::string(G->getName())+"'"; + } + std::string getNodeLabel(const tsar::PDGNode *Node, const tsar::ProgramDependencyGraph *Graph); + std::string getEdgeAttributes(const tsar::PDGNode *Node, + GraphTraits::ChildIteratorType I, const tsar::ProgramDependencyGraph *G); + static bool isNodeHidden(const tsar::PDGNode *Node, const tsar::ProgramDependencyGraph *G); private: - using GT=GraphTraits; - using BaseDOTGT=DOTGraphTraits; -public: - DOTGraphTraits(bool isSimple=false) : BaseDOTGT(isSimple) {} - - std::string getNodeLabel(const DDGNode *Node, const tsar::ProgramDependencyGraph *PDG) { - return BaseDOTGT::getNodeLabel(Node, PDG); - } - - std::string getEdgeAttributes(const DDGNode *Node, typename GT::ChildIteratorType ChildNodeIt, const tsar::ProgramDependencyGraph *PDG) { - assert((*ChildNodeIt.getCurrent())->getKind()!=DDGEdge::EdgeKind::Rooted); - switch ((*ChildNodeIt.getCurrent())->getKind()) { - case DDGEdge::EdgeKind::Unknown: - return "style=\"dashed\""; - case DDGEdge::EdgeKind::RegisterDefUse: - return "style=\"solid\" color=\"blue\" "+BaseDOTGT::getEdgeAttributes(Node, ChildNodeIt, PDG); - case DDGEdge::EdgeKind::MemoryDependence: - return "style=\"solid\" color=\"green\" "+BaseDOTGT::getEdgeAttributes(Node, ChildNodeIt, PDG); - } - } + static std::string getSimpleNodeLabel(const tsar::PDGNode *Node, + const tsar::ProgramDependencyGraph *G); + static std::string getVerboseNodeLabel(const tsar::PDGNode *Node, + const tsar::ProgramDependencyGraph *G); + static std::string getVerboseEdgeAttributes(const tsar::PDGNode *Src, + const tsar::PDGEdge *Edge, const tsar::ProgramDependencyGraph *G); + static std::string getEdgeStyle(const tsar::PDGEdge*); }; -}; +using PDGDotGraphTraits=DOTGraphTraits; + +}//namespace llvm #endif//TSAR_INCLUDE_BUILDPDG_H \ No newline at end of file diff --git a/include/tsar/Analysis/Passes.h b/include/tsar/Analysis/Passes.h index 4016b435..6cc7a5e6 100644 --- a/include/tsar/Analysis/Passes.h +++ b/include/tsar/Analysis/Passes.h @@ -119,39 +119,21 @@ ModulePass *createAnalysisCloseConnectionPass(bool ActiveOnly = false); ModulePass *createAnalysisCloseConnectionPass(const void * ServerID); /// Initialize a pass to build control dependence graph from source code. -void initializeSourceCDGPassPass(PassRegistry &Registry); +void initializeProgramDependencyGraphPassPass(PassRegistry &Registry); /// Create a pass to build control dependence graph from source code. -FunctionPass *createSourceCDGPass(); +FunctionPass *createProgramDependencyGraphPass(); /// Initialize a pass to print control dependence graph from source code to 'dot' file. -void initializeSourceCDGPrinterPass(PassRegistry &Registry); +void initializePDGPrinterPass(PassRegistry &Registry); /// Create a pass to print control dependence graph from source code to 'dot' file. -FunctionPass *createSourceCDGPrinter(); +FunctionPass *createPDGPrinter(); /// Initialize a pass to display control dependence graph from source code. -void initializeSourceCDGViewerPass(PassRegistry &Registry); +void initializePDGViewerPass(PassRegistry &Registry); -/// Create a pass to display control dependence graph from source code. -FunctionPass *createSourceCDGViewer(); - -/// Initialize a pass to build control dependence graph from LLVM IR. -void initializeIRCDGPassPass(PassRegistry &Registry); - -/// Create a pass to build control dependence graph from LLVM IR. -FunctionPass *createIRCDGPass(); - -/// Initialize a pass to print control dependence graph from LLVM IR to 'dot' file. -void initializeIRCDGPrinterPass(PassRegistry &Registry); - -/// Create a pass to print controld dependence graph from LLVM IR to 'dot' file. -FunctionPass *createIRCDGPrinter(); - -/// Initialize a pass to display control dependence graph from LLVM IR. -void initializeIRCDGViewerPass(PassRegistry &Registry); - -/// Create a pass to display control dependence graph from LLVM IR. -FunctionPass *createIRCDGViewer(); +/// Create a pass to display program dependency graph. +FunctionPass *createPDGViewer(); } #endif//TSAR_ANALYSIS_PASSES_H diff --git a/lib/Analysis/PDG.cpp b/lib/Analysis/PDG.cpp index a8363fb2..f7f23a64 100644 --- a/lib/Analysis/PDG.cpp +++ b/lib/Analysis/PDG.cpp @@ -1,26 +1,29 @@ #include "tsar/Analysis/PDG.h" #include "tsar/Support/PassGroupRegistry.h" #include "tsar/Core/Query.h" -#include +#include +#include +#include #include -#include -#include -#include -#include -#include -#include - -// -#include "tsar/Analysis/Memory/DependenceAnalysis.h" #include -// -#include using namespace tsar; using namespace llvm; -using namespace clang; using namespace std; +#undef DEBUG_TYPE +#define DEBUG_TYPE "pdg" + +STATISTIC(TotalGraphs, "Number of dependence graphs created."); +STATISTIC(TotalDefUseEdges, "Number of def-use edges created."); +STATISTIC(TotalMemoryEdges, "Number of memory dependence edges created."); +STATISTIC(TotalFineGrainedNodes, "Number of fine-grained nodes created."); +STATISTIC(TotalPiBlockNodes, "Number of pi-block nodes created."); +STATISTIC(TotalConfusedEdges, "Number of confused memory dependencies between two nodes."); +STATISTIC(TotalEdgeReversals, "Number of times the source and sink of dependence was reversed to expose cycles in the graph."); + +using InstructionListType=SmallVector; + namespace llvm { template<> struct DOTGraphTraits @@ -59,7 +62,7 @@ struct GraphTraits*> using BaseGT=GraphTraits*>; public: static typename BaseGT::NodeRef getEntryNode(PostDomTreeBase *PDT) { - PDT->getRootNode(); + return PDT->getRootNode(); } static typename BaseGT::nodes_iterator nodes_begin(PostDomTreeBase *PDT) { return df_begin(getEntryNode(PDT)); @@ -154,170 +157,813 @@ CDGType *CDGBuilder::populate(CFGType &CFG) { mPDT=PostDomTreeBase(); mPDT.recalculate(*mCFG); /*May be useful*/ - dumpDotGraphToFile(&mPDT, "post-dom-tree.dot", "post-dom-tree"); + //dumpDotGraphToFile(&mPDT, "post-dom-tree.dot", "post-dom-tree"); /**/ processControlDependence(); return mCDG; } -template<> char SourceCDGPass::ID=0; +bool PDGNode::collectInstructions(function_ref const &Pred, SmallVectorImpl &IList) const { + assert(IList.empty() && "Expected the IList to be empty on entry."); + if (isa(this)) { + for (Instruction *I : cast(this)->getInstructions()) + if (Pred(I)) + IList.push_back(I); + } + else + if (isa(this)) { + for (const PDGNode *PN : cast(this)->getInlinedNodes()) { + assert(!isa(PN) && "Nested PiBlocks are not supported."); + SmallVector TmpIList; + PN->collectInstructions(Pred, TmpIList); + llvm::append_range(IList, TmpIList); + } + } + else + llvm_unreachable("unimplemented type of node"); + return !IList.empty(); +} -INITIALIZE_PASS_BEGIN(SourceCDGPass, "source-cdg", - "Control Dependence Graph from source code", false, true) -INITIALIZE_PASS_DEPENDENCY(ClangSourceCFGPass) -INITIALIZE_PASS_END(SourceCDGPass, "source-cdg", - "Control Dependence Graph from source code", false, true) +void PDGNode::destroy() { + switch (mKind) { + case PDGNode::NodeKind::Entry: + delete this; + break; + case PDGNode::NodeKind::SingleInstruction: + case PDGNode::NodeKind::MultiInstruction: + delete (SimplePDGNode*)this; + break; + case PDGNode::NodeKind::PiBlock: + delete (PiBlockPDGNode*)this; + break; + } +} -FunctionPass *createSourceCDGPass() { return new SourceCDGPass; } +PiBlockPDGNode::~PiBlockPDGNode() { + for (PDGNode *N : mInlinedNodes) { + for (PDGEdge *E : N->getEdges()) + E->destroy(); + N->destroy(); + } +} -template<> -void SourceCDGPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); - AU.setPreservesAll(); +void PDGEdge::destroy() { + switch (mKind) { + case PDGEdge::EdgeKind::RegisterDefUse: + case PDGEdge::EdgeKind::Control: + delete this; + break; + case PDGEdge::EdgeKind::MixedData: + case PDGEdge::EdgeKind::Memory: + delete (MemoryPDGEdge*)this; + break; + case PDGEdge::EdgeKind::ComplexData: + case PDGEdge::EdgeKind::ComplexControl: + delete (ComplexPDGEdge*)this; + break; + } } -template<> -bool SourceCDGPass::runOnFunction(Function &F) { - releaseMemory(); - ClangSourceCFGPass &SCFGPass=getAnalysis(); - SCFGPass.getSourceCFG().recalculatePredMap(); - mCDG=mCDGBuilder.populate(SCFGPass.getSourceCFG()); - return false; +llvm::raw_ostream &tsar::operator<<(llvm::raw_ostream &OS, const PDGNode &N) { + OS<<"Node Address:"<<&N<<":"<< N.getKind()<<"\n"; + if (isa(N)) { + OS<<" Instructions:\n"; + for (const Instruction *I : cast(N).getInstructions()) + OS.indent(2)<<*I<<"\n"; + } + else + if (isa(&N)) { + OS<<"--- start of nodes in pi-block ---\n"; + const SmallVectorImpl &Nodes=cast(&N)->getInlinedNodes(); + unsigned Count=0; + for (const PDGNode *N : Nodes) + OS<<*N<<(++Count==Nodes.size()?"":"\n"); + OS<<"--- end of nodes in pi-block ---\n"; + } + else + if (N.getKind()!=PDGNode::NodeKind::Entry) + llvm_unreachable("Unimplemented type of node"); + OS<<(N.getEdges().empty()?" Edges:none!\n" : " Edges:\n"); + for (const PDGEdge *E : N.getEdges()) + OS.indent(2)<<*E; + return OS; +} + +llvm::raw_ostream &tsar::operator<<(llvm::raw_ostream &OS, const PDGNode::NodeKind K) { + switch (K) { + case PDGNode::NodeKind::Entry: + OS<<"entry"; + break; + case PDGNode::NodeKind::SingleInstruction: + OS<<"single-instruction"; + break; + case PDGNode::NodeKind::MultiInstruction: + OS<<"multi-instruction"; + break; + case PDGNode::NodeKind::PiBlock: + OS<<"pi-block"; + break; + } + return OS; +} + +llvm::raw_ostream &tsar::operator<<(llvm::raw_ostream &OS, const PDGEdge &E) { + OS<<"["<< E.getKind()<<"] to "<<&E.getTargetNode()<<"\n"; + return OS; +} + +llvm::raw_ostream &tsar::operator<<(llvm::raw_ostream &OS, const PDGEdge::EdgeKind K) { + switch (K) { + case PDGEdge::EdgeKind::RegisterDefUse: + OS<<"def-use"; + break; + case PDGEdge::EdgeKind::MixedData: + OS<<"mixed data"; + break; + case PDGEdge::EdgeKind::Memory: + OS<<"memory"; + break; + case PDGEdge::EdgeKind::Control: + OS<<"control"; + break; + case PDGEdge::EdgeKind::ComplexData: + OS<<"complex data"; + break; + case PDGEdge::EdgeKind::ComplexControl: + OS<<"complex control"; + break; + } + return OS; +} + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const ProgramDependencyGraph &G) { + for (const PDGNode *Node : G) + OS<<*Node<<"\n"; + OS<<"\n"; + return OS; +} + +//===--------------------------------------------------------------------===// +// PDG DOT Printer Implementation +//===--------------------------------------------------------------------===// +std::string PDGDotGraphTraits::getNodeLabel(const PDGNode *Node, const ProgramDependencyGraph *Graph) { + if (isSimple()) + return getSimpleNodeLabel(Node, Graph); + else + return getVerboseNodeLabel(Node, Graph); +} + +std::string PDGDotGraphTraits::getEdgeAttributes(const PDGNode *Node, + GraphTraits::ChildIteratorType I, const ProgramDependencyGraph *G) { + const PDGEdge *E=static_cast(*I.getCurrent()); + if (isSimple()) + return getEdgeStyle(E); + else + return getEdgeStyle(E)+" "+getVerboseEdgeAttributes(Node, E, G); +} + +bool PDGDotGraphTraits::isNodeHidden(const PDGNode *Node, const ProgramDependencyGraph *Graph) { + if (const SimplePDGNode *SimpleNode=dyn_cast(Node)) { + for (const Instruction *I : SimpleNode->getInstructions()) + if (!PDGBuilder::shouldShadow(*I)) + return false; + return true; + } + else + if (const PiBlockPDGNode *PiNode=dyn_cast(Node)) { + for (const PDGNode *InlinedNode : PiNode->getInlinedNodes()) + if (!isNodeHidden(InlinedNode, Graph)) + return false; + return true; + } + else + return false; +} + +std::string PDGDotGraphTraits::getSimpleNodeLabel(const PDGNode *Node, const ProgramDependencyGraph *G) { + std::string Str; + raw_string_ostream OS(Str); + if (isa(Node)) { + for (const Instruction *II : static_cast(Node)->getInstructions()) + if (!PDGBuilder::shouldShadow(*II)) + OS<<*II<<"\n"; + } + else + if (isa(Node)) { + size_t NotHiddenNodesCount=0; + for (const PDGNode *IN : cast(Node)->getInlinedNodes()) + if (!isNodeHidden(IN, G)) + ++NotHiddenNodesCount; + OS<<"pi-block\nwith\n"<getKind()==PDGNode::NodeKind::Entry) + OS<<"entry\n"; + else + llvm_unreachable("Unimplemented type of node"); + return OS.str(); +} + +std::string PDGDotGraphTraits::getVerboseNodeLabel(const PDGNode *Node, const ProgramDependencyGraph *G) { + std::string Str; + raw_string_ostream OS(Str); + OS<<"getKind()<<">\n"; + if (const SimplePDGNode *SimpleNode=dyn_cast(Node)) { + for (const Instruction *II : SimpleNode->getInstructions()) + if (!PDGBuilder::shouldShadow(*II)) + OS<<*II<<"\n"; + } + else + if (const PiBlockPDGNode *PiNode=dyn_cast(Node)) { + OS<<"--- start of nodes in pi-block ---\n"; + unsigned Count=0; + for (const PDGNode *IN : PiNode->getInlinedNodes()) { + ++Count; + if (!isNodeHidden(IN, G)) + OS<getKind()==PDGNode::NodeKind::Entry) + OS<<"entry\n"; + else + llvm_unreachable("Unimplemented type of node"); + return OS.str(); +} + +std::string PDGDotGraphTraits::getVerboseEdgeAttributes(const PDGNode *Src, const PDGEdge *Edge, const ProgramDependencyGraph *G) { + std::string Str; + raw_string_ostream OS(Str); + if (const MemoryPDGEdge *MemDepEdge=dyn_cast(Edge)) { + OS<<"label=\"["; + MemDepEdge->getMemoryDep().dump(OS); + OS.str().pop_back(); + OS<<"]\""; + } + else + if (const ComplexPDGEdge *ComplexEdge=dyn_cast(Edge)) { + auto StringifyInlinedEdge=[](const PDGEdge &E) -> std::string { + using EdgeKind=PDGEdge::EdgeKind; + std::string Str; + raw_string_ostream OS(Str); + switch (E.getKind()) { + case EdgeKind::RegisterDefUse: + return "def-use"; + case EdgeKind::MixedData: + OS<<"def-use & "; + case EdgeKind::Memory: + cast(E).getMemoryDep().dump(OS); + OS.str().pop_back(); + return OS.str(); + case EdgeKind::Control: + return "control"; + default: + llvm_unreachable("Only simple edges can be inlined in complex edge"); + } + }; + OS<<"label=\""; + for (const ComplexPDGEdge::EdgeHandler &EH : ComplexEdge->getInlinedEdges()) { + if (!isNodeHidden(&EH.E.getTargetNode(), G)) + OS<<"("<getKind()) { + case tsar::PDGEdge::EdgeKind::RegisterDefUse: + return "style=\"solid\" color=\"blue\""; + case tsar::PDGEdge::EdgeKind::MixedData: + return "style=\"solid\" color=\"purple\""; + case tsar::PDGEdge::EdgeKind::Memory: + return "style=\"solid\" color=\"green\""; + case tsar::PDGEdge::EdgeKind::Control: + return "style=\"dotted\""; + case tsar::PDGEdge::EdgeKind::ComplexData: + return "style=\"solid\" color=\"orchid\""; + case tsar::PDGEdge::EdgeKind::ComplexControl: + return "style=\"dashed\""; + } +} +//===--------------------------------------------------------------------===// +// End of PDG DOT Printer Implementation +//===--------------------------------------------------------------------===// + +void PDGBuilder::computeInstructionOrdinals() { + // The BBList is expected to be in program order. + size_t NextOrdinal = 1; + for (const BasicBlock *BB : mBBList) { + assert(BB); + for (const Instruction &I : *BB) + mInstOrdinalMap.insert(std::make_pair(&I, NextOrdinal++)); + } +} + +void PDGBuilder::createFineGrainedNodes() { + ++TotalGraphs; + assert(mIMap.empty() && "Expected empty instruction map at start"); + for (const BasicBlock *BB : mBBList) + for (const Instruction &I : *BB) { + auto &NewNode = createFineGrainedNode(I); + mIMap.insert(std::make_pair(&I, &NewNode)); + mNodeOrdinalMap.insert(std::make_pair(&NewNode, getOrdinal(I))); + ++TotalFineGrainedNodes; + } +} + +void PDGBuilder::createDefUseEdges() { + for (PDGNode *N : mGraph) { + if (N->getKind()==PDGNode::NodeKind::Entry) + continue; + SimplePDGNode &InstrNode=*cast(N); + Instruction &VI=*InstrNode.getFirstInstruction(); + // Use a set to mark the targets that we link to N, so we don't add + // duplicate def-use edges when more than one instruction in a target node + // use results of instructions that are contained in N. + SmallPtrSet VisitedTargets; + for (User *U : VI.users()) { + Instruction*UI =dyn_cast(U); + if (!UI) + continue; + PDGNode *DstNode; + if (mIMap.find(UI)!=mIMap.end()) + DstNode=mIMap.find(UI)->second; + else { + // In the case of loops, the scope of the subgraph is all the + // basic blocks (and instructions within them) belonging to the loop. We + // simply ignore all the edges coming from (or going into) instructions + // or basic blocks outside of this range. + LLVM_DEBUG(dbgs()<<"skipped def-use edge since the sink"<<*UI<<" is outside the range of instructions being considered.\n"); + continue; + } + // Self dependencies are ignored because they are redundant and + // uninteresting. + if (DstNode==N) { + LLVM_DEBUG(dbgs()<<"skipped def-use edge since the sink and the source ("<getKind()==PDGNode::NodeKind::Entry) + continue; + SimplePDGNode &SrcInstrNode=*cast(*SrcNodeIt); + Instruction &SrcInstr=*SrcInstrNode.getFirstInstruction(); + if (!SrcInstr.mayReadOrWriteMemory()) + continue; + for (auto DstNodeIt=SrcNodeIt; DstNodeIt!=mGraph.end(); ++DstNodeIt) { + SmallVector DefUseEdges; + auto CreateDepEdge=[&DefUseEdges, this](PDGNode &Src, PDGNode &Tgt, unique_ptr &&Dep) { + if (Src.findEdgesTo(Tgt, DefUseEdges)) { + assert(DefUseEdges.size()==1); + Src.removeEdge(*DefUseEdges.front()); + DefUseEdges.front()->destroy(); + DefUseEdges.clear(); + assert(mGraph.connect(Src, Tgt, *(new MemoryPDGEdge(Tgt, *Dep.release(), true)))); + } + else + assert(mGraph.connect(Src, Tgt, *(new MemoryPDGEdge(Tgt, *Dep.release(), false)))); + }; + if (**SrcNodeIt==**DstNodeIt) + continue; + SimplePDGNode &DstInstrNode=*cast(*DstNodeIt); + Instruction &DstInstr=*DstInstrNode.getFirstInstruction(); + if (!DstInstr.mayReadOrWriteMemory()) + continue; + if (!(SrcInstr.getParent()==DstInstr.getParent() || isReachable(*SrcInstr.getParent(), *DstInstr.getParent()) || + isReachable(*DstInstr.getParent(), *SrcInstr.getParent()))) + continue; + unique_ptr Dep=mDI.depends(&SrcInstr, &DstInstr, true); + if (!Dep) + continue; + // If we have a dependence with its left-most non-'=' direction + // being '>' we need to reverse the direction of the edge, because + // the source of the dependence cannot occur after the sink. For + // confused dependencies, we will create edges in both directions to + // represent the possibility of a cycle. + if (Dep->isConfused() && confirmMemoryIntersect(SrcInstr, DstInstr)) { + CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); + CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&SrcInstr, &DstInstr, true)); + } + else if (Dep->isOrdered()) { + if (!Dep->isLoopIndependent()) { + bool ReversedEdge=false; + for (unsigned Level=1; Level<=Dep->getLevels(); ++Level) { + if (Dep->getDirection(Level)==Dependence::DVEntry::EQ) + continue; + else if (Dep->getDirection(Level) == Dependence::DVEntry::GT) { + CreateDepEdge(**DstNodeIt, **SrcNodeIt, std::move(Dep)); + ReversedEdge=true; + //++TotalEdgeReversals; + break; + } + else if (Dep->getDirection(Level)==Dependence::DVEntry::LT) + break; + else { + CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); + CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&SrcInstr, &DstInstr, true)); + ReversedEdge=true; + break; + } + } + if (!ReversedEdge) + CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); + } + else + CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); + } + } + } } -template<> char IRCDGPass::ID=0; +void PDGBuilder::createControlDependenceEdges() { + IRCDG *CDG=CDGBuilder().populate(const_cast(mF)); + PDGNode &EntryPDGNode=*(new PDGNode()); + mGraph.addEntryNode(EntryPDGNode); + for (IRCDGNode *BBNode : *CDG) { + auto LinkControlDependent=[this](PDGNode &SrcNode, IRCDGNode::EdgeListTy &CDGDependentNodes) { + for (IRCDGEdge *ControlDependence : CDGDependentNodes) { + BasicBlock *TargetBlock=cast(&ControlDependence->getTargetNode())->getBlock(); + for (Instruction &I : *TargetBlock) { + auto InstrPDGNodeIt=mIMap.find(&I); + if (InstrPDGNodeIt!=mIMap.end()) { + PDGEdge &NewPDGEdge=*(new PDGEdge(*InstrPDGNodeIt->second, PDGEdge::DependenceType::Control)); + // DEBUG: + assert(mGraph.connect(SrcNode, *InstrPDGNodeIt->second, NewPDGEdge)); + // + } + } + } + }; + if (isa(BBNode)) + LinkControlDependent(EntryPDGNode, BBNode->getEdges()); + else { + DefaultIRCDGNode &SrcNode=*cast(BBNode); + assert(mIMap.find(SrcNode.getBlock()->getTerminator())!=mIMap.end()); + LinkControlDependent(*mIMap[SrcNode.getBlock()->getTerminator()], SrcNode.getEdges()); + } + } + delete CDG; +} -INITIALIZE_PASS_BEGIN(IRCDGPass, "llvm-ir-cdg", - "Control Dependence Graph from IR", false, true) +void PDGBuilder::simplify() { + if (!mSimplified) + return; + LLVM_DEBUG(dbgs()<<"==== Start of Graph Simplification ===\n"); + // This algorithm works by first collecting a set of candidate nodes that have + // an out-degree of one (in terms of def-use edges), and then ignoring those + // whose targets have an in-degree more than one. Each node in the resulting + // set can then be merged with its corresponding target and put back into the + // worklist until no further merge candidates are available. + DenseSet CandidateSourceNodes; + // A mapping between nodes and their in-degree. To save space, this map + // only contains nodes that are targets of nodes in the CandidateSourceNodes. + DenseMap TargetInDegreeMap; + for (PDGNode *N : mGraph) { + if (N->getEdges().size()!=1) + continue; + PDGEdge &Edge=N->back(); + if (Edge.getKind()!=PDGEdge::EdgeKind::RegisterDefUse) + continue; + CandidateSourceNodes.insert(N); + // Insert an element into the in-degree map and initialize to zero. The + // count will get updated in the next step. + TargetInDegreeMap.insert({&Edge.getTargetNode(), 0}); + } + LLVM_DEBUG({ + dbgs()<<"Size of candidate src node list:"< CDependentTargets; + for (PDGEdge *E : *N) { + auto RegisterCDNode=[&CDependentTargets](PDGNode &N) { + if (CDependentTargets.contains(&N)) + CDependentTargets.erase(&N); + else + CDependentTargets.insert(&N); + }; + PDGNode &TgtNode=E->getTargetNode(); + auto TgtIt=TargetInDegreeMap.find(&TgtNode); + if (E->isControl()) { + auto SrcIt=CandidateSourceNodes.find(&TgtNode); + if (SrcIt!=CandidateSourceNodes.end()) + RegisterCDNode(TgtNode.back().getTargetNode()); + if (TgtIt!=TargetInDegreeMap.end()) + RegisterCDNode(TgtNode); + } + else + if (TgtIt!=TargetInDegreeMap.end()) + ++(TgtIt->second); + } + for (PDGNode *Target : CDependentTargets) + TargetInDegreeMap[Target]=2; + } + LLVM_DEBUG({ + dbgs()<<"Size of target in-degree map:"< "< Worklist(CandidateSourceNodes.begin(), + CandidateSourceNodes.end()); + while (!Worklist.empty()) { + PDGNode &Src=*Worklist.pop_back_val(); + // As nodes get merged, we need to skip any node that has been removed from + // the candidate set (see below). + if (!CandidateSourceNodes.erase(&Src)) + continue; + assert(Src.getEdges().size()==1 && + "Expected a single edge from the candidate src node."); + PDGNode &Tgt=Src.back().getTargetNode(); + assert(TargetInDegreeMap.find(&Tgt)!=TargetInDegreeMap.end() && + "Expected target to be in the in-degree map."); + // Do not merge if there is also an edge from target to src (immediate + // cycle). + if (TargetInDegreeMap[&Tgt]!=1 || !areNodesMergeable(Src, Tgt) || Tgt.hasEdgeTo(Src)) + continue; + // LLVM_DEBUG(dbgs()<<"Merging:"<(b), (b)->(c), (c)->(d), ...} and the worklist is initially {b, a}, + // then after merging (a) and (b) together, we need to put (a,b) back in + // the worklist so that (c) can get merged in as well resulting in + // {(a,b,c) -> d} + // We also need to remove the old target (b), from the worklist. We first + // remove it from the candidate set here, and skip any item from the + // worklist that is not in the set. + if (CandidateSourceNodes.erase(&Tgt)) { + Worklist.push_back(&Src); + CandidateSourceNodes.insert(&Src); + LLVM_DEBUG(dbgs()<<"Putting "<<&Src<<" back in the worklist.\n"); + } + } + LLVM_DEBUG(dbgs()<<"=== End of Graph Simplification ===\n"); +} + +void PDGBuilder::createPiBlocks() { + using NodeListType=SmallVector; + if (!mCreatedPiBlocks) + return; + LLVM_DEBUG(dbgs()<<"==== Start of Creation of Pi-Blocks ===\n"); + // The overall algorithm is as follows: + // 1. Identify SCCs and for each SCC create a pi-block node containing all + // the nodes in that SCC. + // 2. Identify incoming edges incident to the nodes inside of the SCC and + // reconnect them to the pi-block node. + // 3. Identify outgoing edges from the nodes inside of the SCC to nodes + // outside of it and reconnect them so that the edges are coming out of the + // SCC node instead. + + // Adding nodes as we iterate through the SCCs cause the SCC + // iterators to get invalidated. To prevent this invalidation, we first + // collect a list of nodes that are part of an SCC, and then iterate over + // those lists to create the pi-block nodes. Each element of the list is a + // list of nodes in an SCC. Note: trivial SCCs containing a single node are + // ignored. + SmallVector ListOfSCCs; + for (const vector &SCC : make_range(scc_begin(&mGraph), scc_end(&mGraph))) + if (SCC.size()>1) + ListOfSCCs.emplace_back(SCC.begin(), SCC.end()); + for (NodeListType &NL : ListOfSCCs) { + LLVM_DEBUG(dbgs()<<"Creating pi-block node with "< NodesInSCC(NL.begin(), NL.end()); + // We have the set of nodes in the SCC. We go through the set of nodes + // that are outside of the SCC and look for edges that cross the two sets. + for (auto ExternalNodeIt=mGraph.begin(); ExternalNodeIt!=mGraph.end();) { + // Skip the SCC node. + if (*ExternalNodeIt==&PiNode) { + ++ExternalNodeIt; + continue; + } + // Remove SCC inlined node from graph's node list and skip it. + if (NodesInSCC.count(*ExternalNodeIt)) { + mGraph.Nodes.erase(ExternalNodeIt); + continue; + } + // Use these flags to help us avoid creating redundant edges. If there + // are more than one edges from an outside node to inside nodes, we only + // keep one edge from that node to the pi-block node. Similarly, if + // there are more than one edges from inside nodes to an outside node, + // we only keep one edge from the pi-block node to the outside node. + // There is a flag defined for each direction (incoming vs outgoing) and + // for each type of edge supported, using a two-dimensional boolean + // array. + using Direction=typename ComplexPDGEdge::Direction; + using EdgeKind=typename PDGEdge::EdgeKind; + using DependenceType=typename PDGEdge::DependenceType; + EnumeratedArray NewEdges[Direction::DirectionCount] {nullptr, nullptr}; + for (size_t SCCNodeI=0; SCCNodeI EL; + Src.findEdgesTo(Dst, EL); + if (EL.empty()) + return; + LLVM_DEBUG(dbgs()<<"reconnecting("<<(Dir==Direction::Incoming?"incoming)":"outgoing)") + <<":\nSrc:"<getDependenceType(); + if (NewEdges[Dir][Type]) { + NewEdges[Dir][Type]->absorbEdge(*OldEdge, SCCNodeI, Dir); + LLVM_DEBUG(dbgs()<<"absorbed old edge between Src and Dst.\n\n"); + } + else { + if (Dir==Direction::Incoming) { + NewEdges[Dir][Type]=new ComplexPDGEdge(PiNode, *OldEdge, SCCNodeI, Dir); + mGraph.connect(Src, PiNode, *NewEdges[Dir][Type]); + LLVM_DEBUG(dbgs()<<"created complex edge from Src to PiNode.\n"); + } + else { + NewEdges[Dir][Type]=new ComplexPDGEdge(Dst, *OldEdge, SCCNodeI, Dir); + mGraph.connect(PiNode, Dst, *NewEdges[Dir][Type]); + LLVM_DEBUG(dbgs()<<"created complex edge from PiNode to Dst.\n"); + } + } + Src.removeEdge(*OldEdge); + LLVM_DEBUG(dbgs()<<"removed old edge between Src and Dst.\n\n"); + /*if (OldEdge->getKind()==PDGEdge::EdgeKind::ComplexControl + || OldEdge->getKind()==PDGEdge::EdgeKind::ComplexData) { + OldEdge->destroy(); + LLVM_DEBUG(dbgs()<<"released memory from old complex edge between Src and Dst.\n\n"); + }*/ + } + }; + // Process incoming edges incident to the pi-block node. + ReconnectEdges(**ExternalNodeIt, *NL[SCCNodeI], Direction::Incoming); + // Process edges that are coming out of the pi-block node. + ReconnectEdges(*NL[SCCNodeI], **ExternalNodeIt, Direction::Outgoing); + } + ++ExternalNodeIt; + } + } + // Ordinal maps are no longer needed. + mInstOrdinalMap.clear(); + mNodeOrdinalMap.clear(); + LLVM_DEBUG(dbgs()<<"==== End of Creation of Pi-Blocks ===\n"); +} + +bool PDGBuilder::confirmMemoryIntersect(const Instruction &SrcInst, const Instruction &DstInst) { + bool SrcUnknownMemory=false, DstUnknownMemory=false, *CurrMarker=&SrcUnknownMemory; + MemoryLocationSet SrcMemLocs, DstMemLocs, *CurrSet=&SrcMemLocs; + auto CollectMemory=[&CurrSet](Instruction &I, MemoryLocation &&MemLoc, unsigned OpInd, + AccessInfo IsRead, AccessInfo IsWrite) { + CurrSet->insert(MemLoc); + }; + auto EvaluateUnknown=[&CurrMarker](Instruction&, AccessInfo, AccessInfo) { + *CurrMarker=true; + }; + for_each_memory(const_cast(SrcInst), const_cast(mTLI), + CollectMemory, EvaluateUnknown); + CurrSet=&DstMemLocs; + CurrMarker=&DstUnknownMemory; + for_each_memory(const_cast(DstInst), const_cast(mTLI), + CollectMemory, EvaluateUnknown); + if (SrcMemLocs.empty() || DstMemLocs.empty()) + return SrcMemLocs.empty() && !SrcUnknownMemory || DstMemLocs.empty() && !DstUnknownMemory; + SmallVector SrcDIMems, SrcServerDIMems, DstDIMems, DstServerDIMems; + auto FillDIMemories=[&](const MemoryLocationSet &MemoryLocations, SmallVectorImpl &DIMemories, + SmallVectorImpl &ServerDIMemories) { + for (auto &MemLoc : MemoryLocations) { + const EstimateMemory *EstMem=mAT.find(MemLoc); + const MDNode *MDNode; + while (!(MDNode=getRawDIMemoryIfExists(*EstMem, mF.getContext(), + mF.getParent()->getDataLayout(), mAT.getDomTree()))) + EstMem=EstMem->getParent(); + DIMemories.push_back(&*mDIAT.find(*MDNode)); + ServerDIMemories.push_back(mDIMInfo.findFromClient(*EstMem, SrcInst.getModule()->getDataLayout(), + const_cast(mAT.getDomTree())).get()); + } + }; + FillDIMemories(SrcMemLocs, SrcDIMems, SrcServerDIMems); + FillDIMemories(DstMemLocs, DstDIMems, DstServerDIMems); + bool ShouldDelete=true; + for (int SrcI=0; SrcIgetAliasNode()) && + (DstDINode=DstDIMems[DstI]->getAliasNode()) && + mDIATRel.compare(SrcDINode, DstDINode)!=TreeRelation::TR_UNREACHABLE && + (!mServerDIATRel || + SrcServerDIMems[SrcI] && + DstServerDIMems[DstI] && + (SrcServerDINode=SrcServerDIMems[SrcI]->getAliasNode()) && + (DstServerDINode=DstServerDIMems[DstI]->getAliasNode()) && + mServerDIATRel.value().compare(SrcServerDINode, DstServerDINode)!=TreeRelation::TR_UNREACHABLE) + ) + ShouldDelete=false; + } + } + if (ShouldDelete) + return false; + else { + // At this point we have dependence confirmed by AliasTrees + // mOverridenDeps.insert({{&Src, &Dst}, }) + return true; + } +} + +char ProgramDependencyGraphPass::ID=0; + +INITIALIZE_PASS_BEGIN(ProgramDependencyGraphPass, "pdg", + "Program Dependency Graph", false, true) INITIALIZE_PASS_DEPENDENCY(DependenceAnalysisWrapperPass) INITIALIZE_PASS_DEPENDENCY(EstimateMemoryPass) INITIALIZE_PASS_DEPENDENCY(DIEstimateMemoryPass) INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) -INITIALIZE_PASS_END(IRCDGPass, "llvm-ir-cdg", - "Control Dependence Graph from IR", false, true) +INITIALIZE_PASS_END(ProgramDependencyGraphPass, "pdg", + "Program Dependency Graph", false, true) -FunctionPass *createIRCDGPass() { return new IRCDGPass; } +FunctionPass *createProgramDependencyGraphPass() { return new ProgramDependencyGraphPass; } -template<> -void IRCDGPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); +void ProgramDependencyGraphPass::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); AU.addRequired(); AU.addRequired(); AU.addRequired(); - AU.setPreservesAll(); + AU.setPreservesAll(); } -template<> -bool IRCDGPass::runOnFunction(Function &F) { - releaseMemory(); - mCDG=mCDGBuilder.populate(F); - { - auto &DIPass=getAnalysis(); - /*May be useful*/ - StringMap &OpMap=cl::getRegisteredOptions(); - bool OldDDGSimplifyOpt=((cl::opt*)OpMap["ddg-simplify"])->getValue(), - OldDDGPiBlocksOpt=((cl::opt*)OpMap["ddg-pi-blocks"])->getValue(); - ((cl::opt*)OpMap["ddg-simplify"])->setValue(false); - ((cl::opt*)OpMap["ddg-pi-blocks"])->setValue(false); - // - auto &EMPass=getAnalysis(); - auto &DIEMPass=getAnalysis(); - auto &mTLIPass=getAnalysis(); - // - ProgramDependencyGraph PDG(*this, F, DIPass.getDI(), EMPass.getAliasTree(), DIEMPass.getAliasTree(), mTLIPass.getTLI(F)); - dumpDotGraphToFile((const ProgramDependencyGraph*)&PDG, "pdg.dot", "program dependency graph"); - DataDependenceGraph DDG(F, DIPass.getDI()); - dumpDotGraphToFile((const DataDependenceGraph*)&DDG, "data-dependence-graph.dot", "data dependence graph", false); - ((cl::opt*)OpMap["ddg-simplify"])->setValue(OldDDGSimplifyOpt); - ((cl::opt*)OpMap["ddg-pi-blocks"])->setValue(OldDDGPiBlocksOpt); - DOTFuncInfo DOTCFGInfo(&F); - dumpDotGraphToFile(&DOTCFGInfo, "ircfg.dot", "control flow graph"); - } - /**/ +bool ProgramDependencyGraphPass::runOnFunction(Function &F) { + releaseMemory(); + DependenceAnalysisWrapperPass &DIPass=getAnalysis(); + EstimateMemoryPass &EMPass=getAnalysis(); + DIEstimateMemoryPass &DIEMPass=getAnalysis(); + TargetLibraryInfoWrapperPass &TLIPass=getAnalysis(); + DIMemoryClientServerInfo DIMInfo(const_cast(DIEMPass.getAliasTree()), *this, F); + mPDG=new ProgramDependencyGraph(F); + mPDGBuilder=new PDGBuilder(*mPDG, DIPass.getDI(), F, EMPass.getAliasTree(), DIEMPass.getAliasTree(), TLIPass.getTLI(F), DIMInfo, true); + mPDGBuilder->populate(); return false; } namespace { -template -struct CDGPassGraphTraits { - static CDGType *getGraph(CDGPass *P) { return &P->getCDG(); } +struct PDGPassGraphTraits { + static const ProgramDependencyGraph *getGraph(ProgramDependencyGraphPass *P) { return &P->getPDG(); } }; -struct SourceCDGPrinter : public DOTGraphTraitsPrinterWrapperPass< - SourceCDGPass, false, ControlDependenceGraph*, - CDGPassGraphTraits>> { +struct PDGPrinter : public DOTGraphTraitsPrinterWrapperPass< + ProgramDependencyGraphPass, false, const ProgramDependencyGraph*, + PDGPassGraphTraits> { static char ID; - SourceCDGPrinter() : DOTGraphTraitsPrinterWrapperPass*, - CDGPassGraphTraits>>("source-cdg", ID) { - initializeSourceCDGPrinterPass(*PassRegistry::getPassRegistry()); + PDGPrinter() : DOTGraphTraitsPrinterWrapperPass("pdg", ID) { + initializePDGPrinterPass(*PassRegistry::getPassRegistry()); } }; -char SourceCDGPrinter::ID = 0; +char PDGPrinter::ID = 0; -struct SourceCDGViewer : public DOTGraphTraitsViewerWrapperPass< - SourceCDGPass, false, ControlDependenceGraph*, - CDGPassGraphTraits>> { +struct PDGViewer : public DOTGraphTraitsViewerWrapperPass< + ProgramDependencyGraphPass, false, const ProgramDependencyGraph*, + PDGPassGraphTraits> { static char ID; - SourceCDGViewer() : DOTGraphTraitsViewerWrapperPass*, - CDGPassGraphTraits>>("source-cdg", ID) { - initializeSourceCDGViewerPass(*PassRegistry::getPassRegistry()); + PDGViewer() : DOTGraphTraitsViewerWrapperPass("pdg", ID) { + initializePDGViewerPass(*PassRegistry::getPassRegistry()); } }; -char SourceCDGViewer::ID = 0; - -struct IRCDGPrinter : public DOTGraphTraitsPrinterWrapperPass< - IRCDGPass, false, ControlDependenceGraph*, - CDGPassGraphTraits>> { - static char ID; - IRCDGPrinter() : DOTGraphTraitsPrinterWrapperPass*, - CDGPassGraphTraits>>("ir-cdg", ID) { - initializeIRCDGPrinterPass(*PassRegistry::getPassRegistry()); - } -}; -char IRCDGPrinter::ID = 0; - -struct IRCDGViewer : public DOTGraphTraitsViewerWrapperPass< - IRCDGPass, false, ControlDependenceGraph*, - CDGPassGraphTraits>> { - static char ID; - IRCDGViewer() : DOTGraphTraitsViewerWrapperPass*, - CDGPassGraphTraits>>("ir-cdg", ID) { - initializeIRCDGViewerPass(*PassRegistry::getPassRegistry()); - } -}; -char IRCDGViewer::ID = 0; +char PDGViewer::ID = 0; } //anonymous namespace -INITIALIZE_PASS_IN_GROUP(SourceCDGViewer, "view-source-cdg", - "View Control Dependence Graph from source code", true, true, - DefaultQueryManager::OutputPassGroup::getPassRegistry()) -INITIALIZE_PASS_IN_GROUP(SourceCDGPrinter, "print-source-cdg", - "Print Control Dependence Graph from source code", true, true, - DefaultQueryManager::OutputPassGroup::getPassRegistry()) - -INITIALIZE_PASS_IN_GROUP(IRCDGViewer, "view-ir-cdg", - "View Control Dependence Graph from LLVM IR", true, true, +INITIALIZE_PASS_IN_GROUP(PDGViewer, "view-pdg", + "View Program Dependency Graph", true, true, DefaultQueryManager::OutputPassGroup::getPassRegistry()) -INITIALIZE_PASS_IN_GROUP(IRCDGPrinter, "print-ir-cdg", - "Print Control Dependence Graph from LLVM IR", true, true, +INITIALIZE_PASS_IN_GROUP(PDGPrinter, "print-pdg", + "Print Program Dependency Graph", true, true, DefaultQueryManager::OutputPassGroup::getPassRegistry()) -FunctionPass *llvm::createSourceCDGPrinter() { - return new SourceCDGPrinter; -} - -FunctionPass *llvm::createSourceCDGViewer() { - return new SourceCDGViewer; -} - -FunctionPass *llvm::createIRCDGPrinter() { - return new IRCDGPrinter; +FunctionPass *llvm::createPDGPrinter() { + return new PDGPrinter; } -FunctionPass *llvm::createIRCDGViewer() { - return new IRCDGViewer; +FunctionPass *llvm::createPDGViewer() { + return new PDGViewer; } diff --git a/lib/Analysis/Passes.cpp b/lib/Analysis/Passes.cpp index 421f7acd..61198016 100644 --- a/lib/Analysis/Passes.cpp +++ b/lib/Analysis/Passes.cpp @@ -29,10 +29,7 @@ using namespace llvm; void llvm::initializeAnalysisBase(PassRegistry &Registry) { initializeDFRegionInfoPassPass(Registry); initializeAnalysisConnectionImmutableWrapperPass(Registry); - initializeSourceCDGPassPass(Registry); - initializeSourceCDGPrinterPass(Registry); - initializeSourceCDGViewerPass(Registry); - initializeIRCDGPassPass(Registry); - initializeIRCDGPrinterPass(Registry); - initializeIRCDGViewerPass(Registry); + initializeProgramDependencyGraphPassPass(Registry); + initializePDGPrinterPass(Registry); + initializePDGViewerPass(Registry); } From 69e60db6672007f0bc4100741669aa43b26de1a7 Mon Sep 17 00:00:00 2001 From: a_zel Date: Wed, 17 Apr 2024 22:38:21 +0300 Subject: [PATCH 7/9] with tsar's traits (and turned off llvm depends) --- include/tsar/Analysis/PDG.h | 1187 ++++++++++++---------- lib/Analysis/PDG.cpp | 1916 ++++++++++++++++++++--------------- 2 files changed, 1756 insertions(+), 1347 deletions(-) diff --git a/include/tsar/Analysis/PDG.h b/include/tsar/Analysis/PDG.h index 0345fe36..06942326 100644 --- a/include/tsar/Analysis/PDG.h +++ b/include/tsar/Analysis/PDG.h @@ -16,6 +16,13 @@ #include #include +// New (before adding tsar's traits in graph): +#include "tsar/Analysis/Memory/DIMemoryTrait.h" +#include +#include +#include +// + namespace tsar { template @@ -35,101 +42,101 @@ using CDGBase=llvm::DirectedGraph, CDGEdge class CDGEdge : public CDGEdgeBase { public: - using NodeType=CDGNode; - CDGEdge(NodeType &TargetNode) : CDGEdgeBase(TargetNode){} + using NodeType=CDGNode; + CDGEdge(NodeType &TargetNode) : CDGEdgeBase(TargetNode){} }; template class CDGNode : public CDGNodeBase { public: - enum class NodeKind {Entry, Default, Region}; - CDGNode(NodeKind Kind) : mKind(Kind) {} - inline NodeKind getKind() const { return mKind; } - void destroy(); + enum class NodeKind {Entry, Default, Region}; + CDGNode(NodeKind Kind) : mKind(Kind) {} + inline NodeKind getKind() const { return mKind; } + void destroy(); private: - NodeKind mKind; + NodeKind mKind; }; template class EntryCDGNode : public CDGNode { private: - using Base=CDGNode; + using Base=CDGNode; public: - EntryCDGNode() : Base(Base::NodeKind::Entry) {} - static bool classof(const Base *Node) { return Node->getKind()==Base::NodeKind::Entry; } + EntryCDGNode() : Base(Base::NodeKind::Entry) {} + static bool classof(const Base *Node) { return Node->getKind()==Base::NodeKind::Entry; } }; template class DefaultCDGNode : public CDGNode { private: - using Base=CDGNode; + using Base=CDGNode; public: - using NodeValueType=CFGNodeType*; - DefaultCDGNode(NodeValueType Block) : Base(Base::NodeKind::Default), mBlock(Block) {} - static bool classof(const Base *Node) { return Node->getKind()==Base::NodeKind::Default; } - inline NodeValueType getBlock() const { return mBlock; } + using NodeValueType=CFGNodeType*; + DefaultCDGNode(NodeValueType Block) : Base(Base::NodeKind::Default), mBlock(Block) {} + static bool classof(const Base *Node) { return Node->getKind()==Base::NodeKind::Default; } + inline NodeValueType getBlock() const { return mBlock; } private: - NodeValueType mBlock; + NodeValueType mBlock; }; template class ControlDependenceGraph : public CDGBase { private: - using DefaultNode=DefaultCDGNode; - using EntryNode=EntryCDGNode; + using DefaultNode=DefaultCDGNode; + using EntryNode=EntryCDGNode; public: - using CFGT=CFGType; - using CFGNodeT=CFGNodeType; - using NodeType=CDGNode; - using EdgeType=CDGEdge; - // TODO: NodeValueType must be declared once for all DirectedGraph classes - using NodeValueType=CFGNodeType*; - using CFGNodeMapType=llvm::DenseMap; - - ControlDependenceGraph(const std::string &FunctionName, CFGType *CFG) - : mFunctionName(FunctionName), mCFG(CFG), mEntryNode(new EntryNode()) { - CDGBase::addNode(*mEntryNode); - } - - inline bool addNode(DefaultNode &N) { - if (CDGBase::addNode(N)) { - mBlockToNodeMap.insert({N.getBlock(), &N}); - return true; - } - else - return false; - } - - NodeType &emplaceNode(NodeValueType Block) { - DefaultNode *NewNode=new DefaultNode(Block); - addNode(*NewNode); - return *NewNode; - } - - inline void bindNodes(NodeType &SourceNode, NodeType &TargetNode) { - CDGBase::connect(SourceNode, TargetNode, *(new CDGEdge(TargetNode))); - } - - inline NodeType *getNode(NodeValueType Block) { - return mBlockToNodeMap[Block]; - } - - inline NodeType *getEntryNode() { return mEntryNode; } - - inline CFGType *getCFG() const { return mCFG; } - - ~ControlDependenceGraph() { - for (auto N : CDGBase::Nodes) { - for (auto E : N->getEdges()) - delete E; - delete N; - } - } + using CFGT=CFGType; + using CFGNodeT=CFGNodeType; + using NodeType=CDGNode; + using EdgeType=CDGEdge; + // TODO: NodeValueType must be declared once for all DirectedGraph classes + using NodeValueType=CFGNodeType*; + using CFGNodeMapType=llvm::DenseMap; + + ControlDependenceGraph(const std::string &FunctionName, CFGType *CFG) + : mFunctionName(FunctionName), mCFG(CFG), mEntryNode(new EntryNode()) { + CDGBase::addNode(*mEntryNode); + } + + inline bool addNode(DefaultNode &N) { + if (CDGBase::addNode(N)) { + mBlockToNodeMap.insert({N.getBlock(), &N}); + return true; + } + else + return false; + } + + NodeType &emplaceNode(NodeValueType Block) { + DefaultNode *NewNode=new DefaultNode(Block); + addNode(*NewNode); + return *NewNode; + } + + inline void bindNodes(NodeType &SourceNode, NodeType &TargetNode) { + CDGBase::connect(SourceNode, TargetNode, *(new CDGEdge(TargetNode))); + } + + inline NodeType *getNode(NodeValueType Block) { + return mBlockToNodeMap[Block]; + } + + inline NodeType *getEntryNode() { return mEntryNode; } + + inline CFGType *getCFG() const { return mCFG; } + + ~ControlDependenceGraph() { + for (auto N : CDGBase::Nodes) { + for (auto E : N->getEdges()) + delete E; + delete N; + } + } private: - EntryNode *mEntryNode; - std::string mFunctionName; - CFGNodeMapType mBlockToNodeMap; - CFGType *mCFG; + EntryNode *mEntryNode; + std::string mFunctionName; + CFGNodeMapType mBlockToNodeMap; + CFGType *mCFG; }; using SourceCDG=ControlDependenceGraph; @@ -142,19 +149,19 @@ using IRCDG=ControlDependenceGraph; template class CDGBuilder { private: - using CFGType=typename CDGType::CFGT; - using CFGNodeType=typename CDGType::CFGNodeT; + using CFGType=typename CDGType::CFGT; + using CFGNodeType=typename CDGType::CFGNodeT; public: - // TODO: NodeValueType must be declared once for all DirectedGraph classes - using NodeValueType=typename llvm::GraphTraits::NodeRef; + // TODO: NodeValueType must be declared once for all DirectedGraph classes + using NodeValueType=typename llvm::GraphTraits::NodeRef; - CDGBuilder() : mCDG(nullptr) {} - CDGType *populate(CFGType &_CFG); + CDGBuilder() : mCDG(nullptr) {} + CDGType *populate(CFGType &_CFG); private: - inline void processControlDependence(); - CFGType *mCFG; - CDGType *mCDG; - llvm::PostDomTreeBase mPDT; + inline void processControlDependence(); + CFGType *mCFG; + CDGType *mCDG; + llvm::PostDomTreeBase mPDT; }; class PDGNode; @@ -166,191 +173,235 @@ using PDGBase=llvm::DirectedGraph; class PDGNode : public PDGNodeBase { public: - enum class NodeKind { - SingleInstruction, - MultiInstruction, - PiBlock, - Entry, - }; - PDGNode() : mKind(NodeKind::Entry) {} - NodeKind getKind() const { return mKind; } - bool collectInstructions(llvm::function_ref const &Pred, llvm::SmallVectorImpl &IList) const; - bool collectEdges(llvm::function_ref const &Pred, llvm::SmallVectorImpl &IList) const; - using PDGNodeBase::findEdgeTo; - void destroy(); - ~PDGNode() = default; + enum class NodeKind { + SingleInstruction, + MultiInstruction, + PiBlock, + Entry, + }; + PDGNode() : mKind(NodeKind::Entry) {} + NodeKind getKind() const { return mKind; } + bool collectInstructions(llvm::function_ref const &Pred, llvm::SmallVectorImpl &IList) const; + bool collectEdges(llvm::function_ref const &Pred, llvm::SmallVectorImpl &IList) const; + using PDGNodeBase::findEdgeTo; + void destroy(); + ~PDGNode() = default; protected: - PDGNode(NodeKind Kind) : mKind(Kind) {} - NodeKind mKind; + PDGNode(NodeKind Kind) : mKind(Kind) {} + NodeKind mKind; }; class SimplePDGNode : public PDGNode { - friend class PDGBuilder; + friend class PDGBuilder; public: - SimplePDGNode(llvm::Instruction &Inst) : PDGNode(NodeKind::SingleInstruction), mInstructions({&Inst}) {} - template - SimplePDGNode(InputIt First, InputIt Last) : PDGNode(NodeKind::SingleInstruction), mInstructions(First, Last) { - if (mInstructions.size()>0) - mKind=NodeKind::MultiInstruction; - } - static bool classof(const PDGNode *Node) { return Node->getKind()==NodeKind::SingleInstruction || - Node->getKind()==NodeKind::MultiInstruction; } - const llvm::SmallVectorImpl &getInstructions() const { - assert(!mInstructions.empty() && "Instruction List is empty."); - return mInstructions; - } - llvm::SmallVectorImpl &getInstructions() { - return const_cast&>(static_cast(this)->getInstructions()); - } - llvm::Instruction *getFirstInstruction() const { return getInstructions().front(); } - llvm::Instruction *getLastInstruction() const { return getInstructions().back(); } - ~SimplePDGNode() = default; + SimplePDGNode(llvm::Instruction &Inst) + :PDGNode(NodeKind::SingleInstruction), mInstructions({&Inst}) {} + template + SimplePDGNode(InputIt First, InputIt Last) + : PDGNode(NodeKind::SingleInstruction), mInstructions(First, Last) { + if (mInstructions.size()>0) + mKind=NodeKind::MultiInstruction; + } + static bool classof(const PDGNode *Node) { + return Node->getKind()==NodeKind::SingleInstruction || + Node->getKind()==NodeKind::MultiInstruction; + } + const llvm::SmallVectorImpl &getInstructions() const { + assert(!mInstructions.empty() && "Instruction List is empty."); + return mInstructions; + } + llvm::SmallVectorImpl &getInstructions() { + return const_cast&>( + static_cast(this)->getInstructions()); + } + llvm::Instruction *getFirstInstruction() const { return getInstructions().front(); } + llvm::Instruction *getLastInstruction() const { return getInstructions().back(); } + ~SimplePDGNode() = default; private: - /// Append the list of instructions in \p Input to this node. - void appendInstructions(const llvm::SmallVectorImpl &Input) { - mKind=mInstructions.size()+Input.size()>1?NodeKind::MultiInstruction:NodeKind::SingleInstruction; - llvm::append_range(mInstructions, Input); - } - void appendInstructions(const SimplePDGNode &Input) { - appendInstructions(Input.getInstructions()); - } - /// List of instructions associated with a single or multi-instruction node. - llvm::SmallVector mInstructions; + /// Append the list of instructions in \p Input to this node. + void appendInstructions(const llvm::SmallVectorImpl &Input) { + mKind=mInstructions.size()+Input.size()>1?NodeKind::MultiInstruction:NodeKind::SingleInstruction; + llvm::append_range(mInstructions, Input); + } + void appendInstructions(const SimplePDGNode &Input) { + appendInstructions(Input.getInstructions()); + } + /// List of instructions associated with a single or multi-instruction node. + llvm::SmallVector mInstructions; }; class PiBlockPDGNode : public PDGNode { public: - template - PiBlockPDGNode(InputIt First, InputIt Last) : PDGNode(NodeKind::PiBlock), mInlinedNodes(First, Last) {} - llvm::SmallVectorImpl &getInlinedNodes() { return mInlinedNodes; } - const llvm::SmallVectorImpl &getInlinedNodes() const { return mInlinedNodes; } - static bool classof(const PDGNode *Node) { return Node->getKind()==NodeKind::PiBlock; } - ~PiBlockPDGNode(); + template + PiBlockPDGNode(InputIt First, InputIt Last) : PDGNode(NodeKind::PiBlock), mInlinedNodes(First, Last) {} + llvm::SmallVectorImpl &getInlinedNodes() { return mInlinedNodes; } + const llvm::SmallVectorImpl &getInlinedNodes() const { return mInlinedNodes; } + static bool classof(const PDGNode *Node) { return Node->getKind()==NodeKind::PiBlock; } + ~PiBlockPDGNode(); private: - llvm::SmallVector mInlinedNodes; + llvm::SmallVector mInlinedNodes; }; class PDGEdge : public PDGEdgeBase { public: - enum class DependenceType { - Data, - Control, - Last=Control - }; - enum class EdgeKind { - RegisterDefUse, - Memory, - MixedData, - Control, - ComplexData, - ComplexControl - }; - PDGEdge(PDGNode &TargetNode, DependenceType DT) : PDGEdgeBase(TargetNode), - mKind(DT==DependenceType::Data?EdgeKind::RegisterDefUse:EdgeKind::Control) {} - EdgeKind getKind() const { return mKind; } - DependenceType getDependenceType() const { return (mKind==EdgeKind::Control || - mKind==EdgeKind::ComplexControl)?DependenceType::Control:DependenceType::Data; } - bool isControl() const { return getDependenceType()==DependenceType::Control; } - bool isData() const { return getDependenceType()==DependenceType::Data; } - void destroy(); - ~PDGEdge() = default; + enum class DependenceType { + Data, + Control, + Last=Control + }; + enum class EdgeKind { + RegisterDefUse, + Memory, + MixedData, + Control, + ComplexData, + ComplexControl + }; + PDGEdge(PDGNode &TargetNode, DependenceType DT) : PDGEdgeBase(TargetNode), + mKind(DT==DependenceType::Data?EdgeKind::RegisterDefUse: + EdgeKind::Control) {} + EdgeKind getKind() const { return mKind; } + DependenceType getDependenceType() const { + return (mKind==EdgeKind::Control || + mKind==EdgeKind::ComplexControl)?DependenceType::Control: + DependenceType::Data; + } + bool isControl() const { + return getDependenceType()==DependenceType::Control; + } + bool isData() const { return getDependenceType()==DependenceType::Data; } + void destroy(); + ~PDGEdge() = default; protected: - PDGEdge(PDGNode &TargetNode, EdgeKind Kind) : PDGEdgeBase(TargetNode), mKind(Kind) {} + PDGEdge(PDGNode &TargetNode, EdgeKind Kind) + : PDGEdgeBase(TargetNode), mKind(Kind) {} private: - EdgeKind mKind; + EdgeKind mKind; }; class MemoryPDGEdge : public PDGEdge { public: - MemoryPDGEdge(PDGNode &TargetNode, llvm::Dependence &Dep, bool HasDefUse) - : PDGEdge(TargetNode, HasDefUse?EdgeKind::MixedData:EdgeKind::Memory), mMemoryDep(Dep) {} - ~MemoryPDGEdge() { delete &mMemoryDep; } - static bool classof(const PDGEdge *Edge) { return Edge->getKind()==EdgeKind::Memory || - Edge->getKind()==EdgeKind::MixedData; } - const llvm::Dependence &getMemoryDep() const { return mMemoryDep; } + using DIDepKind=bcl::TraitDescriptor< + bcl::TraitAlternative>; + // 1. + /*using DIDepT=bcl::tagged_pair< + bcl::tagged, + bcl::tagged>;*/ + // 2. + /*using DIDepT=bcl::tagged_pair< + bcl::tagged, + bcl::tagged>;*/ + // 3. + using DIDepT=std::pair; + + using DIDepStorageT=llvm::SmallVector; + using MemDepHandle=std::variant; + MemoryPDGEdge(PDGNode &TargetNode, llvm::Dependence &Dep, bool HasDefUse) + : PDGEdge(TargetNode, HasDefUse?EdgeKind::MixedData:EdgeKind::Memory), + mMemDep(&Dep) {} + + MemoryPDGEdge(PDGNode &TargetNode, + const llvm::SmallVectorImpl &DIDep, bool HasDefUse) + : PDGEdge(TargetNode, HasDefUse?EdgeKind::MixedData:EdgeKind::Memory) { + mMemDep.emplace(DIDep.begin(), DIDep.end()); + } + MemoryPDGEdge(PDGNode &TargetNode, const MemDepHandle &DepHandle, + bool HasDefUse) + : PDGEdge(TargetNode, HasDefUse?EdgeKind::MixedData:EdgeKind::Memory), + mMemDep(DepHandle) {} + /*bool getDIDeps(llvm::SmallVectorImpl &V) { + if () + }*/ + ~MemoryPDGEdge() { + if (llvm::Dependence **IRDep=std::get_if(&mMemDep)) + delete *IRDep; + } + static bool classof(const PDGEdge *Edge) { return Edge->getKind()==EdgeKind::Memory || + Edge->getKind()==EdgeKind::MixedData; } + const MemDepHandle &getMemoryDep() const { return mMemDep; } private: - llvm::Dependence &mMemoryDep; + MemDepHandle mMemDep; }; class ComplexPDGEdge : public PDGEdge { public: - enum Direction { - Incoming, // Incoming edges to the SCC - Outgoing, // Edges going ot of the SCC - DirectionCount // To make the enum usable as an array index. - }; - struct EdgeHandler { - size_t SrcNOrdinal, TgtNordinal; - PDGEdge &E; - }; - ComplexPDGEdge(PDGNode &Dst, PDGEdge &EToInline, size_t SCCOrdinal, const Direction Dir) - : PDGEdge(Dst, EToInline.getDependenceType()==DependenceType::Control?EdgeKind::ComplexControl:EdgeKind::ComplexData) { - absorbEdge(EToInline, SCCOrdinal, Dir); - } - void absorbEdge(PDGEdge &E, size_t SCCOrdinal, const Direction Dir) { - if (E.getKind()==PDGEdge::EdgeKind::ComplexControl || - E.getKind()==PDGEdge::EdgeKind::ComplexData) { - ComplexPDGEdge &ComplexE=llvm::cast(E); - if (Dir==Incoming) - for (EdgeHandler &EH : ComplexE.mInlinedEdges) - mInlinedEdges.push_back({EH.SrcNOrdinal, SCCOrdinal, EH.E}); - else - for (EdgeHandler &EH : ComplexE.mInlinedEdges) - mInlinedEdges.push_back({SCCOrdinal, EH.TgtNordinal, EH.E}); - ComplexE.mInlinedEdges.clear(); - E.destroy(); - } - else - if (Dir==Incoming) - mInlinedEdges.push_back({0, SCCOrdinal, E}); - else - mInlinedEdges.push_back({SCCOrdinal, 0, E}); - } - static bool classof(const PDGEdge *Edge) { return Edge->getKind()==EdgeKind::ComplexControl || - Edge->getKind()==EdgeKind::ComplexData; } - llvm::SmallVectorImpl &getInlinedEdges() { return mInlinedEdges; } - const llvm::SmallVectorImpl &getInlinedEdges() const { return mInlinedEdges; } - ~ComplexPDGEdge() { - for (EdgeHandler &EH : mInlinedEdges) - EH.E.destroy(); - } + enum Direction { + Incoming, // Incoming edges to the SCC + Outgoing, // Edges going ot of the SCC + DirectionCount // To make the enum usable as an array index. + }; + struct EdgeHandle { + size_t SrcNOrdinal, TgtNordinal; + PDGEdge &E; + }; + ComplexPDGEdge(PDGNode &Dst, PDGEdge &EToInline, size_t SCCOrdinal, const Direction Dir) + : PDGEdge(Dst, EToInline.getDependenceType()==DependenceType::Control?EdgeKind::ComplexControl:EdgeKind::ComplexData) { + absorbEdge(EToInline, SCCOrdinal, Dir); + } + void absorbEdge(PDGEdge &E, size_t SCCOrdinal, const Direction Dir) { + if (E.getKind()==PDGEdge::EdgeKind::ComplexControl || + E.getKind()==PDGEdge::EdgeKind::ComplexData) { + ComplexPDGEdge &ComplexE=llvm::cast(E); + if (Dir==Incoming) + for (EdgeHandle &EH : ComplexE.mInlinedEdges) + mInlinedEdges.push_back({EH.SrcNOrdinal, SCCOrdinal, EH.E}); + else + for (EdgeHandle &EH : ComplexE.mInlinedEdges) + mInlinedEdges.push_back({SCCOrdinal, EH.TgtNordinal, EH.E}); + ComplexE.mInlinedEdges.clear(); + E.destroy(); + } + else + if (Dir==Incoming) + mInlinedEdges.push_back({0, SCCOrdinal, E}); + else + mInlinedEdges.push_back({SCCOrdinal, 0, E}); + } + static bool classof(const PDGEdge *Edge) { return Edge->getKind()==EdgeKind::ComplexControl || + Edge->getKind()==EdgeKind::ComplexData; } + llvm::SmallVectorImpl &getInlinedEdges() { return mInlinedEdges; } + const llvm::SmallVectorImpl &getInlinedEdges() const { return mInlinedEdges; } + ~ComplexPDGEdge() { + for (EdgeHandle &EH : mInlinedEdges) + EH.E.destroy(); + } private: - llvm::SmallVector mInlinedEdges; + llvm::SmallVector mInlinedEdges; }; class ProgramDependencyGraph : public PDGBase { - friend class PDGBuilder; + friend class PDGBuilder; public: - using NodeType=PDGNode; - using EdgeType=PDGEdge; - ProgramDependencyGraph(const llvm::Function &F) : PDGBase(), mF(F), mEntryNode(nullptr) {} - llvm::StringRef getName() const { return mF.getName(); } - PDGNode &getEntryNode() { - assert(mEntryNode); - return *mEntryNode; - } - const PDGNode &getEntryNode() const { - assert(mEntryNode); - return *mEntryNode; - } - bool addEntryNode(PDGNode &EntryNode) { - if (addNode(EntryNode)) { - mEntryNode=&EntryNode; - return true; - } - return false; - } - ~ProgramDependencyGraph() { - for (PDGNode *N : Nodes) { - for (PDGEdge *E : N->getEdges()) - E->destroy(); - N->destroy(); - } - - } + using NodeType=PDGNode; + using EdgeType=PDGEdge; + ProgramDependencyGraph(const llvm::Function &F) : PDGBase(), mF(F), mEntryNode(nullptr) {} + llvm::StringRef getName() const { return mF.getName(); } + PDGNode &getEntryNode() { + assert(mEntryNode); + return *mEntryNode; + } + const PDGNode &getEntryNode() const { + assert(mEntryNode); + return *mEntryNode; + } + bool addEntryNode(PDGNode &EntryNode) { + if (addNode(EntryNode)) { + mEntryNode=&EntryNode; + return true; + } + return false; + } + ~ProgramDependencyGraph() { + for (PDGNode *N : Nodes) { + for (PDGEdge *E : N->getEdges()) + E->destroy(); + N->destroy(); + } + + } private: - const llvm::Function &mF; - PDGNode *mEntryNode; + const llvm::Function &mF; + PDGNode *mEntryNode; }; llvm::raw_ostream &operator<<(llvm::raw_ostream&, const PDGNode&); @@ -360,152 +411,228 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream&, const PDGEdge::EdgeKind); llvm::raw_ostream &operator<<(llvm::raw_ostream&, const ProgramDependencyGraph&); class PDGBuilder { - using MemoryLocationSet=llvm::SmallDenseSet; + using MemoryLocationSet=llvm::SmallDenseSet; public: - PDGBuilder(ProgramDependencyGraph &G, llvm::DependenceInfo &DI, const llvm::Function &F, const AliasTree &AT, - const DIAliasTree &DIAT, const llvm::TargetLibraryInfo &TLI, DIMemoryClientServerInfo &DIMInfo, - bool ShouldSolveReachability=true, bool ShouldSimplify=false, bool ShouldCreatePiBlocks=false) - : mGraph(G), mDI(DI), mF(F), mAT(AT), mDIAT(DIAT), mDIATRel(&const_cast(DIAT)), - mTLI(TLI), mDIMInfo(DIMInfo), mSolvedReachability(ShouldSolveReachability), mSimplified(ShouldSimplify), - mCreatedPiBlocks(ShouldCreatePiBlocks), mBBList(F.size()) { - { - size_t BBIdx=F.size(); - for (auto It=llvm::po_begin(&F); It!=llvm::po_end(&F); ++It) - mBBList[--BBIdx]=*It; - } - if (mDIMInfo.isValid()) - mServerDIATRel=SpanningTreeRelation(mDIMInfo.DIAT); - if (ShouldSolveReachability) - solveReachability(); + PDGBuilder(ProgramDependencyGraph &G, llvm::DependenceInfo &DI, const llvm::Function &F, const AliasTree &AT, + const llvm::TargetLibraryInfo &TLI, DIMemoryClientServerInfo &DIMInfo, + const llvm::LoopInfo &LI, bool ShouldSolveReachability=true, bool ShouldSimplify=false, + bool ShouldCreatePiBlocks=false) + : mGraph(G), mDI(DI), mF(F), mAT(AT), mTLI(TLI), mDIMInfo(DIMInfo), + mLI(LI), mDIATRel(DIMInfo.DIAT), mSolvedReachability(ShouldSolveReachability), + mSimplified(ShouldSimplify), mCreatedPiBlocks(ShouldCreatePiBlocks), + mBBList(F.size()) { + if (mDIMInfo.isValid()) + mServerDIATRel=SpanningTreeRelation(mDIMInfo.DIAT); + { + size_t BBIdx=F.size(); + for (auto It=llvm::po_begin(&F); It!=llvm::po_end(&F); ++It) + mBBList[--BBIdx]=*It; + } + if (ShouldSolveReachability) + solveReachability(); + // New (before adding tsar's traits in graph): + /*const DIDependencInfo &DepInfo=*mDIMInfo.DIDepInfo; + for (auto &DepInfoRecord : DepInfo) { + for (const DIAliasTrait &Trait : DepInfoRecord.second) { + auto NodeIt=mReverseDIDepSet.find(Trait.getNode()); + if (NodeIt!=mReverseDIDepSet.end()) + NodeIt->second.insert(&Trait); + else + mReverseDIDepSet.insert({Trait.getNode(), {&Trait}}); + } + }*/ + // DEBUG (this code demonstrates the absence of causes in DIDependence): + if (!mDIMInfo.isValid()) + return; + // + llvm::DOTFuncInfo DOTCFGInfo(&F); + llvm::dumpDotGraphToFile(&DOTCFGInfo, "ircfg.dot", "control flow graph"); + // + for (auto &DepInfoRecord : *mDIMInfo.DIDepInfo) { + for (const DIAliasTrait &AT : DepInfoRecord.second) { + for (const DIMemoryTraitRef &MTRef : AT) { + auto PrintDistanceVector=[](const trait::DIDependence *Dep) -> std::string { + std::string Result; + llvm::raw_string_ostream OS(Result); + if (Dep->getKnownLevel()==0) + return Result; + OS<<"<"; + if (Dep->getDistance(0).first==Dep->getDistance(0).second) + OS<getDistance(0).first; + else + OS<<"("<getDistance(0).first<<", "<getDistance(0).second<<")"; + for (int Level=1; LevelgetKnownLevel(); ++Level) + if (Dep->getDistance(Level).first==Dep->getDistance(Level).second) + OS<<", "<getDistance(Level).first; + else + OS<<", ("<getDistance(Level).first<<", "<getDistance(Level).second<<")"; + OS<<">"; + return Result; + }; + trait::DIDependence *DIFlow=MTRef->get(), + *DIAnti=MTRef->get(), + *DIOutput=MTRef->get(), *Actual; + if (DIFlow) { + std::cout<<" FLOW, causes size - "<getCauses().size() + <<", dist-vec - "; + std::cout<getCauses().size() + <<", dist-vec - "; + std::cout<getCauses().size() + <<", dist-vec - "; + std::cout< { - size_t NodesCount; - ReachabilityMatrix() = default; - ReachabilityMatrix(size_t _NodesCount) : std::vector(_NodesCount*_NodesCount, false), NodesCount(_NodesCount) {} - std::vector::reference operator()(size_t I, size_t J) { - return this->operator[](I*NodesCount+J); - } - std::vector::const_reference operator()(size_t I, size_t J) const { - return this->operator[](I*NodesCount+J); - } - }; - - bool isReachable(const llvm::BasicBlock &From, const llvm::BasicBlock &To) { - return mReachabilityMatrix(mBBToInd[&From], mBBToInd[&To]); - } - - void solveReachability() { - mReachabilityMatrix=ReachabilityMatrix(mF.size()); - size_t Ind=0; - mBBToInd.init(mF.size()); - for (auto &BB : mF) { - // mReachabilityMatrix(Ind, Ind)=true; - mBBToInd[&BB]=Ind++; - } - for (auto &BB : mF) - for (auto SuccBB : llvm::successors(&BB)) - mReachabilityMatrix(mBBToInd[&BB], mBBToInd[SuccBB])=true; - for (size_t K=0; K(I)); - mGraph.addNode(*NewNode); - return *NewNode; + struct ReachabilityMatrix : public std::vector { + size_t NodesCount; + ReachabilityMatrix() = default; + ReachabilityMatrix(size_t _NodesCount) : std::vector(_NodesCount*_NodesCount, false), NodesCount(_NodesCount) {} + std::vector::reference operator()(size_t I, size_t J) { + return this->operator[](I*NodesCount+J); + } + std::vector::const_reference operator()(size_t I, size_t J) const { + return this->operator[](I*NodesCount+J); } - PDGEdge &createDefUseEdge(PDGNode &Src, PDGNode &Tgt) { - PDGEdge *NewEdge=new PDGEdge(Tgt, PDGEdge::DependenceType::Data); - mGraph.connect(Src, Tgt, *NewEdge); - return *NewEdge; + }; + + bool isReachable(const llvm::BasicBlock &From, const llvm::BasicBlock &To) { + return mReachabilityMatrix(mBBToInd[&From], mBBToInd[&To]); + } + + void solveReachability() { + mReachabilityMatrix=ReachabilityMatrix(mF.size()); + size_t Ind=0; + mBBToInd.init(mF.size()); + for (auto &BB : mF) { + // mReachabilityMatrix(Ind, Ind)=true; + mBBToInd[&BB]=Ind++; } - bool areNodesMergeable(const PDGNode &Src, const PDGNode &Tgt) const { - using namespace llvm; - // Only merge two nodes if they are both simple nodes and the consecutive - // instructions after merging belong to the same BB. - const SimplePDGNode *SimpleSrc=dyn_cast(&Src); - const SimplePDGNode *SimpleTgt=dyn_cast(&Tgt); - if (!SimpleSrc || !SimpleTgt) - return false; - return true; - //return SimpleSrc->getLastInstruction()->getParent()==SimpleTgt->getFirstInstruction()->getParent(); - } - void mergeNodes(PDGNode &AbsorbN, PDGNode &OutgoingN) { - using namespace llvm; - PDGEdge &EdgeToFold=AbsorbN.back(); - assert(AbsorbN.getEdges().size()==1 && EdgeToFold.getTargetNode()==OutgoingN && "Expected A to have a single edge to B."); - assert(isa(&AbsorbN) && isa(&OutgoingN) && "Expected simple nodes"); - // Copy instructions from B to the end of A. - cast(&AbsorbN)->appendInstructions(*cast(&OutgoingN)); - // Move to A any outgoing edges from B. - for (PDGEdge *OutgoingE : OutgoingN) - mGraph.connect(AbsorbN, OutgoingE->getTargetNode(), *OutgoingE); - AbsorbN.removeEdge(EdgeToFold); - EdgeToFold.destroy(); - mGraph.removeNode(OutgoingN); - OutgoingN.destroy(); - } - PiBlockPDGNode &createPiBlock(const llvm::SmallVectorImpl &NodeList) { - PiBlockPDGNode *Res=new PiBlockPDGNode(NodeList.begin(), NodeList.end()); - mGraph.addNode(*Res); - return *Res; - } - size_t getOrdinal(const llvm::Instruction &I) { - assert(mInstOrdinalMap.find(&I) != mInstOrdinalMap.end() && - "No ordinal computed for this instruction."); - return mInstOrdinalMap[&I]; - } - size_t getOrdinal(PDGNode &N) { - assert(mNodeOrdinalMap.find(&N)!=mNodeOrdinalMap.end() && - "No ordinal computed for this node."); - return mNodeOrdinalMap[&N]; - } - llvm::DenseMap mIMap; - llvm::DenseMap mInstOrdinalMap; - llvm::DenseMap mNodeOrdinalMap; - llvm::DependenceInfo &mDI; - llvm::SmallVector mBBList; - // - - ProgramDependencyGraph &mGraph; - const llvm::Function &mF; - const AliasTree &mAT; - const DIAliasTree &mDIAT; - SpanningTreeRelation mDIATRel; - const llvm::TargetLibraryInfo &mTLI; - bool mSolvedReachability, mSimplified, mCreatedPiBlocks; - ReachabilityMatrix mReachabilityMatrix; - llvm::DenseMap mBBToInd; - DIMemoryClientServerInfo &mDIMInfo; - std::optional> mServerDIATRel; + for (auto &BB : mF) + for (auto SuccBB : llvm::successors(&BB)) + mReachabilityMatrix(mBBToInd[&BB], mBBToInd[SuccBB])=true; + for (size_t K=0; K(I)); + mGraph.addNode(*NewNode); + return *NewNode; + } + PDGEdge &createDefUseEdge(PDGNode &Src, PDGNode &Tgt) { + PDGEdge *NewEdge=new PDGEdge(Tgt, PDGEdge::DependenceType::Data); + mGraph.connect(Src, Tgt, *NewEdge); + return *NewEdge; + } + bool areNodesMergeable(const PDGNode &Src, const PDGNode &Tgt) const { + using namespace llvm; + // Only merge two nodes if they are both simple nodes and the consecutive + // instructions after merging belong to the same BB. + const SimplePDGNode *SimpleSrc=dyn_cast(&Src); + const SimplePDGNode *SimpleTgt=dyn_cast(&Tgt); + if (!SimpleSrc || !SimpleTgt) + return false; + return true; + //return SimpleSrc->getLastInstruction()->getParent()==SimpleTgt->getFirstInstruction()->getParent(); + } + void mergeNodes(PDGNode &AbsorbN, PDGNode &OutgoingN) { + using namespace llvm; + PDGEdge &EdgeToFold=AbsorbN.back(); + assert(AbsorbN.getEdges().size()==1 && EdgeToFold.getTargetNode()==OutgoingN && "Expected A to have a single edge to B."); + assert(isa(&AbsorbN) && isa(&OutgoingN) && "Expected simple nodes"); + // Copy instructions from B to the end of A. + cast(&AbsorbN)->appendInstructions(*cast(&OutgoingN)); + // Move to A any outgoing edges from B. + for (PDGEdge *OutgoingE : OutgoingN) + mGraph.connect(AbsorbN, OutgoingE->getTargetNode(), *OutgoingE); + AbsorbN.removeEdge(EdgeToFold); + EdgeToFold.destroy(); + mGraph.removeNode(OutgoingN); + OutgoingN.destroy(); + } + PiBlockPDGNode &createPiBlock(const llvm::SmallVectorImpl &NodeList) { + PiBlockPDGNode *Res=new PiBlockPDGNode(NodeList.begin(), NodeList.end()); + mGraph.addNode(*Res); + return *Res; + } + size_t getOrdinal(const llvm::Instruction &I) { + assert(mInstOrdinalMap.find(&I) != mInstOrdinalMap.end() && + "No ordinal computed for this instruction."); + return mInstOrdinalMap[&I]; + } + size_t getOrdinal(PDGNode &N) { + assert(mNodeOrdinalMap.find(&N)!=mNodeOrdinalMap.end() && + "No ordinal computed for this node."); + return mNodeOrdinalMap[&N]; + } + // + llvm::DenseMap mIMap; + llvm::DenseMap mInstOrdinalMap; + llvm::DenseMap mNodeOrdinalMap; + llvm::DependenceInfo &mDI; + llvm::SmallVector mBBList; + // + + // New (before adding tsar's traits in graph): + const llvm::LoopInfo &mLI; + // llvm::DenseMap> mReverseDIDepSet; + + ProgramDependencyGraph &mGraph; + const llvm::Function &mF; + const AliasTree &mAT; + const llvm::TargetLibraryInfo &mTLI; + bool mSolvedReachability, mSimplified, mCreatedPiBlocks; + ReachabilityMatrix mReachabilityMatrix; + llvm::DenseMap mBBToInd; + DIMemoryClientServerInfo &mDIMInfo; + std::optional> mServerDIATRel; + SpanningTreeRelation mDIATRel; }; } //namespace tsar @@ -513,198 +640,198 @@ namespace llvm { class ProgramDependencyGraphPass : public FunctionPass, private bcl::Uncopyable { public: - static char ID; - ProgramDependencyGraphPass() : FunctionPass(ID), mPDGBuilder(nullptr), mPDG(nullptr) { - initializeProgramDependencyGraphPassPass(*PassRegistry::getPassRegistry()); + static char ID; + ProgramDependencyGraphPass() : FunctionPass(ID), mPDGBuilder(nullptr), mPDG(nullptr) { + initializeProgramDependencyGraphPassPass(*PassRegistry::getPassRegistry()); + } + bool runOnFunction(Function &F) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + void releaseMemory() override { + if (mPDGBuilder) { + delete mPDGBuilder; + mPDGBuilder=nullptr; } - bool runOnFunction(Function &F) override; - void getAnalysisUsage(AnalysisUsage &AU) const override; - void releaseMemory() override { - if (mPDGBuilder) { - delete mPDGBuilder; - mPDGBuilder=nullptr; - } - if (mPDG) { - delete mPDG; - mPDG=nullptr; - } - } - inline tsar::ProgramDependencyGraph &getPDG() { return *mPDG; } - inline const tsar::ProgramDependencyGraph &getPDG() const { return *mPDG; } + if (mPDG) { + delete mPDG; + mPDG=nullptr; + } + } + inline tsar::ProgramDependencyGraph &getPDG() { return *mPDG; } + inline const tsar::ProgramDependencyGraph &getPDG() const { return *mPDG; } private: - tsar::PDGBuilder *mPDGBuilder; - tsar::ProgramDependencyGraph *mPDG; + tsar::PDGBuilder *mPDGBuilder; + tsar::ProgramDependencyGraph *mPDG; }; template struct GraphTraits*> { - using NodeRef=tsar::CDGNode*; - static tsar::CDGNode *CDGGetTargetNode(tsar::CDGEdge *E) { - return &E->getTargetNode(); - } - using ChildIteratorType=mapped_iterator::iterator, - decltype(&CDGGetTargetNode)>; - using ChildEdgeIteratorType=typename tsar::CDGNode::iterator; - static NodeRef getEntryNode(NodeRef N) { return N; } - static ChildIteratorType child_begin(NodeRef N) { - return ChildIteratorType(N->begin(), &CDGGetTargetNode); - } - static ChildIteratorType child_end(NodeRef N) { - return ChildIteratorType(N->end(), &CDGGetTargetNode); - } - static ChildEdgeIteratorType child_edge_begin(NodeRef N) { - return N->begin(); - } - static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } + using NodeRef=tsar::CDGNode*; + static tsar::CDGNode *CDGGetTargetNode(tsar::CDGEdge *E) { + return &E->getTargetNode(); + } + using ChildIteratorType=mapped_iterator::iterator, + decltype(&CDGGetTargetNode)>; + using ChildEdgeIteratorType=typename tsar::CDGNode::iterator; + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { + return ChildIteratorType(N->begin(), &CDGGetTargetNode); + } + static ChildIteratorType child_end(NodeRef N) { + return ChildIteratorType(N->end(), &CDGGetTargetNode); + } + static ChildEdgeIteratorType child_edge_begin(NodeRef N) { + return N->begin(); + } + static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } }; template struct GraphTraits*> : - public GraphTraits*> { - using nodes_iterator=typename tsar::ControlDependenceGraph::iterator; - static typename llvm::GraphTraits*>::NodeRef getEntryNode(tsar::ControlDependenceGraph *Graph) { - return Graph->getEntryNode(); - } - static nodes_iterator nodes_begin(tsar::ControlDependenceGraph *Graph) { - return Graph->begin(); - } - static nodes_iterator nodes_end(tsar::ControlDependenceGraph *Graph) { - return Graph->end(); - } - using EdgeRef=tsar::CDGEdge*; - static typename llvm::GraphTraits*>::NodeRef edge_dest(EdgeRef E) { return &E->getTargetNode(); } - static unsigned size(tsar::ControlDependenceGraph *Graph) { return Graph->size(); } + public GraphTraits*> { + using nodes_iterator=typename tsar::ControlDependenceGraph::iterator; + static typename llvm::GraphTraits*>::NodeRef getEntryNode(tsar::ControlDependenceGraph *Graph) { + return Graph->getEntryNode(); + } + static nodes_iterator nodes_begin(tsar::ControlDependenceGraph *Graph) { + return Graph->begin(); + } + static nodes_iterator nodes_end(tsar::ControlDependenceGraph *Graph) { + return Graph->end(); + } + using EdgeRef=tsar::CDGEdge*; + static typename llvm::GraphTraits*>::NodeRef edge_dest(EdgeRef E) { return &E->getTargetNode(); } + static unsigned size(tsar::ControlDependenceGraph *Graph) { return Graph->size(); } }; template struct DOTGraphTraits*> : - public DOTGraphTraits { + public DOTGraphTraits { private: - using GTInstanced=GraphTraits*>; + using GTInstanced=GraphTraits*>; public: - DOTGraphTraits(bool IsSimple=false) : DOTGraphTraits(IsSimple) {} - static std::string getGraphName(const tsar::ControlDependenceGraph *Graph) { - return "Control Dependence Graph"; - } - std::string getNodeLabel(const tsar::CDGNode *Node, - const tsar::ControlDependenceGraph *Graph) { - if (auto *DefNode=dyn_cast>(Node)) - return DOTGraphTraits::getNodeLabel(DefNode->getBlock(), Graph->getCFG()); - else - return "Entry"; - } - std::string getNodeAttributes(const tsar::CDGNode *Node, - tsar::ControlDependenceGraph *Graph) { - if (auto *DefNode=dyn_cast>(Node)) - return DOTGraphTraits::getNodeAttributes(DefNode->getBlock(), Graph->getCFG()); - else - return ""; - } - std::string getEdgeSourceLabel(const tsar::CDGNode *Node, - typename GraphTraits*>::ChildIteratorType It) { return ""; } - std::string getEdgeAttributes(const tsar::CDGNode *Node, - typename GTInstanced::ChildIteratorType EdgeIt, - tsar::ControlDependenceGraph *Graph) { - //return DOTGraphTraits::getEdgeAttributes(Node->getBlock(), EdgeIt, Graph->getCFG()); - return ""; - } - bool isNodeHidden(const tsar::CDGNode *Node, - tsar::ControlDependenceGraph*) { - return false; - } + DOTGraphTraits(bool IsSimple=false) : DOTGraphTraits(IsSimple) {} + static std::string getGraphName(const tsar::ControlDependenceGraph *Graph) { + return "Control Dependence Graph"; + } + std::string getNodeLabel(const tsar::CDGNode *Node, + const tsar::ControlDependenceGraph *Graph) { + if (auto *DefNode=dyn_cast>(Node)) + return DOTGraphTraits::getNodeLabel(DefNode->getBlock(), Graph->getCFG()); + else + return "Entry"; + } + std::string getNodeAttributes(const tsar::CDGNode *Node, + tsar::ControlDependenceGraph *Graph) { + if (auto *DefNode=dyn_cast>(Node)) + return DOTGraphTraits::getNodeAttributes(DefNode->getBlock(), Graph->getCFG()); + else + return ""; + } + std::string getEdgeSourceLabel(const tsar::CDGNode *Node, + typename GraphTraits*>::ChildIteratorType It) { return ""; } + std::string getEdgeAttributes(const tsar::CDGNode *Node, + typename GTInstanced::ChildIteratorType EdgeIt, + tsar::ControlDependenceGraph *Graph) { + //return DOTGraphTraits::getEdgeAttributes(Node->getBlock(), EdgeIt, Graph->getCFG()); + return ""; + } + bool isNodeHidden(const tsar::CDGNode *Node, + tsar::ControlDependenceGraph*) { + return false; + } }; template <> struct GraphTraits { - using NodeRef=tsar::PDGNode *; - static tsar::PDGNode *PDGGetTargetNode(DGEdge *P) { - return &P->getTargetNode(); - } - // Provide a mapped iterator so that the GraphTrait-based implementations can - // find the target nodes without having to explicitly go through the edges. - using ChildIteratorType = - mapped_iterator; - using ChildEdgeIteratorType=tsar::PDGNode::iterator; - static NodeRef getEntryNode(NodeRef N) { return N; } - static ChildIteratorType child_begin(NodeRef N) { - return ChildIteratorType(N->begin(), &PDGGetTargetNode); - } - static ChildIteratorType child_end(NodeRef N) { - return ChildIteratorType(N->end(), &PDGGetTargetNode); - } - static ChildEdgeIteratorType child_edge_begin(NodeRef N) { - return N->begin(); - } - static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } + using NodeRef=tsar::PDGNode *; + static tsar::PDGNode *PDGGetTargetNode(DGEdge *P) { + return &P->getTargetNode(); + } + // Provide a mapped iterator so that the GraphTrait-based implementations can + // find the target nodes without having to explicitly go through the edges. + using ChildIteratorType = + mapped_iterator; + using ChildEdgeIteratorType=tsar::PDGNode::iterator; + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { + return ChildIteratorType(N->begin(), &PDGGetTargetNode); + } + static ChildIteratorType child_end(NodeRef N) { + return ChildIteratorType(N->end(), &PDGGetTargetNode); + } + static ChildEdgeIteratorType child_edge_begin(NodeRef N) { + return N->begin(); + } + static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } }; template <> struct GraphTraits : public GraphTraits { - using nodes_iterator = tsar::ProgramDependencyGraph::iterator; - static NodeRef getEntryNode(tsar::ProgramDependencyGraph *DG) { - return &DG->getEntryNode(); - } - static nodes_iterator nodes_begin(tsar::ProgramDependencyGraph *DG) { - return DG->begin(); - } - static nodes_iterator nodes_end(tsar::ProgramDependencyGraph *DG) { return DG->end(); } + using nodes_iterator = tsar::ProgramDependencyGraph::iterator; + static NodeRef getEntryNode(tsar::ProgramDependencyGraph *DG) { + return &DG->getEntryNode(); + } + static nodes_iterator nodes_begin(tsar::ProgramDependencyGraph *DG) { + return DG->begin(); + } + static nodes_iterator nodes_end(tsar::ProgramDependencyGraph *DG) { return DG->end(); } }; template <> struct GraphTraits { - using NodeRef=const tsar::PDGNode *; - static const tsar::PDGNode *PDGGetTargetNode(const DGEdge *P) { - return &P->getTargetNode(); - } - using ChildIteratorType = - mapped_iterator; - using ChildEdgeIteratorType = tsar::PDGNode::const_iterator; - static NodeRef getEntryNode(NodeRef N) { return N; } - static ChildIteratorType child_begin(NodeRef N) { - return ChildIteratorType(N->begin(), &PDGGetTargetNode); - } - static ChildIteratorType child_end(NodeRef N) { - return ChildIteratorType(N->end(), &PDGGetTargetNode); - } - static ChildEdgeIteratorType child_edge_begin(NodeRef N) { - return N->begin(); - } - static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } + using NodeRef=const tsar::PDGNode *; + static const tsar::PDGNode *PDGGetTargetNode(const DGEdge *P) { + return &P->getTargetNode(); + } + using ChildIteratorType = + mapped_iterator; + using ChildEdgeIteratorType = tsar::PDGNode::const_iterator; + static NodeRef getEntryNode(NodeRef N) { return N; } + static ChildIteratorType child_begin(NodeRef N) { + return ChildIteratorType(N->begin(), &PDGGetTargetNode); + } + static ChildIteratorType child_end(NodeRef N) { + return ChildIteratorType(N->end(), &PDGGetTargetNode); + } + static ChildEdgeIteratorType child_edge_begin(NodeRef N) { + return N->begin(); + } + static ChildEdgeIteratorType child_edge_end(NodeRef N) { return N->end(); } }; template <> struct GraphTraits - : public GraphTraits { - using nodes_iterator=tsar::ProgramDependencyGraph::const_iterator; - static NodeRef getEntryNode(const tsar::ProgramDependencyGraph *DG) { - return &DG->getEntryNode(); - } - static nodes_iterator nodes_begin(const tsar::ProgramDependencyGraph *DG) { - return DG->begin(); - } - static nodes_iterator nodes_end(const tsar::ProgramDependencyGraph *DG) { - return DG->end(); - } + : public GraphTraits { + using nodes_iterator=tsar::ProgramDependencyGraph::const_iterator; + static NodeRef getEntryNode(const tsar::ProgramDependencyGraph *DG) { + return &DG->getEntryNode(); + } + static nodes_iterator nodes_begin(const tsar::ProgramDependencyGraph *DG) { + return DG->begin(); + } + static nodes_iterator nodes_end(const tsar::ProgramDependencyGraph *DG) { + return DG->end(); + } }; template <> struct DOTGraphTraits - : public DefaultDOTGraphTraits { - DOTGraphTraits(bool IsSimple=false) : DefaultDOTGraphTraits(IsSimple) {} - static std::string getGraphName(const tsar::ProgramDependencyGraph *G) { - assert(G && "expected a valid pointer to the graph."); - return "PDG for '"+std::string(G->getName())+"'"; - } - std::string getNodeLabel(const tsar::PDGNode *Node, const tsar::ProgramDependencyGraph *Graph); - std::string getEdgeAttributes(const tsar::PDGNode *Node, - GraphTraits::ChildIteratorType I, const tsar::ProgramDependencyGraph *G); - static bool isNodeHidden(const tsar::PDGNode *Node, const tsar::ProgramDependencyGraph *G); + : public DefaultDOTGraphTraits { + DOTGraphTraits(bool IsSimple=false) : DefaultDOTGraphTraits(IsSimple) {} + static std::string getGraphName(const tsar::ProgramDependencyGraph *G) { + assert(G && "expected a valid pointer to the graph."); + return "PDG for '"+std::string(G->getName())+"'"; + } + std::string getNodeLabel(const tsar::PDGNode *Node, const tsar::ProgramDependencyGraph *Graph); + std::string getEdgeAttributes(const tsar::PDGNode *Node, + GraphTraits::ChildIteratorType I, const tsar::ProgramDependencyGraph *G); + static bool isNodeHidden(const tsar::PDGNode *Node, const tsar::ProgramDependencyGraph *G); private: - static std::string getSimpleNodeLabel(const tsar::PDGNode *Node, - const tsar::ProgramDependencyGraph *G); - static std::string getVerboseNodeLabel(const tsar::PDGNode *Node, - const tsar::ProgramDependencyGraph *G); - static std::string getVerboseEdgeAttributes(const tsar::PDGNode *Src, - const tsar::PDGEdge *Edge, const tsar::ProgramDependencyGraph *G); - static std::string getEdgeStyle(const tsar::PDGEdge*); + static std::string getSimpleNodeLabel(const tsar::PDGNode *Node, + const tsar::ProgramDependencyGraph *G); + static std::string getVerboseNodeLabel(const tsar::PDGNode *Node, + const tsar::ProgramDependencyGraph *G); + static std::string getVerboseEdgeAttributes(const tsar::PDGNode *Src, + const tsar::PDGEdge *Edge, const tsar::ProgramDependencyGraph *G); + static std::string getEdgeStyle(const tsar::PDGEdge*); }; using PDGDotGraphTraits=DOTGraphTraits; diff --git a/lib/Analysis/PDG.cpp b/lib/Analysis/PDG.cpp index f7f23a64..e9021870 100644 --- a/lib/Analysis/PDG.cpp +++ b/lib/Analysis/PDG.cpp @@ -7,6 +7,12 @@ #include #include +// New (before adding tsar's traits in graph): +#include +// ??? +#include +// + using namespace tsar; using namespace llvm; using namespace std; @@ -22,948 +28,1224 @@ STATISTIC(TotalPiBlockNodes, "Number of pi-block nodes created."); STATISTIC(TotalConfusedEdges, "Number of confused memory dependencies between two nodes."); STATISTIC(TotalEdgeReversals, "Number of times the source and sink of dependence was reversed to expose cycles in the graph."); +using PDG=ProgramDependencyGraph; using InstructionListType=SmallVector; namespace llvm { template<> struct DOTGraphTraits - : public DOTGraphTraits { - DOTGraphTraits(bool isSimple=false) : DOTGraphTraits(isSimple) {} - string getNodeLabel(const BasicBlock *Node, Function*) { - return DOTGraphTraits::getNodeLabel(Node, nullptr); - } - string getNodeAttributes(const BasicBlock *Node, Function *F) { - DOTFuncInfo DOTInfo(F); - return DOTGraphTraits::getNodeAttributes(Node, &DOTInfo); - } - string getEdgeAttributes(const BasicBlock *Node, - const_succ_iterator EdgeIt, Function *F) { - DOTFuncInfo DOTInfo(F); - return DOTGraphTraits::getEdgeAttributes(Node, EdgeIt, &DOTInfo); - } - bool isNodeHidden(const BasicBlock *Node, const Function *F) { - DOTFuncInfo DOTInfo(F); - return DOTGraphTraits::isNodeHidden(Node, &DOTInfo); - } + : public DOTGraphTraits { + DOTGraphTraits(bool isSimple=false) : DOTGraphTraits(isSimple) {} + string getNodeLabel(const BasicBlock *Node, Function*) { + return DOTGraphTraits::getNodeLabel(Node, nullptr); + } + string getNodeAttributes(const BasicBlock *Node, Function *F) { + DOTFuncInfo DOTInfo(F); + return DOTGraphTraits::getNodeAttributes(Node, &DOTInfo); + } + string getEdgeAttributes(const BasicBlock *Node, + const_succ_iterator EdgeIt, Function *F) { + DOTFuncInfo DOTInfo(F); + return DOTGraphTraits::getEdgeAttributes(Node, EdgeIt, + &DOTInfo); + } + bool isNodeHidden(const BasicBlock *Node, const Function *F) { + DOTFuncInfo DOTInfo(F); + return DOTGraphTraits::isNodeHidden(Node, &DOTInfo); + } }; template<> struct GraphTraits*> - : public DomTreeGraphTraitsBase, - DomTreeNodeBase::const_iterator> {}; + : public DomTreeGraphTraitsBase, + DomTreeNodeBase::const_iterator> {}; template<> struct GraphTraits*> - : public DomTreeGraphTraitsBase, - DomTreeNodeBase::const_iterator> {}; + : public DomTreeGraphTraitsBase, + DomTreeNodeBase::const_iterator> {}; template struct GraphTraits*> - : public GraphTraits*> { + : public GraphTraits*> { private: - using BaseGT=GraphTraits*>; + using BaseGT=GraphTraits*>; public: - static typename BaseGT::NodeRef getEntryNode(PostDomTreeBase *PDT) { - return PDT->getRootNode(); - } - static typename BaseGT::nodes_iterator nodes_begin(PostDomTreeBase *PDT) { - return df_begin(getEntryNode(PDT)); - } - static typename BaseGT::nodes_iterator nodes_end(PostDomTreeBase *PDT) { - return df_end(getEntryNode(PDT)); - } + static typename BaseGT::NodeRef getEntryNode( + PostDomTreeBase *PDT) { + return PDT->getRootNode(); + } + static typename BaseGT::nodes_iterator nodes_begin( + PostDomTreeBase *PDT) { + return df_begin(getEntryNode(PDT)); + } + static typename BaseGT::nodes_iterator nodes_end( + PostDomTreeBase *PDT) { + return df_end(getEntryNode(PDT)); + } }; template struct DOTGraphTraits*> - : public DOTGraphTraits::ParentPtr> { + : public DOTGraphTraits:: + ParentPtr> { private: - using BaseDOTGT=DOTGraphTraits::ParentPtr>; + using BaseDOTGT=DOTGraphTraits:: + ParentPtr>; public: - DOTGraphTraits(bool IsSimple=false) : BaseDOTGT(IsSimple) {} - static std::string getGraphName(const PostDomTreeBase *Tree) { - return "Post-Dominator Tree"; - } - std::string getNodeLabel(DomTreeNodeBase *Node, - PostDomTreeBase *Tree) { - if (Tree->isVirtualRoot(Node)) - return "Virtual Root"; - else - return BaseDOTGT::getNodeLabel(Node->getBlock(), Node->getBlock()->getParent()); - - } - std::string getEdgeSourceLabel(DomTreeNodeBase *Node, - typename GraphTraits*>::ChildIteratorType It) { return ""; } - static bool isNodeHidden(DomTreeNodeBase *Node, - PostDomTreeBase *Tree) { - return false; - } - std::string getNodeAttributes(DomTreeNodeBase *Node, - PostDomTreeBase *Tree) { - if (Tree->isVirtualRoot(Node)) - return ""; - else - return BaseDOTGT::getNodeAttributes(Node->getBlock(), Node->getBlock()->getParent()); - } - std::string getEdgeAttributes(DomTreeNodeBase*, - typename GraphTraits*>::ChildIteratorType, - PostDomTreeBase*) { - return ""; - } + DOTGraphTraits(bool IsSimple=false) : BaseDOTGT(IsSimple) {} + static std::string getGraphName(const PostDomTreeBase *Tree) { + return "Post-Dominator Tree"; + } + std::string getNodeLabel(DomTreeNodeBase *Node, + PostDomTreeBase *Tree) { + if (Tree->isVirtualRoot(Node)) + return "Virtual Root"; + else + return BaseDOTGT::getNodeLabel(Node->getBlock(), Node->getBlock()-> + getParent()); + + } + std::string getEdgeSourceLabel(DomTreeNodeBase *Node, + typename GraphTraits*>:: + ChildIteratorType It) { return ""; } + static bool isNodeHidden(DomTreeNodeBase *Node, + PostDomTreeBase *Tree) { + return false; + } + std::string getNodeAttributes(DomTreeNodeBase *Node, + PostDomTreeBase *Tree) { + if (Tree->isVirtualRoot(Node)) + return ""; + else + return BaseDOTGT::getNodeAttributes(Node->getBlock(), Node->getBlock()-> + getParent()); + } + std::string getEdgeAttributes(DomTreeNodeBase*, + typename GraphTraits*>::ChildIteratorType, + PostDomTreeBase*) { + return ""; + } }; }; //namespace llvm namespace { template void addToMap(map &Map, KeyT Key, ValueT Value) { - auto It=Map.find(Key); - if (It!=Map.end()) - Map[Key].insert(Value); - else - Map.insert({Key, {Value}}); + auto It=Map.find(Key); + if (It!=Map.end()) + Map[Key].insert(Value); + else + Map.insert({Key, {Value}}); } template bool hasEdgesTo(NodeType *SourceN, NodeType *TargetN) { - for (auto ChildNodeIt=GraphTraits::child_begin(SourceN); - ChildNodeIt!=GraphTraits::child_end(SourceN); ++ChildNodeIt) - if (*ChildNodeIt==TargetN) - return true; - return false; + for (auto ChildNodeIt=GraphTraits::child_begin(SourceN); + ChildNodeIt!=GraphTraits::child_end(SourceN); ++ChildNodeIt) + if (*ChildNodeIt==TargetN) + return true; + return false; } }; //anonymous namespace template inline void CDGBuilder::processControlDependence() { - map> DependenceInfo; - for (auto NIt=GraphTraits::nodes_begin(mCFG); NIt!=GraphTraits::nodes_end(mCFG); ++NIt) - mCDG->emplaceNode(*NIt); - for (auto SourceNodeIt=++df_begin(mPDT.getRootNode()); SourceNodeIt!=df_end(mPDT.getRootNode()); ++SourceNodeIt) { - if (SourceNodeIt->getBlock()==GraphTraits::getEntryNode(mCFG)) - for (unsigned I=SourceNodeIt.getPathLength()-1; I>0; --I) - addToMap(DependenceInfo, mCDG->getEntryNode(), SourceNodeIt.getPath(I)->getBlock()); - for (auto TargetNodeIt=++df_begin(SourceNodeIt->getIDom()); TargetNodeIt!=df_end(SourceNodeIt->getIDom()); ++TargetNodeIt) - if (hasEdgesTo(SourceNodeIt->getBlock(), TargetNodeIt->getBlock())) - for (unsigned I=TargetNodeIt.getPathLength()-1; I>0; --I) - addToMap(DependenceInfo, mCDG->getNode(SourceNodeIt->getBlock()), TargetNodeIt.getPath(I)->getBlock()); - } - for (auto DIIt : DependenceInfo) - for (auto TargetNodeIt : DIIt.second) - mCDG->bindNodes(*DIIt.first, *mCDG->getNode(TargetNodeIt)); + map> DepInfo; + for (auto NIt=GraphTraits::nodes_begin(mCFG); NIt!= + GraphTraits::nodes_end(mCFG); ++NIt) + mCDG->emplaceNode(*NIt); + for (auto SrcNIt=++df_begin(mPDT.getRootNode()); SrcNIt!= + df_end(mPDT.getRootNode()); ++SrcNIt) { + if (SrcNIt->getBlock()==GraphTraits::getEntryNode(mCFG)) + for (unsigned I=SrcNIt.getPathLength()-1; I>0; --I) + addToMap(DepInfo, mCDG->getEntryNode(), SrcNIt.getPath(I)->getBlock()); + for (auto TgtNIt=++df_begin(SrcNIt->getIDom()); + TgtNIt!=df_end(SrcNIt->getIDom()); ++TgtNIt) + if (hasEdgesTo(SrcNIt->getBlock(), TgtNIt->getBlock())) + for (unsigned I=TgtNIt.getPathLength()-1; I>0; --I) + addToMap(DepInfo, mCDG->getNode(SrcNIt->getBlock()), + TgtNIt.getPath(I)->getBlock()); + } + for (auto DIIt : DepInfo) + for (auto TgtNIt : DIIt.second) + mCDG->bindNodes(*DIIt.first, *mCDG->getNode(TgtNIt)); } template CDGType *CDGBuilder::populate(CFGType &CFG) { - mCFG=&CFG; - mCDG=new CDGType(string(CFG.getName()), &CFG); - mPDT=PostDomTreeBase(); - mPDT.recalculate(*mCFG); - /*May be useful*/ - //dumpDotGraphToFile(&mPDT, "post-dom-tree.dot", "post-dom-tree"); - /**/ - processControlDependence(); - return mCDG; -} - -bool PDGNode::collectInstructions(function_ref const &Pred, SmallVectorImpl &IList) const { - assert(IList.empty() && "Expected the IList to be empty on entry."); - if (isa(this)) { - for (Instruction *I : cast(this)->getInstructions()) - if (Pred(I)) - IList.push_back(I); + mCFG=&CFG; + mCDG=new CDGType(string(CFG.getName()), &CFG); + mPDT=PostDomTreeBase(); + mPDT.recalculate(*mCFG); + /*May be useful*/ + //dumpDotGraphToFile(&mPDT, "post-dom-tree.dot", "post-dom-tree"); + /**/ + processControlDependence(); + return mCDG; +} + +bool PDGNode::collectInstructions(function_ref const &Pred, + SmallVectorImpl &IList) const { + assert(IList.empty() && "Expected the IList to be empty on entry."); + if (isa(this)) { + for (Instruction *I : cast(this)->getInstructions()) + if (Pred(I)) + IList.push_back(I); + } + else + if (isa(this)) { + for (const PDGNode *PN : cast(this)-> + getInlinedNodes()) { + assert(!isa(PN) && + "Nested PiBlocks are not supported."); + SmallVector TmpIList; + PN->collectInstructions(Pred, TmpIList); + llvm::append_range(IList, TmpIList); + } } - else - if (isa(this)) { - for (const PDGNode *PN : cast(this)->getInlinedNodes()) { - assert(!isa(PN) && "Nested PiBlocks are not supported."); - SmallVector TmpIList; - PN->collectInstructions(Pred, TmpIList); - llvm::append_range(IList, TmpIList); - } - } - else - llvm_unreachable("unimplemented type of node"); - return !IList.empty(); + else + llvm_unreachable("unimplemented type of node"); + return !IList.empty(); } void PDGNode::destroy() { - switch (mKind) { - case PDGNode::NodeKind::Entry: - delete this; - break; - case PDGNode::NodeKind::SingleInstruction: - case PDGNode::NodeKind::MultiInstruction: - delete (SimplePDGNode*)this; - break; - case PDGNode::NodeKind::PiBlock: - delete (PiBlockPDGNode*)this; - break; - } + switch (mKind) { + case PDGNode::NodeKind::Entry: + delete this; + break; + case PDGNode::NodeKind::SingleInstruction: + case PDGNode::NodeKind::MultiInstruction: + delete (SimplePDGNode*)this; + break; + case PDGNode::NodeKind::PiBlock: + delete (PiBlockPDGNode*)this; + break; + } } PiBlockPDGNode::~PiBlockPDGNode() { - for (PDGNode *N : mInlinedNodes) { - for (PDGEdge *E : N->getEdges()) - E->destroy(); - N->destroy(); - } + for (PDGNode *N : mInlinedNodes) { + for (PDGEdge *E : N->getEdges()) + E->destroy(); + N->destroy(); + } } void PDGEdge::destroy() { - switch (mKind) { - case PDGEdge::EdgeKind::RegisterDefUse: - case PDGEdge::EdgeKind::Control: - delete this; - break; - case PDGEdge::EdgeKind::MixedData: - case PDGEdge::EdgeKind::Memory: - delete (MemoryPDGEdge*)this; - break; - case PDGEdge::EdgeKind::ComplexData: - case PDGEdge::EdgeKind::ComplexControl: - delete (ComplexPDGEdge*)this; - break; - } + switch (mKind) { + case PDGEdge::EdgeKind::RegisterDefUse: + case PDGEdge::EdgeKind::Control: + delete this; + break; + case PDGEdge::EdgeKind::MixedData: + case PDGEdge::EdgeKind::Memory: + delete (MemoryPDGEdge*)this; + break; + case PDGEdge::EdgeKind::ComplexData: + case PDGEdge::EdgeKind::ComplexControl: + delete (ComplexPDGEdge*)this; + break; + } } llvm::raw_ostream &tsar::operator<<(llvm::raw_ostream &OS, const PDGNode &N) { - OS<<"Node Address:"<<&N<<":"<< N.getKind()<<"\n"; - if (isa(N)) { - OS<<" Instructions:\n"; - for (const Instruction *I : cast(N).getInstructions()) - OS.indent(2)<<*I<<"\n"; - } - else - if (isa(&N)) { - OS<<"--- start of nodes in pi-block ---\n"; - const SmallVectorImpl &Nodes=cast(&N)->getInlinedNodes(); - unsigned Count=0; - for (const PDGNode *N : Nodes) - OS<<*N<<(++Count==Nodes.size()?"":"\n"); - OS<<"--- end of nodes in pi-block ---\n"; - } - else - if (N.getKind()!=PDGNode::NodeKind::Entry) - llvm_unreachable("Unimplemented type of node"); - OS<<(N.getEdges().empty()?" Edges:none!\n" : " Edges:\n"); - for (const PDGEdge *E : N.getEdges()) - OS.indent(2)<<*E; - return OS; -} - -llvm::raw_ostream &tsar::operator<<(llvm::raw_ostream &OS, const PDGNode::NodeKind K) { - switch (K) { - case PDGNode::NodeKind::Entry: - OS<<"entry"; - break; - case PDGNode::NodeKind::SingleInstruction: - OS<<"single-instruction"; - break; - case PDGNode::NodeKind::MultiInstruction: - OS<<"multi-instruction"; - break; - case PDGNode::NodeKind::PiBlock: - OS<<"pi-block"; - break; - } - return OS; + OS<<"Node Address:"<<&N<<":"<< N.getKind()<<"\n"; + if (isa(N)) { + OS<<" Instructions:\n"; + for (const Instruction *I : cast(N).getInstructions()) + OS.indent(2)<<*I<<"\n"; + } + else + if (isa(&N)) { + OS<<"--- start of nodes in pi-block ---\n"; + const SmallVectorImpl &Nodes=cast(&N)-> + getInlinedNodes(); + unsigned Count=0; + for (const PDGNode *N : Nodes) + OS<<*N<<(++Count==Nodes.size()?"":"\n"); + OS<<"--- end of nodes in pi-block ---\n"; + } + else + if (N.getKind()!=PDGNode::NodeKind::Entry) + llvm_unreachable("Unimplemented type of node"); + OS<<(N.getEdges().empty()?" Edges:none!\n" : " Edges:\n"); + for (const PDGEdge *E : N.getEdges()) + OS.indent(2)<<*E; + return OS; +} + +llvm::raw_ostream &tsar::operator<<(llvm::raw_ostream &OS, + const PDGNode::NodeKind K) { + switch (K) { + case PDGNode::NodeKind::Entry: + OS<<"entry"; + break; + case PDGNode::NodeKind::SingleInstruction: + OS<<"single-instruction"; + break; + case PDGNode::NodeKind::MultiInstruction: + OS<<"multi-instruction"; + break; + case PDGNode::NodeKind::PiBlock: + OS<<"pi-block"; + break; + } + return OS; } llvm::raw_ostream &tsar::operator<<(llvm::raw_ostream &OS, const PDGEdge &E) { - OS<<"["<< E.getKind()<<"] to "<<&E.getTargetNode()<<"\n"; - return OS; -} - -llvm::raw_ostream &tsar::operator<<(llvm::raw_ostream &OS, const PDGEdge::EdgeKind K) { - switch (K) { - case PDGEdge::EdgeKind::RegisterDefUse: - OS<<"def-use"; - break; - case PDGEdge::EdgeKind::MixedData: - OS<<"mixed data"; - break; - case PDGEdge::EdgeKind::Memory: - OS<<"memory"; - break; - case PDGEdge::EdgeKind::Control: - OS<<"control"; - break; - case PDGEdge::EdgeKind::ComplexData: - OS<<"complex data"; - break; - case PDGEdge::EdgeKind::ComplexControl: - OS<<"complex control"; - break; - } - return OS; -} - -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const ProgramDependencyGraph &G) { - for (const PDGNode *Node : G) - OS<<*Node<<"\n"; - OS<<"\n"; - return OS; + OS<<"["<< E.getKind()<<"] to "<<&E.getTargetNode()<<"\n"; + return OS; +} + +llvm::raw_ostream &tsar::operator<<(llvm::raw_ostream &OS, + const PDGEdge::EdgeKind K) { + switch (K) { + case PDGEdge::EdgeKind::RegisterDefUse: + OS<<"def-use"; + break; + case PDGEdge::EdgeKind::MixedData: + OS<<"mixed data"; + break; + case PDGEdge::EdgeKind::Memory: + OS<<"memory"; + break; + case PDGEdge::EdgeKind::Control: + OS<<"control"; + break; + case PDGEdge::EdgeKind::ComplexData: + OS<<"complex data"; + break; + case PDGEdge::EdgeKind::ComplexControl: + OS<<"complex control"; + break; + } + return OS; +} + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const PDG &G) { + for (const PDGNode *Node : G) + OS<<*Node<<"\n"; + OS<<"\n"; + return OS; } //===--------------------------------------------------------------------===// // PDG DOT Printer Implementation //===--------------------------------------------------------------------===// -std::string PDGDotGraphTraits::getNodeLabel(const PDGNode *Node, const ProgramDependencyGraph *Graph) { - if (isSimple()) - return getSimpleNodeLabel(Node, Graph); - else - return getVerboseNodeLabel(Node, Graph); +std::string PDGDotGraphTraits::getNodeLabel(const PDGNode *Node, + const PDG *Graph) { + if (isSimple()) + return getSimpleNodeLabel(Node, Graph); + else + return getVerboseNodeLabel(Node, Graph); } std::string PDGDotGraphTraits::getEdgeAttributes(const PDGNode *Node, - GraphTraits::ChildIteratorType I, const ProgramDependencyGraph *G) { - const PDGEdge *E=static_cast(*I.getCurrent()); - if (isSimple()) - return getEdgeStyle(E); - else - return getEdgeStyle(E)+" "+getVerboseEdgeAttributes(Node, E, G); -} - -bool PDGDotGraphTraits::isNodeHidden(const PDGNode *Node, const ProgramDependencyGraph *Graph) { - if (const SimplePDGNode *SimpleNode=dyn_cast(Node)) { - for (const Instruction *I : SimpleNode->getInstructions()) - if (!PDGBuilder::shouldShadow(*I)) - return false; - return true; - } - else - if (const PiBlockPDGNode *PiNode=dyn_cast(Node)) { - for (const PDGNode *InlinedNode : PiNode->getInlinedNodes()) - if (!isNodeHidden(InlinedNode, Graph)) - return false; - return true; - } - else - return false; -} - -std::string PDGDotGraphTraits::getSimpleNodeLabel(const PDGNode *Node, const ProgramDependencyGraph *G) { - std::string Str; - raw_string_ostream OS(Str); - if (isa(Node)) { - for (const Instruction *II : static_cast(Node)->getInstructions()) - if (!PDGBuilder::shouldShadow(*II)) - OS<<*II<<"\n"; - } - else - if (isa(Node)) { - size_t NotHiddenNodesCount=0; - for (const PDGNode *IN : cast(Node)->getInlinedNodes()) - if (!isNodeHidden(IN, G)) - ++NotHiddenNodesCount; - OS<<"pi-block\nwith\n"<getKind()==PDGNode::NodeKind::Entry) - OS<<"entry\n"; - else - llvm_unreachable("Unimplemented type of node"); - return OS.str(); -} - -std::string PDGDotGraphTraits::getVerboseNodeLabel(const PDGNode *Node, const ProgramDependencyGraph *G) { - std::string Str; - raw_string_ostream OS(Str); - OS<<"getKind()<<">\n"; - if (const SimplePDGNode *SimpleNode=dyn_cast(Node)) { - for (const Instruction *II : SimpleNode->getInstructions()) - if (!PDGBuilder::shouldShadow(*II)) - OS<<*II<<"\n"; - } - else - if (const PiBlockPDGNode *PiNode=dyn_cast(Node)) { - OS<<"--- start of nodes in pi-block ---\n"; - unsigned Count=0; - for (const PDGNode *IN : PiNode->getInlinedNodes()) { - ++Count; - if (!isNodeHidden(IN, G)) - OS<getKind()==PDGNode::NodeKind::Entry) - OS<<"entry\n"; - else - llvm_unreachable("Unimplemented type of node"); - return OS.str(); -} - -std::string PDGDotGraphTraits::getVerboseEdgeAttributes(const PDGNode *Src, const PDGEdge *Edge, const ProgramDependencyGraph *G) { - std::string Str; - raw_string_ostream OS(Str); - if (const MemoryPDGEdge *MemDepEdge=dyn_cast(Edge)) { - OS<<"label=\"["; - MemDepEdge->getMemoryDep().dump(OS); - OS.str().pop_back(); - OS<<"]\""; - } - else - if (const ComplexPDGEdge *ComplexEdge=dyn_cast(Edge)) { - auto StringifyInlinedEdge=[](const PDGEdge &E) -> std::string { - using EdgeKind=PDGEdge::EdgeKind; - std::string Str; - raw_string_ostream OS(Str); - switch (E.getKind()) { - case EdgeKind::RegisterDefUse: - return "def-use"; - case EdgeKind::MixedData: - OS<<"def-use & "; - case EdgeKind::Memory: - cast(E).getMemoryDep().dump(OS); - OS.str().pop_back(); - return OS.str(); - case EdgeKind::Control: - return "control"; - default: - llvm_unreachable("Only simple edges can be inlined in complex edge"); - } - }; - OS<<"label=\""; - for (const ComplexPDGEdge::EdgeHandler &EH : ComplexEdge->getInlinedEdges()) { - if (!isNodeHidden(&EH.E.getTargetNode(), G)) - OS<<"("<::ChildIteratorType I, const PDG *G) { + const PDGEdge *E=static_cast(*I.getCurrent()); + if (isSimple()) + return getEdgeStyle(E); + else + return getEdgeStyle(E)+" "+getVerboseEdgeAttributes(Node, E, G); +} + +bool PDGDotGraphTraits::isNodeHidden(const PDGNode *Node, const PDG *Graph) { + if (const SimplePDGNode *SimpleNode=dyn_cast(Node)) { + for (const Instruction *I : SimpleNode->getInstructions()) + if (!PDGBuilder::shouldShadow(*I)) + return false; + return true; + } + else + if (const PiBlockPDGNode *PiNode=dyn_cast(Node)) { + for (const PDGNode *InlinedNode : PiNode->getInlinedNodes()) + if (!isNodeHidden(InlinedNode, Graph)) + return false; + return true; + } + else + return false; +} + +std::string PDGDotGraphTraits::getSimpleNodeLabel(const PDGNode *Node, + const PDG *G) { + std::string Str; + raw_string_ostream OS(Str); + if (isa(Node)) { + for (const Instruction *II : static_cast(Node)-> + getInstructions()) + if (!PDGBuilder::shouldShadow(*II)) + OS<<*II<<"\n"; + } + else + if (isa(Node)) { + size_t NotHiddenNodesCount=0; + for (const PDGNode *IN : cast(Node)->getInlinedNodes()) + if (!isNodeHidden(IN, G)) + ++NotHiddenNodesCount; + OS<<"pi-block\nwith\n"<getKind()==PDGNode::NodeKind::Entry) + OS<<"entry\n"; + else + llvm_unreachable("Unimplemented type of node"); + return OS.str(); +} + +std::string PDGDotGraphTraits::getVerboseNodeLabel(const PDGNode *Node, + const PDG *G) { + std::string Str; + raw_string_ostream OS(Str); + OS<<"getKind()<<">\n"; + if (const SimplePDGNode *SimpleNode=dyn_cast(Node)) { + for (const Instruction *II : SimpleNode->getInstructions()) + if (!PDGBuilder::shouldShadow(*II)) + OS<<*II<<"\n"; + } + else + if (const PiBlockPDGNode *PiNode=dyn_cast(Node)) { + OS<<"--- start of nodes in pi-block ---\n"; + unsigned Count=0; + for (const PDGNode *IN : PiNode->getInlinedNodes()) { + ++Count; + if (!isNodeHidden(IN, G)) + OS<getKind()==PDGNode::NodeKind::Entry) + OS<<"entry\n"; + else + llvm_unreachable("Unimplemented type of node"); + return OS.str(); +} + +std::string PDGDotGraphTraits::getVerboseEdgeAttributes(const PDGNode *Src, + const PDGEdge *Edge, const PDG *G) { + std::string Str; + raw_string_ostream OS(Str); + // DEBUG: + auto PrintMemoryEdge=[&OS](const MemoryPDGEdge &E) { + if (llvm::Dependence * const *Dep=std::get_if(&E.getMemoryDep())) { + (*Dep)->dump(OS); + OS.str().pop_back(); + } + else { + // DEBUG: + auto PrintDIMemDep=[&OS](const MemoryPDGEdge::DIDepT &Dep) -> void { + const trait::DIDependence *DistVec; + const DIMemoryTraitRef &MTRef=Dep.first; + Dep.second.for_each([&OS, &DistVec, &MTRef]() -> void { + DistVec=MTRef->get(); + OS<getKnownLevel()==0) + return; + OS<<"<"; + if (DistVec->getDistance(0).first==DistVec->getDistance(0).second) + OS<getDistance(0).first; + else + OS<<"("<getDistance(0).first<<", "<< + DistVec->getDistance(0).second<<")"; + for (int Level=1; LevelgetKnownLevel(); ++Level) + if (DistVec->getDistance(Level).first==DistVec->getDistance(Level).second) + OS<<", "<getDistance(Level).first; + else + OS<<", ("<getDistance(Level).first<<", "<< + DistVec->getDistance(Level).second<<")"; + OS<<">"; + }; + const MemoryPDGEdge::DIDepStorageT &DIDeps=std::get(E.getMemoryDep()); + for (auto &DIMemDep : DIDeps) { + PrintDIMemDep(DIMemDep); + OS<<"\n"; + } + // + } + }; + // + if (const MemoryPDGEdge *MemDepEdge=dyn_cast(Edge)) { + OS<<"label=\"["; + // DEBUG: + PrintMemoryEdge(*MemDepEdge); + OS.str().pop_back(); + // + OS<<"]\""; + } + else + if (const ComplexPDGEdge *ComplexEdge=dyn_cast(Edge)) { + auto StringifyInlinedEdge=[&OS, &PrintMemoryEdge](const PDGEdge &E) -> + std::string { + using EdgeKind=PDGEdge::EdgeKind; + std::string Str; + raw_string_ostream OS(Str); + switch (E.getKind()) { + case EdgeKind::RegisterDefUse: + return "def-use"; + case EdgeKind::MixedData: + OS<<"def-use & "; + case EdgeKind::Memory: + PrintMemoryEdge(cast(E)); + // cast(E).getMemoryDep().dump(OS); + // OS.str().pop_back(); + return OS.str(); + case EdgeKind::Control: + return "control"; + default: + llvm_unreachable("Only simple edges can be inlined in complex edge"); + } + }; + OS<<"label=\""; + for (const ComplexPDGEdge::EdgeHandle &EH : ComplexEdge->getInlinedEdges()) { + if (!isNodeHidden(&EH.E.getTargetNode(), G)) + OS<<"("<getKind()) { - case tsar::PDGEdge::EdgeKind::RegisterDefUse: - return "style=\"solid\" color=\"blue\""; - case tsar::PDGEdge::EdgeKind::MixedData: - return "style=\"solid\" color=\"purple\""; - case tsar::PDGEdge::EdgeKind::Memory: - return "style=\"solid\" color=\"green\""; - case tsar::PDGEdge::EdgeKind::Control: - return "style=\"dotted\""; - case tsar::PDGEdge::EdgeKind::ComplexData: - return "style=\"solid\" color=\"orchid\""; - case tsar::PDGEdge::EdgeKind::ComplexControl: - return "style=\"dashed\""; - } + switch (Edge->getKind()) { + case tsar::PDGEdge::EdgeKind::RegisterDefUse: + return "style=\"solid\" color=\"blue\""; + case tsar::PDGEdge::EdgeKind::MixedData: + return "style=\"solid\" color=\"purple\""; + case tsar::PDGEdge::EdgeKind::Memory: + return "style=\"solid\" color=\"green\""; + case tsar::PDGEdge::EdgeKind::Control: + return "style=\"dotted\""; + case tsar::PDGEdge::EdgeKind::ComplexData: + return "style=\"solid\" color=\"orchid\""; + case tsar::PDGEdge::EdgeKind::ComplexControl: + return "style=\"dashed\""; + } } //===--------------------------------------------------------------------===// // End of PDG DOT Printer Implementation //===--------------------------------------------------------------------===// void PDGBuilder::computeInstructionOrdinals() { - // The BBList is expected to be in program order. - size_t NextOrdinal = 1; - for (const BasicBlock *BB : mBBList) { - assert(BB); - for (const Instruction &I : *BB) - mInstOrdinalMap.insert(std::make_pair(&I, NextOrdinal++)); - } + // The BBList is expected to be in program order. + size_t NextOrdinal=1; + for (const BasicBlock *BB : mBBList) { + assert(BB); + for (const Instruction &I : *BB) + mInstOrdinalMap.insert(std::make_pair(&I, NextOrdinal++)); + } } void PDGBuilder::createFineGrainedNodes() { - ++TotalGraphs; - assert(mIMap.empty() && "Expected empty instruction map at start"); - for (const BasicBlock *BB : mBBList) - for (const Instruction &I : *BB) { - auto &NewNode = createFineGrainedNode(I); - mIMap.insert(std::make_pair(&I, &NewNode)); - mNodeOrdinalMap.insert(std::make_pair(&NewNode, getOrdinal(I))); - ++TotalFineGrainedNodes; - } + ++TotalGraphs; + assert(mIMap.empty() && "Expected empty instruction map at start"); + for (const BasicBlock *BB : mBBList) + for (const Instruction &I : *BB) { + auto &NewNode=createFineGrainedNode(I); + mIMap.insert(std::make_pair(&I, &NewNode)); + mNodeOrdinalMap.insert(std::make_pair(&NewNode, getOrdinal(I))); + ++TotalFineGrainedNodes; + } } void PDGBuilder::createDefUseEdges() { - for (PDGNode *N : mGraph) { - if (N->getKind()==PDGNode::NodeKind::Entry) - continue; - SimplePDGNode &InstrNode=*cast(N); - Instruction &VI=*InstrNode.getFirstInstruction(); - // Use a set to mark the targets that we link to N, so we don't add - // duplicate def-use edges when more than one instruction in a target node - // use results of instructions that are contained in N. - SmallPtrSet VisitedTargets; - for (User *U : VI.users()) { - Instruction*UI =dyn_cast(U); - if (!UI) - continue; - PDGNode *DstNode; - if (mIMap.find(UI)!=mIMap.end()) - DstNode=mIMap.find(UI)->second; - else { - // In the case of loops, the scope of the subgraph is all the - // basic blocks (and instructions within them) belonging to the loop. We - // simply ignore all the edges coming from (or going into) instructions - // or basic blocks outside of this range. - LLVM_DEBUG(dbgs()<<"skipped def-use edge since the sink"<<*UI<<" is outside the range of instructions being considered.\n"); - continue; - } - // Self dependencies are ignored because they are redundant and - // uninteresting. - if (DstNode==N) { - LLVM_DEBUG(dbgs()<<"skipped def-use edge since the sink and the source ("<getKind()==PDGNode::NodeKind::Entry) + continue; + SimplePDGNode &InstrNode=*cast(N); + Instruction &VI=*InstrNode.getFirstInstruction(); + // Use a set to mark the targets that we link to N, so we don't add + // duplicate def-use edges when more than one instruction in a target node + // use results of instructions that are contained in N. + SmallPtrSet VisitedTargets; + for (User *U : VI.users()) { + Instruction*UI =dyn_cast(U); + if (!UI) + continue; + PDGNode *DstNode; + if (mIMap.find(UI)!=mIMap.end()) + DstNode=mIMap.find(UI)->second; + else { + // In the case of loops, the scope of the subgraph is all the + // basic blocks (and instructions within them) belonging to the loop. We + // simply ignore all the edges coming from (or going into) instructions + // or basic blocks outside of this range. + LLVM_DEBUG(dbgs()<<"skipped def-use edge since the sink"<<*UI<< + " is outside the range of instructions being considered.\n"); + continue; + } + // Self dependencies are ignored because they are redundant and + // uninteresting. + if (DstNode==N) { + LLVM_DEBUG(dbgs()<< + "skipped def-use edge since the sink and the source ("<getKind()==PDGNode::NodeKind::Entry) - continue; - SimplePDGNode &SrcInstrNode=*cast(*SrcNodeIt); - Instruction &SrcInstr=*SrcInstrNode.getFirstInstruction(); - if (!SrcInstr.mayReadOrWriteMemory()) - continue; - for (auto DstNodeIt=SrcNodeIt; DstNodeIt!=mGraph.end(); ++DstNodeIt) { - SmallVector DefUseEdges; - auto CreateDepEdge=[&DefUseEdges, this](PDGNode &Src, PDGNode &Tgt, unique_ptr &&Dep) { - if (Src.findEdgesTo(Tgt, DefUseEdges)) { - assert(DefUseEdges.size()==1); - Src.removeEdge(*DefUseEdges.front()); - DefUseEdges.front()->destroy(); - DefUseEdges.clear(); - assert(mGraph.connect(Src, Tgt, *(new MemoryPDGEdge(Tgt, *Dep.release(), true)))); - } - else - assert(mGraph.connect(Src, Tgt, *(new MemoryPDGEdge(Tgt, *Dep.release(), false)))); - }; - if (**SrcNodeIt==**DstNodeIt) - continue; - SimplePDGNode &DstInstrNode=*cast(*DstNodeIt); - Instruction &DstInstr=*DstInstrNode.getFirstInstruction(); - if (!DstInstr.mayReadOrWriteMemory()) - continue; - if (!(SrcInstr.getParent()==DstInstr.getParent() || isReachable(*SrcInstr.getParent(), *DstInstr.getParent()) || - isReachable(*DstInstr.getParent(), *SrcInstr.getParent()))) - continue; - unique_ptr Dep=mDI.depends(&SrcInstr, &DstInstr, true); - if (!Dep) - continue; - // If we have a dependence with its left-most non-'=' direction - // being '>' we need to reverse the direction of the edge, because - // the source of the dependence cannot occur after the sink. For - // confused dependencies, we will create edges in both directions to - // represent the possibility of a cycle. - if (Dep->isConfused() && confirmMemoryIntersect(SrcInstr, DstInstr)) { - CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); - CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&SrcInstr, &DstInstr, true)); - } - else if (Dep->isOrdered()) { - if (!Dep->isLoopIndependent()) { - bool ReversedEdge=false; - for (unsigned Level=1; Level<=Dep->getLevels(); ++Level) { - if (Dep->getDirection(Level)==Dependence::DVEntry::EQ) - continue; - else if (Dep->getDirection(Level) == Dependence::DVEntry::GT) { - CreateDepEdge(**DstNodeIt, **SrcNodeIt, std::move(Dep)); - ReversedEdge=true; - //++TotalEdgeReversals; - break; - } - else if (Dep->getDirection(Level)==Dependence::DVEntry::LT) - break; - else { - CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); - CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&SrcInstr, &DstInstr, true)); - ReversedEdge=true; - break; - } - } - if (!ReversedEdge) - CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); - } - else - CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); - } - } - } + for (auto SrcNodeIt=mGraph.begin(); SrcNodeIt!=mGraph.end(); ++SrcNodeIt) { + if ((*SrcNodeIt)->getKind()==PDGNode::NodeKind::Entry) + continue; + SimplePDGNode &SrcInstrNode=*cast(*SrcNodeIt); + Instruction &SrcInstr=*SrcInstrNode.getFirstInstruction(); + if (!SrcInstr.mayReadOrWriteMemory()) + continue; + for (auto DstNodeIt=SrcNodeIt; DstNodeIt!=mGraph.end(); ++DstNodeIt) { + SmallVector DefUseEdges; + auto CreateDepEdge=[&DefUseEdges, this](PDGNode &Src, PDGNode &Tgt, + const MemoryPDGEdge::MemDepHandle &Dep) { + if (Src.findEdgesTo(Tgt, DefUseEdges)) { + assert(DefUseEdges.size()==1); + Src.removeEdge(*DefUseEdges.front()); + DefUseEdges.front()->destroy(); + DefUseEdges.clear(); + assert(mGraph.connect(Src, Tgt, *(new MemoryPDGEdge(Tgt, Dep, true)))); + // assert(mGraph.connect(Src, Tgt, *(new MemoryPDGEdge(Tgt, *Dep.release(), true)))); + } + else + assert(mGraph.connect(Src, Tgt, *(new MemoryPDGEdge(Tgt, Dep, false)))); + // assert(mGraph.connect(Src, Tgt, *(new MemoryPDGEdge(Tgt, *Dep.release(), false)))); + }; + if (**SrcNodeIt==**DstNodeIt) + continue; + SimplePDGNode &DstInstrNode=*cast(*DstNodeIt); + Instruction &DstInstr=*DstInstrNode.getFirstInstruction(); + if (!DstInstr.mayReadOrWriteMemory()) + continue; + if (!(SrcInstr.getParent()==DstInstr.getParent() || + isReachable(*SrcInstr.getParent(), *DstInstr.getParent()) || + isReachable(*DstInstr.getParent(), *SrcInstr.getParent()))) + continue; + // unique_ptr Dep=mDI.depends(&SrcInstr, &DstInstr, true); + MemoryPDGEdge::DIDepStorageT ForwardDIDep, BackwardDIDep; + /*if (!Dep) + continue;*/ + // If we have a dependence with its left-most non-'=' direction + // being '>' we need to reverse the direction of the edge, because + // the source of the dependence cannot occur after the sink. For + // confused dependencies, we will create edges in both directions to + // represent the possibility of a cycle. + if (/*Dep->isConfused() &&*/ confirmMemoryIntersect(SrcInstr, DstInstr, ForwardDIDep, BackwardDIDep)) + // TODO: rewrite + if (!ForwardDIDep.empty() || !BackwardDIDep.empty()) { + if (!ForwardDIDep.empty()) + CreateDepEdge(**SrcNodeIt, **DstNodeIt, ForwardDIDep); + if (!BackwardDIDep.empty()) + CreateDepEdge(**DstNodeIt, **SrcNodeIt, BackwardDIDep); + } + /*else { + CreateDepEdge(**SrcNodeIt, **DstNodeIt, Dep.release()); + CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&SrcInstr, &DstInstr, true).release()); + }*/ + /*else if (Dep->isOrdered()) { + if (!Dep->isLoopIndependent()) { + bool ReversedEdge=false; + for (unsigned Level=1; Level<=Dep->getLevels(); ++Level) { + if (Dep->getDirection(Level)==Dependence::DVEntry::EQ) + continue; + else if (Dep->getDirection(Level) == Dependence::DVEntry::GT) { + CreateDepEdge(**DstNodeIt, **SrcNodeIt, std::move(Dep)); + ReversedEdge=true; + //++TotalEdgeReversals; + break; + } + else if (Dep->getDirection(Level)==Dependence::DVEntry::LT) + break; + else { + CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); + CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&SrcInstr, &DstInstr, true)); + ReversedEdge=true; + break; + } + } + if (!ReversedEdge) + CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); + } + else + CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); + }*/ + } + } } void PDGBuilder::createControlDependenceEdges() { - IRCDG *CDG=CDGBuilder().populate(const_cast(mF)); - PDGNode &EntryPDGNode=*(new PDGNode()); - mGraph.addEntryNode(EntryPDGNode); - for (IRCDGNode *BBNode : *CDG) { - auto LinkControlDependent=[this](PDGNode &SrcNode, IRCDGNode::EdgeListTy &CDGDependentNodes) { - for (IRCDGEdge *ControlDependence : CDGDependentNodes) { - BasicBlock *TargetBlock=cast(&ControlDependence->getTargetNode())->getBlock(); - for (Instruction &I : *TargetBlock) { - auto InstrPDGNodeIt=mIMap.find(&I); - if (InstrPDGNodeIt!=mIMap.end()) { - PDGEdge &NewPDGEdge=*(new PDGEdge(*InstrPDGNodeIt->second, PDGEdge::DependenceType::Control)); - // DEBUG: - assert(mGraph.connect(SrcNode, *InstrPDGNodeIt->second, NewPDGEdge)); - // - } - } - } - }; - if (isa(BBNode)) - LinkControlDependent(EntryPDGNode, BBNode->getEdges()); - else { - DefaultIRCDGNode &SrcNode=*cast(BBNode); - assert(mIMap.find(SrcNode.getBlock()->getTerminator())!=mIMap.end()); - LinkControlDependent(*mIMap[SrcNode.getBlock()->getTerminator()], SrcNode.getEdges()); - } - } - delete CDG; + IRCDG *CDG=CDGBuilder().populate(const_cast(mF)); + PDGNode &EntryPDGNode=*(new PDGNode()); + mGraph.addEntryNode(EntryPDGNode); + for (IRCDGNode *BBNode : *CDG) { + auto LinkControlDependent=[this](PDGNode &SrcNode, + IRCDGNode::EdgeListTy &CDGDependentNodes) { + for (IRCDGEdge *ControlDependence : CDGDependentNodes) { + BasicBlock *TargetBlock=cast(&ControlDependence-> + getTargetNode())->getBlock(); + for (Instruction &I : *TargetBlock) { + auto InstrPDGNodeIt=mIMap.find(&I); + if (InstrPDGNodeIt!=mIMap.end()) { + PDGEdge &NewPDGEdge=*(new PDGEdge(*InstrPDGNodeIt->second, + PDGEdge::DependenceType::Control)); + // DEBUG: + assert(mGraph.connect(SrcNode, *InstrPDGNodeIt->second, NewPDGEdge)); + // + } + } + } + }; + if (isa(BBNode)) + LinkControlDependent(EntryPDGNode, BBNode->getEdges()); + else { + DefaultIRCDGNode &SrcNode=*cast(BBNode); + assert(mIMap.find(SrcNode.getBlock()->getTerminator())!=mIMap.end()); + LinkControlDependent(*mIMap[SrcNode.getBlock()->getTerminator()], + SrcNode.getEdges()); + } + } + delete CDG; } void PDGBuilder::simplify() { - if (!mSimplified) - return; - LLVM_DEBUG(dbgs()<<"==== Start of Graph Simplification ===\n"); - // This algorithm works by first collecting a set of candidate nodes that have - // an out-degree of one (in terms of def-use edges), and then ignoring those - // whose targets have an in-degree more than one. Each node in the resulting - // set can then be merged with its corresponding target and put back into the - // worklist until no further merge candidates are available. - DenseSet CandidateSourceNodes; - // A mapping between nodes and their in-degree. To save space, this map - // only contains nodes that are targets of nodes in the CandidateSourceNodes. - DenseMap TargetInDegreeMap; - for (PDGNode *N : mGraph) { - if (N->getEdges().size()!=1) - continue; - PDGEdge &Edge=N->back(); - if (Edge.getKind()!=PDGEdge::EdgeKind::RegisterDefUse) - continue; - CandidateSourceNodes.insert(N); - // Insert an element into the in-degree map and initialize to zero. The - // count will get updated in the next step. - TargetInDegreeMap.insert({&Edge.getTargetNode(), 0}); - } - LLVM_DEBUG({ - dbgs()<<"Size of candidate src node list:"< CDependentTargets; - for (PDGEdge *E : *N) { - auto RegisterCDNode=[&CDependentTargets](PDGNode &N) { - if (CDependentTargets.contains(&N)) - CDependentTargets.erase(&N); - else - CDependentTargets.insert(&N); - }; - PDGNode &TgtNode=E->getTargetNode(); - auto TgtIt=TargetInDegreeMap.find(&TgtNode); - if (E->isControl()) { - auto SrcIt=CandidateSourceNodes.find(&TgtNode); - if (SrcIt!=CandidateSourceNodes.end()) - RegisterCDNode(TgtNode.back().getTargetNode()); - if (TgtIt!=TargetInDegreeMap.end()) - RegisterCDNode(TgtNode); - } - else - if (TgtIt!=TargetInDegreeMap.end()) - ++(TgtIt->second); - } - for (PDGNode *Target : CDependentTargets) - TargetInDegreeMap[Target]=2; - } - LLVM_DEBUG({ - dbgs()<<"Size of target in-degree map:"< "< Worklist(CandidateSourceNodes.begin(), - CandidateSourceNodes.end()); - while (!Worklist.empty()) { - PDGNode &Src=*Worklist.pop_back_val(); - // As nodes get merged, we need to skip any node that has been removed from - // the candidate set (see below). - if (!CandidateSourceNodes.erase(&Src)) - continue; - assert(Src.getEdges().size()==1 && - "Expected a single edge from the candidate src node."); - PDGNode &Tgt=Src.back().getTargetNode(); - assert(TargetInDegreeMap.find(&Tgt)!=TargetInDegreeMap.end() && - "Expected target to be in the in-degree map."); - // Do not merge if there is also an edge from target to src (immediate - // cycle). - if (TargetInDegreeMap[&Tgt]!=1 || !areNodesMergeable(Src, Tgt) || Tgt.hasEdgeTo(Src)) - continue; - // LLVM_DEBUG(dbgs()<<"Merging:"<(b), (b)->(c), (c)->(d), ...} and the worklist is initially {b, a}, - // then after merging (a) and (b) together, we need to put (a,b) back in - // the worklist so that (c) can get merged in as well resulting in - // {(a,b,c) -> d} - // We also need to remove the old target (b), from the worklist. We first - // remove it from the candidate set here, and skip any item from the - // worklist that is not in the set. - if (CandidateSourceNodes.erase(&Tgt)) { - Worklist.push_back(&Src); - CandidateSourceNodes.insert(&Src); - LLVM_DEBUG(dbgs()<<"Putting "<<&Src<<" back in the worklist.\n"); - } - } - LLVM_DEBUG(dbgs()<<"=== End of Graph Simplification ===\n"); + if (!mSimplified) + return; + LLVM_DEBUG(dbgs()<<"==== Start of Graph Simplification ===\n"); + // This algorithm works by first collecting a set of candidate nodes that have + // an out-degree of one (in terms of def-use edges), and then ignoring those + // whose targets have an in-degree more than one. Each node in the resulting + // set can then be merged with its corresponding target and put back into the + // worklist until no further merge candidates are available. + DenseSet CandidateSourceNodes; + // A mapping between nodes and their in-degree. To save space, this map + // only contains nodes that are targets of nodes in the CandidateSourceNodes. + DenseMap TargetInDegreeMap; + for (PDGNode *N : mGraph) { + if (N->getEdges().size()!=1) + continue; + PDGEdge &Edge=N->back(); + if (Edge.getKind()!=PDGEdge::EdgeKind::RegisterDefUse) + continue; + CandidateSourceNodes.insert(N); + // Insert an element into the in-degree map and initialize to zero. The + // count will get updated in the next step. + TargetInDegreeMap.insert({&Edge.getTargetNode(), 0}); + } + LLVM_DEBUG({ + dbgs()<<"Size of candidate src node list:"< CDependentTargets; + for (PDGEdge *E : *N) { + auto RegisterCDNode=[&CDependentTargets](PDGNode &N) { + if (CDependentTargets.contains(&N)) + CDependentTargets.erase(&N); + else + CDependentTargets.insert(&N); + }; + PDGNode &TgtNode=E->getTargetNode(); + auto TgtIt=TargetInDegreeMap.find(&TgtNode); + if (E->isControl()) { + auto SrcIt=CandidateSourceNodes.find(&TgtNode); + if (SrcIt!=CandidateSourceNodes.end()) + RegisterCDNode(TgtNode.back().getTargetNode()); + if (TgtIt!=TargetInDegreeMap.end()) + RegisterCDNode(TgtNode); + } + else + if (TgtIt!=TargetInDegreeMap.end()) + ++(TgtIt->second); + } + for (PDGNode *Target : CDependentTargets) + TargetInDegreeMap[Target]=2; + } + LLVM_DEBUG({ + dbgs()<<"Size of target in-degree map:"< "< Worklist(CandidateSourceNodes.begin(), + CandidateSourceNodes.end()); + while (!Worklist.empty()) { + PDGNode &Src=*Worklist.pop_back_val(); + // As nodes get merged, we need to skip any node that has been removed from + // the candidate set (see below). + if (!CandidateSourceNodes.erase(&Src)) + continue; + assert(Src.getEdges().size()==1 && + "Expected a single edge from the candidate src node."); + PDGNode &Tgt=Src.back().getTargetNode(); + assert(TargetInDegreeMap.find(&Tgt)!=TargetInDegreeMap.end() && + "Expected target to be in the in-degree map."); + // Do not merge if there is also an edge from target to src (immediate + // cycle). + if (TargetInDegreeMap[&Tgt]!=1 || !areNodesMergeable(Src, Tgt) || Tgt.hasEdgeTo(Src)) + continue; + // LLVM_DEBUG(dbgs()<<"Merging:"<(b), (b)->(c), (c)->(d), ...} and the worklist is initially {b, a}, + // then after merging (a) and (b) together, we need to put (a,b) back in + // the worklist so that (c) can get merged in as well resulting in + // {(a,b,c) -> d} + // We also need to remove the old target (b), from the worklist. We first + // remove it from the candidate set here, and skip any item from the + // worklist that is not in the set. + if (CandidateSourceNodes.erase(&Tgt)) { + Worklist.push_back(&Src); + CandidateSourceNodes.insert(&Src); + LLVM_DEBUG(dbgs()<<"Putting "<<&Src<<" back in the worklist.\n"); + } + } + LLVM_DEBUG(dbgs()<<"=== End of Graph Simplification ===\n"); } void PDGBuilder::createPiBlocks() { - using NodeListType=SmallVector; - if (!mCreatedPiBlocks) - return; - LLVM_DEBUG(dbgs()<<"==== Start of Creation of Pi-Blocks ===\n"); - // The overall algorithm is as follows: - // 1. Identify SCCs and for each SCC create a pi-block node containing all - // the nodes in that SCC. - // 2. Identify incoming edges incident to the nodes inside of the SCC and - // reconnect them to the pi-block node. - // 3. Identify outgoing edges from the nodes inside of the SCC to nodes - // outside of it and reconnect them so that the edges are coming out of the - // SCC node instead. - - // Adding nodes as we iterate through the SCCs cause the SCC - // iterators to get invalidated. To prevent this invalidation, we first - // collect a list of nodes that are part of an SCC, and then iterate over - // those lists to create the pi-block nodes. Each element of the list is a - // list of nodes in an SCC. Note: trivial SCCs containing a single node are - // ignored. - SmallVector ListOfSCCs; - for (const vector &SCC : make_range(scc_begin(&mGraph), scc_end(&mGraph))) - if (SCC.size()>1) - ListOfSCCs.emplace_back(SCC.begin(), SCC.end()); - for (NodeListType &NL : ListOfSCCs) { - LLVM_DEBUG(dbgs()<<"Creating pi-block node with "< NodesInSCC(NL.begin(), NL.end()); - // We have the set of nodes in the SCC. We go through the set of nodes - // that are outside of the SCC and look for edges that cross the two sets. - for (auto ExternalNodeIt=mGraph.begin(); ExternalNodeIt!=mGraph.end();) { - // Skip the SCC node. - if (*ExternalNodeIt==&PiNode) { - ++ExternalNodeIt; - continue; - } - // Remove SCC inlined node from graph's node list and skip it. - if (NodesInSCC.count(*ExternalNodeIt)) { - mGraph.Nodes.erase(ExternalNodeIt); - continue; - } - // Use these flags to help us avoid creating redundant edges. If there - // are more than one edges from an outside node to inside nodes, we only - // keep one edge from that node to the pi-block node. Similarly, if - // there are more than one edges from inside nodes to an outside node, - // we only keep one edge from the pi-block node to the outside node. - // There is a flag defined for each direction (incoming vs outgoing) and - // for each type of edge supported, using a two-dimensional boolean - // array. - using Direction=typename ComplexPDGEdge::Direction; - using EdgeKind=typename PDGEdge::EdgeKind; - using DependenceType=typename PDGEdge::DependenceType; - EnumeratedArray NewEdges[Direction::DirectionCount] {nullptr, nullptr}; - for (size_t SCCNodeI=0; SCCNodeI EL; - Src.findEdgesTo(Dst, EL); - if (EL.empty()) - return; - LLVM_DEBUG(dbgs()<<"reconnecting("<<(Dir==Direction::Incoming?"incoming)":"outgoing)") - <<":\nSrc:"<getDependenceType(); - if (NewEdges[Dir][Type]) { - NewEdges[Dir][Type]->absorbEdge(*OldEdge, SCCNodeI, Dir); - LLVM_DEBUG(dbgs()<<"absorbed old edge between Src and Dst.\n\n"); - } - else { - if (Dir==Direction::Incoming) { - NewEdges[Dir][Type]=new ComplexPDGEdge(PiNode, *OldEdge, SCCNodeI, Dir); - mGraph.connect(Src, PiNode, *NewEdges[Dir][Type]); - LLVM_DEBUG(dbgs()<<"created complex edge from Src to PiNode.\n"); - } - else { - NewEdges[Dir][Type]=new ComplexPDGEdge(Dst, *OldEdge, SCCNodeI, Dir); - mGraph.connect(PiNode, Dst, *NewEdges[Dir][Type]); - LLVM_DEBUG(dbgs()<<"created complex edge from PiNode to Dst.\n"); - } - } - Src.removeEdge(*OldEdge); - LLVM_DEBUG(dbgs()<<"removed old edge between Src and Dst.\n\n"); - /*if (OldEdge->getKind()==PDGEdge::EdgeKind::ComplexControl - || OldEdge->getKind()==PDGEdge::EdgeKind::ComplexData) { - OldEdge->destroy(); - LLVM_DEBUG(dbgs()<<"released memory from old complex edge between Src and Dst.\n\n"); - }*/ - } - }; - // Process incoming edges incident to the pi-block node. - ReconnectEdges(**ExternalNodeIt, *NL[SCCNodeI], Direction::Incoming); - // Process edges that are coming out of the pi-block node. - ReconnectEdges(*NL[SCCNodeI], **ExternalNodeIt, Direction::Outgoing); - } - ++ExternalNodeIt; - } - } - // Ordinal maps are no longer needed. - mInstOrdinalMap.clear(); - mNodeOrdinalMap.clear(); - LLVM_DEBUG(dbgs()<<"==== End of Creation of Pi-Blocks ===\n"); -} - -bool PDGBuilder::confirmMemoryIntersect(const Instruction &SrcInst, const Instruction &DstInst) { - bool SrcUnknownMemory=false, DstUnknownMemory=false, *CurrMarker=&SrcUnknownMemory; - MemoryLocationSet SrcMemLocs, DstMemLocs, *CurrSet=&SrcMemLocs; - auto CollectMemory=[&CurrSet](Instruction &I, MemoryLocation &&MemLoc, unsigned OpInd, - AccessInfo IsRead, AccessInfo IsWrite) { - CurrSet->insert(MemLoc); - }; - auto EvaluateUnknown=[&CurrMarker](Instruction&, AccessInfo, AccessInfo) { - *CurrMarker=true; - }; - for_each_memory(const_cast(SrcInst), const_cast(mTLI), - CollectMemory, EvaluateUnknown); - CurrSet=&DstMemLocs; - CurrMarker=&DstUnknownMemory; - for_each_memory(const_cast(DstInst), const_cast(mTLI), - CollectMemory, EvaluateUnknown); - if (SrcMemLocs.empty() || DstMemLocs.empty()) - return SrcMemLocs.empty() && !SrcUnknownMemory || DstMemLocs.empty() && !DstUnknownMemory; - SmallVector SrcDIMems, SrcServerDIMems, DstDIMems, DstServerDIMems; - auto FillDIMemories=[&](const MemoryLocationSet &MemoryLocations, SmallVectorImpl &DIMemories, - SmallVectorImpl &ServerDIMemories) { - for (auto &MemLoc : MemoryLocations) { - const EstimateMemory *EstMem=mAT.find(MemLoc); - const MDNode *MDNode; - while (!(MDNode=getRawDIMemoryIfExists(*EstMem, mF.getContext(), - mF.getParent()->getDataLayout(), mAT.getDomTree()))) - EstMem=EstMem->getParent(); - DIMemories.push_back(&*mDIAT.find(*MDNode)); - ServerDIMemories.push_back(mDIMInfo.findFromClient(*EstMem, SrcInst.getModule()->getDataLayout(), - const_cast(mAT.getDomTree())).get()); - } - }; - FillDIMemories(SrcMemLocs, SrcDIMems, SrcServerDIMems); - FillDIMemories(DstMemLocs, DstDIMems, DstServerDIMems); - bool ShouldDelete=true; - for (int SrcI=0; SrcIgetAliasNode()) && - (DstDINode=DstDIMems[DstI]->getAliasNode()) && - mDIATRel.compare(SrcDINode, DstDINode)!=TreeRelation::TR_UNREACHABLE && - (!mServerDIATRel || - SrcServerDIMems[SrcI] && - DstServerDIMems[DstI] && - (SrcServerDINode=SrcServerDIMems[SrcI]->getAliasNode()) && - (DstServerDINode=DstServerDIMems[DstI]->getAliasNode()) && - mServerDIATRel.value().compare(SrcServerDINode, DstServerDINode)!=TreeRelation::TR_UNREACHABLE) - ) - ShouldDelete=false; - } - } - if (ShouldDelete) - return false; - else { - // At this point we have dependence confirmed by AliasTrees - // mOverridenDeps.insert({{&Src, &Dst}, }) - return true; - } + using NodeListType=SmallVector; + if (!mCreatedPiBlocks) + return; + LLVM_DEBUG(dbgs()<<"==== Start of Creation of Pi-Blocks ===\n"); + // The overall algorithm is as follows: + // 1. Identify SCCs and for each SCC create a pi-block node containing all + // the nodes in that SCC. + // 2. Identify incoming edges incident to the nodes inside of the SCC and + // reconnect them to the pi-block node. + // 3. Identify outgoing edges from the nodes inside of the SCC to nodes + // outside of it and reconnect them so that the edges are coming out of the + // SCC node instead. + + // Adding nodes as we iterate through the SCCs cause the SCC + // iterators to get invalidated. To prevent this invalidation, we first + // collect a list of nodes that are part of an SCC, and then iterate over + // those lists to create the pi-block nodes. Each element of the list is a + // list of nodes in an SCC. Note: trivial SCCs containing a single node are + // ignored. + SmallVector ListOfSCCs; + for (const vector &SCC : make_range(scc_begin(&mGraph), scc_end(&mGraph))) + if (SCC.size()>1) + ListOfSCCs.emplace_back(SCC.begin(), SCC.end()); + for (NodeListType &NL : ListOfSCCs) { + LLVM_DEBUG(dbgs()<<"Creating pi-block node with "< NodesInSCC(NL.begin(), NL.end()); + // We have the set of nodes in the SCC. We go through the set of nodes + // that are outside of the SCC and look for edges that cross the two sets. + for (auto ExternalNodeIt=mGraph.begin(); ExternalNodeIt!=mGraph.end();) { + // Skip the SCC node. + if (*ExternalNodeIt==&PiNode) { + ++ExternalNodeIt; + continue; + } + // Remove SCC inlined node from graph's node list and skip it. + if (NodesInSCC.count(*ExternalNodeIt)) { + mGraph.Nodes.erase(ExternalNodeIt); + continue; + } + // Use these flags to help us avoid creating redundant edges. If there + // are more than one edges from an outside node to inside nodes, we only + // keep one edge from that node to the pi-block node. Similarly, if + // there are more than one edges from inside nodes to an outside node, + // we only keep one edge from the pi-block node to the outside node. + // There is a flag defined for each direction (incoming vs outgoing) and + // for each type of edge supported, using a two-dimensional boolean + // array. + using Direction=typename ComplexPDGEdge::Direction; + using EdgeKind=typename PDGEdge::EdgeKind; + using DependenceType=typename PDGEdge::DependenceType; + EnumeratedArray NewEdges[Direction::DirectionCount] {nullptr, nullptr}; + for (size_t SCCNodeI=0; SCCNodeI EL; + Src.findEdgesTo(Dst, EL); + if (EL.empty()) + return; + LLVM_DEBUG(dbgs()<<"reconnecting("<<(Dir==Direction::Incoming?"incoming)":"outgoing)") + <<":\nSrc:"<getDependenceType(); + if (NewEdges[Dir][Type]) { + NewEdges[Dir][Type]->absorbEdge(*OldEdge, SCCNodeI, Dir); + LLVM_DEBUG(dbgs()<<"absorbed old edge between Src and Dst.\n\n"); + } + else { + if (Dir==Direction::Incoming) { + NewEdges[Dir][Type]=new ComplexPDGEdge(PiNode, *OldEdge, SCCNodeI, Dir); + mGraph.connect(Src, PiNode, *NewEdges[Dir][Type]); + LLVM_DEBUG(dbgs()<<"created complex edge from Src to PiNode.\n"); + } + else { + NewEdges[Dir][Type]=new ComplexPDGEdge(Dst, *OldEdge, SCCNodeI, Dir); + mGraph.connect(PiNode, Dst, *NewEdges[Dir][Type]); + LLVM_DEBUG(dbgs()<<"created complex edge from PiNode to Dst.\n"); + } + } + Src.removeEdge(*OldEdge); + LLVM_DEBUG(dbgs()<<"removed old edge between Src and Dst.\n\n"); + /*if (OldEdge->getKind()==PDGEdge::EdgeKind::ComplexControl + || OldEdge->getKind()==PDGEdge::EdgeKind::ComplexData) { + OldEdge->destroy(); + LLVM_DEBUG(dbgs()<<"released memory from old complex edge between Src and Dst.\n\n"); + }*/ + } + }; + // Process incoming edges incident to the pi-block node. + ReconnectEdges(**ExternalNodeIt, *NL[SCCNodeI], Direction::Incoming); + // Process edges that are coming out of the pi-block node. + ReconnectEdges(*NL[SCCNodeI], **ExternalNodeIt, Direction::Outgoing); + } + ++ExternalNodeIt; + } + } + // Ordinal maps are no longer needed. + mInstOrdinalMap.clear(); + mNodeOrdinalMap.clear(); + LLVM_DEBUG(dbgs()<<"==== End of Creation of Pi-Blocks ===\n"); +} + +bool PDGBuilder::confirmMemoryIntersect(const Instruction &SrcInst, + const Instruction &DstInst, MemoryPDGEdge::DIDepStorageT &NewForwardDep, + MemoryPDGEdge::DIDepStorageT &NewBackwardDep) { + bool SrcUnknownMemory=false, DstUnknownMemory=false, + *CurrMarker=&SrcUnknownMemory; + MemoryLocationSet SrcMemLocs, DstMemLocs, *CurrSet=&SrcMemLocs; + auto CollectMemory=[&CurrSet](Instruction &I, MemoryLocation &&MemLoc, + unsigned OpInd, AccessInfo IsRead, AccessInfo IsWrite) { + CurrSet->insert(MemLoc); + }; + auto EvaluateUnknown=[&CurrMarker](Instruction&, AccessInfo, AccessInfo) { + *CurrMarker=true; + }; + for_each_memory(const_cast(SrcInst), + const_cast(mTLI), CollectMemory, EvaluateUnknown); + CurrSet=&DstMemLocs; + CurrMarker=&DstUnknownMemory; + for_each_memory(const_cast(DstInst), + const_cast(mTLI), CollectMemory, EvaluateUnknown); + if (SrcMemLocs.empty() || DstMemLocs.empty()) + return SrcMemLocs.empty() && !SrcUnknownMemory || DstMemLocs.empty() && + !DstUnknownMemory; + SmallVector SrcClientDIMems, SrcServerDIMems, + DstClientDIMems, DstServerDIMems; + // SmallSetVector SrcClientDIMems, SrcServerDIMems, + // DstClientDIMems, DstServerDIMems; + auto FillDIMemories=[this, &SrcInst](const MemoryLocationSet &MemLocs, + SmallVectorImpl &DIMemories, + SmallVectorImpl &ServerDIMemories) { + for (auto &MemLoc : MemLocs) { + const EstimateMemory *EstMem=mAT.find(MemLoc); + const MDNode *Metadata; + while (!(Metadata=getRawDIMemoryIfExists(*EstMem, mF.getContext(), + mF.getParent()->getDataLayout(), mAT.getDomTree()))) + EstMem=EstMem->getParent(); + DIMemories.push_back(&*mDIMInfo.ClientDIAT->find(*Metadata)); + if (mDIMInfo.isServerAvailable()) + ServerDIMemories.push_back(mDIMInfo.findFromClient(*EstMem, + SrcInst.getModule()->getDataLayout(), + const_cast(mAT.getDomTree())).get()); + } + }; + FillDIMemories(SrcMemLocs, SrcClientDIMems, SrcServerDIMems); + FillDIMemories(DstMemLocs, DstClientDIMems, DstServerDIMems); + bool HasDependence=false, FoundMemory=false; + for (int SrcI=0; SrcIgetAliasNode()) && + (DstServerDINode=DstServerDIMems[DstI]->getAliasNode()) + ) { + if (mServerDIATRel.value().compare(SrcServerDINode, DstServerDINode)!= + TreeRelation::TR_UNREACHABLE) + HasDependence=true; + } + else + if ( + SrcClientDIMems[SrcI] && + DstClientDIMems[DstI] && + (SrcDINode=SrcClientDIMems[SrcI]->getAliasNode()) && + (DstDINode=DstClientDIMems[DstI]->getAliasNode()) && + mDIATRel.compare(SrcDINode, DstDINode)!=TreeRelation::TR_UNREACHABLE + ) + HasDependence=true; + FoundMemory|=SrcDINode && DstDINode || SrcServerDINode && + DstServerDINode; + } + } + if (!HasDependence && FoundMemory) + return false; + // At this point we have dependence confirmed by AliasTrees + auto FindDIDependencies=[this, &SrcInst, &DstInst, &NewForwardDep, + &NewBackwardDep](const SmallVectorImpl &SrcDIMems, + const SmallVectorImpl &DstDIMems, + const SpanningTreeRelation &DIATRel) -> void { + using namespace trait; + auto FindCommonLoop=[](const Loop *&SrcL, const Loop *&DstL) + -> const Loop* { + if (!SrcL || !DstL) + return nullptr; + if (SrcL->getLoopDepth()getLoopDepth()) { + unsigned LargerNL=DstL->getLoopDepth(); + for (; LargerNL>SrcL->getLoopDepth(); --LargerNL) + DstL=DstL->getParentLoop(); + } + else { + unsigned LargerNL=SrcL->getLoopDepth(); + for (; LargerNL>DstL->getLoopDepth(); --LargerNL) + SrcL=SrcL->getParentLoop(); + } + while (SrcL!=DstL) { + SrcL=SrcL->getParentLoop(); + DstL=DstL->getParentLoop(); + } + if (SrcL) { + const Loop *Result=SrcL; + SrcL=SrcL->getParentLoop(); + DstL=DstL->getParentLoop(); + return Result; + } + return nullptr; + }; + SmallPtrSet NewDepSet; + NewForwardDep.clear(); + NewBackwardDep.clear(); + // Attempting to arrange Instruction's DI-mems sets for possible better + // dependence analysis + const SmallVectorImpl *LowerMem, *HigherMem; + auto DefineMemOrder=[&LowerMem, &HigherMem, &DIATRel, + &SrcDIMems, &DstDIMems]() -> void { + for (const DIMemory *SrcMem : SrcDIMems) + for (const DIMemory *DstMem : DstDIMems) { + const DIAliasNode *SrcAliasN, *DstAliasN; + if (SrcMem && DstMem && (SrcAliasN=SrcMem->getAliasNode()) && + (DstAliasN=DstMem->getAliasNode())) + if (DIATRel.compare(SrcAliasN, DstAliasN)== + TreeRelation::TR_ANCESTOR) { + LowerMem=&DstDIMems; + HigherMem=&SrcDIMems; + return; + } + else + if (DIATRel.compare(SrcAliasN, DstAliasN)== + TreeRelation::TR_DESCENDANT) { + LowerMem=&SrcDIMems; + HigherMem=&DstDIMems; + return; + } + } + LowerMem=&SrcDIMems; + HigherMem=&DstDIMems; + }; + DefineMemOrder(); + const Loop *SrcL=mLI[SrcInst.getParent()], *DstL=mLI[DstInst.getParent()]; + while (const Loop *CommonLopp=FindCommonLoop(SrcL, DstL)) { + const DIDependenceSet *DIDepSet=mDIMInfo.findFromClient(*CommonLopp); + if (!DIDepSet) + continue; + for (const DIMemory *LoMem : *LowerMem) { + for (const DIAliasTrait &AT : *DIDepSet) { + auto MemAccessIt=AT.find(LoMem); + if (MemAccessIt==AT.end()) + continue; + const DIMemoryTraitRef &MemAccess=*MemAccessIt; + const DIDependence *FlowDep=MemAccess->get(), + *AntiDep=MemAccess->get(), + *OutputDep=MemAccess->get(); + if (NewDepSet.contains(FlowDep) || NewDepSet.contains(AntiDep) || + NewDepSet.contains(OutputDep)) + continue; + MemoryPDGEdge::DIDepKind FlowDK, AntiDK, OutputDK; + FlowDK.set(); + AntiDK.set(); + OutputDK.set(); + // First, we check Causes + auto CheckCauses=[&SrcInst, &DstInst, &NewForwardDep, + &NewBackwardDep, &NewDepSet, &MemAccess](const DIDependence *Dep, + MemoryPDGEdge::DIDepKind DK) -> bool { + if (!Dep) + return false; + for (const DIDependence::Cause &C : Dep->getCauses()) + if (C.get()) + if (SrcInst.getDebugLoc() && C.get()== + SrcInst.getDebugLoc()) { + NewForwardDep.push_back({MemAccess, DK}); + NewDepSet.insert(Dep); + return true; + } + else + if (DstInst.getDebugLoc() && C.get()== + DstInst.getDebugLoc()) { + NewBackwardDep.push_back({MemAccess, DK}); + NewDepSet.insert(Dep); + return true; + } + return false; + }; + if (CheckCauses(FlowDep, FlowDK) || CheckCauses(AntiDep, AntiDK) || + CheckCauses(OutputDep, OutputDK)) + continue; + auto HiMemIt=find(HigherMem->begin(), HigherMem->end(), + MemAccess->getMemory()); + if (HiMemIt==HigherMem->end()) + continue; + const DIMemoryTraitSet &DepTS=MemAccess->getSecond(); + if (SrcInst.mayWriteToMemory() && !SrcInst.mayReadFromMemory()) { + if (DstInst.mayReadFromMemory() && !DstInst.mayWriteToMemory()) { + if (FlowDep) { + NewForwardDep.push_back({MemAccess, FlowDK}); + NewDepSet.insert(FlowDep); + } + if (AntiDep) { + NewBackwardDep.push_back({MemAccess, AntiDK}); + NewDepSet.insert(AntiDep); + } + } + else + if (DstInst.mayWriteToMemory() && !DstInst.mayReadFromMemory() && + OutputDep) { + NewForwardDep.push_back({MemAccess, OutputDK}); + NewBackwardDep.push_back({MemAccess, OutputDK}); + NewDepSet.insert(OutputDep); + } + } + else + if (SrcInst.mayReadFromMemory() && !SrcInst.mayWriteToMemory() && + DstInst.mayWriteToMemory() && !DstInst.mayReadFromMemory()) { + if (FlowDep) { + NewBackwardDep.push_back({MemAccess, FlowDK}); + NewDepSet.insert(FlowDep); + } + if (AntiDep) { + NewForwardDep.push_back({MemAccess, AntiDK}); + NewDepSet.insert(AntiDep); + } + } + } + } + } + }; + if (!mDIMInfo) + return true; + if (mDIMInfo.isServerAvailable()) + FindDIDependencies(SrcServerDIMems, DstServerDIMems, + mServerDIATRel.value()); + else + FindDIDependencies(SrcClientDIMems, DstClientDIMems, mDIATRel); + return true; } char ProgramDependencyGraphPass::ID=0; INITIALIZE_PASS_BEGIN(ProgramDependencyGraphPass, "pdg", - "Program Dependency Graph", false, true) + "Program Dependency Graph", false, true) INITIALIZE_PASS_DEPENDENCY(DependenceAnalysisWrapperPass) +INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) INITIALIZE_PASS_DEPENDENCY(EstimateMemoryPass) INITIALIZE_PASS_DEPENDENCY(DIEstimateMemoryPass) INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) INITIALIZE_PASS_END(ProgramDependencyGraphPass, "pdg", - "Program Dependency Graph", false, true) + "Program Dependency Graph", false, true) -FunctionPass *createProgramDependencyGraphPass() { return new ProgramDependencyGraphPass; } +FunctionPass *createProgramDependencyGraphPass() { + return new ProgramDependencyGraphPass; +} void ProgramDependencyGraphPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired(); - AU.addRequired(); - AU.addRequired(); - AU.addRequired(); - AU.setPreservesAll(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.addRequired(); + AU.setPreservesAll(); } bool ProgramDependencyGraphPass::runOnFunction(Function &F) { - releaseMemory(); - DependenceAnalysisWrapperPass &DIPass=getAnalysis(); - EstimateMemoryPass &EMPass=getAnalysis(); - DIEstimateMemoryPass &DIEMPass=getAnalysis(); - TargetLibraryInfoWrapperPass &TLIPass=getAnalysis(); - DIMemoryClientServerInfo DIMInfo(const_cast(DIEMPass.getAliasTree()), *this, F); - mPDG=new ProgramDependencyGraph(F); - mPDGBuilder=new PDGBuilder(*mPDG, DIPass.getDI(), F, EMPass.getAliasTree(), DIEMPass.getAliasTree(), TLIPass.getTLI(F), DIMInfo, true); - mPDGBuilder->populate(); - return false; + releaseMemory(); + DependenceAnalysisWrapperPass &DIPass= + getAnalysis(); + LoopInfoWrapperPass &LIPass=getAnalysis(); + EstimateMemoryPass &EMPass=getAnalysis(); + DIEstimateMemoryPass &DIEMPass=getAnalysis(); + TargetLibraryInfoWrapperPass &TLIPass= + getAnalysis(); + DIMemoryClientServerInfo DIMInfo(const_cast(DIEMPass. + getAliasTree()), *this, F); + mPDG=new ProgramDependencyGraph(F); + mPDGBuilder=new PDGBuilder(*mPDG, + DIPass.getDI(), + F, + EMPass.getAliasTree(), + TLIPass.getTLI(F), + DIMInfo, + LIPass.getLoopInfo(), + true); + mPDGBuilder->populate(); + return false; } namespace { struct PDGPassGraphTraits { - static const ProgramDependencyGraph *getGraph(ProgramDependencyGraphPass *P) { return &P->getPDG(); } + static const PDG *getGraph(ProgramDependencyGraphPass *P) { + return &P->getPDG(); + } }; struct PDGPrinter : public DOTGraphTraitsPrinterWrapperPass< - ProgramDependencyGraphPass, false, const ProgramDependencyGraph*, - PDGPassGraphTraits> { - static char ID; - PDGPrinter() : DOTGraphTraitsPrinterWrapperPass("pdg", ID) { - initializePDGPrinterPass(*PassRegistry::getPassRegistry()); - } + ProgramDependencyGraphPass, false, const PDG*, PDGPassGraphTraits> { + static char ID; + PDGPrinter() : DOTGraphTraitsPrinterWrapperPass("pdg", ID) { + initializePDGPrinterPass(*PassRegistry::getPassRegistry()); + } }; -char PDGPrinter::ID = 0; +char PDGPrinter::ID=0; struct PDGViewer : public DOTGraphTraitsViewerWrapperPass< - ProgramDependencyGraphPass, false, const ProgramDependencyGraph*, - PDGPassGraphTraits> { - static char ID; - PDGViewer() : DOTGraphTraitsViewerWrapperPass("pdg", ID) { - initializePDGViewerPass(*PassRegistry::getPassRegistry()); - } + ProgramDependencyGraphPass, false, const PDG*, + PDGPassGraphTraits> { + static char ID; + PDGViewer() : DOTGraphTraitsViewerWrapperPass("pdg", ID) { + initializePDGViewerPass(*PassRegistry::getPassRegistry()); + } }; -char PDGViewer::ID = 0; +char PDGViewer::ID=0; } //anonymous namespace INITIALIZE_PASS_IN_GROUP(PDGViewer, "view-pdg", - "View Program Dependency Graph", true, true, - DefaultQueryManager::OutputPassGroup::getPassRegistry()) + "View Program Dependency Graph", true, true, + DefaultQueryManager::OutputPassGroup::getPassRegistry()) INITIALIZE_PASS_IN_GROUP(PDGPrinter, "print-pdg", - "Print Program Dependency Graph", true, true, - DefaultQueryManager::OutputPassGroup::getPassRegistry()) + "Print Program Dependency Graph", true, true, + DefaultQueryManager::OutputPassGroup::getPassRegistry()) FunctionPass *llvm::createPDGPrinter() { - return new PDGPrinter; + return new PDGPrinter; } FunctionPass *llvm::createPDGViewer() { - return new PDGViewer; + return new PDGViewer; } From b279e0d1c7924962a45efb168177e9fbf4b0c582 Mon Sep 17 00:00:00 2001 From: a_zel Date: Sun, 21 Apr 2024 07:46:44 +0300 Subject: [PATCH 8/9] with another tsar's traits (and, again, shadowed llvm) --- include/tsar/Analysis/PDG.h | 87 ++++++++---- lib/Analysis/PDG.cpp | 273 +++++++++++++++++++++--------------- 2 files changed, 217 insertions(+), 143 deletions(-) diff --git a/include/tsar/Analysis/PDG.h b/include/tsar/Analysis/PDG.h index 06942326..a7eb457d 100644 --- a/include/tsar/Analysis/PDG.h +++ b/include/tsar/Analysis/PDG.h @@ -281,8 +281,10 @@ class PDGEdge : public PDGEdgeBase { class MemoryPDGEdge : public PDGEdge { public: - using DIDepKind=bcl::TraitDescriptor< - bcl::TraitAlternative>; + /*using DIDepKind=bcl::TraitDescriptor< + bcl::TraitAlternative>;*/ + using DIDepKind=MemoryDescriptor; + // 1. /*using DIDepT=bcl::tagged_pair< bcl::tagged, @@ -413,12 +415,14 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream&, const ProgramDependencyGraph&) class PDGBuilder { using MemoryLocationSet=llvm::SmallDenseSet; public: - PDGBuilder(ProgramDependencyGraph &G, llvm::DependenceInfo &DI, const llvm::Function &F, const AliasTree &AT, + PDGBuilder(ProgramDependencyGraph &G, llvm::DependenceInfo &DI, + const llvm::Function &F, const AliasTree &AT, const llvm::TargetLibraryInfo &TLI, DIMemoryClientServerInfo &DIMInfo, - const llvm::LoopInfo &LI, bool ShouldSolveReachability=true, bool ShouldSimplify=false, - bool ShouldCreatePiBlocks=false) + const llvm::LoopInfo &LI, bool ShouldSolveReachability=true, + bool ShouldSimplify=false, bool ShouldCreatePiBlocks=false) : mGraph(G), mDI(DI), mF(F), mAT(AT), mTLI(TLI), mDIMInfo(DIMInfo), - mLI(LI), mDIATRel(DIMInfo.DIAT), mSolvedReachability(ShouldSolveReachability), + mLI(LI), mDIATRel(DIMInfo.DIAT), + mSolvedReachability(ShouldSolveReachability), mSimplified(ShouldSimplify), mCreatedPiBlocks(ShouldCreatePiBlocks), mBBList(F.size()) { if (mDIMInfo.isValid()) @@ -448,10 +452,18 @@ class PDGBuilder { llvm::DOTFuncInfo DOTCFGInfo(&F); llvm::dumpDotGraphToFile(&DOTCFGInfo, "ircfg.dot", "control flow graph"); // + // Code below prints DIDependenceInfo, + // which contains a set of DIAliasTraits for each loop in function + // In each DIMemoryTrait it attempts to find NoAccess, ReadOnly, Shared, + // Local, Private, FirstPrivate, SecondToLastPrivate, LastPrivate, + // DynamicPrivate and, finally, Flow, Anti, Output + { + using namespace trait; for (auto &DepInfoRecord : *mDIMInfo.DIDepInfo) { for (const DIAliasTrait &AT : DepInfoRecord.second) { for (const DIMemoryTraitRef &MTRef : AT) { - auto PrintDistanceVector=[](const trait::DIDependence *Dep) -> std::string { + auto PrintDistanceVector=[](const trait::DIDependence *Dep) + -> std::string { std::string Result; llvm::raw_string_ostream OS(Result); if (Dep->getKnownLevel()==0) @@ -460,42 +472,57 @@ class PDGBuilder { if (Dep->getDistance(0).first==Dep->getDistance(0).second) OS<getDistance(0).first; else - OS<<"("<getDistance(0).first<<", "<getDistance(0).second<<")"; + OS<<"("<getDistance(0).first<<", "<< + Dep->getDistance(0).second<<")"; for (int Level=1; LevelgetKnownLevel(); ++Level) - if (Dep->getDistance(Level).first==Dep->getDistance(Level).second) + if (Dep->getDistance(Level).first== + Dep->getDistance(Level).second) OS<<", "<getDistance(Level).first; else - OS<<", ("<getDistance(Level).first<<", "<getDistance(Level).second<<")"; + OS<<", ("<getDistance(Level).first<<", "<< + Dep->getDistance(Level).second<<")"; OS<<">"; return Result; }; + if (MTRef->is()) + std::cout<<"------------NoAccess\n"; + if (MTRef->is()) + std::cout<<"------------Readonly\n"; + if (MTRef->is()) + std::cout<<"------------Shared\n"; + /*if (MTRef->is()) + std::cout<<" - - -Local\n";*/ + if (MTRef->is()) + std::cout<<"------------Private\n"; + if (MTRef->is()) + std::cout<<"------------FirstPrivate\n"; + if (MTRef->is()) + std::cout<<"------------SecondToLastPrivate\n"; + if (MTRef->is()) + std::cout<<"------------LastPrivate\n"; + if (MTRef->is()) + std::cout<<"------------DynamicPrivate\n"; trait::DIDependence *DIFlow=MTRef->get(), *DIAnti=MTRef->get(), *DIOutput=MTRef->get(), *Actual; - if (DIFlow) { - std::cout<<" FLOW, causes size - "<getCauses().size() - <<", dist-vec - "; - std::cout<getCauses().size() - <<", dist-vec - "; - std::cout<getCauses().size() - <<", dist-vec - "; - std::cout<getCauses().size()<<"\n"; + if (DIAnti) + std::cout<<"------------Anti, "<getCauses().size()<<"\n"; + if (DIOutput) + std::cout<<"------------Output, "<getCauses().size()<<"\n"; + std::cout<<"--------end of di-memory-trait hasNoDep - "<< + hasNoDep(*MTRef)<<", hasSpuriosDep - "<(&E.getMemoryDep())) { + if (llvm::Dependence * const *Dep=std::get_if(&E. + getMemoryDep())) { (*Dep)->dump(OS); OS.str().pop_back(); } else { + using namespace trait; // DEBUG: auto PrintDIMemDep=[&OS](const MemoryPDGEdge::DIDepT &Dep) -> void { - const trait::DIDependence *DistVec; - const DIMemoryTraitRef &MTRef=Dep.first; - Dep.second.for_each([&OS, &DistVec, &MTRef]() -> void { - DistVec=MTRef->get(); - OS<getKnownLevel()==0) - return; - OS<<"<"; - if (DistVec->getDistance(0).first==DistVec->getDistance(0).second) + auto PrintDistVec=[&OS](const DIMemoryTraitRef &MT) + -> void { + const DIDependence *DistVec=MT->get(); + OS<getKnownLevel()==0) + return; + if (DistVec->getDistance(0).first==DistVec->getDistance(0).second) OS<getDistance(0).first; - else - OS<<"("<getDistance(0).first<<", "<< - DistVec->getDistance(0).second<<")"; - for (int Level=1; LevelgetKnownLevel(); ++Level) - if (DistVec->getDistance(Level).first==DistVec->getDistance(Level).second) - OS<<", "<getDistance(Level).first; else - OS<<", ("<getDistance(Level).first<<", "<< - DistVec->getDistance(Level).second<<")"; - OS<<">"; + OS<<"("<getDistance(0).first<<", "< + getDistance(0).second<<")"; + for (int Level=1; LevelgetKnownLevel(); ++Level) + if (DistVec->getDistance(Level).first==DistVec-> + getDistance(Level).second) + OS<<", "<getDistance(Level).first; + else + OS<<", ("<getDistance(Level).first<<", "< + getDistance(Level).second<<")"; + OS<<">\n"; + }; + if (Dep.second.is()) + PrintDistVec.operator()(Dep.first); + if (Dep.second.is()) + PrintDistVec.operator()(Dep.first); + if (Dep.second.is()) + PrintDistVec.operator()(Dep.first); + if (Dep.second.is()) + OS<()) + OS<()) + OS<()) + OS<()) + OS<(E.getMemoryDep()); + const MemoryPDGEdge::DIDepStorageT &DIDeps= + std::get(E.getMemoryDep()); for (auto &DIMemDep : DIDeps) { PrintDIMemDep(DIMemDep); OS<<"\n"; @@ -625,16 +644,16 @@ void PDGBuilder::createMemoryDependenceEdges() { isReachable(*SrcInstr.getParent(), *DstInstr.getParent()) || isReachable(*DstInstr.getParent(), *SrcInstr.getParent()))) continue; - // unique_ptr Dep=mDI.depends(&SrcInstr, &DstInstr, true); + unique_ptr Dep=mDI.depends(&SrcInstr, &DstInstr, true); MemoryPDGEdge::DIDepStorageT ForwardDIDep, BackwardDIDep; - /*if (!Dep) - continue;*/ + if (!Dep) + continue; // If we have a dependence with its left-most non-'=' direction // being '>' we need to reverse the direction of the edge, because // the source of the dependence cannot occur after the sink. For // confused dependencies, we will create edges in both directions to // represent the possibility of a cycle. - if (/*Dep->isConfused() &&*/ confirmMemoryIntersect(SrcInstr, DstInstr, ForwardDIDep, BackwardDIDep)) + if (/*Dep->isConfused() && */confirmMemoryIntersect(SrcInstr, DstInstr, ForwardDIDep, BackwardDIDep)) // TODO: rewrite if (!ForwardDIDep.empty() || !BackwardDIDep.empty()) { if (!ForwardDIDep.empty()) @@ -642,10 +661,14 @@ void PDGBuilder::createMemoryDependenceEdges() { if (!BackwardDIDep.empty()) CreateDepEdge(**DstNodeIt, **SrcNodeIt, BackwardDIDep); } - /*else { - CreateDepEdge(**SrcNodeIt, **DstNodeIt, Dep.release()); - CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&SrcInstr, &DstInstr, true).release()); - }*/ + else { + // if (Dep->isConfused()) { + CreateDepEdge(**SrcNodeIt, **DstNodeIt, new Dependence(&SrcInstr, &DstInstr)); + CreateDepEdge(**DstNodeIt, **SrcNodeIt, new Dependence(&DstInstr, &SrcInstr)); + // CreateDepEdge(**SrcNodeIt, **DstNodeIt, Dep.release()); + // CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&SrcInstr, &DstInstr, true).release()); + // } + } /*else if (Dep->isOrdered()) { if (!Dep->isLoopIndependent()) { bool ReversedEdge=false; @@ -653,7 +676,8 @@ void PDGBuilder::createMemoryDependenceEdges() { if (Dep->getDirection(Level)==Dependence::DVEntry::EQ) continue; else if (Dep->getDirection(Level) == Dependence::DVEntry::GT) { - CreateDepEdge(**DstNodeIt, **SrcNodeIt, std::move(Dep)); + // CreateDepEdge(**DstNodeIt, **SrcNodeIt, std::move(Dep)); + CreateDepEdge(**DstNodeIt, **SrcNodeIt, Dep.release()); ReversedEdge=true; //++TotalEdgeReversals; break; @@ -661,17 +685,21 @@ void PDGBuilder::createMemoryDependenceEdges() { else if (Dep->getDirection(Level)==Dependence::DVEntry::LT) break; else { - CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); - CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&SrcInstr, &DstInstr, true)); + // CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); + CreateDepEdge(**SrcNodeIt, **DstNodeIt, Dep.release()); + // CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&SrcInstr, &DstInstr, true)); + CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&SrcInstr, &DstInstr, true).release()); ReversedEdge=true; break; } } if (!ReversedEdge) - CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); + // CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); + CreateDepEdge(**SrcNodeIt, **DstNodeIt, Dep.release()); } else - CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); + // CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); + CreateDepEdge(**SrcNodeIt, **DstNodeIt, Dep.release()); }*/ } } @@ -942,8 +970,8 @@ bool PDGBuilder::confirmMemoryIntersect(const Instruction &SrcInst, for_each_memory(const_cast(DstInst), const_cast(mTLI), CollectMemory, EvaluateUnknown); if (SrcMemLocs.empty() || DstMemLocs.empty()) - return SrcMemLocs.empty() && !SrcUnknownMemory || DstMemLocs.empty() && - !DstUnknownMemory; + return !(SrcMemLocs.empty() && !SrcUnknownMemory || DstMemLocs.empty() && + !DstUnknownMemory); SmallVector SrcClientDIMems, SrcServerDIMems, DstClientDIMems, DstServerDIMems; // SmallSetVector SrcClientDIMems, SrcServerDIMems, @@ -997,12 +1025,15 @@ bool PDGBuilder::confirmMemoryIntersect(const Instruction &SrcInst, } if (!HasDependence && FoundMemory) return false; - // At this point we have dependence confirmed by AliasTrees + // At this point we have memory intersection confirmed by AliasTrees, + // but this fact doesn't mean the presence of dependence, so we need to + // observe trait set auto FindDIDependencies=[this, &SrcInst, &DstInst, &NewForwardDep, &NewBackwardDep](const SmallVectorImpl &SrcDIMems, const SmallVectorImpl &DstDIMems, - const SpanningTreeRelation &DIATRel) -> void { + const SpanningTreeRelation &DIATRel) -> bool { using namespace trait; + using EdgeTraitInfoT=SmallDenseMap; auto FindCommonLoop=[](const Loop *&SrcL, const Loop *&DstL) -> const Loop* { if (!SrcL || !DstL) @@ -1029,83 +1060,102 @@ bool PDGBuilder::confirmMemoryIntersect(const Instruction &SrcInst, } return nullptr; }; - SmallPtrSet NewDepSet; - NewForwardDep.clear(); - NewBackwardDep.clear(); + auto AddTrait=[](EdgeTraitInfoT &EdgeTraits, + const DIMemoryTraitRef &Access) -> void { + auto It=EdgeTraits.find(Access); + if (It!=EdgeTraits.end()) + It->second.set(); + else { + MemoryDescriptor NewDK; + NewDK.set(); + EdgeTraits.insert({Access, NewDK}); + } + }; + EdgeTraitInfoT ForwTraits, BackwTraits; + bool FoundDep=false; + const Loop *SrcL=mLI[SrcInst.getParent()], *DstL=mLI[DstInst.getParent()]; // Attempting to arrange Instruction's DI-mems sets for possible better // dependence analysis - const SmallVectorImpl *LowerMem, *HigherMem; - auto DefineMemOrder=[&LowerMem, &HigherMem, &DIATRel, - &SrcDIMems, &DstDIMems]() -> void { - for (const DIMemory *SrcMem : SrcDIMems) - for (const DIMemory *DstMem : DstDIMems) { - const DIAliasNode *SrcAliasN, *DstAliasN; - if (SrcMem && DstMem && (SrcAliasN=SrcMem->getAliasNode()) && - (DstAliasN=DstMem->getAliasNode())) + const SmallVectorImpl *LowerMem=&SrcDIMems, + *HigherMem=&DstDIMems; + for (int ExitFlag=0, SrcI=0; SrcI + getAliasNode()) && (DstAliasN=DstDIMems[DstI]->getAliasNode())) + if (DIATRel.compare(SrcAliasN, DstAliasN)== + TreeRelation::TR_ANCESTOR) { + LowerMem=&DstDIMems; + HigherMem=&SrcDIMems; + ExitFlag=1; + } + else if (DIATRel.compare(SrcAliasN, DstAliasN)== - TreeRelation::TR_ANCESTOR) { - LowerMem=&DstDIMems; - HigherMem=&SrcDIMems; - return; + TreeRelation::TR_DESCENDANT) { + LowerMem=&SrcDIMems; + HigherMem=&DstDIMems; + ExitFlag=1; } - else - if (DIATRel.compare(SrcAliasN, DstAliasN)== - TreeRelation::TR_DESCENDANT) { - LowerMem=&SrcDIMems; - HigherMem=&DstDIMems; - return; - } - } - LowerMem=&SrcDIMems; - HigherMem=&DstDIMems; - }; - DefineMemOrder(); - const Loop *SrcL=mLI[SrcInst.getParent()], *DstL=mLI[DstInst.getParent()]; + } while (const Loop *CommonLopp=FindCommonLoop(SrcL, DstL)) { const DIDependenceSet *DIDepSet=mDIMInfo.findFromClient(*CommonLopp); if (!DIDepSet) continue; for (const DIMemory *LoMem : *LowerMem) { for (const DIAliasTrait &AT : *DIDepSet) { - auto MemAccessIt=AT.find(LoMem); - if (MemAccessIt==AT.end()) - continue; - const DIMemoryTraitRef &MemAccess=*MemAccessIt; - const DIDependence *FlowDep=MemAccess->get(), - *AntiDep=MemAccess->get(), - *OutputDep=MemAccess->get(); - if (NewDepSet.contains(FlowDep) || NewDepSet.contains(AntiDep) || - NewDepSet.contains(OutputDep)) - continue; - MemoryPDGEdge::DIDepKind FlowDK, AntiDK, OutputDK; - FlowDK.set(); - AntiDK.set(); - OutputDK.set(); - // First, we check Causes - auto CheckCauses=[&SrcInst, &DstInst, &NewForwardDep, - &NewBackwardDep, &NewDepSet, &MemAccess](const DIDependence *Dep, - MemoryPDGEdge::DIDepKind DK) -> bool { + auto CheckCauses=[&SrcInst, &DstInst, &ForwTraits, &BackwTraits, + &AddTrait](const DIMemoryTraitRef &Access) + -> bool { + DIDependence *Dep=Access->get(); if (!Dep) return false; for (const DIDependence::Cause &C : Dep->getCauses()) if (C.get()) if (SrcInst.getDebugLoc() && C.get()== SrcInst.getDebugLoc()) { - NewForwardDep.push_back({MemAccess, DK}); - NewDepSet.insert(Dep); + AddTrait.operator()(ForwTraits, Access); return true; } else if (DstInst.getDebugLoc() && C.get()== DstInst.getDebugLoc()) { - NewBackwardDep.push_back({MemAccess, DK}); - NewDepSet.insert(Dep); + AddTrait.operator()(BackwTraits, Access); return true; } return false; }; - if (CheckCauses(FlowDep, FlowDK) || CheckCauses(AntiDep, AntiDK) || - CheckCauses(OutputDep, OutputDK)) + auto CheckPrivateTrait=[&ForwTraits, &BackwTraits, &AddTrait] + (const DIMemoryTraitRef &Access) -> bool { + if (Access->is()) { + AddTrait.operator()(ForwTraits, Access); + AddTrait.operator()(BackwTraits, Access); + return true; + } + return false; + }; + auto MemAccessIt=AT.find(LoMem); + if (MemAccessIt==AT.end()) + continue; + const DIMemoryTraitRef &MemAccess=*MemAccessIt; + // 1.: NoAccess, Readonly, Shared - No dependencies + // It is worth to notice, that hasSpuriosDep really excludes some + // of deps (mostly containing unions of private-like and shared + // traits), which would have been showed otherwise + if (hasNoDep(*MemAccess) || hasSpuriousDep(*MemAccess)) + continue; + FoundDep=true; + // 2.: Private, FirstPrivate, SecondToLastPrivate, LastPrivate, + // DynamicPrivate - All dependencies + if (CheckPrivateTrait.operator()(MemAccess) || + CheckPrivateTrait.operator()(MemAccess) || + CheckPrivateTrait.operator()(MemAccess) || + CheckPrivateTrait.operator()(MemAccess) || + CheckPrivateTrait.operator()(MemAccess)) + continue; + // 3.: Flow, Anti, Output - Concrete dependence + if (CheckCauses.operator()(MemAccess) || + CheckCauses.operator()(MemAccess) || + CheckCauses.operator()(MemAccess)) continue; auto HiMemIt=find(HigherMem->begin(), HigherMem->end(), MemAccess->getMemory()); @@ -1114,47 +1164,44 @@ bool PDGBuilder::confirmMemoryIntersect(const Instruction &SrcInst, const DIMemoryTraitSet &DepTS=MemAccess->getSecond(); if (SrcInst.mayWriteToMemory() && !SrcInst.mayReadFromMemory()) { if (DstInst.mayReadFromMemory() && !DstInst.mayWriteToMemory()) { - if (FlowDep) { - NewForwardDep.push_back({MemAccess, FlowDK}); - NewDepSet.insert(FlowDep); - } - if (AntiDep) { - NewBackwardDep.push_back({MemAccess, AntiDK}); - NewDepSet.insert(AntiDep); - } + if (MemAccess->is()) + AddTrait.operator()(ForwTraits, MemAccess); + if (MemAccess->is()) + AddTrait.operator()(BackwTraits, MemAccess); } else if (DstInst.mayWriteToMemory() && !DstInst.mayReadFromMemory() && - OutputDep) { - NewForwardDep.push_back({MemAccess, OutputDK}); - NewBackwardDep.push_back({MemAccess, OutputDK}); - NewDepSet.insert(OutputDep); + MemAccess->is()) { + AddTrait.operator()(ForwTraits, MemAccess); + AddTrait.operator()(BackwTraits, MemAccess); } } else if (SrcInst.mayReadFromMemory() && !SrcInst.mayWriteToMemory() && DstInst.mayWriteToMemory() && !DstInst.mayReadFromMemory()) { - if (FlowDep) { - NewBackwardDep.push_back({MemAccess, FlowDK}); - NewDepSet.insert(FlowDep); - } - if (AntiDep) { - NewForwardDep.push_back({MemAccess, AntiDK}); - NewDepSet.insert(AntiDep); - } + if (MemAccess->is()) + AddTrait.operator()(BackwTraits, MemAccess); + if (MemAccess->is()) + AddTrait.operator()(ForwTraits, MemAccess); } } } } + NewForwardDep.clear(); + NewBackwardDep.clear(); + for (auto &DepTrait : ForwTraits) + NewForwardDep.push_back(DepTrait); + for (auto &DepTrait : BackwTraits) + NewBackwardDep.push_back(DepTrait); + return FoundDep; }; if (!mDIMInfo) return true; if (mDIMInfo.isServerAvailable()) - FindDIDependencies(SrcServerDIMems, DstServerDIMems, + return FindDIDependencies(SrcServerDIMems, DstServerDIMems, mServerDIATRel.value()); else - FindDIDependencies(SrcClientDIMems, DstClientDIMems, mDIATRel); - return true; + return FindDIDependencies(SrcClientDIMems, DstClientDIMems, mDIATRel); } char ProgramDependencyGraphPass::ID=0; From 592a5777d264ea459e0703bc2627ce1f85af988e Mon Sep 17 00:00:00 2001 From: a_zel Date: Fri, 3 May 2024 20:35:50 +0300 Subject: [PATCH 9/9] 1. fixed bug with client-server infos 2. formatted 3. turned on llvm --- include/tsar/Analysis/PDG.h | 374 +++++++++++++++-------------------- lib/Analysis/PDG.cpp | 380 +++++++++++++++++++++++------------- 2 files changed, 406 insertions(+), 348 deletions(-) diff --git a/include/tsar/Analysis/PDG.h b/include/tsar/Analysis/PDG.h index a7eb457d..17e0f3f6 100644 --- a/include/tsar/Analysis/PDG.h +++ b/include/tsar/Analysis/PDG.h @@ -2,26 +2,22 @@ #define TSAR_INCLUDE_BUILDPDG_H #include "tsar/ADT/SpanningTreeRelation.h" - #include "tsar/Analysis/Memory/DependenceAnalysis.h" +#include "tsar/Analysis/Memory/DependenceAnalysis.h" #include "tsar/Analysis/Memory/EstimateMemory.h" #include "tsar/Analysis/Memory/DIEstimateMemory.h" #include "tsar/Analysis/Memory/DIClientServerInfo.h" +#include "tsar/Analysis/Memory/DIMemoryTrait.h" #include "tsar/Analysis/Memory/MemoryAccessUtils.h" #include "tsar/Analysis/Clang/SourceCFG.h" #include "tsar/Analysis/Passes.h" #include -#include #include +#include #include #include #include - -// New (before adding tsar's traits in graph): -#include "tsar/Analysis/Memory/DIMemoryTrait.h" -#include +#include #include -#include -// namespace tsar { @@ -33,17 +29,21 @@ template class CDGBuilder; template -using CDGNodeBase=llvm::DGNode, CDGEdge>; +using CDGNodeBase=llvm::DGNode, CDGEdge>; template -using CDGEdgeBase=llvm::DGEdge, CDGEdge>; +using CDGEdgeBase=llvm::DGEdge, CDGEdge>; template -using CDGBase=llvm::DirectedGraph, CDGEdge>; +using CDGBase=llvm::DirectedGraph, + CDGEdge>; template class CDGEdge : public CDGEdgeBase { public: using NodeType=CDGNode; - CDGEdge(NodeType &TargetNode) : CDGEdgeBase(TargetNode){} + CDGEdge(NodeType &TargetNode) + : CDGEdgeBase(TargetNode){} }; template @@ -63,7 +63,9 @@ class EntryCDGNode : public CDGNode { using Base=CDGNode; public: EntryCDGNode() : Base(Base::NodeKind::Entry) {} - static bool classof(const Base *Node) { return Node->getKind()==Base::NodeKind::Entry; } + static bool classof(const Base *Node) { + return Node->getKind()==Base::NodeKind::Entry; + } }; template @@ -72,8 +74,11 @@ class DefaultCDGNode : public CDGNode { using Base=CDGNode; public: using NodeValueType=CFGNodeType*; - DefaultCDGNode(NodeValueType Block) : Base(Base::NodeKind::Default), mBlock(Block) {} - static bool classof(const Base *Node) { return Node->getKind()==Base::NodeKind::Default; } + DefaultCDGNode(NodeValueType Block) + : Base(Base::NodeKind::Default), mBlock(Block) {} + static bool classof(const Base *Node) { + return Node->getKind()==Base::NodeKind::Default; + } inline NodeValueType getBlock() const { return mBlock; } private: NodeValueType mBlock; @@ -89,7 +94,6 @@ class ControlDependenceGraph : public CDGBase { using CFGNodeT=CFGNodeType; using NodeType=CDGNode; using EdgeType=CDGEdge; - // TODO: NodeValueType must be declared once for all DirectedGraph classes using NodeValueType=CFGNodeType*; using CFGNodeMapType=llvm::DenseMap; @@ -114,7 +118,8 @@ class ControlDependenceGraph : public CDGBase { } inline void bindNodes(NodeType &SourceNode, NodeType &TargetNode) { - CDGBase::connect(SourceNode, TargetNode, *(new CDGEdge(TargetNode))); + CDGBase::connect(SourceNode, TargetNode, + *(new CDGEdge(TargetNode))); } inline NodeType *getNode(NodeValueType Block) { @@ -122,7 +127,6 @@ class ControlDependenceGraph : public CDGBase { } inline NodeType *getEntryNode() { return mEntryNode; } - inline CFGType *getCFG() const { return mCFG; } ~ControlDependenceGraph() { @@ -152,9 +156,7 @@ class CDGBuilder { using CFGType=typename CDGType::CFGT; using CFGNodeType=typename CDGType::CFGNodeT; public: - // TODO: NodeValueType must be declared once for all DirectedGraph classes using NodeValueType=typename llvm::GraphTraits::NodeRef; - CDGBuilder() : mCDG(nullptr) {} CDGType *populate(CFGType &_CFG); private: @@ -181,8 +183,10 @@ class PDGNode : public PDGNodeBase { }; PDGNode() : mKind(NodeKind::Entry) {} NodeKind getKind() const { return mKind; } - bool collectInstructions(llvm::function_ref const &Pred, llvm::SmallVectorImpl &IList) const; - bool collectEdges(llvm::function_ref const &Pred, llvm::SmallVectorImpl &IList) const; + bool collectInstructions(llvm::function_ref const + &Pred, llvm::SmallVectorImpl &IList) const; + bool collectEdges(llvm::function_ref const &Pred, + llvm::SmallVectorImpl &IList) const; using PDGNodeBase::findEdgeTo; void destroy(); ~PDGNode() = default; @@ -214,13 +218,19 @@ class SimplePDGNode : public PDGNode { return const_cast&>( static_cast(this)->getInstructions()); } - llvm::Instruction *getFirstInstruction() const { return getInstructions().front(); } - llvm::Instruction *getLastInstruction() const { return getInstructions().back(); } + llvm::Instruction *getFirstInstruction() const { + return getInstructions().front(); + } + llvm::Instruction *getLastInstruction() const { + return getInstructions().back(); + } ~SimplePDGNode() = default; private: /// Append the list of instructions in \p Input to this node. - void appendInstructions(const llvm::SmallVectorImpl &Input) { - mKind=mInstructions.size()+Input.size()>1?NodeKind::MultiInstruction:NodeKind::SingleInstruction; + void appendInstructions(const llvm::SmallVectorImpl + &Input) { + mKind=mInstructions.size()+Input.size()>1?NodeKind::MultiInstruction: + NodeKind::SingleInstruction; llvm::append_range(mInstructions, Input); } void appendInstructions(const SimplePDGNode &Input) { @@ -233,10 +243,15 @@ class SimplePDGNode : public PDGNode { class PiBlockPDGNode : public PDGNode { public: template - PiBlockPDGNode(InputIt First, InputIt Last) : PDGNode(NodeKind::PiBlock), mInlinedNodes(First, Last) {} + PiBlockPDGNode(InputIt First, InputIt Last) + : PDGNode(NodeKind::PiBlock), mInlinedNodes(First, Last) {} llvm::SmallVectorImpl &getInlinedNodes() { return mInlinedNodes; } - const llvm::SmallVectorImpl &getInlinedNodes() const { return mInlinedNodes; } - static bool classof(const PDGNode *Node) { return Node->getKind()==NodeKind::PiBlock; } + const llvm::SmallVectorImpl &getInlinedNodes() const { + return mInlinedNodes; + } + static bool classof(const PDGNode *Node) { + return Node->getKind()==NodeKind::PiBlock; + } ~PiBlockPDGNode(); private: llvm::SmallVector mInlinedNodes; @@ -281,27 +296,14 @@ class PDGEdge : public PDGEdgeBase { class MemoryPDGEdge : public PDGEdge { public: - /*using DIDepKind=bcl::TraitDescriptor< - bcl::TraitAlternative>;*/ using DIDepKind=MemoryDescriptor; - - // 1. - /*using DIDepT=bcl::tagged_pair< - bcl::tagged, - bcl::tagged>;*/ - // 2. - /*using DIDepT=bcl::tagged_pair< - bcl::tagged, - bcl::tagged>;*/ - // 3. using DIDepT=std::pair; - using DIDepStorageT=llvm::SmallVector; using MemDepHandle=std::variant; + MemoryPDGEdge(PDGNode &TargetNode, llvm::Dependence &Dep, bool HasDefUse) : PDGEdge(TargetNode, HasDefUse?EdgeKind::MixedData:EdgeKind::Memory), mMemDep(&Dep) {} - MemoryPDGEdge(PDGNode &TargetNode, const llvm::SmallVectorImpl &DIDep, bool HasDefUse) : PDGEdge(TargetNode, HasDefUse?EdgeKind::MixedData:EdgeKind::Memory) { @@ -311,15 +313,14 @@ class MemoryPDGEdge : public PDGEdge { bool HasDefUse) : PDGEdge(TargetNode, HasDefUse?EdgeKind::MixedData:EdgeKind::Memory), mMemDep(DepHandle) {} - /*bool getDIDeps(llvm::SmallVectorImpl &V) { - if () - }*/ ~MemoryPDGEdge() { if (llvm::Dependence **IRDep=std::get_if(&mMemDep)) delete *IRDep; } - static bool classof(const PDGEdge *Edge) { return Edge->getKind()==EdgeKind::Memory || - Edge->getKind()==EdgeKind::MixedData; } + static bool classof(const PDGEdge *Edge) { + return Edge->getKind()==EdgeKind::Memory || Edge->getKind()== + EdgeKind::MixedData; + } const MemDepHandle &getMemoryDep() const { return mMemDep; } private: MemDepHandle mMemDep; @@ -336,8 +337,10 @@ class ComplexPDGEdge : public PDGEdge { size_t SrcNOrdinal, TgtNordinal; PDGEdge &E; }; - ComplexPDGEdge(PDGNode &Dst, PDGEdge &EToInline, size_t SCCOrdinal, const Direction Dir) - : PDGEdge(Dst, EToInline.getDependenceType()==DependenceType::Control?EdgeKind::ComplexControl:EdgeKind::ComplexData) { + ComplexPDGEdge(PDGNode &Dst, PDGEdge &EToInline, size_t SCCOrdinal, + const Direction Dir) + : PDGEdge(Dst, EToInline.getDependenceType()==DependenceType::Control? + EdgeKind::ComplexControl:EdgeKind::ComplexData) { absorbEdge(EToInline, SCCOrdinal, Dir); } void absorbEdge(PDGEdge &E, size_t SCCOrdinal, const Direction Dir) { @@ -359,10 +362,16 @@ class ComplexPDGEdge : public PDGEdge { else mInlinedEdges.push_back({SCCOrdinal, 0, E}); } - static bool classof(const PDGEdge *Edge) { return Edge->getKind()==EdgeKind::ComplexControl || - Edge->getKind()==EdgeKind::ComplexData; } - llvm::SmallVectorImpl &getInlinedEdges() { return mInlinedEdges; } - const llvm::SmallVectorImpl &getInlinedEdges() const { return mInlinedEdges; } + static bool classof(const PDGEdge *Edge) { + return Edge->getKind()==EdgeKind::ComplexControl || Edge->getKind()== + EdgeKind::ComplexData; + } + llvm::SmallVectorImpl &getInlinedEdges() { + return mInlinedEdges; + } + const llvm::SmallVectorImpl &getInlinedEdges() const { + return mInlinedEdges; + } ~ComplexPDGEdge() { for (EdgeHandle &EH : mInlinedEdges) EH.E.destroy(); @@ -376,7 +385,8 @@ class ProgramDependencyGraph : public PDGBase { public: using NodeType=PDGNode; using EdgeType=PDGEdge; - ProgramDependencyGraph(const llvm::Function &F) : PDGBase(), mF(F), mEntryNode(nullptr) {} + ProgramDependencyGraph(const llvm::Function &F) + : PDGBase(), mF(F), mEntryNode(nullptr) {} llvm::StringRef getName() const { return mF.getName(); } PDGNode &getEntryNode() { assert(mEntryNode); @@ -399,7 +409,6 @@ class ProgramDependencyGraph : public PDGBase { E->destroy(); N->destroy(); } - } private: const llvm::Function &mF; @@ -410,122 +419,19 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream&, const PDGNode&); llvm::raw_ostream &operator<<(llvm::raw_ostream&, const PDGNode::NodeKind); llvm::raw_ostream &operator<<(llvm::raw_ostream&, const PDGEdge&); llvm::raw_ostream &operator<<(llvm::raw_ostream&, const PDGEdge::EdgeKind); -llvm::raw_ostream &operator<<(llvm::raw_ostream&, const ProgramDependencyGraph&); +llvm::raw_ostream &operator<<(llvm::raw_ostream&, + const ProgramDependencyGraph&); class PDGBuilder { using MemoryLocationSet=llvm::SmallDenseSet; public: - PDGBuilder(ProgramDependencyGraph &G, llvm::DependenceInfo &DI, - const llvm::Function &F, const AliasTree &AT, - const llvm::TargetLibraryInfo &TLI, DIMemoryClientServerInfo &DIMInfo, - const llvm::LoopInfo &LI, bool ShouldSolveReachability=true, - bool ShouldSimplify=false, bool ShouldCreatePiBlocks=false) - : mGraph(G), mDI(DI), mF(F), mAT(AT), mTLI(TLI), mDIMInfo(DIMInfo), - mLI(LI), mDIATRel(DIMInfo.DIAT), - mSolvedReachability(ShouldSolveReachability), - mSimplified(ShouldSimplify), mCreatedPiBlocks(ShouldCreatePiBlocks), - mBBList(F.size()) { - if (mDIMInfo.isValid()) - mServerDIATRel=SpanningTreeRelation(mDIMInfo.DIAT); - { - size_t BBIdx=F.size(); - for (auto It=llvm::po_begin(&F); It!=llvm::po_end(&F); ++It) - mBBList[--BBIdx]=*It; - } - if (ShouldSolveReachability) - solveReachability(); - // New (before adding tsar's traits in graph): - /*const DIDependencInfo &DepInfo=*mDIMInfo.DIDepInfo; - for (auto &DepInfoRecord : DepInfo) { - for (const DIAliasTrait &Trait : DepInfoRecord.second) { - auto NodeIt=mReverseDIDepSet.find(Trait.getNode()); - if (NodeIt!=mReverseDIDepSet.end()) - NodeIt->second.insert(&Trait); - else - mReverseDIDepSet.insert({Trait.getNode(), {&Trait}}); - } - }*/ - // DEBUG (this code demonstrates the absence of causes in DIDependence): - if (!mDIMInfo.isValid()) - return; - // - llvm::DOTFuncInfo DOTCFGInfo(&F); - llvm::dumpDotGraphToFile(&DOTCFGInfo, "ircfg.dot", "control flow graph"); - // - // Code below prints DIDependenceInfo, - // which contains a set of DIAliasTraits for each loop in function - // In each DIMemoryTrait it attempts to find NoAccess, ReadOnly, Shared, - // Local, Private, FirstPrivate, SecondToLastPrivate, LastPrivate, - // DynamicPrivate and, finally, Flow, Anti, Output - { - using namespace trait; - for (auto &DepInfoRecord : *mDIMInfo.DIDepInfo) { - for (const DIAliasTrait &AT : DepInfoRecord.second) { - for (const DIMemoryTraitRef &MTRef : AT) { - auto PrintDistanceVector=[](const trait::DIDependence *Dep) - -> std::string { - std::string Result; - llvm::raw_string_ostream OS(Result); - if (Dep->getKnownLevel()==0) - return Result; - OS<<"<"; - if (Dep->getDistance(0).first==Dep->getDistance(0).second) - OS<getDistance(0).first; - else - OS<<"("<getDistance(0).first<<", "<< - Dep->getDistance(0).second<<")"; - for (int Level=1; LevelgetKnownLevel(); ++Level) - if (Dep->getDistance(Level).first== - Dep->getDistance(Level).second) - OS<<", "<getDistance(Level).first; - else - OS<<", ("<getDistance(Level).first<<", "<< - Dep->getDistance(Level).second<<")"; - OS<<">"; - return Result; - }; - if (MTRef->is()) - std::cout<<"------------NoAccess\n"; - if (MTRef->is()) - std::cout<<"------------Readonly\n"; - if (MTRef->is()) - std::cout<<"------------Shared\n"; - /*if (MTRef->is()) - std::cout<<" - - -Local\n";*/ - if (MTRef->is()) - std::cout<<"------------Private\n"; - if (MTRef->is()) - std::cout<<"------------FirstPrivate\n"; - if (MTRef->is()) - std::cout<<"------------SecondToLastPrivate\n"; - if (MTRef->is()) - std::cout<<"------------LastPrivate\n"; - if (MTRef->is()) - std::cout<<"------------DynamicPrivate\n"; - trait::DIDependence *DIFlow=MTRef->get(), - *DIAnti=MTRef->get(), - *DIOutput=MTRef->get(), *Actual; - if (DIFlow) - std::cout<<"------------Flow, "<getCauses().size()<<"\n"; - if (DIAnti) - std::cout<<"------------Anti, "<getCauses().size()<<"\n"; - if (DIOutput) - std::cout<<"------------Output, "<getCauses().size()<<"\n"; - std::cout<<"--------end of di-memory-trait hasNoDep - "<< - hasNoDep(*MTRef)<<", hasSpuriosDep - "< { size_t NodesCount; ReachabilityMatrix() = default; - ReachabilityMatrix(size_t _NodesCount) : std::vector(_NodesCount*_NodesCount, false), NodesCount(_NodesCount) {} + ReachabilityMatrix(size_t _NodesCount) + : std::vector(_NodesCount*_NodesCount, false), + NodesCount(_NodesCount) {} std::vector::reference operator()(size_t I, size_t J) { return this->operator[](I*NodesCount+J); } @@ -579,7 +488,8 @@ class PDGBuilder { const llvm::Instruction&, MemoryPDGEdge::DIDepStorageT&, MemoryPDGEdge::DIDepStorageT&); - /// Part of code, inherited from AbstractDependenceGraphBuilder and partially redefined + /// Part of code, inherited from AbstractDependenceGraphBuilder + // and partially redefined void computeInstructionOrdinals(); void createFineGrainedNodes(); void createDefUseEdges(); @@ -587,16 +497,19 @@ class PDGBuilder { void createControlDependenceEdges(); void simplify(); void createPiBlocks(); + PDGNode &createFineGrainedNode(const llvm::Instruction &I) { PDGNode *NewNode=new SimplePDGNode(const_cast(I)); mGraph.addNode(*NewNode); return *NewNode; } + PDGEdge &createDefUseEdge(PDGNode &Src, PDGNode &Tgt) { PDGEdge *NewEdge=new PDGEdge(Tgt, PDGEdge::DependenceType::Data); mGraph.connect(Src, Tgt, *NewEdge); return *NewEdge; } + bool areNodesMergeable(const PDGNode &Src, const PDGNode &Tgt) const { using namespace llvm; // Only merge two nodes if they are both simple nodes and the consecutive @@ -606,15 +519,20 @@ class PDGBuilder { if (!SimpleSrc || !SimpleTgt) return false; return true; - //return SimpleSrc->getLastInstruction()->getParent()==SimpleTgt->getFirstInstruction()->getParent(); + /*return SimpleSrc->getLastInstruction()->getParent()== + SimpleTgt->getFirstInstruction()->getParent();*/ } + void mergeNodes(PDGNode &AbsorbN, PDGNode &OutgoingN) { using namespace llvm; PDGEdge &EdgeToFold=AbsorbN.back(); - assert(AbsorbN.getEdges().size()==1 && EdgeToFold.getTargetNode()==OutgoingN && "Expected A to have a single edge to B."); - assert(isa(&AbsorbN) && isa(&OutgoingN) && "Expected simple nodes"); + assert(AbsorbN.getEdges().size()==1 && EdgeToFold.getTargetNode()== + OutgoingN && "Expected A to have a single edge to B."); + assert(isa(&AbsorbN) && isa(&OutgoingN) && + "Expected simple nodes"); // Copy instructions from B to the end of A. - cast(&AbsorbN)->appendInstructions(*cast(&OutgoingN)); + cast(&AbsorbN)-> + appendInstructions(*cast(&OutgoingN)); // Move to A any outgoing edges from B. for (PDGEdge *OutgoingE : OutgoingN) mGraph.connect(AbsorbN, OutgoingE->getTargetNode(), *OutgoingE); @@ -623,33 +541,33 @@ class PDGBuilder { mGraph.removeNode(OutgoingN); OutgoingN.destroy(); } - PiBlockPDGNode &createPiBlock(const llvm::SmallVectorImpl &NodeList) { + + PiBlockPDGNode &createPiBlock(const llvm::SmallVectorImpl + &NodeList) { PiBlockPDGNode *Res=new PiBlockPDGNode(NodeList.begin(), NodeList.end()); mGraph.addNode(*Res); return *Res; } + size_t getOrdinal(const llvm::Instruction &I) { assert(mInstOrdinalMap.find(&I) != mInstOrdinalMap.end() && "No ordinal computed for this instruction."); return mInstOrdinalMap[&I]; } + size_t getOrdinal(PDGNode &N) { assert(mNodeOrdinalMap.find(&N)!=mNodeOrdinalMap.end() && "No ordinal computed for this node."); return mNodeOrdinalMap[&N]; } - // + llvm::DenseMap mIMap; llvm::DenseMap mInstOrdinalMap; llvm::DenseMap mNodeOrdinalMap; llvm::DependenceInfo &mDI; llvm::SmallVector mBBList; // - - // New (before adding tsar's traits in graph): const llvm::LoopInfo &mLI; - // llvm::DenseMap> mReverseDIDepSet; - ProgramDependencyGraph &mGraph; const llvm::Function &mF; const AliasTree &mAT; @@ -659,16 +577,18 @@ class PDGBuilder { llvm::DenseMap mBBToInd; DIMemoryClientServerInfo &mDIMInfo; std::optional> mServerDIATRel; - SpanningTreeRelation mDIATRel; + SpanningTreeRelation mClientDIATRel; }; } //namespace tsar namespace llvm { -class ProgramDependencyGraphPass : public FunctionPass, private bcl::Uncopyable { +class ProgramDependencyGraphPass + : public FunctionPass, private bcl::Uncopyable { public: static char ID; - ProgramDependencyGraphPass() : FunctionPass(ID), mPDGBuilder(nullptr), mPDG(nullptr) { + ProgramDependencyGraphPass() + : FunctionPass(ID), mPDGBuilder(nullptr), mPDG(nullptr) { initializeProgramDependencyGraphPassPass(*PassRegistry::getPassRegistry()); } bool runOnFunction(Function &F) override; @@ -693,12 +613,14 @@ class ProgramDependencyGraphPass : public FunctionPass, private bcl::Uncopyable template struct GraphTraits*> { using NodeRef=tsar::CDGNode*; - static tsar::CDGNode *CDGGetTargetNode(tsar::CDGEdge *E) { + static tsar::CDGNode *CDGGetTargetNode(tsar::CDGEdge< + CFGType, CFGNodeType> *E) { return &E->getTargetNode(); } - using ChildIteratorType=mapped_iterator::iterator, - decltype(&CDGGetTargetNode)>; - using ChildEdgeIteratorType=typename tsar::CDGNode::iterator; + using ChildIteratorType=mapped_iterator::iterator, decltype(&CDGGetTargetNode)>; + using ChildEdgeIteratorType=typename tsar::CDGNode:: + iterator; static NodeRef getEntryNode(NodeRef N) { return N; } static ChildIteratorType child_begin(NodeRef N) { return ChildIteratorType(N->begin(), &CDGGetTargetNode); @@ -715,51 +637,67 @@ struct GraphTraits*> { template struct GraphTraits*> : public GraphTraits*> { - using nodes_iterator=typename tsar::ControlDependenceGraph::iterator; - static typename llvm::GraphTraits*>::NodeRef getEntryNode(tsar::ControlDependenceGraph *Graph) { + using nodes_iterator=typename tsar::ControlDependenceGraph::iterator; + static typename llvm::GraphTraits*>:: + NodeRef getEntryNode(tsar::ControlDependenceGraph + *Graph) { return Graph->getEntryNode(); } - static nodes_iterator nodes_begin(tsar::ControlDependenceGraph *Graph) { + static nodes_iterator nodes_begin(tsar::ControlDependenceGraph *Graph) { return Graph->begin(); } - static nodes_iterator nodes_end(tsar::ControlDependenceGraph *Graph) { + static nodes_iterator nodes_end(tsar::ControlDependenceGraph *Graph) { return Graph->end(); } using EdgeRef=tsar::CDGEdge*; - static typename llvm::GraphTraits*>::NodeRef edge_dest(EdgeRef E) { return &E->getTargetNode(); } - static unsigned size(tsar::ControlDependenceGraph *Graph) { return Graph->size(); } + static typename llvm::GraphTraits*>:: + NodeRef edge_dest(EdgeRef E) { return &E->getTargetNode(); } + static unsigned size(tsar::ControlDependenceGraph + *Graph) { return Graph->size(); } }; template struct DOTGraphTraits*> : public DOTGraphTraits { private: - using GTInstanced=GraphTraits*>; + using GTInstanced=GraphTraits*>; public: DOTGraphTraits(bool IsSimple=false) : DOTGraphTraits(IsSimple) {} - static std::string getGraphName(const tsar::ControlDependenceGraph *Graph) { + static std::string getGraphName(const tsar::ControlDependenceGraph *Graph) { return "Control Dependence Graph"; } std::string getNodeLabel(const tsar::CDGNode *Node, const tsar::ControlDependenceGraph *Graph) { - if (auto *DefNode=dyn_cast>(Node)) - return DOTGraphTraits::getNodeLabel(DefNode->getBlock(), Graph->getCFG()); + if (auto *DefNode=dyn_cast>(Node)) + return DOTGraphTraits::getNodeLabel(DefNode->getBlock(), + Graph->getCFG()); else return "Entry"; } - std::string getNodeAttributes(const tsar::CDGNode *Node, - tsar::ControlDependenceGraph *Graph) { - if (auto *DefNode=dyn_cast>(Node)) - return DOTGraphTraits::getNodeAttributes(DefNode->getBlock(), Graph->getCFG()); + std::string getNodeAttributes(const tsar::CDGNode *Node, tsar::ControlDependenceGraph + *Graph) { + if (auto *DefNode=dyn_cast>(Node)) + return DOTGraphTraits::getNodeAttributes(DefNode->getBlock(), + Graph->getCFG()); else return ""; } - std::string getEdgeSourceLabel(const tsar::CDGNode *Node, - typename GraphTraits*>::ChildIteratorType It) { return ""; } - std::string getEdgeAttributes(const tsar::CDGNode *Node, - typename GTInstanced::ChildIteratorType EdgeIt, + std::string getEdgeSourceLabel(const tsar::CDGNode + *Node, typename GraphTraits*>::ChildIteratorType It) { return ""; } + std::string getEdgeAttributes(const tsar::CDGNode + *Node, typename GTInstanced::ChildIteratorType EdgeIt, tsar::ControlDependenceGraph *Graph) { - //return DOTGraphTraits::getEdgeAttributes(Node->getBlock(), EdgeIt, Graph->getCFG()); + /*return DOTGraphTraits::getEdgeAttributes(Node->getBlock(), + EdgeIt, Graph->getCFG());*/ return ""; } bool isNodeHidden(const tsar::CDGNode *Node, @@ -770,7 +708,8 @@ struct DOTGraphTraits*> : template <> struct GraphTraits { using NodeRef=tsar::PDGNode *; - static tsar::PDGNode *PDGGetTargetNode(DGEdge *P) { + static tsar::PDGNode *PDGGetTargetNode(DGEdge *P) { return &P->getTargetNode(); } // Provide a mapped iterator so that the GraphTrait-based implementations can @@ -792,7 +731,8 @@ template <> struct GraphTraits { }; template <> -struct GraphTraits : public GraphTraits { +struct GraphTraits + : public GraphTraits { using nodes_iterator = tsar::ProgramDependencyGraph::iterator; static NodeRef getEntryNode(tsar::ProgramDependencyGraph *DG) { return &DG->getEntryNode(); @@ -800,16 +740,19 @@ struct GraphTraits : public GraphTraitsbegin(); } - static nodes_iterator nodes_end(tsar::ProgramDependencyGraph *DG) { return DG->end(); } + static nodes_iterator nodes_end(tsar::ProgramDependencyGraph *DG) { + return DG->end(); + } }; template <> struct GraphTraits { using NodeRef=const tsar::PDGNode *; - static const tsar::PDGNode *PDGGetTargetNode(const DGEdge *P) { + static const tsar::PDGNode *PDGGetTargetNode(const DGEdge *P) { return &P->getTargetNode(); } - using ChildIteratorType = - mapped_iterator; + using ChildIteratorType=mapped_iterator; using ChildEdgeIteratorType = tsar::PDGNode::const_iterator; static NodeRef getEntryNode(NodeRef N) { return N; } static ChildIteratorType child_begin(NodeRef N) { @@ -847,10 +790,13 @@ struct DOTGraphTraits assert(G && "expected a valid pointer to the graph."); return "PDG for '"+std::string(G->getName())+"'"; } - std::string getNodeLabel(const tsar::PDGNode *Node, const tsar::ProgramDependencyGraph *Graph); + std::string getNodeLabel(const tsar::PDGNode *Node, + const tsar::ProgramDependencyGraph *Graph); std::string getEdgeAttributes(const tsar::PDGNode *Node, - GraphTraits::ChildIteratorType I, const tsar::ProgramDependencyGraph *G); - static bool isNodeHidden(const tsar::PDGNode *Node, const tsar::ProgramDependencyGraph *G); + GraphTraits::ChildIteratorType I, + const tsar::ProgramDependencyGraph *G); + static bool isNodeHidden(const tsar::PDGNode *Node, + const tsar::ProgramDependencyGraph *G); private: static std::string getSimpleNodeLabel(const tsar::PDGNode *Node, const tsar::ProgramDependencyGraph *G); diff --git a/lib/Analysis/PDG.cpp b/lib/Analysis/PDG.cpp index 74b6e6c2..f92eb3de 100644 --- a/lib/Analysis/PDG.cpp +++ b/lib/Analysis/PDG.cpp @@ -2,20 +2,14 @@ #include "tsar/Support/PassGroupRegistry.h" #include "tsar/Core/Query.h" #include +#include #include #include #include #include -// New (before adding tsar's traits in graph): -#include -// ??? -#include -// - using namespace tsar; using namespace llvm; -using namespace std; #undef DEBUG_TYPE #define DEBUG_TYPE "pdg" @@ -25,7 +19,7 @@ STATISTIC(TotalDefUseEdges, "Number of def-use edges created."); STATISTIC(TotalMemoryEdges, "Number of memory dependence edges created."); STATISTIC(TotalFineGrainedNodes, "Number of fine-grained nodes created."); STATISTIC(TotalPiBlockNodes, "Number of pi-block nodes created."); -STATISTIC(TotalConfusedEdges, "Number of confused memory dependencies between two nodes."); +STATISTIC(TotalConfusedLLVMEdges, "Number of confused memory dependencies between two nodes."); STATISTIC(TotalEdgeReversals, "Number of times the source and sink of dependence was reversed to expose cycles in the graph."); using PDG=ProgramDependencyGraph; @@ -35,15 +29,16 @@ namespace llvm { template<> struct DOTGraphTraits : public DOTGraphTraits { - DOTGraphTraits(bool isSimple=false) : DOTGraphTraits(isSimple) {} - string getNodeLabel(const BasicBlock *Node, Function*) { + DOTGraphTraits(bool isSimple=false) + : DOTGraphTraits(isSimple) {} + std::string getNodeLabel(const BasicBlock *Node, Function*) { return DOTGraphTraits::getNodeLabel(Node, nullptr); } - string getNodeAttributes(const BasicBlock *Node, Function *F) { + std::string getNodeAttributes(const BasicBlock *Node, Function *F) { DOTFuncInfo DOTInfo(F); return DOTGraphTraits::getNodeAttributes(Node, &DOTInfo); } - string getEdgeAttributes(const BasicBlock *Node, + std::string getEdgeAttributes(const BasicBlock *Node, const_succ_iterator EdgeIt, Function *F) { DOTFuncInfo DOTInfo(F); return DOTGraphTraits::getEdgeAttributes(Node, EdgeIt, @@ -129,7 +124,7 @@ struct DOTGraphTraits*> namespace { template -void addToMap(map &Map, KeyT Key, ValueT Value) { +void addToMap(std::map &Map, KeyT Key, ValueT Value) { auto It=Map.find(Key); if (It!=Map.end()) Map[Key].insert(Value); @@ -149,7 +144,7 @@ bool hasEdgesTo(NodeType *SourceN, NodeType *TargetN) { template inline void CDGBuilder::processControlDependence() { - map> DepInfo; + std::map> DepInfo; for (auto NIt=GraphTraits::nodes_begin(mCFG); NIt!= GraphTraits::nodes_end(mCFG); ++NIt) mCDG->emplaceNode(*NIt); @@ -173,12 +168,12 @@ inline void CDGBuilder::processControlDependence() { template CDGType *CDGBuilder::populate(CFGType &CFG) { mCFG=&CFG; - mCDG=new CDGType(string(CFG.getName()), &CFG); + mCDG=new CDGType(std::string(CFG.getName()), &CFG); mPDT=PostDomTreeBase(); mPDT.recalculate(*mCFG); - /*May be useful*/ - //dumpDotGraphToFile(&mPDT, "post-dom-tree.dot", "post-dom-tree"); - /**/ + /*May be useful + dumpDotGraphToFile(&mPDT, "post-dom-tree.dot", "post-dom-tree"); + */ processControlDependence(); return mCDG; } @@ -426,7 +421,6 @@ std::string PDGDotGraphTraits::getVerboseEdgeAttributes(const PDGNode *Src, const PDGEdge *Edge, const PDG *G) { std::string Str; raw_string_ostream OS(Str); - // DEBUG: auto PrintMemoryEdge=[&OS](const MemoryPDGEdge &E) { if (llvm::Dependence * const *Dep=std::get_if(&E. getMemoryDep())) { @@ -435,7 +429,6 @@ std::string PDGDotGraphTraits::getVerboseEdgeAttributes(const PDGNode *Src, } else { using namespace trait; - // DEBUG: auto PrintDIMemDep=[&OS](const MemoryPDGEdge::DIDepT &Dep) -> void { auto PrintDistVec=[&OS](const DIMemoryTraitRef &MT) -> void { @@ -481,16 +474,12 @@ std::string PDGDotGraphTraits::getVerboseEdgeAttributes(const PDGNode *Src, PrintDIMemDep(DIMemDep); OS<<"\n"; } - // } }; - // if (const MemoryPDGEdge *MemDepEdge=dyn_cast(Edge)) { OS<<"label=\"["; - // DEBUG: PrintMemoryEdge(*MemDepEdge); OS.str().pop_back(); - // OS<<"]\""; } else @@ -507,19 +496,20 @@ std::string PDGDotGraphTraits::getVerboseEdgeAttributes(const PDGNode *Src, OS<<"def-use & "; case EdgeKind::Memory: PrintMemoryEdge(cast(E)); - // cast(E).getMemoryDep().dump(OS); - // OS.str().pop_back(); return OS.str(); case EdgeKind::Control: return "control"; default: - llvm_unreachable("Only simple edges can be inlined in complex edge"); + llvm_unreachable( + "Only simple edges can be inlined in complex edge"); } }; OS<<"label=\""; - for (const ComplexPDGEdge::EdgeHandle &EH : ComplexEdge->getInlinedEdges()) { + for (const ComplexPDGEdge::EdgeHandle &EH : ComplexEdge-> + getInlinedEdges()) { if (!isNodeHidden(&EH.E.getTargetNode(), G)) - OS<<"("<(mDIMInfo.DIAT); + { + size_t BBIdx=F.size(); + for (auto It=po_begin(&F); It!=po_end(&F); ++It) + mBBList[--BBIdx]=*It; + } + if (SolveReachability) + solveReachability(); + LLVM_DEBUG( + { + DOTFuncInfo DOTCFGInfo(&F); + dumpDotGraphToFile(&DOTCFGInfo, "ircfg.dot", "control flow graph"); + if (!mDIMInfo.isValid()) + return; + // Code below prints DIDependenceInfo, + // which contains a set of DIAliasTraits for each loop in function + // In each DIMemoryTrait it attempts to find NoAccess, ReadOnly, Shared, + // Local, Private, FirstPrivate, SecondToLastPrivate, LastPrivate, + // DynamicPrivate and, finally, Flow, Anti, Output + auto PrintDIDepInfo=[](const DIDependencInfo &DIDepInfo) -> void { + using namespace trait; + dbgs()<<"==== Start of DIDependenceInfo Printing! ===\n"; + for (auto &DepInfoRecord : DIDepInfo) { + for (const DIAliasTrait &AT : DepInfoRecord.second) { + for (const DIMemoryTraitRef &MTRef : AT) { + auto PrintDistanceVector=[](const trait::DIDependence *Dep) + -> std::string { + std::string Result; + llvm::raw_string_ostream OS(Result); + if (Dep->getKnownLevel()==0) + return Result; + OS<<"<"; + if (Dep->getDistance(0).first==Dep->getDistance(0).second) + OS<getDistance(0).first; + else + OS<<"("<getDistance(0).first<<", "<< + Dep->getDistance(0).second<<")"; + for (int Level=1; LevelgetKnownLevel(); ++Level) + if (Dep->getDistance(Level).first== + Dep->getDistance(Level).second) + OS<<", "<getDistance(Level).first; + else + OS<<", ("<getDistance(Level).first<<", "<< + Dep->getDistance(Level).second<<")"; + OS<<">"; + return Result; + }; + if (MTRef->is()) + dbgs()<<"------------NoAccess\n"; + if (MTRef->is()) + dbgs()<<"------------Readonly\n"; + if (MTRef->is()) + dbgs()<<"------------Shared\n"; + /*if (MTRef->is()) + dbgs()<<" - - -Local\n";*/ + if (MTRef->is()) + dbgs()<<"------------Private\n"; + if (MTRef->is()) + dbgs()<<"------------FirstPrivate\n"; + if (MTRef->is()) + dbgs()<<"------------SecondToLastPrivate\n"; + if (MTRef->is()) + dbgs()<<"------------LastPrivate\n"; + if (MTRef->is()) + dbgs()<<"------------DynamicPrivate\n"; + trait::DIDependence *DIFlow=MTRef->get(); + trait::DIDependence *DIAnti=MTRef->get(); + trait::DIDependence *DIOutput=MTRef->get(); + if (DIFlow) + dbgs()<<"------------Flow, "<getCauses().size()<<"\n"; + if (DIAnti) + dbgs()<<"------------Anti, "<getCauses().size()<<"\n"; + if (DIOutput) + dbgs()<<"------------Output, "<getCauses().size()<<"\n"; + dbgs()<<"--------end of di-memory-trait hasNoDep - "<< + hasNoDep(*MTRef)<<", hasSpuriosDep - "<destroy(); DefUseEdges.clear(); - assert(mGraph.connect(Src, Tgt, *(new MemoryPDGEdge(Tgt, Dep, true)))); - // assert(mGraph.connect(Src, Tgt, *(new MemoryPDGEdge(Tgt, *Dep.release(), true)))); + assert(mGraph.connect(Src, Tgt, *(new MemoryPDGEdge(Tgt, Dep, + true)))); } else - assert(mGraph.connect(Src, Tgt, *(new MemoryPDGEdge(Tgt, Dep, false)))); - // assert(mGraph.connect(Src, Tgt, *(new MemoryPDGEdge(Tgt, *Dep.release(), false)))); + assert(mGraph.connect(Src, Tgt, *(new MemoryPDGEdge(Tgt, Dep, + false)))); + ++TotalMemoryEdges; }; if (**SrcNodeIt==**DstNodeIt) continue; @@ -644,7 +735,8 @@ void PDGBuilder::createMemoryDependenceEdges() { isReachable(*SrcInstr.getParent(), *DstInstr.getParent()) || isReachable(*DstInstr.getParent(), *SrcInstr.getParent()))) continue; - unique_ptr Dep=mDI.depends(&SrcInstr, &DstInstr, true); + std::unique_ptr Dep=mDI.depends(&SrcInstr, &DstInstr, + true); MemoryPDGEdge::DIDepStorageT ForwardDIDep, BackwardDIDep; if (!Dep) continue; @@ -653,54 +745,55 @@ void PDGBuilder::createMemoryDependenceEdges() { // the source of the dependence cannot occur after the sink. For // confused dependencies, we will create edges in both directions to // represent the possibility of a cycle. - if (/*Dep->isConfused() && */confirmMemoryIntersect(SrcInstr, DstInstr, ForwardDIDep, BackwardDIDep)) - // TODO: rewrite + if (Dep->isConfused() && confirmMemoryIntersect(SrcInstr, DstInstr, + ForwardDIDep, BackwardDIDep)) { if (!ForwardDIDep.empty() || !BackwardDIDep.empty()) { if (!ForwardDIDep.empty()) CreateDepEdge(**SrcNodeIt, **DstNodeIt, ForwardDIDep); - if (!BackwardDIDep.empty()) + if (!BackwardDIDep.empty()) { CreateDepEdge(**DstNodeIt, **SrcNodeIt, BackwardDIDep); + ++TotalEdgeReversals; + } } else { - // if (Dep->isConfused()) { - CreateDepEdge(**SrcNodeIt, **DstNodeIt, new Dependence(&SrcInstr, &DstInstr)); - CreateDepEdge(**DstNodeIt, **SrcNodeIt, new Dependence(&DstInstr, &SrcInstr)); - // CreateDepEdge(**SrcNodeIt, **DstNodeIt, Dep.release()); - // CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&SrcInstr, &DstInstr, true).release()); - // } + /*CreateDepEdge(**SrcNodeIt, **DstNodeIt, new Dependence(&SrcInstr, + &DstInstr)); + CreateDepEdge(**DstNodeIt, **SrcNodeIt, new Dependence(&DstInstr, + &SrcInstr));*/ + CreateDepEdge(**SrcNodeIt, **DstNodeIt, Dep.release()); + CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&DstInstr, + &SrcInstr, true).release()); + ++TotalConfusedLLVMEdges; } - /*else if (Dep->isOrdered()) { + continue; + } + if (Dep->isOrdered()) { if (!Dep->isLoopIndependent()) { bool ReversedEdge=false; for (unsigned Level=1; Level<=Dep->getLevels(); ++Level) { if (Dep->getDirection(Level)==Dependence::DVEntry::EQ) continue; - else if (Dep->getDirection(Level) == Dependence::DVEntry::GT) { - // CreateDepEdge(**DstNodeIt, **SrcNodeIt, std::move(Dep)); + if (Dep->getDirection(Level) == Dependence::DVEntry::GT) { CreateDepEdge(**DstNodeIt, **SrcNodeIt, Dep.release()); ReversedEdge=true; - //++TotalEdgeReversals; + ++TotalEdgeReversals; break; } - else if (Dep->getDirection(Level)==Dependence::DVEntry::LT) + if (Dep->getDirection(Level)==Dependence::DVEntry::LT) break; - else { - // CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); - CreateDepEdge(**SrcNodeIt, **DstNodeIt, Dep.release()); - // CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&SrcInstr, &DstInstr, true)); - CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&SrcInstr, &DstInstr, true).release()); - ReversedEdge=true; - break; - } + CreateDepEdge(**SrcNodeIt, **DstNodeIt, Dep.release()); + CreateDepEdge(**DstNodeIt, **SrcNodeIt, mDI.depends(&DstInstr, + &SrcInstr, true).release()); + ReversedEdge=true; + ++TotalConfusedLLVMEdges; + break; } if (!ReversedEdge) - // CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); CreateDepEdge(**SrcNodeIt, **DstNodeIt, Dep.release()); } else - // CreateDepEdge(**SrcNodeIt, **DstNodeIt, std::move(Dep)); CreateDepEdge(**SrcNodeIt, **DstNodeIt, Dep.release()); - }*/ + } } } } @@ -720,9 +813,8 @@ void PDGBuilder::createControlDependenceEdges() { if (InstrPDGNodeIt!=mIMap.end()) { PDGEdge &NewPDGEdge=*(new PDGEdge(*InstrPDGNodeIt->second, PDGEdge::DependenceType::Control)); - // DEBUG: - assert(mGraph.connect(SrcNode, *InstrPDGNodeIt->second, NewPDGEdge)); - // + assert(mGraph.connect(SrcNode, *InstrPDGNodeIt->second, + NewPDGEdge)); } } } @@ -816,9 +908,10 @@ void PDGBuilder::simplify() { "Expected target to be in the in-degree map."); // Do not merge if there is also an edge from target to src (immediate // cycle). - if (TargetInDegreeMap[&Tgt]!=1 || !areNodesMergeable(Src, Tgt) || Tgt.hasEdgeTo(Src)) + if (TargetInDegreeMap[&Tgt]!=1 || !areNodesMergeable(Src, Tgt) || + Tgt.hasEdgeTo(Src)) continue; - // LLVM_DEBUG(dbgs()<<"Merging:"< ListOfSCCs; - for (const vector &SCC : make_range(scc_begin(&mGraph), scc_end(&mGraph))) + for (const std::vector &SCC : make_range(scc_begin(&mGraph), + scc_end(&mGraph))) if (SCC.size()>1) ListOfSCCs.emplace_back(SCC.begin(), SCC.end()); for (NodeListType &NL : ListOfSCCs) { - LLVM_DEBUG(dbgs()<<"Creating pi-block node with "< NewEdges[Direction::DirectionCount] {nullptr, nullptr}; + EnumeratedArray + NewEdges[Direction::DirectionCount] {nullptr, nullptr}; for (size_t SCCNodeI=0; SCCNodeI EL; Src.findEdgesTo(Dst, EL); if (EL.empty()) return; - LLVM_DEBUG(dbgs()<<"reconnecting("<<(Dir==Direction::Incoming?"incoming)":"outgoing)") - <<":\nSrc:"<getDependenceType(); if (NewEdges[Dir][Type]) { @@ -917,14 +1015,18 @@ void PDGBuilder::createPiBlocks() { } else { if (Dir==Direction::Incoming) { - NewEdges[Dir][Type]=new ComplexPDGEdge(PiNode, *OldEdge, SCCNodeI, Dir); + NewEdges[Dir][Type]=new ComplexPDGEdge(PiNode, *OldEdge, + SCCNodeI, Dir); mGraph.connect(Src, PiNode, *NewEdges[Dir][Type]); - LLVM_DEBUG(dbgs()<<"created complex edge from Src to PiNode.\n"); + LLVM_DEBUG(dbgs()<< + "created complex edge from Src to PiNode.\n"); } else { - NewEdges[Dir][Type]=new ComplexPDGEdge(Dst, *OldEdge, SCCNodeI, Dir); + NewEdges[Dir][Type]=new ComplexPDGEdge(Dst, *OldEdge, SCCNodeI, + Dir); mGraph.connect(PiNode, Dst, *NewEdges[Dir][Type]); - LLVM_DEBUG(dbgs()<<"created complex edge from PiNode to Dst.\n"); + LLVM_DEBUG(dbgs()<< + "created complex edge from PiNode to Dst.\n"); } } Src.removeEdge(*OldEdge); @@ -932,7 +1034,8 @@ void PDGBuilder::createPiBlocks() { /*if (OldEdge->getKind()==PDGEdge::EdgeKind::ComplexControl || OldEdge->getKind()==PDGEdge::EdgeKind::ComplexData) { OldEdge->destroy(); - LLVM_DEBUG(dbgs()<<"released memory from old complex edge between Src and Dst.\n\n"); + LLVM_DEBUG(dbgs()<<"released memory from old complex edge \\ + between Src and Dst.\n\n"); }*/ } }; @@ -972,64 +1075,71 @@ bool PDGBuilder::confirmMemoryIntersect(const Instruction &SrcInst, if (SrcMemLocs.empty() || DstMemLocs.empty()) return !(SrcMemLocs.empty() && !SrcUnknownMemory || DstMemLocs.empty() && !DstUnknownMemory); - SmallVector SrcClientDIMems, SrcServerDIMems, - DstClientDIMems, DstServerDIMems; - // SmallSetVector SrcClientDIMems, SrcServerDIMems, - // DstClientDIMems, DstServerDIMems; + enum InfoType { + Client, + Server, + Last=Server + }; + EnumeratedArray, InfoType> SrcDIMems, + DstDIMems; + /*EnumeratedArray, InfoType> SrcDIMems, + DstDIMems;*/ auto FillDIMemories=[this, &SrcInst](const MemoryLocationSet &MemLocs, - SmallVectorImpl &DIMemories, - SmallVectorImpl &ServerDIMemories) { + SmallVectorImpl &ClientDIMems, + SmallVectorImpl &ServerDIMems) { for (auto &MemLoc : MemLocs) { const EstimateMemory *EstMem=mAT.find(MemLoc); const MDNode *Metadata; while (!(Metadata=getRawDIMemoryIfExists(*EstMem, mF.getContext(), mF.getParent()->getDataLayout(), mAT.getDomTree()))) EstMem=EstMem->getParent(); - DIMemories.push_back(&*mDIMInfo.ClientDIAT->find(*Metadata)); + ClientDIMems.push_back(&*mDIMInfo.ClientDIAT->find(*Metadata)); if (mDIMInfo.isServerAvailable()) - ServerDIMemories.push_back(mDIMInfo.findFromClient(*EstMem, + ServerDIMems.push_back(mDIMInfo.findFromClient(*EstMem, SrcInst.getModule()->getDataLayout(), const_cast(mAT.getDomTree())).get()); } }; - FillDIMemories(SrcMemLocs, SrcClientDIMems, SrcServerDIMems); - FillDIMemories(DstMemLocs, DstClientDIMems, DstServerDIMems); - bool HasDependence=false, FoundMemory=false; - for (int SrcI=0; SrcI FoundDINode(false); + for (int SrcI=0; SrcI SrcDINode(nullptr); + for (int DstI=0; DstI DstDINode(nullptr); if ( mDIMInfo.isServerAvailable() && - SrcServerDIMems[SrcI] && - DstServerDIMems[DstI] && - (SrcServerDINode=SrcServerDIMems[SrcI]->getAliasNode()) && - (DstServerDINode=DstServerDIMems[DstI]->getAliasNode()) + SrcDIMems[Server][SrcI] && + DstDIMems[Server][DstI] && + (SrcDINode[Server]=SrcDIMems[Server][SrcI]->getAliasNode()) && + (DstDINode[Server]=DstDIMems[Server][DstI]->getAliasNode()) ) { - if (mServerDIATRel.value().compare(SrcServerDINode, DstServerDINode)!= - TreeRelation::TR_UNREACHABLE) + if (mServerDIATRel.value().compare(SrcDINode[Server], + DstDINode[Server])!=TreeRelation::TR_UNREACHABLE) HasDependence=true; } else if ( - SrcClientDIMems[SrcI] && - DstClientDIMems[DstI] && - (SrcDINode=SrcClientDIMems[SrcI]->getAliasNode()) && - (DstDINode=DstClientDIMems[DstI]->getAliasNode()) && - mDIATRel.compare(SrcDINode, DstDINode)!=TreeRelation::TR_UNREACHABLE - ) + SrcDIMems[Client][SrcI] && + DstDIMems[Client][DstI] && + (SrcDINode[Client]=SrcDIMems[Client][SrcI]->getAliasNode()) && + (DstDINode[Client]=DstDIMems[Client][DstI]->getAliasNode()) && + mClientDIATRel.compare(SrcDINode[Client], DstDINode[Client])!= + TreeRelation::TR_UNREACHABLE) HasDependence=true; - FoundMemory|=SrcDINode && DstDINode || SrcServerDINode && - DstServerDINode; + FoundDINode[Client]|=SrcDINode[Client] && DstDINode[Client]; + FoundDINode[Server]|=SrcDINode[Server] && DstDINode[Server]; } } - if (!HasDependence && FoundMemory) + if (!HasDependence && (FoundDINode[Client] || FoundDINode[Server])) return false; // At this point we have memory intersection confirmed by AliasTrees, - // but this fact doesn't mean the presence of dependence, so we need to - // observe trait set + // but this fact doesn't mean the presence of loop-carried dependence, so we + // need to observe trait set auto FindDIDependencies=[this, &SrcInst, &DstInst, &NewForwardDep, - &NewBackwardDep](const SmallVectorImpl &SrcDIMems, + &NewBackwardDep]( + const SmallVectorImpl &SrcDIMems, const SmallVectorImpl &DstDIMems, const SpanningTreeRelation &DIATRel) -> bool { using namespace trait; @@ -1038,16 +1148,14 @@ bool PDGBuilder::confirmMemoryIntersect(const Instruction &SrcInst, -> const Loop* { if (!SrcL || !DstL) return nullptr; - if (SrcL->getLoopDepth()getLoopDepth()) { - unsigned LargerNL=DstL->getLoopDepth(); - for (; LargerNL>SrcL->getLoopDepth(); --LargerNL) + if (SrcL->getLoopDepth()getLoopDepth()) + for (unsigned LargerNL=DstL->getLoopDepth(); LargerNL>SrcL-> + getLoopDepth(); --LargerNL) DstL=DstL->getParentLoop(); - } - else { - unsigned LargerNL=SrcL->getLoopDepth(); - for (; LargerNL>DstL->getLoopDepth(); --LargerNL) + else + for (unsigned LargerNL=SrcL->getLoopDepth(); LargerNL>DstL-> + getLoopDepth(); --LargerNL) SrcL=SrcL->getParentLoop(); - } while (SrcL!=DstL) { SrcL=SrcL->getParentLoop(); DstL=DstL->getParentLoop(); @@ -1072,7 +1180,7 @@ bool PDGBuilder::confirmMemoryIntersect(const Instruction &SrcInst, } }; EdgeTraitInfoT ForwTraits, BackwTraits; - bool FoundDep=false; + bool FoundDep=false, FoundTrait=false; const Loop *SrcL=mLI[SrcInst.getParent()], *DstL=mLI[DstInst.getParent()]; // Attempting to arrange Instruction's DI-mems sets for possible better // dependence analysis @@ -1097,11 +1205,11 @@ bool PDGBuilder::confirmMemoryIntersect(const Instruction &SrcInst, ExitFlag=1; } } - while (const Loop *CommonLopp=FindCommonLoop(SrcL, DstL)) { - const DIDependenceSet *DIDepSet=mDIMInfo.findFromClient(*CommonLopp); + while (const Loop *CommonLoop=FindCommonLoop(SrcL, DstL)) { + const DIDependenceSet *DIDepSet=mDIMInfo.findFromClient(*CommonLoop); if (!DIDepSet) continue; - for (const DIMemory *LoMem : *LowerMem) { + for (const DIMemory *LoMem : *LowerMem) for (const DIAliasTrait &AT : *DIDepSet) { auto CheckCauses=[&SrcInst, &DstInst, &ForwTraits, &BackwTraits, &AddTrait](const DIMemoryTraitRef &Access) @@ -1137,11 +1245,16 @@ bool PDGBuilder::confirmMemoryIntersect(const Instruction &SrcInst, if (MemAccessIt==AT.end()) continue; const DIMemoryTraitRef &MemAccess=*MemAccessIt; + auto HiMemIt=std::find(HigherMem->begin(), HigherMem->end(), + MemAccess->getMemory()); + if (HiMemIt==HigherMem->end()) + continue; // 1.: NoAccess, Readonly, Shared - No dependencies // It is worth to notice, that hasSpuriosDep really excludes some // of deps (mostly containing unions of private-like and shared // traits), which would have been showed otherwise - if (hasNoDep(*MemAccess) || hasSpuriousDep(*MemAccess)) + FoundTrait=true; + if (hasNoDep(*MemAccess) /*|| hasSpuriousDep(*MemAccess)*/) continue; FoundDep=true; // 2.: Private, FirstPrivate, SecondToLastPrivate, LastPrivate, @@ -1157,10 +1270,6 @@ bool PDGBuilder::confirmMemoryIntersect(const Instruction &SrcInst, CheckCauses.operator()(MemAccess) || CheckCauses.operator()(MemAccess)) continue; - auto HiMemIt=find(HigherMem->begin(), HigherMem->end(), - MemAccess->getMemory()); - if (HiMemIt==HigherMem->end()) - continue; const DIMemoryTraitSet &DepTS=MemAccess->getSecond(); if (SrcInst.mayWriteToMemory() && !SrcInst.mayReadFromMemory()) { if (DstInst.mayReadFromMemory() && !DstInst.mayWriteToMemory()) { @@ -1185,7 +1294,6 @@ bool PDGBuilder::confirmMemoryIntersect(const Instruction &SrcInst, AddTrait.operator()(ForwTraits, MemAccess); } } - } } NewForwardDep.clear(); NewBackwardDep.clear(); @@ -1193,15 +1301,19 @@ bool PDGBuilder::confirmMemoryIntersect(const Instruction &SrcInst, NewForwardDep.push_back(DepTrait); for (auto &DepTrait : BackwTraits) NewBackwardDep.push_back(DepTrait); - return FoundDep; + return FoundDep || !FoundTrait; }; - if (!mDIMInfo) + if (!mDIMInfo.isValid()) return true; - if (mDIMInfo.isServerAvailable()) - return FindDIDependencies(SrcServerDIMems, DstServerDIMems, + if (FoundDINode[Server]) + return FindDIDependencies(SrcDIMems[Server], DstDIMems[Server], mServerDIATRel.value()); else - return FindDIDependencies(SrcClientDIMems, DstClientDIMems, mDIATRel); + if (FoundDINode[Client]) + return FindDIDependencies(SrcDIMems[Client], DstDIMems[Client], + mClientDIATRel); + else + return true; } char ProgramDependencyGraphPass::ID=0; @@ -1240,13 +1352,13 @@ bool ProgramDependencyGraphPass::runOnFunction(Function &F) { getAnalysis(); DIMemoryClientServerInfo DIMInfo(const_cast(DIEMPass. getAliasTree()), *this, F); - mPDG=new ProgramDependencyGraph(F); + mPDG=new PDG(F); mPDGBuilder=new PDGBuilder(*mPDG, - DIPass.getDI(), F, + DIPass.getDI(), EMPass.getAliasTree(), - TLIPass.getTLI(F), DIMInfo, + TLIPass.getTLI(F), LIPass.getLoopInfo(), true); mPDGBuilder->populate();