Skip to content

Commit

Permalink
Fixed some issues with dataflow analysis.
Browse files Browse the repository at this point in the history
  • Loading branch information
fabrizioferrandi authored and Ansaya committed Mar 28, 2024
1 parent 8dfa426 commit bf08e79
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 51 deletions.
1 change: 1 addition & 0 deletions QTCreator-PandA-GitHub.includes
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ ext/or-tools/ortools/base
ext/or-tools/ortools/graph
ext/or-tools/ortools/util
ext/sollya
ext/pugixml
src
src/HLS
src/HLS/architecture_creation
Expand Down
11 changes: 7 additions & 4 deletions etc/clang_plugin/plugin_ASTAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
* @author Michele Fiorito <[email protected]>
*
*/
// #undef NDEBUG
//#undef NDEBUG
#include "plugin_includes.hpp"

#include <clang/AST/AST.h>
Expand Down Expand Up @@ -837,10 +837,9 @@ class DataflowHLSPragmaHandler : public HLSPragmaAnalyzer, public HLSPragmaParse
forceNoInline(FD);
for(auto* stmt : FD->getBody()->children())
{
auto callExpr = dyn_cast<CallExpr>(stmt);
if(callExpr)
if(auto callExpr = dyn_cast<CallExpr>(stmt))
{
const auto calleeDecl = dyn_cast<FunctionDecl>(callExpr->getCalleeDecl());
const auto calleeDecl = callExpr->getDirectCallee();
if(calleeDecl)
{
LLVM_DEBUG(dbgs() << " -> " << MangledName(calleeDecl) << "\n");
Expand All @@ -850,6 +849,10 @@ class DataflowHLSPragmaHandler : public HLSPragmaAnalyzer, public HLSPragmaParse

hasModule = true;
}
else if(callExpr->isTypeDependent())
{
return;
}
}
}
if(!hasModule)
Expand Down
146 changes: 106 additions & 40 deletions etc/clang_plugin/plugin_topfname.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
// #undef NDEBUG
#include "plugin_includes.hpp"

#include "llvm/Analysis/CallGraph.h"
#include <llvm/ADT/StringExtras.h>
#include <llvm/ADT/StringSet.h>
#include <llvm/IR/LegacyPassManager.h>
Expand Down Expand Up @@ -166,6 +167,7 @@ namespace llvm
CLANG_VERSION_SYMBOL(_plugin_topfname)
() : ModulePass(ID)
{
initializeCallGraphWrapperPassPass(*PassRegistry::getPassRegistry());
}

#if __clang_major__ >= 13
Expand All @@ -175,16 +177,57 @@ namespace llvm
}
#endif

bool exec(Module& M)
bool exec(Module& M, const CallGraph& CG)
{
bool changed = false;
bool hasTopFun = false;
std::list<std::string> symbolList;
std::vector<std::string> Starting_TopFunctionNames;
std::vector<std::string> TopFunctionNames;

const auto handleFunction = [&](Function* F, const std::string& fsymbol, const std::string& fname) {
if(!F->isIntrinsic() && !F->isDeclaration())
{
LLVM_DEBUG(llvm::dbgs() << "Checking function: " << fsymbol << " | " << fname << " (" << F->getLinkage()
<< ")\n");
if(is_builtin_fn(fsymbol) || is_builtin_fn(fname))
{
LLVM_DEBUG(llvm::dbgs() << " builtin\n");
symbolList.push_back(fsymbol);
}
if(llvm::find(TopFunctionNames, fsymbol) != TopFunctionNames.end() ||
llvm::find(TopFunctionNames, fname) != TopFunctionNames.end())
{
LLVM_DEBUG(llvm::dbgs() << " top function\n");
F->addFnAttr(Attribute::NoInline);
F->setLinkage(GlobalValue::LinkageTypes::ExternalLinkage);
#if __clang_major__ >= 7
F->setDSOLocal(false);
#endif
symbolList.push_back(fsymbol);
hasTopFun = true;
/// in case add noalias
if(add_noalias)
{
for(auto& par : F->args())
{
if(!par.hasNoAliasAttr() && par.getType()->isPointerTy())
{
par.addAttr(llvm::Attribute::NoAlias);
}
}
}
}
}
};

// Initialize top functions list
for(std::size_t last = 0, it = 0; it < TopFunctionName_TFP.size(); last = it + 1)
{
it = TopFunctionName_TFP.find(",", last);
const auto func_symbol = TopFunctionName_TFP.substr(last, it);
LLVM_DEBUG(dbgs() << " - " << func_symbol << "\n");
Starting_TopFunctionNames.push_back(func_symbol);
TopFunctionNames.push_back(func_symbol);
}
pugi::xml_document doc;
Expand All @@ -204,12 +247,12 @@ namespace llvm
}
}
}
if(TopFunctionNames.empty())
if(Starting_TopFunctionNames.empty())
{
LLVM_DEBUG(llvm::dbgs() << "No top function specified\n");
return false;
}
std::list<std::string> symbolList;
// Initialize external symbols list
if(!ExternSymbolsList.empty())
{
std::stringstream ss(ExternSymbolsList);
Expand All @@ -221,45 +264,56 @@ namespace llvm
symbolList.push_back(substr);
}
}
/// check if the translation unit has the top function name
for(auto& fun : M.getFunctionList())

SmallPtrSet<Function*, 32> Reachable;
for(auto&& CGN : CG)
{
if(!fun.isIntrinsic() && !fun.isDeclaration())
if(!CGN.second)
{
const auto funName = fun.getName().str();
const auto demangled = getDemangled(funName);
LLVM_DEBUG(llvm::dbgs() << "Checking function: " << funName << " | " << demangled << " ("
<< fun.getLinkage() << ")\n");
if(is_builtin_fn(funName) || is_builtin_fn(demangled))
{
LLVM_DEBUG(llvm::dbgs() << " builtin\n");
symbolList.push_back(funName);
}
if(llvm::find(TopFunctionNames, funName) != TopFunctionNames.end() ||
llvm::find(TopFunctionNames, demangled) != TopFunctionNames.end())
continue;
}
auto fun = CGN.second->getFunction();
if(!fun)
{
continue;
}
const auto fsymbol = fun->getName().str();
const auto fname = getDemangled(fsymbol);
if(!(is_builtin_fn(fsymbol) || is_builtin_fn(fname) ||
llvm::find(Starting_TopFunctionNames, fsymbol) != Starting_TopFunctionNames.end() ||
llvm::find(Starting_TopFunctionNames, fname) != Starting_TopFunctionNames.end()))
{
continue;
}

Reachable.insert(fun);
handleFunction(fun, fsymbol, fname);

SmallVector<const Function*, 8> Tmp({CGN.first});
do
{
auto F = std::move(Tmp.back());
Tmp.pop_back();

for(auto&& N : *CG[F])
{
LLVM_DEBUG(llvm::dbgs() << " top function\n");
fun.addFnAttr(Attribute::NoInline);
fun.setLinkage(GlobalValue::LinkageTypes::ExternalLinkage);
#if __clang_major__ >= 7
fun.setDSOLocal(false);
#endif
symbolList.push_back(funName);
hasTopFun = true;
/// in case add noalias
if(add_noalias)
{
for(auto& par : fun.args())
{
if(!par.hasNoAliasAttr() && par.getType()->isPointerTy())
{
par.addAttr(llvm::Attribute::NoAlias);
}
}
}
if(!N.second)
continue;
auto funCalled = N.second->getFunction();
if(!funCalled)
continue;
if(Reachable.find(funCalled) != Reachable.end())
continue;

Tmp.push_back(funCalled);

const auto _fsymbol = funCalled->getName().str();
const auto _fname = getDemangled(_fsymbol);
handleFunction(funCalled, _fsymbol, _fname);
}
}
} while(!Tmp.empty());
}

if(!hasTopFun)
{
return changed;
Expand Down Expand Up @@ -297,7 +351,18 @@ namespace llvm

bool runOnModule(Module& M) override
{
return exec(M);
#if __clang_major__ < 13

CallGraphWrapperPass* CGPass = getAnalysisIfAvailable<CallGraphWrapperPass>();
if(!CGPass)
{
report_fatal_error("not able to retrieve the call graph");
}
return exec(M, CGPass->getCallGraph());
#else
report_fatal_error("Call to runOnModule not expected with current LLVM version");
return false;
#endif
}

StringRef getPassName() const override
Expand All @@ -307,12 +372,13 @@ namespace llvm

void getAnalysisUsage(AnalysisUsage& AU) const override
{
AU.addRequired<CallGraphWrapperPass>();
}

#if __clang_major__ >= 13
llvm::PreservedAnalyses run(llvm::Module& M, llvm::ModuleAnalysisManager&)
llvm::PreservedAnalyses run(llvm::Module& M, llvm::ModuleAnalysisManager& MAM)
{
const auto changed = exec(M);
const auto changed = exec(M, MAM.getResult<CallGraphAnalysis>(M));
return (changed ? llvm::PreservedAnalyses::none() : llvm::PreservedAnalyses::all());
}
#endif
Expand Down
6 changes: 4 additions & 2 deletions src/frontend_analysis/IR_analysis/Range_Analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1017,11 +1017,13 @@ namespace
case ge_expr_K:
return RangeRef(new Range(Regular, bw, Other->getSignedMax(), APInt::getSignedMaxValue(bw)));
case gt_expr_K:
return RangeRef(new Range(Regular, bw, Other->getSignedMax() + Range::MinDelta, APInt::getSignedMaxValue(bw)));
return RangeRef(
new Range(Regular, bw, Other->getSignedMax() + Range::MinDelta, APInt::getSignedMaxValue(bw)));
case le_expr_K:
return RangeRef(new Range(Regular, bw, APInt::getSignedMinValue(bw), Other->getSignedMin()));
case lt_expr_K:
return RangeRef(new Range(Regular, bw, APInt::getSignedMinValue(bw), Other->getSignedMin() - Range::MinDelta));
return RangeRef(
new Range(Regular, bw, APInt::getSignedMinValue(bw), Other->getSignedMin() - Range::MinDelta));
case unge_expr_K:
return RangeRef(new Range(Regular, bw, Other->getUnsignedMax(), APInt::getMaxValue(bw)));
case ungt_expr_K:
Expand Down
4 changes: 0 additions & 4 deletions src/frontend_analysis/IR_analysis/call_graph_computation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,6 @@ DesignFlowStep_Status call_graph_computation::Exec()
"---Root function " + STR(GET_INDEX_CONST_NODE(fnode)) + " - " + symbol);
functions.insert(GET_INDEX_CONST_NODE(fnode));
}
else
{
THROW_ERROR("Function " + symbol + " not found in IR");
}
}
CGM->SetRootFunctions(functions);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,6 @@ DesignFlowStep_Status create_tree_manager::Exec()
const auto fnode = TM->GetFunction(symbol);
if(!fnode)
{
THROW_WARNING("Function specified in architecture XML is missing in the IR: " + symbol);
continue;
}
const auto fd = GetPointer<function_decl>(GET_NODE(fnode));
Expand Down

0 comments on commit bf08e79

Please sign in to comment.