0

最近我使用 LLVM API 来测试 C++ 程序。现在我想找出不同函数之间的共享变量,有什么办法吗?AliasAnalysis似乎不起作用!

我编写了一个函数传递如下:

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;
}

测试 main.cpp 如下:#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;
}

全局变量 X 是函数 bar 和函数 foo 之间的共享变量。但是当我使用如下命令运行传球时:

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

我得到结果:

R: 1 , NoAlias: 0

所有结果都是一样的。我打印出 escapePoint 中的变量,发现函数 bar 中的变量 a、z、y 在 escapePoint 中。这是不对的!

注意:我写了一个 opt pass 来测试程序。

4

1 回答 1

2

如果要确定两个不同变量何时可能指向同一内存,则需要进行别名分析。如果您只想检查哪些变量与同一模块中的其他函数共享,您可以:

  1. 遍历所有指令,并为每个指令:
  2. 遍历它的所有操作数,并且对于每个:
  3. 检查它是否是GlobalVariableisa例如,通过),如果是:
  4. 迭代所有全局的使用(通过use_beginuse_end),并且对于每个:
  5. 检查它是否是Instruction,如果是:
  6. 检索封闭函数(通过getParent()->getParent()),并为该函数:
  7. 检查是否是当前正在处理的函数。如果不是,则意味着您找到了一个在当前函数和另一个函数之间共享的变量。

还有其他检查方法,例如检查当前模块中的所有全局变量。

于 2012-12-12T13:51:06.103 回答