[PATCH v2 16/50] helper-to-tcg: PrepareForOptPass, undef llvm.returnaddress
Anton Johansson via qemu development <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
Convert llvm.returnaddress arguments to cpu_[ld|st]*() to undef, causing the LLVM optmizer to discard the intrinsics. Needed as llvm.returnadress is not representable in TCG, and usually results from usage of GETPC() in helper functions. Signed-off-by: Anton Johansson <[email protected]> --- .../PrepareForOptPass/PrepareForOptPass.cpp | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/subprojects/helper-to-tcg/src/PrepareForOptPass/PrepareForOptPass.cpp b/subprojects/helper-to-tcg/src/PrepareForOptPass/PrepareForOptPass.cpp index df6d9eeec8..157f8cd05e 100644 --- a/subprojects/helper-to-tcg/src/PrepareForOptPass/PrepareForOptPass.cpp +++ b/subprojects/helper-to-tcg/src/PrepareForOptPass/PrepareForOptPass.cpp @@ -29,6 +29,7 @@ #include <llvm/IR/Function.h> #include <llvm/IR/Instruction.h> #include <llvm/IR/Instructions.h> +#include <llvm/IR/Intrinsics.h> #include <llvm/IR/Module.h> #include <llvm/Support/Debug.h> @@ -241,10 +242,56 @@ static void cullUnusedFunctions(Module &M, AnnotationMapTy &Annotations) { } } +struct RetAddrReplaceInfo { + User *Parent; + unsigned OpIndex; + Type *Ty; +}; + +static void replaceRetaddrWithUndef(Module &M) { + // Replace uses of llvm.returnaddress arguments to cpu_ld* w. undef, + // and let optimizations remove it. Needed as llvm.returnaddress is + // not reprensentable in TCG. + SmallVector<RetAddrReplaceInfo, 24> UsesToReplace; + Function *Retaddr = compat::Intrinsic::getOrInsertDeclaration( + &M, Intrinsic::returnaddress, {}); + // Loop over all calls to llvm.returnaddress + for (auto *CallUser : Retaddr->users()) { + auto *Call = dyn_cast<CallInst>(CallUser); + if (!Call) { + continue; + } + for (auto *PtrToIntUser : Call->users()) { + auto *Cast = dyn_cast<PtrToIntInst>(PtrToIntUser); + if (!Cast) { + continue; + } + for (Use &U : Cast->uses()) { + auto *Call = dyn_cast<CallInst>(U.getUser()); + Function *F = Call->getCalledFunction(); + if (compat::isFunctionQemuLoadStore(F->getName())) { + UsesToReplace.push_back({ + .Parent = U.getUser(), + .OpIndex = U.getOperandNo(), + .Ty = U->getType(), + }); + } + } + } + } + + // Defer replacement to not invalidate iterators + for (RetAddrReplaceInfo &RI : UsesToReplace) { + auto *Undef = UndefValue::get(RI.Ty); + RI.Parent->setOperand(RI.OpIndex, Undef); + } +} + PreservedAnalyses PrepareForOptPass::run(Module &M, ModuleAnalysisManager &MAM) { demangleFunctionNames(M); collectAnnotations(M, ResultAnnotations); cullUnusedFunctions(M, ResultAnnotations); + replaceRetaddrWithUndef(M); return PreservedAnalyses::none(); } -- 2.52.0