diff options
author | Chris Lattner <sabre@nondot.org> | 2012-06-01 05:16:33 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2012-06-01 05:16:33 +0000 |
commit | 5b0d9465375c4e175f5805038c5ef1d7d11193bd (patch) | |
tree | 363630bb125a33d74d278e9a9c90b1e4b9f7792a | |
parent | 09c14c083676eb83867e349e2b549b22ab1ed5c3 (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.cpp | 48 | ||||
-rw-r--r-- | test/CodeGen/X86/tailcall-64.ll | 22 |
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 |