summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp42
1 files changed, 28 insertions, 14 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 22832aadf4a..e70171ce989 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1620,6 +1620,30 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) {
/// Given an OR instruction, check to see if this is a bswap idiom. If so,
/// insert the new intrinsic and return it.
Instruction *InstCombiner::MatchBSwap(BinaryOperator &I) {
+ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
+
+ // Look through zero extends.
+ if (Instruction *Ext = dyn_cast<ZExtInst>(Op0))
+ Op0 = Ext->getOperand(0);
+
+ if (Instruction *Ext = dyn_cast<ZExtInst>(Op1))
+ Op1 = Ext->getOperand(0);
+
+ // (A | B) | C and A | (B | C) -> bswap if possible.
+ bool OrOfOrs = match(Op0, m_Or(m_Value(), m_Value())) ||
+ match(Op1, m_Or(m_Value(), m_Value()));
+
+ // (A >> B) | (C << D) and (A << B) | (B >> C) -> bswap if possible.
+ bool OrOfShifts = match(Op0, m_LogicalShift(m_Value(), m_Value())) &&
+ match(Op1, m_LogicalShift(m_Value(), m_Value()));
+
+ // (A & B) | (C & D) -> bswap if possible.
+ bool OrOfAnds = match(Op0, m_And(m_Value(), m_Value())) &&
+ match(Op1, m_And(m_Value(), m_Value()));
+
+ if (!OrOfOrs && !OrOfShifts && !OrOfAnds)
+ return nullptr;
+
SmallVector<Instruction*, 4> Insts;
if (!recognizeBSwapOrBitReverseIdiom(&I, true, false, Insts))
return nullptr;
@@ -2162,23 +2186,13 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) {
return NV;
}
+ // Given an OR instruction, check to see if this is a bswap.
+ if (Instruction *BSwap = MatchBSwap(I))
+ return BSwap;
+
Value *A = nullptr, *B = nullptr;
ConstantInt *C1 = nullptr, *C2 = nullptr;
- // (A | B) | C and A | (B | C) -> bswap if possible.
- bool OrOfOrs = match(Op0, m_Or(m_Value(), m_Value())) ||
- match(Op1, m_Or(m_Value(), m_Value()));
- // (A >> B) | (C << D) and (A << B) | (B >> C) -> bswap if possible.
- bool OrOfShifts = match(Op0, m_LogicalShift(m_Value(), m_Value())) &&
- match(Op1, m_LogicalShift(m_Value(), m_Value()));
- // (A & B) | (C & D) -> bswap if possible.
- bool OrOfAnds = match(Op0, m_And(m_Value(), m_Value())) &&
- match(Op1, m_And(m_Value(), m_Value()));
-
- if (OrOfOrs || OrOfShifts || OrOfAnds)
- if (Instruction *BSwap = MatchBSwap(I))
- return BSwap;
-
// (X^C)|Y -> (X|Y)^C iff Y&C == 0
if (Op0->hasOneUse() &&
match(Op0, m_Xor(m_Value(A), m_ConstantInt(C1))) &&
OpenPOWER on IntegriCloud