diff --git a/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp b/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp index 81dbd329c4b6..d372ba22d6e3 100644 --- a/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -531,6 +531,13 @@ DAE::Liveness DAE::SurveyUses(const Value *V, UseVector &MaybeLiveUses) { // well as arguments to functions which have their "address taken". // void DAE::SurveyFunction(const Function &F) { + // Functions with inalloca parameters are expecting args in a particular + // register and memory layout. + if (F.getAttributes().hasAttrSomewhere(Attribute::InAlloca)) { + MarkLive(F); + return; + } + unsigned RetCount = NumRetVals(&F); // Assume all return values are dead typedef SmallVector RetVals; diff --git a/llvm/test/Transforms/DeadArgElim/keepalive.ll b/llvm/test/Transforms/DeadArgElim/keepalive.ll index 82e01f225843..b66df792ca84 100644 --- a/llvm/test/Transforms/DeadArgElim/keepalive.ll +++ b/llvm/test/Transforms/DeadArgElim/keepalive.ll @@ -28,4 +28,20 @@ define void @caller() { ret void } +; We can't remove 'this' here, as that would put argmem in ecx instead of +; memory. +define internal x86_thiscallcc i32 @unused_this(i32* %this, i32* inalloca %argmem) { + %v = load i32* %argmem + ret i32 %v +} +; CHECK-LABEL: define internal x86_thiscallcc i32 @unused_this(i32* %this, i32* inalloca %argmem) + +define i32 @caller2() { + %t = alloca i32 + %m = alloca i32, inalloca + store i32 42, i32* %m + %v = call x86_thiscallcc i32 @unused_this(i32* %t, i32* inalloca %m) + ret i32 %v +} + ; CHECK: attributes #0 = { nounwind }