aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2012-06-01 05:16:33 +0000
committerChris Lattner <sabre@nondot.org>2012-06-01 05:16:33 +0000
commit5b0d9465375c4e175f5805038c5ef1d7d11193bd (patch)
tree363630bb125a33d74d278e9a9c90b1e4b9f7792a
parent09c14c083676eb83867e349e2b549b22ab1ed5c3 (diff)
enhance getNoopInput to know about vector<->vector bitcasts of legal
types, as well as int<->ptr casts. This allows us to tailcall functions with some trivial casts between the call and return (i.e. because the return types disagree). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157798 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/Analysis.cpp48
-rw-r--r--test/CodeGen/X86/tailcall-64.ll22
2 files changed, 60 insertions, 10 deletions
diff --git a/lib/CodeGen/Analysis.cpp b/lib/CodeGen/Analysis.cpp
index f8492f092d..dd11d15975 100644
--- a/lib/CodeGen/Analysis.cpp
+++ b/lib/CodeGen/Analysis.cpp
@@ -210,22 +210,50 @@ ISD::CondCode llvm::getICmpCondCode(ICmpInst::Predicate Pred) {
///
static const Value *getNoopInput(const Value *V, const TargetLowering &TLI) {
// If V is not an instruction, it can't be looked through.
- const Instruction *U = dyn_cast<Instruction>(V);
- if (U == 0 || !U->hasOneUse()) return V;
+ const Instruction *I = dyn_cast<Instruction>(V);
+ if (I == 0 || !I->hasOneUse() || I->getNumOperands() == 0) return V;
+ Value *Op = I->getOperand(0);
+
// Look through truly no-op truncates.
- if (isa<TruncInst>(U) &&
- TLI.isTruncateFree(U->getOperand(0)->getType(), U->getType()))
- return getNoopInput(U->getOperand(0), TLI);
+ if (isa<TruncInst>(I) &&
+ TLI.isTruncateFree(I->getOperand(0)->getType(), I->getType()))
+ return getNoopInput(I->getOperand(0), TLI);
// Look through truly no-op bitcasts.
- if (isa<BitCastInst>(U)) {
- Value *Op = U->getOperand(0);
- if (Op->getType() == U->getType() || // No type change.
- // Pointer to pointer cast.
- (Op->getType()->isPointerTy() && U->getType()->isPointerTy()))
+ if (isa<BitCastInst>(I)) {
+ // No type change at all.
+ if (Op->getType() == I->getType())
+ return getNoopInput(Op, TLI);
+
+ // Pointer to pointer cast.
+ if (Op->getType()->isPointerTy() && I->getType()->isPointerTy())
+ return getNoopInput(Op, TLI);
+
+ if (isa<VectorType>(Op->getType()) && isa<VectorType>(I->getType()) &&
+ TLI.isTypeLegal(EVT::getEVT(Op->getType())) &&
+ TLI.isTypeLegal(EVT::getEVT(I->getType())))
return getNoopInput(Op, TLI);
}
+
+ // Look through inttoptr.
+ if (isa<IntToPtrInst>(I) && !isa<VectorType>(I->getType())) {
+ // Make sure this isn't a truncating or extending cast. We could support
+ // this eventually, but don't bother for now.
+ if (TLI.getPointerTy().getSizeInBits() ==
+ cast<IntegerType>(Op->getType())->getBitWidth())
+ return getNoopInput(Op, TLI);
+ }
+
+ // Look through ptrtoint.
+ if (isa<PtrToIntInst>(I) && !isa<VectorType>(I->getType())) {
+ // Make sure this isn't a truncating or extending cast. We could support
+ // this eventually, but don't bother for now.
+ if (TLI.getPointerTy().getSizeInBits() ==
+ cast<IntegerType>(I->getType())->getBitWidth())
+ return getNoopInput(Op, TLI);
+ }
+
// Otherwise it's not something we can look through.
return V;
diff --git a/test/CodeGen/X86/tailcall-64.ll b/test/CodeGen/X86/tailcall-64.ll
index 569a67c253..a3ef2dc8ef 100644
--- a/test/CodeGen/X86/tailcall-64.ll
+++ b/test/CodeGen/X86/tailcall-64.ll
@@ -19,3 +19,25 @@ define i64 @test_noop_bitcast() {
}
; CHECK: test_noop_bitcast:
; CHECK: jmp _testi ## TAILCALL
+
+
+; Tail call shouldn't be blocked by no-op inttoptr.
+define i8* @test_inttoptr() {
+ %A = tail call i64 @testi()
+ %B = inttoptr i64 %A to i8*
+ ret i8* %B
+}
+
+; CHECK: test_inttoptr:
+; CHECK: jmp _testi ## TAILCALL
+
+
+declare <4 x float> @testv()
+
+define <4 x i32> @test_vectorbitcast() {
+ %A = tail call <4 x float> @testv()
+ %B = bitcast <4 x float> %A to <4 x i32>
+ ret <4 x i32> %B
+}
+; CHECK: test_vectorbitcast:
+; CHECK: jmp _testv ## TAILCALL