DominatorsAnalysisProvider.cpp
No OneTemporary

File Metadata

Created
Thu, Jul 9, 2:47 AM

DominatorsAnalysisProvider.cpp

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: DominatorsAnalysisProvider.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on May 13, 2016, 11:39 AM
*/
/**
* \file DominatorsAnalysisProvider.h
* \brief Dominators Tree analysis
*/
#include "analysis/cfagraph.h"
#include "analysis/DominatorsAnalysisProvider.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/Support/GenericDomTreeConstruction.h"
#include "llvm/Support/GenericDomTree.h"
#include <list>
#include <iostream>
#include <boost/format.hpp>
using namespace std;
using namespace xreate;
using namespace boost;
using namespace boost::bimaps;
namespace xreate { namespace dominators {
struct CFAGraphAdapter;
struct ScopeNode {
ScopePacked id;
CFAGraphAdapter* parent;
std::list<ScopeNode*> nodesFrom;
std::list<ScopeNode*> nodesTo;
CFAGraphAdapter* getParent(){ return parent; }
void printAsOperand(llvm::raw_ostream&, bool) {}
ScopeNode(ScopePacked scope, CFAGraphAdapter* parentAdapter):
id(scope), parent(parentAdapter) {}
};
}
} //end of namespace xreate::dominators
namespace llvm {
using namespace xreate::dominators;
template<>
struct GraphTraits<ScopeNode*> {
typedef ScopeNode* NodeRef;
typedef std::list<ScopeNode*>::iterator ChildIteratorType;
static ChildIteratorType
child_begin(ScopeNode* node) {
return node->nodesTo.begin();
}
static ChildIteratorType
child_end(ScopeNode* node) {
return node->nodesTo.end();
}
};
template<>
struct GraphTraits<Inverse<ScopeNode*>>
{
typedef ScopeNode* NodeRef;
typedef std::list<ScopeNode*>::iterator ChildIteratorType;
static ChildIteratorType
child_begin(ScopeNode* node) {
return node->nodesFrom.begin();
}
static ChildIteratorType
child_end(ScopeNode* node) {
return node->nodesFrom.end();
}
};
template<>
struct GraphTraits<CFAGraphAdapter*> {
typedef std::list<ScopeNode*>::iterator nodes_iterator;
static nodes_iterator
nodes_begin(CFAGraphAdapter* graph) {
return graph->nodes.begin();
}
static nodes_iterator
nodes_end(CFAGraphAdapter* graph) {
return graph->nodes.end();
}
static ScopeNode*
getEntryNode(CFAGraphAdapter* F) {
return F->nodeRoot;
}
static unsigned int
size(CFAGraphAdapter* graph) {
return graph->nodes.size();
}
};
}
namespace xreate {
namespace dominators {
class DominatorTree : public llvm::DominatorTreeBase<ScopeNode, false> {
friend class DominatorsAnalysisProvider;
public:
DominatorTree() : llvm::DominatorTreeBase<ScopeNode, false>() {}
void
run(CFAGraphAdapter& program) {
recalculate(program);
updateDFSNumbers();
//extract dominators info
for(auto& entry : DomTreeNodes) {
if(!entry.getFirst()) continue;
dominators.emplace(entry.getFirst()->id, make_pair(entry.getSecond()->getDFSNumIn(), entry.getSecond()->getDFSNumOut()));
}
}
void
print(std::ostringstream& output, const std::string& atom) const {
boost::format formatAtom(atom+"(%1%, range(%2%, %3%)).");
for(auto entry : dominators) {
output<<formatAtom%(entry.first)%(entry.second.first)%(entry.second.second)
<<std::endl;
}
}
private:
DominatorsAnalysisProvider::Dominators dominators;
};
class PostDominatorTree : public llvm::DominatorTreeBase<ScopeNode, true> {
friend class DominatorsAnalysisProvider;
public:
PostDominatorTree() : llvm::DominatorTreeBase<ScopeNode, true>() {}
void
run(CFAGraphAdapter& program) {
recalculate(program);
updateDFSNumbers();
//extract dominators info
for(auto& entry : DomTreeNodes) {
if(!entry.getFirst()) continue;
dominators.emplace(entry.getFirst()->id, make_pair(entry.getSecond()->getDFSNumIn(), entry.getSecond()->getDFSNumOut()));
}
}
void
print(std::ostringstream& output, const std::string& atom) const {
boost::format formatAtom(atom+"(%1%, range(%2%, %3%)).");
for(auto entry : dominators) {
output<<formatAtom%(entry.first)%(entry.second.first)%(entry.second.second)
<<std::endl;
}
}
private:
DominatorsAnalysisProvider::Dominators dominators;
};
ScopeNode*
CFAGraphAdapter::registerScope(ScopePacked scope){
ScopeNode elemNew(scope, this);
auto fnComp = [](const ScopeNode* a, const ScopeNode* b){return a->id < b->id;};
auto posLowerBound = std::lower_bound(nodes.begin(), nodes.end(), &elemNew, fnComp);
if(posLowerBound==nodes.end()|| (*posLowerBound)->id > scope){
ScopeNode* elemNewP = new ScopeNode(elemNew);
*elemNewP = elemNew;
return *nodes.insert(posLowerBound, elemNewP);
}
return *posLowerBound;
}
CFAGraphAdapter*
CFAGraphAdapter::build(const cfa::CFAGraph* graph) {
return build(graph->__dependencyRelations);
}
CFAGraphAdapter*
CFAGraphAdapter::build(const std::multimap<ScopePacked, ScopePacked>& dataScopesOrder){
CFAGraphAdapter* tree=new CFAGraphAdapter();
enum NODE_MARK{NO_ROOT, POSSIBLE_ROOT};
std::unordered_map<unsigned int, NODE_MARK> nodeMarks;
for (const auto& edge: dataScopesOrder){
ScopeNode* nodeTo = tree->registerScope(edge.first);
ScopeNode* nodeFrom = tree->registerScope(edge.second);
nodeTo->nodesFrom.push_back(nodeFrom);
nodeFrom->nodesTo.push_back(nodeTo);
nodeMarks.emplace(edge.second, POSSIBLE_ROOT); //weak optional insert
auto result = nodeMarks.emplace(edge.first, NO_ROOT); //strong insert or update
if(!result.second){
result.first->second = NO_ROOT;
}
}
std::list<ScopePacked> nodeRoots;
for(auto nodeMark: nodeMarks){
if(nodeMark.second == POSSIBLE_ROOT) nodeRoots.push_back(nodeMark.first);
}
if(nodeRoots.size()>1){
ScopeNode* nodeGlobalRoot = tree->registerScope(SCOPE_ABSTRACT_GLOBAL);
for(auto rootLocal: nodeRoots){
ScopeNode* nodeLocalRoot = tree->registerScope(rootLocal);
nodeLocalRoot->nodesFrom.push_back(nodeGlobalRoot);
nodeGlobalRoot->nodesTo.push_back(nodeLocalRoot);
}
tree->nodeRoot = nodeGlobalRoot;
} else if (nodeRoots.size()==1){
tree->nodeRoot = tree->registerScope(nodeRoots.front());
} else {
ScopeNode* nodeGlobalRoot = tree->registerScope(SCOPE_ABSTRACT_GLOBAL);
tree->nodeRoot = nodeGlobalRoot;
}
return tree;
}
void
DominatorsAnalysisProvider::run(CFAGraphAdapter* program) {
treeForwardDominators.reset(new DominatorTree());
treePostDominators.reset(new PostDominatorTree());
treeForwardDominators->run(*program);
treePostDominators->run(*program);
}
void
DominatorsAnalysisProvider::print(std::ostringstream& output) const {
treeForwardDominators->print(output, "cfa_forwdom");
treePostDominators->print(output, "cfa_postdom");
}
const DominatorsAnalysisProvider::Dominators&
DominatorsAnalysisProvider::getForwardDominators() const {
return treeForwardDominators->dominators;
}
const DominatorsAnalysisProvider::Dominators&
DominatorsAnalysisProvider::getPostDominators() const {
return treePostDominators->dominators;
}
DominatorsAnalysisProvider::DominatorsAnalysisProvider() {}
DominatorsAnalysisProvider::~DominatorsAnalysisProvider() { }
}} //end of namespace xreate::dominators

Event Timeline