From dada1d20ba7ad2795793946d9f570eeb05e21f58 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 1 Sep 2015 18:06:46 +0000 Subject: [PATCH] DeadArgElim: don't eliminate arguments from naked functions Differential Revision: http://reviews.llvm.org/D12534 llvm-svn: 246564 --- .../IPO/DeadArgumentElimination.cpp | 21 +++++++++++++ .../Transforms/DeadArgElim/naked_functions.ll | 31 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 llvm/test/Transforms/DeadArgElim/naked_functions.ll diff --git a/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp b/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp index d0447640259e..64c5ab9cb1b0 100644 --- a/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -198,6 +198,13 @@ bool DAE::DeleteDeadVarargs(Function &Fn) { if (Fn.hasAddressTaken()) return false; + // Don't touch naked functions. The assembly might be using an argument, or + // otherwise rely on the frame layout in a way that this analysis will not + // see. + if (Fn.hasFnAttribute(Attribute::Naked)) { + return false; + } + // Okay, we know we can transform this function if safe. Scan its body // looking for calls marked musttail or calls to llvm.vastart. for (Function::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { @@ -345,6 +352,12 @@ bool DAE::RemoveDeadArgumentsFromCallers(Function &Fn) if (Fn.hasLocalLinkage() && !Fn.getFunctionType()->isVarArg()) return false; + // Don't touch naked functions. The assembly might be using an argument, or + // otherwise rely on the frame layout in a way that this analysis will not + // see. + if (Fn.hasFnAttribute(Attribute::Naked)) + return false; + if (Fn.use_empty()) return false; @@ -543,6 +556,14 @@ void DAE::SurveyFunction(const Function &F) { return; } + // Don't touch naked functions. The assembly might be using an argument, or + // otherwise rely on the frame layout in a way that this analysis will not + // see. + if (F.hasFnAttribute(Attribute::Naked)) { + MarkLive(F); + return; + } + unsigned RetCount = NumRetVals(&F); // Assume all return values are dead typedef SmallVector RetVals; diff --git a/llvm/test/Transforms/DeadArgElim/naked_functions.ll b/llvm/test/Transforms/DeadArgElim/naked_functions.ll new file mode 100644 index 000000000000..b7955a10127d --- /dev/null +++ b/llvm/test/Transforms/DeadArgElim/naked_functions.ll @@ -0,0 +1,31 @@ +; RUN: opt -S -deadargelim %s | FileCheck %s + +; Don't eliminate dead arugments from naked functions. +; CHECK: define internal i32 @naked(i32 %x) + +define internal i32 @naked(i32 %x) #0 { + tail call void asm sideeffect inteldialect "mov eax, [esp + $$4]\0A\09ret", "~{eax},~{dirflag},~{fpsr},~{flags}"() + unreachable +} + + +; Don't eliminate dead varargs from naked functions. +; CHECK: define internal i32 @naked_va(i32 %x, ...) + +define internal i32 @naked_va(i32 %x, ...) #0 { + tail call void asm sideeffect inteldialect "mov eax, [esp + $$8]\0A\09ret", "~{eax},~{dirflag},~{fpsr},~{flags}"() + unreachable +} + +define i32 @f(i32 %x, i32 %y) { + %r = call i32 @naked(i32 %x) + %s = call i32 (i32, ...) @naked_va(i32 %x, i32 %r) + +; Make sure the arguments are still there: not removed or replaced with undef. +; CHECK: %r = call i32 @naked(i32 %x) +; CHECK: %s = call i32 (i32, ...) @naked_va(i32 %x, i32 %r) + + ret i32 %s +} + +attributes #0 = { naked }