diff options
| author | Reid Kleckner <rnk@google.com> | 2016-08-12 22:23:04 +0000 |
|---|---|---|
| committer | Reid Kleckner <rnk@google.com> | 2016-08-12 22:23:04 +0000 |
| commit | 6ee00a2602732c8db543e7fc0c84bc34a3ef9f14 (patch) | |
| tree | 7d9a0a653b284b3b43f205e4f874bf6b04baa03c /llvm | |
| parent | ab47fa643b77923322368dc2b8f277080c988c98 (diff) | |
| download | bcm5719-llvm-6ee00a2602732c8db543e7fc0c84bc34a3ef9f14.tar.gz bcm5719-llvm-6ee00a2602732c8db543e7fc0c84bc34a3ef9f14.zip | |
[Inliner] Don't treat inalloca allocas as static
They aren't static, and moving them to the entry block across something
else will only result in tears.
Root cause of http://crbug.com/636558.
llvm-svn: 278571
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Transforms/Utils/InlineFunction.cpp | 13 | ||||
| -rw-r--r-- | llvm/test/Transforms/Inline/inalloca-not-static.ll | 63 |
2 files changed, 73 insertions, 3 deletions
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index e101412bf79..6b2ff14f02d 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -1294,6 +1294,13 @@ updateInlinedAtInfo(const DebugLoc &DL, DILocation *InlinedAtNode, return DebugLoc::get(DL.getLine(), DL.getCol(), DL.getScope(), Last); } +/// Return the result of AI->isStaticAlloca() if AI were moved to the entry +/// block. Allocas used in inalloca calls and allocas of dynamic array size +/// cannot be static. +static bool allocaWouldBeStaticInEntry(const AllocaInst *AI ) { + return isa<Constant>(AI->getArraySize()) && !AI->isUsedWithInAlloca(); +} + /// Update inlined instructions' line numbers to /// to encode location where these instructions are inlined. static void fixupLineNumbers(Function *Fn, Function::iterator FI, @@ -1328,7 +1335,7 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI, // Don't update static allocas, as they may get moved later. if (auto *AI = dyn_cast<AllocaInst>(BI)) - if (isa<Constant>(AI->getArraySize())) + if (allocaWouldBeStaticInEntry(AI)) continue; BI->setDebugLoc(TheCallDL); @@ -1626,7 +1633,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI, continue; } - if (!isa<Constant>(AI->getArraySize())) + if (!allocaWouldBeStaticInEntry(AI)) continue; // Keep track of the static allocas that we inline into the caller. @@ -1635,7 +1642,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI, // Scan for the block of allocas that we can move over, and move them // all at once. while (isa<AllocaInst>(I) && - isa<Constant>(cast<AllocaInst>(I)->getArraySize())) { + allocaWouldBeStaticInEntry(cast<AllocaInst>(I))) { IFI.StaticAllocas.push_back(cast<AllocaInst>(I)); ++I; } diff --git a/llvm/test/Transforms/Inline/inalloca-not-static.ll b/llvm/test/Transforms/Inline/inalloca-not-static.ll new file mode 100644 index 00000000000..e70e30d1a7e --- /dev/null +++ b/llvm/test/Transforms/Inline/inalloca-not-static.ll @@ -0,0 +1,63 @@ +; RUN: opt -always-inline -S < %s | FileCheck %s + +; We used to misclassify inalloca as a static alloca in the inliner. This only +; arose with for alwaysinline functions, because the normal inliner refuses to +; inline such things. + +; Generated using this C++ source: +; struct Foo { +; Foo(); +; Foo(const Foo &o); +; ~Foo(); +; int a; +; }; +; __forceinline void h(Foo o) {} +; __forceinline void g() { h(Foo()); } +; void f() { g(); } + +; ModuleID = 't.cpp' +source_filename = "t.cpp" +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i386-pc-windows-msvc19.0.24210" + +%struct.Foo = type { i32 } + +declare i8* @llvm.stacksave() +declare void @llvm.stackrestore(i8*) + +declare x86_thiscallcc %struct.Foo* @"\01??0Foo@@QAE@XZ"(%struct.Foo* returned) unnamed_addr +declare x86_thiscallcc void @"\01??1Foo@@QAE@XZ"(%struct.Foo*) unnamed_addr + +define void @f() { +entry: + call void @g() + ret void +} + +define internal void @g() alwaysinline { +entry: + %inalloca.save = call i8* @llvm.stacksave() + %argmem = alloca inalloca <{ %struct.Foo }>, align 4 + %0 = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %argmem, i32 0, i32 0 + %call = call x86_thiscallcc %struct.Foo* @"\01??0Foo@@QAE@XZ"(%struct.Foo* %0) + call void @h(<{ %struct.Foo }>* inalloca %argmem) + call void @llvm.stackrestore(i8* %inalloca.save) + ret void +} + +; Function Attrs: alwaysinline inlinehint nounwind +define internal void @h(<{ %struct.Foo }>* inalloca) alwaysinline { +entry: + %o = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %0, i32 0, i32 0 + call x86_thiscallcc void @"\01??1Foo@@QAE@XZ"(%struct.Foo* %o) + ret void +} + +; CHECK: define void @f() +; CHECK: %inalloca.save.i = call i8* @llvm.stacksave() +; CHECK: alloca inalloca <{ %struct.Foo }>, align 4 +; CHECK: %call.i = call x86_thiscallcc %struct.Foo* @"\01??0Foo@@QAE@XZ"(%struct.Foo* %0) +; CHECK: %o.i.i = getelementptr inbounds <{ %struct.Foo }>, <{ %struct.Foo }>* %argmem.i, i32 0, i32 0 +; CHECK: call x86_thiscallcc void @"\01??1Foo@@QAE@XZ"(%struct.Foo* %o.i.i) +; CHECK: call void @llvm.stackrestore(i8* %inalloca.save.i) +; CHECK: ret void |

