2

LLVM フロントエンド モジュール パスの作成に取り組んでいます。したがって、基本的には、すべてのロード命令を複製して別のレジスタに格納する必要があります。clang、opt、および llc ツールの -O0 では、この重複したロード命令が削除されます。objdump を使用して最終的なアセンブリを確認したところ、重複したロード命令が削除されていることがわかりました。重複するロード命令を何らかの形で削除しないソリューションが必要です。

実際のCプログラムは、

int main(){
    int* p = (int *)(0x600000);//Some address
    int x=0x01, y=0x01;
    int z;
    z=x+y;
    *p=z;
}

対応するIRは、

define i32 @main() #0 {
entry:
  %p = alloca i32*, align 8
  %x = alloca i32, align 4
  %y = alloca i32, align 4
  %z = alloca i32, align 4
  store i32* inttoptr (i64 6291456 to i32*), i32** %p, align 8
  store i32 1, i32* %x, align 4
  store i32 1, i32* %y, align 4
  %0 = load i32, i32* %x, align 4
  %1 = load i32, i32* %y, align 4
  %add = add nsw i32 %0, %1
  store i32 %add, i32* %z, align 4
  %2 = load i32, i32* %z, align 4
  %3 = load i32*, i32** %p, align 8
  store i32 %2, i32* %3, align 4
  ret i32 0
}

しかし、私のパスが有効になると、この IR が変更され、複製されたロードであっても、ロード アドレスが同じメモリであるロード命令のみが複製されます。

変更されたIRは、

define i32 @main() #0 {
entry:
  %p = alloca i32*, align 8
  %x = alloca i32, align 4
  %y = alloca i32, align 4
  %z = alloca i32, align 4
  store i32* inttoptr (i64 6291456 to i32*), i32** %p, align 8
  store i32 1, i32* %x, align 4
  store i32 1, i32* %y, align 4
  %0 = load i32, i32* %x, align 4
  %1 = load i32, i32* %y, align 4
  %2 = load i32, i32* %x, align 4 //Added
  %3 = load i32, i32* %y, align 4 //Added
  %add = add nsw i32 %0, %1
  store i32 %add, i32* %z, align 4
  %4 = load i32, i32* %z, align 4
  %5 = load i32*, i32** %p, align 8
  %6 = load i32, i32* %z, align 4 //Added
  %7 = load i32*, i32** %p, align 8        //Added
  store i32 %4, i32* %5, align 4
  ret i32 0
}

IR レベルでは変更された IR を確認できますが、llc 後の最終アセンブリ レベルでは確認できません。llc は重複した負荷をすべて削除していると思います。llc が削除されないようにするにはどうすればよいですか?

注:すべての変数を揮発性にしてみました。これが機能するため、llc の後に重複したロードを確認できます。しかし、これは適切な解決策ではありません。1000 個すべての変数を volatile にすることはできません :(.

4

0 に答える 0