Using the results of LLVM alias analysis from an LLVM loop pass - llvm

I have an LLVM loop pass, and I need to check whether
two values may alias to one another. If I first run an alias analysis pass, and then the loop pass, how can I query the results of the AA pass?
It should probably be something similar to:
virtual bool runOnLoop(Loop *loop, LPPassManager &LPM)
{
Value *v1 = getValueSomehow();
Value *v2 = getValueSomeOtherWay();
// EDITED with compor's answer
AliasAnalysis *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
if (AA->isNoAlias(v1,v2))
{
errs() << "OK";
}
}
However when I run it with this opt command (I put the aa pass first)
opt \
-basicaa \
-loop-simplify \
-instnamer \
-indvars \
-simplifycfg \
-view-cfg \
-o input.ready.bc input.bc
I get this runtime error:
opt: PassAnalysisSupport.h:236: [...]:
Assertion `ResultPass && "getAnalysis*() called on an analysis that was not " "'required' by pass!"' failed.
...
Aborted (core dumped)
EDIT:
It does not suffice to simply put the -basicaa pass first to opt.
Indeed, like compor said, one has to override the getAnalysisUsage,
and explicitly say which passes are required.
struct StaticAnalyzer : public LoopPass
{
static char ID;
StaticAnalyzer():LoopPass(ID){}
void getAnalysisUsage(AnalysisUsage &AU) const override
{
AU.addRequired<AAResultsWrapperPass>();
}
// ...
};

When in doubt do as LLVM does; for example, in this case have a look in llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp.
Using the llvm::legacy::PassManager this is done by adding the Alias Analysis as a requirement of your pass:
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<AAResultsWrapperPass>();
[...]
}
and then accessing the analysis results in the run() method:
AliasAnalysis *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
Also, note that you can "plug" and combine various alias analyses (plural) via the commandline (mentioned here), e.g.
opt -basicaa [...]

Related

How to pass string argument to macro

I am trying to print IT SUCCESS\nET SUCCESS\n using following code but it's failing in compilation with error error: ‘printds’ was not declared in this scope which I know is because it's taking macro input as ds literal. Does anyone know how to do this? The use case is that there are several printXX() functions which should be called based on value passed in macro.
#include <stdio.h>
#define FOO(val) { \
print ## val(); \
}
void printIT() { printf("IT SUCCESS\n"); }
void printET() { printf("ET SUCCESS\n"); }
int main() {
const char* ds = "IT", es = "ET";
FOO(ds); FOO(es);
return 0;
}
You can change
FOO(ds); FOO(es);
to
FOO(IT); FOO(ET);
Because macro substitutions happen before your code is compiled.
But you can define a function called FOO like
#include <stdio.h>
#include <iostream>
using namespace std;
void printIT() { printf("IT SUCCESS\n"); }
void printET() { printf("ET SUCCESS\n"); }
void FOO(const string str)
{
if(str=="IT")
printIT();
else
printET();
}
int main()
{
const char* ds = "IT",*es="ET";
FOO(ds);FOO(es);
return 0;
}
it's taking macro input as ds literal.
Yes, that's to be expected. Preprocessor macros are expanded at compile time. The arguments to function-like macros are the literal source-code tokens that appear between the parentheses in the macro invocation. These have no additional meaning to the preprocessor.
Does anyone know how to do this? The use case is that there are several printXX() functions which should be called based on value passed in macro.
Again, macros are expanded, to source code (approximately), at compile time. The process does not and cannot take into account C++ runtime semantics such as converting variables' identifiers into corresponding values.
If runtime dynamic function dispatch based on variables' values is what you're after then you need an altogether different mechanism. You could use ordinary conditional statements to select between different function calls, for example. If you wanted to be even more dynamic then you could consider preparing a lookup table of function pointers, and using that to select and call appropriate functions.
In comments, you added
I've several methods queryServers, queryNodes, queryTargets which I want to call using above trick.
You may be able to accomplish something similar to what you ask via templates or overloaded functions. These mechanisms, too, operate at compile time, so they have no access to runtime information such as variables' values, but they do know about and rely upon C++ data types.
Alternatively, perhaps you're looking for the Strategy pattern.
The first thing you need to know is that the Macros are preprocessor directives which are a fragment of code with a given name. if you use macro name in your program it will replace that code fragment into that place you use the macro name at compile time first stage called Pre-processing stage.
#include <stdio.h>
#define FOO(val) { \
print ## val(); \
}
void printIT() { printf("IT SUCCESS\n"); }
void printET() { printf("ET SUCCESS\n"); }
int main() {
const char* ds = "IT", es = "ET";
FOO(ds); FOO(es);
return 0;
}
In your code, you try to input ds and es variables into FOO function like macro. But ds and es variables declared in program stack only when you run the program. At the compile-time, it just treats them as only texts. Therefore macro function input it takes as text ds and es and replaced with val. That's why you got the compile time error. The following code fragment I have changed is working as you expected.
#include <stdio.h>
#define FOO(val) { \
print ## val(); \
}
void printIT() { printf("IT SUCCESS\n"); }
void printET() { printf("ET SUCCESS\n"); }
int main() {
const char* ds = "IT", *es = "ET";
FOO(IT); FOO(ET);
return 0;
}
If you are interested you can find more about Macros in the following resources.
GCC online documentation and Article about Macros . Also, you can view the preprocessed code using g++ -E (your cpp file name). Thanks.
Possible solution without MACRO:
void printIT() { printf("IT SUCCESS\n"); }
void printET() { printf("ET SUCCESS\n"); }
void foo(std::string_view s)
{
static const std::map<std::string_view, void(*)()> funcs{
{"IT", &printIT},
{"ET", &printET}
};
auto it = funcs.find(s);
if (it != funcs.end()) {
(*it->second)();
}
}
int main() {
const char* ds = "IT";
const char* es = "ET";
foo(ds); foo(es);
}
Demo

Workflow of LLVM and clang

I am just a beginner in LLVM, and (https://www.cs.cornell.edu/~asampson/blog/llvm.html) webpage along with the stack overflow, and my fellow researcher has helped me a lot.
I would first like to illustrate what I am trying to work on (the problem) and then I will describe the approach that I have taken to work on the problem.
Then, I need your advice and guidance if I am missing anything.
Work Problem
My input is a C program and output is its SSA form in prefix representation printed in an output File.
For eg, if the C code segment is :
x=4;
x++;
z=x+7;
The output SSA form in prefix representation is :
( = x0 4)
( = x1 (+ x0 1) )
( = z (x1 + 7) )
Please ignore the actual IR instruction for now, just assume that I am able to read the IR and convert it to this form, with some extra statements (which I am not presenting here for readability).
My ignorant Approach of using LLVM (Please find the complete program below)
using namespace llvm;
namespace {
struct TestPass: public ModulePass {
IRssa::ptr ir_ssa = IRssa::ptr(new IRssa());
static char ID;
typedef std::list<std::pair<std::string, std::list<Instruction *> > > funcDump;
TestPass() : ModulePass(ID) { }
std::map<std::string, funcDump> workingList;
bool runOnModule(Module &M) {
std::string funcName, bkName;
for (Function &F : M) { //Found a new Function
if (isa<Function>(F) && !(F.getName().startswith("llvm."))) {
funcName = F.getName();
std::pair<std::string, std::list<Instruction *> > funcBlockList;
std::list<std::pair<std::string, std::list<Instruction *> > > wholeFuncBlocks;
for (BasicBlock &B : F) { //Blocks of the Function
if (isa<BasicBlock>(B)) {
bkName = B.getName();
}
std::list<Instruction *> listInst;
for (auto &I : B) {
Instruction *ins;
ins = &I;
listInst.push_back(ins);
}
funcBlockList.first = bkName;
funcBlockList.second = listInst;
wholeFuncBlocks.push_back(funcBlockList);
}
workingList[funcName] = wholeFuncBlocks;//Mapping of the functions
}
}
ir_ssa->setFunctionDump(workingList);
funcDump funcData;
funcData = workingList["start_program"]; //Starting from the start_program function
convertFunctionToSSA(funcData, ir_ssa);
std::ofstream outFile;
outFile.open("Out.ssa");
printSSA_toFile(outFile, ir_ssa);
return false;
}
};
}
char TestPass::ID = 0;
static RegisterPass<TestPass> X("testPass", "Testing A Pass");
static void registerTestPass(const PassManagerBuilder &, legacy::PassManagerBase &PM) {
PM.add(new TestPass());
}
static RegisterStandardPasses RegisterMyPass(PassManagerBuilder::EP_ModuleOptimizerEarly, registerTestPass);
static RegisterStandardPasses RegisterMyPass0(PassManagerBuilder::EP_EnabledOnOptLevel0, registerTestPass);
//Automatically enable the pass (http://adriansampson.net/blog/clangpass.html)
Description:
As shown above I am calling a runOnModule() and collecting all the IR Instructions of all the blocks for each function in the program into a workingList data structure (a std::map in this case). After all the functions in the given program is finished reading, I then do my required task of reading IR instructions one at a time, function by function and block by block (in the user defined function convertFunctionToSSA(funcData, ir_ssa) taking the whole function IR as argument and the result of processing these IR is returned in the argument ir_ssa). I am also printing the resulted value from ir_ssa onto the output file outFile.
Now How do I Run (I type the following)
clang -O1 -g -Xclang -emit-llvm -c someProgram.c -o test.bc
opt -O1 -instnamer -mem2reg -simplifycfg -loops -lcssa -loop-simplify -loop-rotate -loop-unroll -unroll-count=15 -unroll-allow-partial -load src/libTestPass.so -testPass test.bc -o test
My Expectation
I assume (as per my understanding) that the above two commands does the following.
First clang takes the program someProgram.c and generates IR as an output file "test.bc".
The next command opt, takes the file "test.bc" and then applies all the above passes one by one till the last pass "-unroll-allow-partial" and it also links my library libTestPass.so (this .so file is generated on compiling the above ModulePass program) then, finally the pass "-testPass" which I think is the pass where I am doing my process (of converting to SSA prefix representation).
Your Advice and Comments
I am not sure if LLVM is actually running in the sequence as I am assuming (My Expectation). Kindly comment if I am missing anything or if my assumption is not correct. Also please feel free to ask more details if necessary.
Current Problem Faced
I am able to successfully convert most of the C programs but on a specific program I stuck with some error. Debugging this error lead me to think that I am missing somethink or my assumption about this working of LLVM in regards to the calling order of clang and opt is not correct.
Your help is highly appreciated.

How to run the Function Pass before the Module Pass in LLVM?

I'm implementing several Passes on the LLVM in order to add original optimization,
These Passes are based on FunctionPass and ModulePass.
Now, each Pass is invoked by corresponding opt command option which is
registerd by RegisterPass template.
In future, I'd like to these Passes to be invoked only by one opt command option.
My idea is as follows:
First, Function passes to run, and finally Module pass to run.
Each Function passes to use the former Function passes' analysis information.
The final Module pass to construct a new function using the former Function passes' result.
All of these Passes sequence to invoke by only one opt command option specifying the final Module pass.
I thought I could make it with addRequired method in the AnalysisUsage class.
However, it doesn't seem to work:
In the Function pass, several Function passes may be addRequired in the order.
In the Function pass, only one Module pass may be addRequired.
In the Function pass(X), Function pass and Module pass cannot be addRequired simultaneously.
i.e. opt command execution with option X causes to a lock status.
In the Module pass, only one Module pass may be addRequired.
In the Module pass(Y), Function pass(Z) cannot be addRequired.
i.e. opt command with option Y executes only Y, and Function pass(Z) is ignored.
I am not familiar to the Pass manager mechanism.
Anybody help me how to run the Function pass before the Module pass with only one opt command option?
The case of execution is shown below:-
$ opt -stats -load ~/samples/tryPass4.so -MPass4 hello2.ll -S -o tryPass4.ll -debug-pass=Structure
Pass Arguments: -targetlibinfo -datalayout -notti -basictti -x86tti -MPass4 -verify -verify-di -print-module
Target Library Information ↑
Data Layout                              -FPass4 doesn't appear here
No target information
Target independent code generator's TTI
X86 Target Transform Info
ModulePass Manager
Module Pass
Unnamed pass: implement Pass::getPassName()
FunctionPass Manager
Module Verifier
Debug Info Verifier
Print module to stderr
Pass Arguments: -FPass4    <- here -FPass4 appears, but not executed
FunctionPass Manager
Function Pass
***** Module Name : hello2.ll <- output from the Module pass
The source code for above is as follows:-
using namespace llvm;
namespace{
class tryFPass4 : public FunctionPass {
public :
static char ID;
tryFPass4() : FunctionPass(ID){}
~tryFPass4(){}
virtual bool runOnFunction(llvm::Function &F);
virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const;
};
class tryMPass4 : public ModulePass {
public :
static char ID;
tryMPass4() : ModulePass(ID){}
~tryMPass4(){}
virtual bool runOnModule(llvm::Module &M);
virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const;
};
}
bool tryFPass4::runOnFunction(Function &F) {
bool change = false;
....
return change;
}
bool tryMPass4::runOnModule(Module &M) {
bool change = false ;
....
return change;
}
void tryFPass4::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
}
void tryMPass4::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
AU.addRequired<tryFPass4>();
}
char tryFPass4::ID = 0;
static RegisterPass<tryFPass4> X("FPass4", "Function Pass", false, false);
char tryMPass4::ID = 0;
static RegisterPass<tryMPass4> Y("MPass4", "Module Pass", false, false);
I tried to simulate the problem here using LLVM 3.8.1.
I believe your Function pass gets to run here:
Module Pass
Unnamed pass: implement Pass::getPassName()
I do not know why it is marked as unnamed although getPassName is overriden.
A fine detail that you need to watch is that in order for the function pass to actually execute its runOnFunction method, you need to invoke the Function & specific method of getAnalysis as in:
getAnalysis<tryFPass4>(f); // where f is the current Function operating on
It seems if the dependent pass operates on a small unit of IR than the pass that requires it, it needs to be executed explicitly. I might be mistaken since I have not yet tried it with a BasicBlockPass required by a FunctionPass.

LLVM unable to get a required analysis

I am writing a pass that needs information about loops. Therefore I am overriding getAnalysisUsage(AnalysisUsage&) to let the pass manager know that my pass depends on LoopInfoWrapperPass. However, when I try to get the result of that analysis, LLVM asserts that the analysis wasn't required by my pass. Here's a simple pass that I'm having trouble with:
#include <llvm/Pass.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Analysis/LoopInfo.h>
struct Example : public ModulePass {
static char ID;
Example() : ModulePass(ID) {}
bool runOnModule(Module& M) override {
errs() << "what\n";
LoopInfo& loops = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
loops.print(errs());
return false;
}
virtual void getAnalysisUsage(AnalysisUsage& AU) const override {
errs() << "here\n";
AU.addRequired<LoopInfoWrapperPass>();
}
};
char Example::ID = 0;
static RegisterPass<Example> X("example", "an example", false, false);
When I run this pass, the two debug statements are printed in the correct order (here then what) but when getAnalysis<LoopInfoWrapperPass>() is called, I get this assertion error:
opt: /home/matt/llvm/llvm/include/llvm/PassAnalysisSupport.h:211: AnalysisType& llvm::Pass::getAnalysisID(llvm::AnalysisID) const [with AnalysisType = llvm::LoopInfoWrapperPass; llvm::AnalysisID = const void*]: Assertion `ResultPass && "getAnalysis*() called on an analysis that was not " "'required' by pass!"' failed.
This is the same method that is given in LLVM's documentation on writing passes, so I'm not quite sure what's going wrong here. Could anyone point me in the right direction?
LoopInfoWrapperPass is derived from FunctionPass. Your Example class, however, derives from ModulePass. It works on the module level, so you'll need to tell LoopInfoWrapperPass which function you want to analyze. Basically, you might want to loop every function f in the module, and use getAnalysis<LoopInfoWrapperPass>(f).
Alternatively, the easiest way to fix the code above is to replace ModulePass with FunctionPass and runOnModule(Module& M) with runOnFunction(Function& F). Then, getAnalysis<LoopInfoWrapperPass>() should work just fine.

Code coverage (c++ code execution path)

Let's say I have this code:
int function(bool b)
{
// execution path 1
int ret = 0;
if(b)
{
// execution path 2
ret = 55;
}
else
{
// execution path 3
ret = 120;
}
return ret;
}
I need some sort of a mechanism to make sure that the code has gone in any possible path, i.e execution paths 1, 2 & 3 in the code above.
I thought about having a global function, vector and a macro.
This macro would simply call that function, passing as parameters the source file name and the line of code, and that function would mark that as "checked", by inserting to the vector the info that the macro passed.
The problem is that I will not see anything about paths that did not "check".
Any idea how do I do this? How to "register" a line of code at compile-time, so in run-time I can see that it didn't "check" yet?
I hope I'm clear.
Usually coverage utilities (such as gcov) are supplied with compiler. However please note that they will usually give you only C0 coverage. I.e.
C0 - every line is executed at least once. Please note that a ? b : c is marked as executed even if only one branch have been used.
C1 - every branch is executed at least once.
C2 - every path is executed at least once
So even if your tests shows 100% C0 coverage you may not catch every path in code - and probably you don't have time to do it (number of paths grows exponentially with respect to branches). However it is good to know if you have 10% C2 or 70% C2 (or 0.1% C2).
Quite often there will be a utility supplied with your compiler to do this sort of code coverage analysis. For example, GCC has the gcov utility.
You need a code coverage program (gcov, bullseye, dev partner) and unit-testing (unittest++, cppunit, etc.). You write test that will test that function.
TEST( UnitTestFunction )
{
CHECK( function(true) == 55 );
CHECK( function(false) == 120 );
}
Then unit tests in this case do not just check for integrity (though they still do) but they also test for coverage.
Try SD C++ TestCoverage for a VisualStudio compatible test coverage tool. I believe that it in fact actually will tell you about test coverage of a?b:c, too.
The problem is that I will not see anything about paths that did not "check".
If this means in other words that you're not only looking for the set of code points which are actually executed but also for the set of code points which have been "marked" somehow as expected to be executed to maybe finally report the difference, i might have a very dangerous solution. It works for me on MSVC 2010 and 2013.
The approach is to make use of the pre program start initialization of static variables, but since all code points are in functions and therefore, the "static anker point" has to be put there somehow and so, the c++ feature of delayed initialization of static function variables has to be overcome.
This seems to be possible by adding an indirection through a template class (X) with a static member variable (progloc_) to enforce the initialization per template parameter which in turn is a wrapper struct which transports the needed information (_.FILE._ " at line " _.LINE._).
Putting this together, the most important code to achieve this could look like the following:
template <class T> class X {
public:
static T progloc_;
};
template <class T> T X<T>::progloc_;
#define TRACE_CODE_POINT \
struct ProgLocation { \
public: \
std::string loc_; \
ProgLocation() : loc_(std::string(__FILE__ " at line " S__LINE__)) \
{ \
TestFw::CodePoints::Test::imHere(loc_); \
} \
}; \
TestFw::CodePoints::X<ProgLocation> dummy; \
TestFw::CodePoints::Test::iGotCalled(dummy.progloc_.loc_);
The S__LINE__ - trick which is used in the ProgLocation - ctor comes from here on SO.
#define S(x) #x
#define S_(x) S(x)
#define S__LINE__ S_(__LINE__)
To track, the following is used:
class Test
{
private:
typedef std::set<std::string> TFuncs;
static TFuncs registeredFunctions;
static TFuncs calledFunctions;
public:
static int imHere(const std::string fileAndLine)
{
assert(registeredFunctions.find(fileAndLine) == registeredFunctions.end());
registeredFunctions.insert(fileAndLine);
return 0;
}
static void iGotCalled(const std::string fileAndLine)
{
if (calledFunctions.find(fileAndLine) == calledFunctions.end())
calledFunctions.insert(fileAndLine);
}
static void report()
{
for (TFuncs::const_iterator rfIt = registeredFunctions.begin(); rfIt != registeredFunctions.end(); ++rfIt)
if (calledFunctions.find(*rfIt) == calledFunctions.end())
std::cout << (*rfIt) << " didn't get called" << std::endl;
}
};
Maybe there are many problems connected with this approach which I don't see yet and make it inpracticable for your case, and as others pointed out, using static code analysis tools is for most situations the better solution.
EDIT:
Just found out that the provided solution has been discussed before in another context:
non-deferred-static-member-initialization-for-templates-in-gcc
You can use FILE and LINE preprocessor directives:
#define TRACE(msg) MyTraceNotify(msg,__FILE__,__LINE__)
Just insert TRACE(msg) macro in your code at the places you want to track, with your custom message, and write your MyTraceNotify function.
void MyTraceNotify(const char *msg, const char *filename, ULONG line)
{
/* Put your code here... */
}