diff options
author | Sanjay Patel <spatel@rotateright.com> | 2016-11-22 22:05:48 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2016-11-22 22:05:48 +0000 |
commit | e359eaaf708e227eeeaf3f4a9640e5cde0f3c05a (patch) | |
tree | 47bd8a4315d352018517d37c89c2e9dd60e6d22e /llvm/lib | |
parent | eda365cf807c22ad939dd6d3017cf6a3679675b6 (diff) | |
download | bcm5719-llvm-e359eaaf708e227eeeaf3f4a9640e5cde0f3c05a.tar.gz bcm5719-llvm-e359eaaf708e227eeeaf3f4a9640e5cde0f3c05a.zip |
[InstCombine] change bitwise logic type to eliminate bitcasts
In PR27925:
https://llvm.org/bugs/show_bug.cgi?id=27925
...we proposed adding this fold to eliminate a bitcast. In D20774, there was
some concern about changing the type of a bitwise op as well as creating
bitcasts that might not be free for a target. However, if we're strictly
eliminating an instruction (by limiting this to one-use ops), then we should
be able to do this in InstCombine.
But we're cautiously restricting the transform for now to vector types to
avoid possible backend problems. A transform to make sure the logic op is
legal for the target should be added to reverse this transform and improve
codegen.
Differential Revision: https://reviews.llvm.org/D26641
llvm-svn: 287707
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp index 8115a8c51ca..c085a31b5cd 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -1778,6 +1778,46 @@ static Instruction *canonicalizeBitCastExtElt(BitCastInst &BitCast, return ExtractElementInst::Create(NewBC, ExtElt->getIndexOperand()); } +/// Change the type of a bitwise logic operation if we can eliminate a bitcast. +static Instruction *foldBitCastBitwiseLogic(BitCastInst &BitCast, + InstCombiner::BuilderTy &Builder) { + BinaryOperator *BO; + if (!match(BitCast.getOperand(0), m_OneUse(m_BinOp(BO)))) + return nullptr; + + auto Opcode = BO->getOpcode(); + if (Opcode != Instruction::And && Opcode != Instruction::Or && + Opcode != Instruction::Xor) + return nullptr; + + Type *DestTy = BitCast.getType(); + if (!DestTy->getScalarType()->isIntegerTy()) + return nullptr; + + // FIXME: This transform is restricted to vector types 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() || !BO->getType()->isVectorTy()) + return nullptr; + + Value *X; + if (match(BO->getOperand(0), m_OneUse(m_BitCast(m_Value(X)))) && + X->getType() == DestTy && !isa<Constant>(X)) { + // bitcast(logic(bitcast(X), Y)) --> logic'(X, bitcast(Y)) + Value *CastedOp1 = Builder.CreateBitCast(BO->getOperand(1), DestTy); + return BinaryOperator::Create(Opcode, X, CastedOp1); + } + + if (match(BO->getOperand(1), m_OneUse(m_BitCast(m_Value(X)))) && + X->getType() == DestTy && !isa<Constant>(X)) { + // bitcast(logic(Y, bitcast(X))) --> logic'(bitcast(Y), X) + Value *CastedOp0 = Builder.CreateBitCast(BO->getOperand(0), DestTy); + return BinaryOperator::Create(Opcode, CastedOp0, X); + } + + return nullptr; +} + /// Check if all users of CI are StoreInsts. static bool hasStoreUsersOnly(CastInst &CI) { for (User *U : CI.users()) { @@ -2030,6 +2070,9 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) { if (Instruction *I = canonicalizeBitCastExtElt(CI, *this, DL)) return I; + if (Instruction *I = foldBitCastBitwiseLogic(CI, *Builder)) + return I; + if (SrcTy->isPointerTy()) return commonPointerCastTransforms(CI); return commonCastTransforms(CI); |