summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2016-11-22 22:05:48 +0000
committerSanjay Patel <spatel@rotateright.com>2016-11-22 22:05:48 +0000
commite359eaaf708e227eeeaf3f4a9640e5cde0f3c05a (patch)
tree47bd8a4315d352018517d37c89c2e9dd60e6d22e /llvm/lib
parenteda365cf807c22ad939dd6d3017cf6a3679675b6 (diff)
downloadbcm5719-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.cpp43
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);
OpenPOWER on IntegriCloud