diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 1e291fbe3f7394..2911886636f900 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2010,7 +2010,16 @@ Instruction *InstCombinerImpl::matchBSwapOrBitReverse(BinaryOperator &Or, bool OrWithAnds = match(Op0, m_And(m_Value(), m_Value())) || match(Op1, m_And(m_Value(), m_Value())); - if (!OrWithOrs && !OrWithShifts && !OrWithAnds) + // fshl(A,B,C) | D and A | fshl(B,C,D) -> bswap if possible. + // fshr(A,B,C) | D and A | fshr(B,C,D) -> bswap if possible. + bool OrWithFunnels = match(Op0, m_FShl(m_Value(), m_Value(), m_Value())) || + match(Op0, m_FShr(m_Value(), m_Value(), m_Value())) || + match(Op0, m_FShl(m_Value(), m_Value(), m_Value())) || + match(Op0, m_FShr(m_Value(), m_Value(), m_Value())); + + // TODO: Do we need all these filtering checks or should we just rely on + // recognizeBSwapOrBitReverseIdiom + collectBitParts to reject them quickly? + if (!OrWithOrs && !OrWithShifts && !OrWithAnds && !OrWithFunnels) return nullptr; SmallVector Insts; diff --git a/llvm/test/Transforms/InstCombine/bswap.ll b/llvm/test/Transforms/InstCombine/bswap.ll index f0a322d589130a..c0893dd23b80d0 100644 --- a/llvm/test/Transforms/InstCombine/bswap.ll +++ b/llvm/test/Transforms/InstCombine/bswap.ll @@ -687,11 +687,7 @@ define i32 @funnel_binary(i32 %abcd) { define i32 @funnel_and(i32 %abcd) { ; CHECK-LABEL: @funnel_and( -; CHECK-NEXT: [[ZZCZ:%.*]] = and i32 [[ABCD:%.*]], 65280 -; CHECK-NEXT: [[ZCZA:%.*]] = call i32 @llvm.fshl.i32(i32 [[ZZCZ]], i32 [[ABCD]], i32 8) -; CHECK-NEXT: [[ZBZZ:%.*]] = and i32 [[ABCD]], 16711680 -; CHECK-NEXT: [[DZBZ:%.*]] = call i32 @llvm.fshl.i32(i32 [[ABCD]], i32 [[ZBZZ]], i32 24) -; CHECK-NEXT: [[DCBA:%.*]] = or i32 [[ZCZA]], [[DZBZ]] +; CHECK-NEXT: [[DCBA:%.*]] = call i32 @llvm.bswap.i32(i32 [[ABCD:%.*]]) ; CHECK-NEXT: ret i32 [[DCBA]] ; %zzcz = and i32 %abcd, 65280