Index: llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -198,6 +198,13 @@ 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 @@ 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 @@ 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; Index: llvm/trunk/test/Transforms/DeadArgElim/naked_functions.ll =================================================================== --- llvm/trunk/test/Transforms/DeadArgElim/naked_functions.ll +++ llvm/trunk/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 }