Skip to content

Commit

Permalink
[InstCombine] Handle a bitreverse idiom which ends with a bswap (#77677)
Browse files Browse the repository at this point in the history
This patch handles the following `bitreverse` idiom, which is found in
https://github.com/abseil/abseil-cpp/blob/8bd6445acc4bd0d123da2a44448b7218dfc70939/absl/crc/internal/crc.cc#L75-L80:

```
uint32_t ReverseBits(uint32_t bits) {
  bits = (bits & 0xaaaaaaaau) >> 1 | (bits & 0x55555555u) << 1;
  bits = (bits & 0xccccccccu) >> 2 | (bits & 0x33333333u) << 2;
  bits = (bits & 0xf0f0f0f0u) >> 4 | (bits & 0x0f0f0f0fu) << 4;
  return absl::gbswap_32(bits);
}
```

Alive2: https://alive2.llvm.org/ce/z/ZYXNmj
  • Loading branch information
dtcxzyw committed Jan 11, 2024
1 parent 164f85d commit 3d795bd
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 1 deletion.
4 changes: 4 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Transforms/Utils/Local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3905,7 +3905,8 @@ bool llvm::recognizeBSwapOrBitReverseIdiom(
SmallVectorImpl<Instruction *> &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;
Expand Down
26 changes: 26 additions & 0 deletions llvm/test/Transforms/InstCombine/bitreverse.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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)

0 comments on commit 3d795bd

Please sign in to comment.