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 <a...@rev.ng> --- .../PrepareForOptPass/PrepareForOptPass.cpp | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/subprojects/helper-to-tcg/passes/PrepareForOptPass/PrepareForOptPass.cpp b/subprojects/helper-to-tcg/passes/PrepareForOptPass/PrepareForOptPass.cpp index 22509008c8..b357debb5d 100644 --- a/subprojects/helper-to-tcg/passes/PrepareForOptPass/PrepareForOptPass.cpp +++ b/subprojects/helper-to-tcg/passes/PrepareForOptPass/PrepareForOptPass.cpp @@ -23,6 +23,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 <queue> @@ -197,9 +198,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 = Intrinsic::getDeclaration(&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(); + StringRef Name = F->getName(); + if (Name.startswith("cpu_ld") or Name.startswith("cpu_st")) { + 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) { collectAnnotations(M, ResultAnnotations); cullUnusedFunctions(M, ResultAnnotations, TranslateAllHelpers); + replaceRetaddrWithUndef(M); return PreservedAnalyses::none(); } -- 2.45.2