From 3d36e5c3e6cf8ed0ce68fd9e123654ddcfbaf7a3 Mon Sep 17 00:00:00 2001 From: Tom Stellard Date: Wed, 16 Jan 2019 05:15:31 +0000 Subject: Only promote args when function attributes are compatible Summary: Check to make sure that the caller and the callee have compatible function arguments before promoting arguments. This uses the same TargetTransformInfo queries that are used to determine if attributes are compatible for inlining. The goal here is to avoid breaking ABI when a called function's ABI depends on a target feature that is not enabled in the caller. This is a very conservative fix for PR37358. Ideally we would have a more sophisticated check for ABI compatiblity rather than checking if the attributes are compatible for inlining. Reviewers: echristo, chandlerc, eli.friedman, craig.topper Reviewed By: echristo, chandlerc Subscribers: nikic, xbolva00, rkruppe, alexcrichton, llvm-commits Differential Revision: https://reviews.llvm.org/D53554 llvm-svn: 351296 --- llvm/lib/Transforms/IPO/ArgumentPromotion.cpp | 35 ++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) (limited to 'llvm/lib/Transforms/IPO') diff --git a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp index 517a9c082a4..4663de0b049 100644 --- a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -49,6 +49,7 @@ #include "llvm/Analysis/Loads.h" #include "llvm/Analysis/MemoryLocation.h" #include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" @@ -809,6 +810,21 @@ static bool canPaddingBeAccessed(Argument *arg) { return false; } +static bool areFunctionArgsABICompatible( + const Function &F, const TargetTransformInfo &TTI, + SmallPtrSetImpl &ArgsToPromote, + SmallPtrSetImpl &ByValArgsToTransform) { + for (const Use &U : F.uses()) { + CallSite CS(U.getUser()); + const Function *Caller = CS.getCaller(); + const Function *Callee = CS.getCalledFunction(); + if (!TTI.areFunctionArgsABICompatible(Caller, Callee, ArgsToPromote) || + !TTI.areFunctionArgsABICompatible(Caller, Callee, ByValArgsToTransform)) + return false; + } + return true; +} + /// PromoteArguments - This method checks the specified function to see if there /// are any promotable arguments and if it is safe to promote the function (for /// example, all callers are direct). If safe to promote some arguments, it @@ -817,7 +833,8 @@ static Function * promoteArguments(Function *F, function_ref AARGetter, unsigned MaxElements, Optional> - ReplaceCallSite) { + ReplaceCallSite, + const TargetTransformInfo &TTI) { // Don't perform argument promotion for naked functions; otherwise we can end // up removing parameters that are seemingly 'not used' as they are referred // to in the assembly. @@ -846,7 +863,7 @@ promoteArguments(Function *F, function_ref AARGetter, // Second check: make sure that all callers are direct callers. We can't // transform functions that have indirect callers. Also see if the function - // is self-recursive. + // is self-recursive and check that target features are compatible. bool isSelfRecursive = false; for (Use &U : F->uses()) { CallSite CS(U.getUser()); @@ -955,6 +972,10 @@ promoteArguments(Function *F, function_ref AARGetter, if (ArgsToPromote.empty() && ByValArgsToTransform.empty()) return nullptr; + if (!areFunctionArgsABICompatible(*F, TTI, ArgsToPromote, + ByValArgsToTransform)) + return nullptr; + return doPromotion(F, ArgsToPromote, ByValArgsToTransform, ReplaceCallSite); } @@ -980,7 +1001,9 @@ PreservedAnalyses ArgumentPromotionPass::run(LazyCallGraph::SCC &C, return FAM.getResult(F); }; - Function *NewF = promoteArguments(&OldF, AARGetter, MaxElements, None); + const TargetTransformInfo &TTI = FAM.getResult(OldF); + Function *NewF = + promoteArguments(&OldF, AARGetter, MaxElements, None, TTI); if (!NewF) continue; LocalChange = true; @@ -1018,6 +1041,7 @@ struct ArgPromotion : public CallGraphSCCPass { void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); AU.addRequired(); + AU.addRequired(); getAAResultsAnalysisUsage(AU); CallGraphSCCPass::getAnalysisUsage(AU); } @@ -1043,6 +1067,7 @@ INITIALIZE_PASS_BEGIN(ArgPromotion, "argpromotion", INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) +INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) INITIALIZE_PASS_END(ArgPromotion, "argpromotion", "Promote 'by reference' arguments to scalars", false, false) @@ -1079,8 +1104,10 @@ bool ArgPromotion::runOnSCC(CallGraphSCC &SCC) { CallerNode->replaceCallEdge(OldCS, NewCS, NewCalleeNode); }; + const TargetTransformInfo &TTI = + getAnalysis().getTTI(*OldF); if (Function *NewF = promoteArguments(OldF, AARGetter, MaxElements, - {ReplaceCallSite})) { + {ReplaceCallSite}, TTI)) { LocalChange = true; // Update the call graph for the newly promoted function. -- cgit v1.2.3