From c581acbbba3cb1af6a08e17314b26344333f9267 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 27 Oct 2009 05:39:41 +0000 Subject: [PATCH] Fix a pretty serious misfeature of the inliner: if it inlines a function with multiple return values it inserts a PHI to merge them all together. However, if the return values are all the same, it ends up with a pointless PHI and this pointless PHI happens to really block SRoA from happening in at least a silly C++ example written by Doug, but probably others. This fixes rdar://7339069. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@85206 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/InlineFunction.cpp | 9 +++++++ test/Transforms/Inline/basictest.ll | 33 ++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index 619c939064d..20f5a4a9423 100644 --- a/lib/Transforms/Utils/InlineFunction.cpp +++ b/lib/Transforms/Utils/InlineFunction.cpp @@ -619,8 +619,17 @@ bool llvm::InlineFunction(CallSite CS, CallGraph *CG, const TargetData *TD, "Ret value not consistent in function!"); PHI->addIncoming(RI->getReturnValue(), RI->getParent()); } + + // Now that we inserted the PHI, check to see if it has a single value + // (e.g. all the entries are the same or undef). If so, remove the PHI so + // it doesn't block other optimizations. + if (Value *V = PHI->hasConstantValue()) { + PHI->replaceAllUsesWith(V); + PHI->eraseFromParent(); + } } + // Add a branch to the merge points and remove return instructions. for (unsigned i = 0, e = Returns.size(); i != e; ++i) { ReturnInst *RI = Returns[i]; diff --git a/test/Transforms/Inline/basictest.ll b/test/Transforms/Inline/basictest.ll index 451b8cbdfd9..e61f50c7603 100644 --- a/test/Transforms/Inline/basictest.ll +++ b/test/Transforms/Inline/basictest.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -inline -S | FileCheck %s +; RUN: opt < %s -inline -scalarrepl -S | FileCheck %s define i32 @test1f(i32 %i) { ret i32 %i @@ -13,3 +13,34 @@ define i32 @test1(i32 %W) { ; CHECK-NEXT: ret i32 %Y } + + +; rdar://7339069 + +%T = type { i32, i32 } + +; CHECK-NOT: @test2f +define internal %T* @test2f(i1 %cond, %T* %P) { + br i1 %cond, label %T, label %F + +T: + %A = getelementptr %T* %P, i32 0, i32 0 + store i32 42, i32* %A + ret %T* %P + +F: + ret %T* %P +} + +define i32 @test2(i1 %cond) { + %A = alloca %T + + %B = call %T* @test2f(i1 %cond, %T* %A) + %C = getelementptr %T* %B, i32 0, i32 0 + %D = load i32* %C + ret i32 %D + +; CHECK: @test2( +; CHECK-NOT: = alloca +; CHECK: ret i32 42 +} -- 2.34.1