From 1646851b87cfe131eb79f2a1302aa5db201bacb6 Mon Sep 17 00:00:00 2001 From: Francis Visoiu Mistrih Date: Tue, 23 Apr 2019 21:57:46 +0000 Subject: [PATCH] [CGP] Look through bitcasts when duplicating returns for tail calls The simple case of: ``` int *callee(); void *caller(void *a) { if (a == NULL) return callee(); return a; } ``` would generate a regular call instead of a tail call because we don't look through the bitcast of the call to `callee` when duplicating the return blocks. Differential Revision: https://reviews.llvm.org/D60837 llvm-svn: 359041 --- llvm/lib/CodeGen/CodeGenPrepare.cpp | 4 +++- llvm/test/CodeGen/X86/tailcall-cgp-dup.ll | 17 +++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 544f998..4335f10 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -2032,7 +2032,9 @@ bool CodeGenPrepare::dupRetToEnableTailCallOpts(BasicBlock *BB, bool &ModifiedDT SmallVector TailCalls; if (PN) { for (unsigned I = 0, E = PN->getNumIncomingValues(); I != E; ++I) { - CallInst *CI = dyn_cast(PN->getIncomingValue(I)); + // Look through bitcasts. + Value *IncomingVal = PN->getIncomingValue(I)->stripPointerCasts(); + CallInst *CI = dyn_cast(IncomingVal); // Make sure the phi value is indeed produced by the tail call. if (CI && CI->hasOneUse() && CI->getParent() == PN->getIncomingBlock(I) && TLI->mayBeEmittedAsTailCall(CI) && diff --git a/llvm/test/CodeGen/X86/tailcall-cgp-dup.ll b/llvm/test/CodeGen/X86/tailcall-cgp-dup.ll index cd1d1594..fd6bb4c 100644 --- a/llvm/test/CodeGen/X86/tailcall-cgp-dup.ll +++ b/llvm/test/CodeGen/X86/tailcall-cgp-dup.ll @@ -118,21 +118,18 @@ define i8* @f_ret8(i8* %obj) nounwind { ; OPT: if.then: ; OPT-NEXT: [[PTR:%.*]] = tail call i32* @g_ret32() ; OPT-NEXT: [[CASTED:%.*]] = bitcast i32* [[PTR]] to i8* -; OPT-NEXT: br label [[RETURN]] +; OPT-NEXT: ret i8* [[CASTED]] ; OPT: return: -; OPT-NEXT: [[RETVAL:%.*]] = phi i8* [ [[CASTED]], [[IF_THEN]] ], [ [[OBJ]], [[ENTRY:%.*]] ] -; OPT-NEXT: ret i8* [[RETVAL]] +; OPT-NEXT: ret i8* [[OBJ]] ; ; CHECK-LABEL: f_ret8: ; CHECK: ## %bb.0: ## %entry -; CHECK-NEXT: movq %rdi, %rax ; CHECK-NEXT: testq %rdi, %rdi -; CHECK-NEXT: je LBB3_2 -; CHECK-NEXT: ## %bb.1: ## %if.then -; CHECK-NEXT: pushq %rax -; CHECK-NEXT: callq _g_ret32 -; CHECK-NEXT: addq $8, %rsp -; CHECK-NEXT: LBB3_2: ## %return +; CHECK-NEXT: je LBB3_1 +; CHECK-NEXT: ## %bb.2: ## %if.then +; CHECK-NEXT: jmp _g_ret32 ## TAILCALL +; CHECK-NEXT: LBB3_1: ## %return +; CHECK-NEXT: movq %rdi, %rax ; CHECK-NEXT: retq entry: %cmp = icmp eq i8* %obj, null -- 2.7.4