LLVM uses static single assignment (SSA) form for its IR, meaning that every Value has a single definition point. So what is the easiest (and most generic) way to find "the" definition point of a Value without having to examine each use and determine how our Value is being used? In the code below, I am interested in definition points of Values used as function arguments.
protected: void getValueDefs( Function * F ) {
for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
ImmutableCallSite CS( cast<Value>(I) );
if ( !CS || isa<IntrinsicInst>(I) ) continue;
for ( User::const_op_iterator Ab = CS.arg_begin(), Ae = CS.arg_end(); Ab != Ae; ++Ab ) {
for ( User *U : Ab->get()->users() ) {
if (Instruction *Inst = dyn_cast<Instruction>(U)) {
/* How to do the check here?? */
}
}
}
}
}
That's a bit of an odd way to write it. I'd probably do something like this:
void scanFunc(Function &F) {
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
for (BasicBlock::iterator BBI = BB->begin(), BBE = BB->end(); BBI != BBE;
++BBI) {
if (CallInst *CI = dyn_cast<CallInst>(BBI)) {
dbgs() << "Call: ";
CI->dump();
dbgs() << "\n";
ImmutableCallSite CS(CI);
for (ImmutableCallSite::arg_iterator I = CS.arg_begin(),
E = CS.arg_end();
I != E; ++I) {
if (Instruction *Inst = dyn_cast<Instruction>(*I)) {
// Do stuff
dbgs() << "\tInst: ";
Inst->dump();
dbgs() << "\n";
}
}
}
}
}
}
Basically though, if it is an instruction, it is the definition of the value. That's how the IR works. Otherwise, it might be a constant etc. If you take this code:
int a (int b) {
return b + 4;
}
int b (int c) {
return a(c) + a(c-1);
}
int d (int e, int f, int g) {
int h = a(4);
int i = b(5);
int j = b(6);
return h + i + j + e + f + g;
}
and compile it to IR and run this code on it you'll see:
Call: %call = call i32 #_Z1ai(i32 %0)
Inst: %0 = load i32* %c.addr, align 4
Call: %call1 = call i32 #_Z1ai(i32 %sub)
Inst: %sub = sub nsw i32 %1, 1
Call: %call = call i32 #_Z1ai(i32 4)
Call: %call1 = call i32 #_Z1bi(i32 5)
Call: %call2 = call i32 #_Z1bi(i32 6)
Related
how to make tail recursion optimization enabled, when function more and vals call each other?
now, when I set n = 5, but when I set n = 50000000, it will occur error.
using Cb = std::function<void(bool, int)>;
using Read = std::function<void(bool, Cb)>;
using Sink = std::function<void(Read&)>;
using Through = std::function<Read(Read&)>;
int main() {
int n = 5;
Read vals = [&](bool abort, Cb cb) {
if (n-- <= 0) {
return;
}
cb(false, n); // call `more` function
};
Sink logInt = [&](Read &read) {
Cb more;
more = [&](bool abort, int val) {
cout << val << endl;
read(false, more); // call `vals` function
};
read(false, more);
};
logInt(vals);
return 0;
}
whole real code example
I need to find out the nesting level of a function call site(or any instruction, for that matter) using an LLVM Function pass. I have written the code below, but it always returns 0 as nesting levels.
virtual bool runOnFunction(Function &F) {
LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
errs() << "Function: " << F.getName() << "\n";
for (User *U : F.users()) {
CallSite CS(dyn_cast<Instruction>(U));
Function *callerFn = CS.getCaller();
if (callerFn && !callerFn->isDeclaration()) {
errs() <<callerFn->getName() << "--> " << F.getName()<<"\n";
Instruction *callInstr = CS.getInstruction();
BasicBlock *callerBB = callInstr->getParent();
callerBB->dump();
bool isLoop = LI.getLoopFor(callerBB);
errs()<<"Is Loop: "<<isLoop<<"\n";
int LoopDepth = LI.getLoopDepth(callerBB);
errs()<<"Loop Depth: "<< LoopDepth <<"\n";
}
}
I need to find out the nesting level of a function call site(or any
instruction, for that matter)
For loops, you can do this be editing your pass in the following way:
namespace {
struct LoopDepthPass: public FunctionPass {
static char ID;
LoopDepthPass: () : FunctionPass(ID) {}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
AU.addRequired<LoopInfoWrapperPass>();
}
bool runOnFunction(Function& F) override {
LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
for (LoopInfo::iterator LIT = LI.begin(); LIT != LI.end(); ++LIT) {
Loop* ll = *LIT;
ll->dump();
}
return false;
}
};
Execute this pass with the opt command.
Assume the following sample input:
int main(int argc, char* argv[]) {
int a;
for (int i = 0; i < 1000; i++){
for (int j = 0; j < 1000; j++)
a = i + j;
}
return 0;
}
The output would be:
Loop at depth 1 containing: %for.cond<header><exiting>,%for.body,%for.cond.1,%for.end,%for.inc.7<latch>,%for.body.4,%for.inc
Loop at depth 2 containing: %for.cond.1<header><exiting>,%for.body.4,%for.inc<latch>
I have printed out the loop->dump(), you can easily adapt it for another property too.
I am trying to create a for loop that runs through a vector, pushes something into a queue, updates all appropriate elements of the struct of the vector and then loops again until the vector is empty.
The problem I am having is that the function to run through my for loop does not seem to be updating my vector elements, I am getting the same output even though I know it should be changing.
Here is the link to a gist of the project https://gist.github.com/sgodfrey321/6cffd85896432b2942aa , it just has a lot of filler, I had to input alot of stuff by hand so it is kinda messy.
So to start with I pass my vector to the function in a while loop
void queueNodes(vector<vertex>& list, queue<vertex>& q);
as such
int counter = 0;
while (counter < 11) {
queueNodes(nodes, q);
counter++;
}
the while loop is to make sure that I run through the vector enough times. Now in the function I check to see if incomingEdges of the struct is 0 and if it is I push it into the queue and update the next door incomingEdges:
void queueNodes(vector<vertex>& nodes, queue<vertex>& q) {
for (auto i : nodes) {
cout << endl << i.vertexName << " ";
if (i.incomingEdges == 0) {
i.nextDoorTop->incomingEdges--;
i.nextDoorMiddle->incomingEdges--;
i.nextDoorBottom->incomingEdges--;
q.push(i);
cout << "foo";
} else {
cout << "bar";
}
}
Now I would expect that when I use the function again with the updated vector I would see a change in output as updating the next door incomingEdges would cause some to trigger the condition I am looking for. I have written outputs that show the next door incomingEdges are in fact decreasing however I can not seem to use the updated vector in the function call.
Do I need to return the vector somehow? I am sure that I am calling the function incorrectly, but does anyone have any ideas?
Thank You
edit: forgot to pass by reference the queue!
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct vertex {
char vertexName;
int incomingEdges;
vertex* nextDoorTop;
vertex* nextDoorMiddle;
vertex* nextDoorBottom;
};
void queueNodes(vector<vertex>& nodes);
int main() {
vertex s, A, G, D, B, H, E, C, I, F, t;
s.vertexName = 's';
s.incomingEdges = 0;
s.nextDoorTop = &A;
s.nextDoorMiddle = &D;
s.nextDoorBottom = &G;
A.vertexName = 'A';
A.incomingEdges = 2;
A.nextDoorTop = &B;
A.nextDoorMiddle = &E;
G.vertexName = 'G';
G.incomingEdges = 1;
G.nextDoorTop = &D;
G.nextDoorMiddle = &E;
G.nextDoorBottom = &H;
D.vertexName = 'D';
D.incomingEdges = 2;
D.nextDoorMiddle = &E;
B.vertexName = 'B';
B.incomingEdges = 1;
B.nextDoorTop = &C;
H.vertexName = 'H';
H.incomingEdges = 1;
H.nextDoorTop = &E;
H.nextDoorMiddle = &I;
E.vertexName = 'E';
E.incomingEdges = 4;
E.nextDoorTop = &C;
E.nextDoorMiddle = &F;
E.nextDoorBottom = &I;
C.vertexName = 'C';
C.incomingEdges = 3;
C.nextDoorMiddle = &t;
I.vertexName = 'I';
I.incomingEdges = 2;
I.nextDoorTop = &F;
I.nextDoorMiddle = &t;
F.vertexName = 'F';
F.incomingEdges = 2;
F.nextDoorMiddle = &t;
t.vertexName = 't';
t.incomingEdges = 3;
vector<vertex> nodes { s, A, G, D, B, H, E, C, I, F, t };
cout << "Vertex Name: " << " Number Of Edges: " << endl;
for (auto i : nodes) {
cout << i.vertexName << " " << i.incomingEdges << " "
<< endl;
}
int counter = 0;
while (counter < 11) {
queueNodes(nodes);
counter++;
}
return 0;
}
void queueNodes(vector<vertex>& nodes) {
for (auto& i : nodes) {
cout << endl << i.vertexName << " ";
if (i.incomingEdges == 0) {
i.nextDoorTop->incomingEdges--;
i.nextDoorMiddle->incomingEdges--;
i.nextDoorBottom->incomingEdges--;
cout << "foo";
} else {
cout << "bar";
}
}
}
I am a llvm newbie.
I am trying to write a llvm pass to optimize for algebraic identities in a function (like, if my function has an instruction a = b * 0, my pass should replace all following uses of "a" with 0).
So, my pass looks like follows:-
...
for (Function::iterator f_it = F.begin(), f_ite = F.end(); f_it != f_ite; ++f_it) {
for(BasicBlock::iterator b_it = f_it->begin(), b_ite = f_it->end(); b_it != b_ite; ++b_it) {
if(op->getOpcode() == Instruction::Mul) {
if(ConstantInt *CI_F = dyn_cast<ConstantInt>(&*b_it->getOperand(0))) {
if(CI_F->isZero()) {
firstop_zero = 1;
}
}
if(ConstantInt *CI_S = dyn_cast<ConstantInt>(&*b_it->getOperand(1))) {
if(CI_S->isZero()) {
secop_zero = 1;
}
}
if(first_zero || second_zero) {
errs()<<"found zero operand\n";
ReplaceInstWithValue(b_it->getParent()->getInstList(),b_it,(first_zero?(&*b_it->getOperand(1)):(&*b_it->getOperand(0))));
}
}
}
}
I can see that my comment "found zero operand gets printed out on std-err, but I can't see the replacement in the resulting .bc's disassembly.
What am I missing here? Any help is sincerely appreciated.
Thanks a lot!
Praveena
Try
for (Function::iterator f_it = F.begin(), f_ite = F.end(); f_it != f_ite; ++f_it) {
for(BasicBlock::iterator b_it = f_it->begin(), b_ite = f_it->end(); b_it != b_ite; ++b_it) {
Instruction *I = *b_it;
Value *Zeroval;
if(op->getOpcode() == Instruction::Mul) {
if(ConstantInt *CI_F = dyn_cast<ConstantInt>(&*b_it->getOperand(0))) {
if(CI_F->isZero()) {
firstop_zero = 1;
Zeroval = CI_F;
}
}
if(ConstantInt *CI_S = dyn_cast<ConstantInt>(&*b_it->getOperand(1))) {
if(CI_S->isZero()) {
secop_zero = 1;
ZeroVal = CI_S;
}
}
if(first_zero || second_zero) {
errs()<<"found zero operand\n";
I->ReplaceAlluseswith(ZeroVal);
}
}
}
}
I got this implementation for maximum matching off the net and is trying to give its input through main class. But I am getting zero for all the places in match. What am I doing wrong?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <queue>
using namespace std;
void add_edge(int u, int v);
void edmonds();
struct edge {
int v, nx;
};
const int MAXN = 1000, MAXE = 2000;
edge graph[MAXE];
int last[MAXN], match[MAXN], px[MAXN], base[MAXN], N, M, edges;
bool used[MAXN], blossom[MAXN], lused[MAXN];
int main ()
{
// return 0;
add_edge(1,4);
add_edge(1,5);
add_edge(1,6);
add_edge(2,5);
add_edge(2,7);
add_edge(3,4);
add_edge(4,1);
add_edge(4,3);
add_edge(5,1);
add_edge(5,2);
add_edge(6,1);
add_edge(7,2);
edmonds();
cout << match[0];
cout << match[1];
cout << match[2];
cout << match[3];
cout << match[4];
cout << match[5];
cout << match[6];
}
inline void add_edge(int u, int v) {
graph[edges] = (edge) {v, last[u]};
last[u] = edges++;
graph[edges] = (edge) {u, last[v]};
last[v] = edges++;
}
void mark_path(int v, int b, int children) {
while (base[v] != b) {
blossom[base[v]] = blossom[base[match[v]]] = true;
px[v] = children;
children = match[v];
v = px[match[v]];
}
}
int lca(int a, int b) {
memset(lused, 0, N);
while (1) {
lused[a = base[a]] = true;
if (match[a] == -1)
break;
a = px[match[a]];
}
while (1) {
b = base[b];
if (lused[b])
return b;
b = px[match[b]];
}
}
int find_path(int root) {
memset(used, 0, N);
memset(px, -1, sizeof(int) * N);
for (int i = 0; i < N; ++i)
base[i] = i;
used[root] = true;
queue<int> q;
q.push(root);
register int v, e, to, i;
while (!q.empty()) {
v = q.front(); q.pop();
for (e = last[v]; e >= 0; e = graph[e].nx) {
to = graph[e].v;
if (base[v] == base[to] || match[v] == to)
continue;
if (to == root || (match[to] != -1 && px[match[to]] != -1)) {
int curbase = lca(v, to);
memset(blossom, 0, N);
mark_path(v, curbase, to);
mark_path(to, curbase, v);
for (i = 0; i < N; ++i)
if (blossom[base[i]]) {
base[i] = curbase;
if (!used[i]) {
used[i] = true;
q.push(i);
}
}
} else if (px[to] == -1) {
px[to] = v;
if (match[to] == -1)
return to;
to = match[to];
used[to] = true;
q.push(to);
}
}
}
return -1;
}
void build_pre_matching() {
register int u, e, v;
for (u = 0; u < N; ++u)
if (match[u] == -1)
for (e = last[u]; e >= 0; e = graph[e].nx) {
v = graph[e].v;
if (match[v] == -1) {
match[u] = v;
match[v] = u;
break;
}
}
}
void edmonds() {
memset(match, 0xff, sizeof(int) * N);
build_pre_matching();
register int i, v, pv, ppv;
for (i = 0; i < N; ++i)
if (match[i] == -1) {
v = find_path(i);
while (v != -1) {
pv = px[v], ppv = match[pv];
match[v] = pv, match[pv] = v;
v = ppv;
}
}
}
You set elements of match in two locations: In build_pre_matching() and in edmonds(). In both of these cases, no change will happen if match[x] for some index x isn't -1. The only other place elements of match get a value is during static initialization where the values get zero initialized. Since the initial value is zero and the values are only ever changed if at least one of them happens to be -1, I would expect that the values retain the value 0.
You might want to use something like
std::fill(std::begin(match), std::end(match), -1);
at a strategic location since you seem to assume that the values are initially -1. Of course, you also should consider the idea of not using global variables because this doesn't scale and works really badly in a multi-threaded program.