From 6c1e6bbe0c609489ef49f9d64f1370a43e05c19c Mon Sep 17 00:00:00 2001 From: Luke Cheeseman Date: Thu, 22 Feb 2018 14:42:08 +0000 Subject: [PATCH] [FunctionAttrs][ArgumentPromotion][GlobalOpt] Disable some optimisations passes for naked functions - Fix for bug 36078. - Prevent the functionattrs, function-attrs, globalopt and argpromotion passes from changing naked functions. - These passes can perform some alterations to the functions that should not be applied. An example is removing parameters that are seemingly not used because they are only referenced in the inline assembly. Another example is marking the function as fastcc. llvm-svn: 325788 --- llvm/lib/Transforms/IPO/ArgumentPromotion.cpp | 6 ++++++ llvm/lib/Transforms/IPO/FunctionAttrs.cpp | 6 ++++-- llvm/lib/Transforms/IPO/GlobalOpt.cpp | 5 +++++ .../ArgumentPromotion/naked_functions.ll | 23 ++++++++++++++++++++ .../Transforms/FunctionAttrs/naked_functions.ll | 25 ++++++++++++++++++++++ llvm/test/Transforms/GlobalOpt/naked_functions.ll | 23 ++++++++++++++++++++ 6 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 llvm/test/Transforms/ArgumentPromotion/naked_functions.ll create mode 100644 llvm/test/Transforms/FunctionAttrs/naked_functions.ll create mode 100644 llvm/test/Transforms/GlobalOpt/naked_functions.ll diff --git a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp index d3a7b0e..461c4e1 100644 --- a/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/llvm/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -817,6 +817,12 @@ promoteArguments(Function *F, function_ref AARGetter, unsigned MaxElements, Optional> ReplaceCallSite) { + // 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. + if(F->hasFnAttribute(Attribute::Naked)) + return nullptr; + // Make sure that it is local to this module. if (!F->hasLocalLinkage()) return nullptr; diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index 5352e32..353daec 100644 --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -1136,7 +1136,8 @@ PreservedAnalyses PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C, bool HasUnknownCall = false; for (LazyCallGraph::Node &N : C) { Function &F = N.getFunction(); - if (F.hasFnAttribute(Attribute::OptimizeNone)) { + if (F.hasFnAttribute(Attribute::OptimizeNone) || + F.hasFnAttribute(Attribute::Naked)) { // Treat any function we're trying not to optimize as if it were an // indirect call and omit it from the node set used below. HasUnknownCall = true; @@ -1221,7 +1222,8 @@ static bool runImpl(CallGraphSCC &SCC, AARGetterT AARGetter) { bool ExternalNode = false; for (CallGraphNode *I : SCC) { Function *F = I->getFunction(); - if (!F || F->hasFnAttribute(Attribute::OptimizeNone)) { + if (!F || F->hasFnAttribute(Attribute::OptimizeNone) || + F->hasFnAttribute(Attribute::Naked)) { // External node or function we're trying not to optimize - we both avoid // transform them and avoid leveraging information they provide. ExternalNode = true; diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index 9dfb61d..274ecf0 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -2221,6 +2221,11 @@ OptimizeFunctions(Module &M, TargetLibraryInfo *TLI, for (Module::iterator FI = M.begin(), E = M.end(); FI != E; ) { Function *F = &*FI++; + // Don't perform global opt pass on naked functions; we don't want fast + // calling conventions for naked functions. + if (F->hasFnAttribute(Attribute::Naked)) + continue; + // Functions without names cannot be referenced outside this module. if (!F->hasName() && !F->isDeclaration() && !F->hasLocalLinkage()) F->setLinkage(GlobalValue::InternalLinkage); diff --git a/llvm/test/Transforms/ArgumentPromotion/naked_functions.ll b/llvm/test/Transforms/ArgumentPromotion/naked_functions.ll new file mode 100644 index 0000000..70a63f4 --- /dev/null +++ b/llvm/test/Transforms/ArgumentPromotion/naked_functions.ll @@ -0,0 +1,23 @@ +; RUN: opt < %s -argpromotion -S | FileCheck %s + +; Don't promote paramaters of/arguments to naked functions + +@g = common global i32 0, align 4 + +define i32 @bar() { +entry: + %call = call i32 @foo(i32* @g) +; CHECK: %call = call i32 @foo(i32* @g) + ret i32 %call +} + +define internal i32 @foo(i32*) #0 { +entry: + %retval = alloca i32, align 4 + call void asm sideeffect "ldr r0, [r0] \0Abx lr \0A", ""() + unreachable +} + +; CHECK: define internal i32 @foo(i32*) + +attributes #0 = { naked } diff --git a/llvm/test/Transforms/FunctionAttrs/naked_functions.ll b/llvm/test/Transforms/FunctionAttrs/naked_functions.ll new file mode 100644 index 0000000..d34dc0c --- /dev/null +++ b/llvm/test/Transforms/FunctionAttrs/naked_functions.ll @@ -0,0 +1,25 @@ +; RUN: opt -S -functionattrs %s | FileCheck %s +; RUN: opt -S -passes='function-attrs' %s | FileCheck %s + +; Don't change the attributes of parameters of naked functions, in particular +; don't mark them as readnone + +@g = common global i32 0, align 4 + +define i32 @bar() { +entry: + %call = call i32 @foo(i32* @g) +; CHECK: %call = call i32 @foo(i32* @g) + ret i32 %call +} + +define internal i32 @foo(i32*) #0 { +entry: + %retval = alloca i32, align 4 + call void asm sideeffect "ldr r0, [r0] \0Abx lr \0A", ""() + unreachable +} + +; CHECK: define internal i32 @foo(i32*) + +attributes #0 = { naked } diff --git a/llvm/test/Transforms/GlobalOpt/naked_functions.ll b/llvm/test/Transforms/GlobalOpt/naked_functions.ll new file mode 100644 index 0000000..80c3aa8 --- /dev/null +++ b/llvm/test/Transforms/GlobalOpt/naked_functions.ll @@ -0,0 +1,23 @@ +; RUN: opt < %s -globalopt -S | FileCheck %s + +; Check that naked functions don't get marked with fast calling conventions + +@g = common global i32 0, align 4 + +define i32 @bar() { +entry: + %call = call i32 @foo(i32* @g) +; CHECK: %call = call i32 @foo(i32* @g) + ret i32 %call +} + +define internal i32 @foo(i32*) #0 { +entry: + %retval = alloca i32, align 4 + call void asm sideeffect "ldr r0, [r0] \0Abx lr \0A", ""() + unreachable +} + +; CHECK: define internal i32 @foo(i32*) + +attributes #0 = { naked } -- 2.7.4