元のプログラムの浮動小数点変数の型をlong doubleに変更するために、LLVMパスを作成しています。おもちゃのテストプログラムは次のとおりです:LLVMパスを書いて元のプログラムの浮動小数点変数の型をlong doubleに変更するにはどうすればよいですか?
int main(){
double i = 0.0000000000000001;
if(i + 1 > 1)
printf("correct answer");
else
printf("wrong answer");
return 0;
}
私のパスは、 "long double"に変更する必要があります。 元のプログラムのIRと変換されたプログラムの間には5つの異なる場所があります。
< %i = alloca x86_fp80, align 16
---
> %i = alloca double, align 8
< store x86_fp80 0xK3FC9E69594BEC44DE000, x86_fp80* %i, align 16
< %0 = load x86_fp80, x86_fp80* %i, align 16
< %add = fadd x86_fp80 %0, 0xK3FFF8000000000000000
< %cmp = fcmp ogt x86_fp80 %add, 0xK3FFF8000000000000000
---
> store double 1.000000e-16, double* %i, align 8
> %0 = load double, double* %i, align 8
> %add = fadd double %0, 1.000000e+00
> %cmp = fcmp ogt double %add, 1.000000e+00
次のように上記の変換を行うには、私のパスの概要は次のとおりです。
virtual bool runOnFunction(Function &F) {
std::string svariable ("i");
const ValueSymbolTable& symbolTable = F.getValueSymbolTable();
Value* target = symbolTable.lookup(svariable);
AllocaInst* old_target = dyn_cast<AllocaInst>(target);
errs() <<"old_target: " << *target << "\n";
errs() <<"num of old_target_uses:" << old_target->getNumUses() <<"\n";
//get the type of long double and construct new AllocaInst
LLVMContext &context = F.getContext();
Type* type = Type::getX86_FP80Ty(context);
unsigned alignment = 16;
AllocaInst* new_target = new AllocaInst(type, 0, alignment, "new", old_target);
new_target->takeName(old_target);
// iterating through instructions using old AllocaInst
Value::use_iterator it = old_target->use_begin();
for(; it != old_target->use_end(); it++) {
Value * temp = it->get();
errs() <<"temp:" << *temp <<"\n";
//transform() is under construction
transform(it, new_target, type, alignment);
}
old_target->eraseFromParent();
return false;
}
元のプログラムのIRに示したように、私を倍増するために関連する4つの命令がなければならない:
> store double 1.000000e-16, double* %i, align 8
> %0 = load double, double* %i, align 8
> %add = fadd double %0, 1.000000e+00
> %cmp = fcmp ogt double %add, 1.000000e+00
が、上記予想通りパスの出力はありません:
old_target: %i = alloca double, align 8
num of old_target_uses:2
temp: %0 = alloca double, align 8
temp: %0 = alloca double, align 8
私の最初の質問は、getNumUses()とuse_iteratorが正解を返さなかった理由です。パスのアウトラインで間違った方法で使用しましたか?
私の2番目の質問は、私のtransform()関数にあります。LoadInst、StoreInst、BinaryOperationなどのあらゆる種類の命令を列挙し、新しい型でそれらを再構築する必要がありますか?最初の質問のように、各Use
オブジェクトは、基本的にそのUsers
(命令や定数のいずれかにValue
(主に命令または定数)を結ぶデータ・フロー・グラフにおけるエッジ予め
感謝:)
は、なぜあなたは(例えば、クランを使用して)LLVMのレベルではなく、ソースコードレベルでこの問題を攻撃することを選択したのですか? – eush77
ご意見ありがとうございました。 LLVMのIRレベルでそれを攻撃すると、C/C++、Fortran、RなどのLLVMをコンパイルする(またはコンパイルする)ソース言語を簡単にサポートできます。 – Sue