diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index 1761d7faff576315c0fbb81e299ac4d9f08030f6..5518ef8fce988d626522324a3bf80070c87990b3 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -2107,6 +2107,13 @@ static bool hasChangeableCC(Function *F) { if (CC != CallingConv::C && CC != CallingConv::X86_ThisCall) return false; + // Don't break the invariant that the inalloca parameter is the only parameter + // passed in memory. + // FIXME: GlobalOpt should remove inalloca when possible and hoist the dynamic + // alloca it uses to the entry block if possible. + if (F->getAttributes().hasAttrSomewhere(Attribute::InAlloca)) + return false; + // FIXME: Change CC for the whole chain of musttail calls when possible. // // Can't change CC of the function that either has musttail calls, or is a diff --git a/llvm/test/Transforms/GlobalOpt/fastcc.ll b/llvm/test/Transforms/GlobalOpt/fastcc.ll index 26398d2bb900100969a79a74bffaca62931b4122..64c4a268ff3cba918897f43d462c90633e2b2f09 100644 --- a/llvm/test/Transforms/GlobalOpt/fastcc.ll +++ b/llvm/test/Transforms/GlobalOpt/fastcc.ll @@ -26,12 +26,20 @@ define internal i32 @j(i32* %m) { ret i32 %v } +define internal i32 @inalloca(i32* inalloca %p) { +; CHECK-LABEL: define internal i32 @inalloca(i32* inalloca %p) + %rv = load i32, i32* %p + ret i32 %rv +} + define void @call_things() { %m = alloca i32 call i32 @f(i32* %m) call x86_thiscallcc i32 @g(i32* %m) call coldcc i32 @h(i32* %m) call i32 @j(i32* %m) + %args = alloca inalloca i32 + call i32 @inalloca(i32* inalloca %args) ret void } @@ -44,3 +52,4 @@ define void @call_things() { ; CHECK: call fastcc i32 @g ; CHECK: call coldcc i32 @h ; CHECK: call i32 @j +; CHECK: call i32 @inalloca(i32* inalloca %args)