From 82ef8e19ef1dc06e7dde6a07ed035bf42213af07 Mon Sep 17 00:00:00 2001 From: Omer Paparo Bivas Date: Tue, 1 May 2018 12:25:46 +0000 Subject: [PATCH] [InstCombine] Adjusting bswap pattern matching to hold for And/Shift mixed case Differential Revision: https://reviews.llvm.org/D45731 Change-Id: I85d4226504e954933c41598327c91b2d08192a9d llvm-svn: 331257 --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 13 ++++++++++++- llvm/test/Transforms/InstCombine/bswap.ll | 7 ++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index e389af2..9a5183c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1675,7 +1675,18 @@ Instruction *InstCombiner::MatchBSwap(BinaryOperator &I) { bool OrOfAnds = match(Op0, m_And(m_Value(), m_Value())) && match(Op1, m_And(m_Value(), m_Value())); - if (!OrOfOrs && !OrOfShifts && !OrOfAnds) + // (A << B) | (C & D) -> bswap if possible. + // The bigger pattern here is ((A & C1) << C2) | ((B >> C2) & C1), which is a + // part of the bswap idiom for specific values of C1, C2 (e.g. C1 = 16711935, + // C2 = 8 for i32). + // This pattern can occur when the operands of the 'or' are not canonicalized + // for some reason (not having only one use, for example). + bool OrOfAndAndSh = (match(Op0, m_LogicalShift(m_Value(), m_Value())) && + match(Op1, m_And(m_Value(), m_Value()))) || + (match(Op0, m_And(m_Value(), m_Value())) && + match(Op1, m_LogicalShift(m_Value(), m_Value()))); + + if (!OrOfOrs && !OrOfShifts && !OrOfAnds && !OrOfAndAndSh) return nullptr; SmallVector Insts; diff --git a/llvm/test/Transforms/InstCombine/bswap.ll b/llvm/test/Transforms/InstCombine/bswap.ll index c63e16c..69be38d 100644 --- a/llvm/test/Transforms/InstCombine/bswap.ll +++ b/llvm/test/Transforms/InstCombine/bswap.ll @@ -116,7 +116,7 @@ define i32 @bswap32_and_first(i32 %x) { ret i32 %bswap } -; FIXME: Extra use should not prevent matching to bswap. +; Extra use should not prevent matching to bswap. ; swaphalf = (x << 16 | x >> 16) ; ((swaphalf & 0x00ff00ff) << 8) | ((swaphalf >> 8) & 0x00ff00ff) @@ -126,10 +126,7 @@ define i32 @bswap32_and_first_extra_use(i32 %x) { ; CHECK-NEXT: [[SHR:%.*]] = lshr i32 %x, 16 ; CHECK-NEXT: [[SWAPHALF:%.*]] = or i32 [[SHL]], [[SHR]] ; CHECK-NEXT: [[T:%.*]] = and i32 [[SWAPHALF]], 16711935 -; CHECK-NEXT: [[TSHL:%.*]] = shl nuw i32 [[T]], 8 -; CHECK-NEXT: [[B:%.*]] = lshr i32 [[SWAPHALF]], 8 -; CHECK-NEXT: [[BAND:%.*]] = and i32 [[B]], 16711935 -; CHECK-NEXT: [[BSWAP:%.*]] = or i32 [[TSHL]], [[BAND]] +; CHECK-NEXT: [[BSWAP:%.*]] = call i32 @llvm.bswap.i32(i32 %x) ; CHECK-NEXT: call void @extra_use(i32 [[T]]) ; CHECK-NEXT: ret i32 [[BSWAP]] ; -- 2.7.4