ZZB
ZZB

Reputation: 285

How to find out shared variables among functions by using LLVM API?

Recently I used LLVM API to test C++ program. Now I want to find out the shared variables among different functions, is there any way to do that? It seems that the AliasAnalysis doesn't work!

I write a Function Pass as following:

bool EscapeAnalysis::runOnFunction(Function& F) {
    EscapePoints.clear();

    TargetData& TD = getAnalysis<TargetData>();
    AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
    Module* M = F.getParent();
 // errs() << *M << "\n";
 // Walk through all instructions in the function, identifying those that
 // may allow their inputs to escape.
    for(inst_iterator II = inst_begin(F), IE = inst_end(F); II != IE; ++II) {
        Instruction* I = &*II;

     // The most obvious case is stores.  Any store that may write to global
     // memory or to a function argument potentially allows its input to escape.
        if (StoreInst* S = dyn_cast<StoreInst>(I)) {
             Type* StoreType = S->getOperand(0)->getType();
             unsigned StoreSize = TD.getTypeStoreSize(StoreType);
             Value* Pointer = S->getPointerOperand();

             bool inserted = false;
             for (Function::arg_iterator AI = F.arg_begin(), AE = F.arg_end(); 
                  AI != AE; ++AI) {
                 if (!isa<PointerType>(AI->getType())) continue;
                 AliasAnalysis::AliasResult R = AA.alias(Pointer, StoreSize, AI, ~0UL);
                 if (R != AliasAnalysis::NoAlias) {
                     EscapePoints.insert(S);
                     inserted = true;
                     break;
                 }
            }

            if (inserted)
                continue;

            for (Module::global_iterator GI = M->global_begin(), GE = M->global_end();
                 GI != GE; ++GI) {
                errs() << *GI << "\n";
                AliasAnalysis::AliasResult R = AA.alias(Pointer, StoreSize, GI, ~0UL);
                errs() << "R: " << R << " , NoAlias: " << AliasAnalysis::NoAlias << "\n";

                if (R != AliasAnalysis::NoAlias) {
                    EscapePoints.insert(S);
                    break;
                }
            }

      // Calls and invokes potentially allow their parameters to escape.
      // FIXME: This can and should be refined.  Intrinsics have known escape
      // behavior, and alias analysis may be able to tell us more about callees.
        } else if (isa<CallInst>(I) || isa<InvokeInst>(I)) {
            EscapePoints.insert(I);

            // Returns allow the return value to escape.  This is mostly important
            // for malloc to alloca promotion.
        } else if (isa<ReturnInst>(I)) {
            EscapePoints.insert(I);

            // Branching on the value of a pointer may allow the value to escape through
            // methods not discoverable via def-use chaining.
        } else if(isa<BranchInst>(I) || isa<SwitchInst>(I)) {
            EscapePoints.insert(I);
        }

     // FIXME: Are there any other possible escape points?
    }

     return false;
}

Test the main.cpp as following: #include

using namespace std;

int X = 0;

int foo() {
X = 1;
int b = 1;
return 0;
}

int bar(int param) {
int y = X;
int z = 9;
int a = z;

++a;
return 0;
}

int main(int argc, char *argv[])
{
    cout << "Hello world!" << endl;
    return 0;
}

the global variable X is the shared variable between function bar and function foo. But when I use the command as following to run the pass:

opt -load ./EscapeAnalysis.so -escape-analysis main.o | llc > main.ss

I get the result:

R: 1 , NoAlias: 0

all result are the same. I print out the variables in escapePoint, find that variable a, z, y in function bar are in escapePoint. It is not right!

Note: I write a opt pass to test program.

Upvotes: 0

Views: 1107

Answers (1)

Oak
Oak

Reputation: 26898

Alias analysis is required if you want to identify when two different variables might point to the same memory. If you just want to check which variables are shared with other functions in the same module, you can:

  1. Iterate over all instructions, and for each:
  2. Iterate over all its operands, and for each:
  3. Check whether it's a GlobalVariable (via isa, for instance), and if so:
  4. Iterate over all the global's uses (via use_begin and use_end), and for each:
  5. Check whether it's an Instruction, and if so:
  6. Retrieve the enclosing function (via getParent()->getParent()), and for that function:
  7. Check whether it is the currently-processed function. If not, it means you found a variable shared between the current function and another function.

There are also other ways of checking this, for example going over all the globals in the current module.

Upvotes: 2

Related Questions