diff options
author | Andrea Di Biagio <Andrea_DiBiagio@sn.scee.net> | 2015-01-06 17:41:18 +0000 |
---|---|---|
committer | Andrea Di Biagio <Andrea_DiBiagio@sn.scee.net> | 2015-01-06 17:41:18 +0000 |
commit | f807a6f2970398b85ccd2a3ba6d8959426a9872f (patch) | |
tree | 911eb76a03413e1686ee193038b3d84907aef6a6 /llvm/lib/CodeGen | |
parent | a76dfbd4288271d3a61fe2f4307c406780ce7c49 (diff) | |
download | bcm5719-llvm-f807a6f2970398b85ccd2a3ba6d8959426a9872f.tar.gz bcm5719-llvm-f807a6f2970398b85ccd2a3ba6d8959426a9872f.zip |
[CodeGenPrepare] Improved logic to speculate calls to cttz/ctlz.
This patch improves the logic added at revision 224899 (see review D6728) that
teaches the backend when it is profitable to speculate calls to cttz/ctlz.
The original algorithm conservatively avoided speculating more than one
instruction from a basic block in a control flow grap modelling an if-statement.
In particular, the only allowed instruction (excluding the terminator) was a
call to cttz/ctlz. However, there are cases where we could be less conservative
and still be able to speculate a call to cttz/ctlz.
With this patch, CodeGenPrepare now tries to speculate a cttz/ctlz if the
result is zero extended/truncated in the same basic block, and the zext/trunc
instruction is "free" for the target.
Added new test cases to CodeGen/X86/cttz-ctlz.ll
Differential Revision: http://reviews.llvm.org/D6853
llvm-svn: 225274
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/CodeGenPrepare.cpp | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 51ea7db30ba..be2cb51785f 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -4008,15 +4008,41 @@ static bool OptimizeBranchInst(BranchInst *BrInst, const TargetLowering &TLI) { // See if ThenBB contains only one instruction (excluding the // terminator and DbgInfoIntrinsic calls). IntrinsicInst *II = nullptr; + CastInst *CI = nullptr; for (BasicBlock::iterator I = ThenBB->begin(), E = std::prev(ThenBB->end()); I != E; ++I) { // Skip debug info. if (isa<DbgInfoIntrinsic>(I)) continue; - if (II) - // Avoid speculating more than one instruction. - return false; + // Check if this is a zero extension or a truncate of a previously + // matched call to intrinsic cttz/ctlz. + if (II) { + // Early exit if we already found a "free" zero extend/truncate. + if (CI) + return false; + + Type *SrcTy = II->getType(); + Type *DestTy = I->getType(); + Value *V; + + if (match(cast<Instruction>(I), m_ZExt(m_Value(V))) && V == II) { + // Speculate this zero extend only if it is "free" for the target. + if (TLI.isZExtFree(SrcTy, DestTy)) { + CI = cast<CastInst>(I); + continue; + } + } else if (match(cast<Instruction>(I), m_Trunc(m_Value(V))) && V == II) { + // Speculate this truncate only if it is "free" for the target. + if (TLI.isTruncateFree(SrcTy, DestTy)) { + CI = cast<CastInst>(I); + continue; + } + } else { + // Avoid speculating more than one instruction. + return false; + } + } // See if this is a call to intrinsic cttz/ctlz. if (match(cast<Instruction>(I), m_Intrinsic<Intrinsic::cttz>())) { @@ -4041,11 +4067,14 @@ static bool OptimizeBranchInst(BranchInst *BrInst, const TargetLowering &TLI) { Value *ThenV = PN->getIncomingValueForBlock(ThenBB); Value *OrigV = PN->getIncomingValueForBlock(EntryBB); - if (!OrigV || ThenV != II) + if (!OrigV) return false; + if (ThenV != II && (!CI || ThenV != CI)) + return false; + if (ConstantInt *CInt = dyn_cast<ConstantInt>(OrigV)) { - unsigned BitWidth = ThenV->getType()->getIntegerBitWidth(); + unsigned BitWidth = II->getType()->getIntegerBitWidth(); // Don't try to simplify this phi node if 'ThenV' is a cttz/ctlz // intrinsic call, but 'OrigV' is not equal to the 'size-of' in bits @@ -4070,7 +4099,7 @@ static bool OptimizeBranchInst(BranchInst *BrInst, const TargetLowering &TLI) { ConstantInt::getFalse(II->getContext()) }; Module *M = EntryBB->getParent()->getParent(); Value *IF = Intrinsic::getDeclaration(M, II->getIntrinsicID(), Ty); - IRBuilder<> Builder(BrInst); + IRBuilder<> Builder(II); Instruction *NewI = Builder.CreateCall(IF, Args); // Replace the old call to cttz/ctlz. |