diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index 40b48699f7585..64fbd5543a9e2 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1884,6 +1884,10 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) { return crossLogicOpFold; } + // Try to fold into bitreverse if bswap is the root of the expression tree. + if (Instruction *BitOp = matchBSwapOrBitReverse(*II, /*MatchBSwaps*/ false, + /*MatchBitReversals*/ true)) + return BitOp; break; } case Intrinsic::masked_load: diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index c76cc9db16d7e..b9cad764aaef8 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -3905,7 +3905,8 @@ bool llvm::recognizeBSwapOrBitReverseIdiom( SmallVectorImpl &InsertedInsts) { if (!match(I, m_Or(m_Value(), m_Value())) && !match(I, m_FShl(m_Value(), m_Value(), m_Value())) && - !match(I, m_FShr(m_Value(), m_Value(), m_Value()))) + !match(I, m_FShr(m_Value(), m_Value(), m_Value())) && + !match(I, m_BSwap(m_Value()))) return false; if (!MatchBSwaps && !MatchBitReversals) return false; diff --git a/llvm/test/Transforms/InstCombine/bitreverse.ll b/llvm/test/Transforms/InstCombine/bitreverse.ll index 7d122297c11b2..cbe9695c48690 100644 --- a/llvm/test/Transforms/InstCombine/bitreverse.ll +++ b/llvm/test/Transforms/InstCombine/bitreverse.ll @@ -106,6 +106,30 @@ entry: ret i32 %or.4 } +define i32 @rev32_bswap(i32 %v) { +; CHECK-LABEL: @rev32_bswap( +; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.bitreverse.i32(i32 [[V:%.*]]) +; CHECK-NEXT: ret i32 [[RET]] +; + %and.i = lshr i32 %v, 1 + %shr.i = and i32 %and.i, 1431655765 + %and1.i = shl i32 %v, 1 + %shl.i = and i32 %and1.i, -1431655766 + %or.i = or disjoint i32 %shr.i, %shl.i + %and2.i = lshr i32 %or.i, 2 + %shr3.i = and i32 %and2.i, 858993459 + %and4.i = shl i32 %or.i, 2 + %shl5.i = and i32 %and4.i, -858993460 + %or6.i = or disjoint i32 %shr3.i, %shl5.i + %and7.i = lshr i32 %or6.i, 4 + %shr8.i = and i32 %and7.i, 252645135 + %and9.i = shl i32 %or6.i, 4 + %shl10.i = and i32 %and9.i, -252645136 + %or11.i = or disjoint i32 %shr8.i, %shl10.i + %ret = call i32 @llvm.bswap.i32(i32 %or11.i) + ret i32 %ret +} + define i64 @rev64(i64 %v) { ; CHECK-LABEL: @rev64( ; CHECK-NEXT: entry: @@ -508,3 +532,5 @@ define i64 @rev_all_operand64_multiuse_both(i64 %a, i64 %b) #0 { call void @use_i64(i64 %2) ret i64 %4 } + +declare i32 @llvm.bswap.i32(i32 %or11.i)