diff options
author | Sanjay Patel <spatel@rotateright.com> | 2016-12-03 15:25:16 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2016-12-03 15:25:16 +0000 |
commit | b7f8cb698c3d34a1503400eea8ea68740c495dac (patch) | |
tree | 816700efb3265bff9d00b8f445d909e18b0bce03 /llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | |
parent | bbcf74f5856003f3b78859ca0b392db6d37650f8 (diff) | |
download | bcm5719-llvm-b7f8cb698c3d34a1503400eea8ea68740c495dac.tar.gz bcm5719-llvm-b7f8cb698c3d34a1503400eea8ea68740c495dac.zip |
[InstCombine] change select type to eliminate bitcasts
This solves a secondary problem seen in PR6137:
https://llvm.org/bugs/show_bug.cgi?id=6137#c6
This is similar to the bitwise logic op fold added with:
https://reviews.llvm.org/rL287707
And like that patch, I'm artificially restricting the
transform from vector <-> scalar types until we're sure
that the backend can handle that.
llvm-svn: 288584
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index c9345506803..445f72f4353 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -1824,6 +1824,50 @@ static Instruction *foldBitCastBitwiseLogic(BitCastInst &BitCast, return nullptr; } +/// Change the type of a select if we can eliminate a bitcast. +static Instruction *foldBitCastSelect(BitCastInst &BitCast, + InstCombiner::BuilderTy &Builder) { + Value *Cond, *TVal, *FVal; + if (!match(BitCast.getOperand(0), + m_OneUse(m_Select(m_Value(Cond), m_Value(TVal), m_Value(FVal))))) + return nullptr; + + // A vector select must maintain the same number of elements in its operands. + Type *CondTy = Cond->getType(); + Type *DestTy = BitCast.getType(); + if (CondTy->isVectorTy()) { + if (!DestTy->isVectorTy()) + return nullptr; + if (DestTy->getVectorNumElements() != CondTy->getVectorNumElements()) + return nullptr; + } + + // FIXME: This transform is restricted from changing the select between + // scalars and vectors to avoid backend problems caused by creating + // potentially illegal operations. If a fix-up is added to handle that + // situation, we can remove this check. + if (DestTy->isVectorTy() != TVal->getType()->isVectorTy()) + return nullptr; + + auto *Sel = cast<Instruction>(BitCast.getOperand(0)); + Value *X; + if (match(TVal, m_OneUse(m_BitCast(m_Value(X)))) && X->getType() == DestTy && + !isa<Constant>(X)) { + // bitcast(select(Cond, bitcast(X), Y)) --> select'(Cond, X, bitcast(Y)) + Value *CastedVal = Builder.CreateBitCast(FVal, DestTy); + return SelectInst::Create(Cond, X, CastedVal, "", nullptr, Sel); + } + + if (match(FVal, m_OneUse(m_BitCast(m_Value(X)))) && X->getType() == DestTy && + !isa<Constant>(X)) { + // bitcast(select(Cond, Y, bitcast(X))) --> select'(Cond, bitcast(Y), X) + Value *CastedVal = Builder.CreateBitCast(TVal, DestTy); + return SelectInst::Create(Cond, CastedVal, X, "", nullptr, Sel); + } + + return nullptr; +} + /// Check if all users of CI are StoreInsts. static bool hasStoreUsersOnly(CastInst &CI) { for (User *U : CI.users()) { @@ -2079,6 +2123,9 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) { if (Instruction *I = foldBitCastBitwiseLogic(CI, *Builder)) return I; + if (Instruction *I = foldBitCastSelect(CI, *Builder)) + return I; + if (SrcTy->isPointerTy()) return commonPointerCastTransforms(CI); return commonCastTransforms(CI); |