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 をテストします。

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 にあることがわかります。それは正しくありません!

注: テスト プログラムへのオプト パスを作成します。

4

1 に答える 1

2

2 つの異なる変数がいつ同じメモリを指している可能性があるかを特定するには、エイリアス分析が必要です。同じモジュール内の他の関数と共有されている変数を確認したいだけの場合は、次のことができます。

  1. すべての命令を反復し、それぞれについて:
  2. すべてのオペランドを反復し、それぞれについて:
  3. それが(たとえば、GlobalVariable経由で)かどうかを確認し、そうであれば:isa
  4. すべてのグローバルの使用を ( および を介しuse_beginuse_end) 反復処理し、それぞれについて:
  5. かどうかを確認しInstruction、そうであれば:
  6. 囲んでいる関数を ( 経由でgetParent()->getParent()) 取得し、その関数に対して:
  7. 現在処理中の関数かどうかを確認します。そうでない場合は、現在の関数と別の関数の間で共有されている変数が見つかったことを意味します。

これを確認する他の方法もあります。たとえば、現在のモジュール内のすべてのグローバルを調べます。

于 2012-12-12T13:51:06.103 に答える