[llvm] 3d795bd - [InstCombine] Handle a bitreverse idiom which ends with a bswap (#77677)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 10 23:15:16 PST 2024


Author: Yingwei Zheng
Date: 2024-01-11T15:15:12+08:00
New Revision: 3d795bdd4d9067e96b2ff9e6278a5b8847eebe2b

URL: https://github.com/llvm/llvm-project/commit/3d795bdd4d9067e96b2ff9e6278a5b8847eebe2b
DIFF: https://github.com/llvm/llvm-project/commit/3d795bdd4d9067e96b2ff9e6278a5b8847eebe2b.diff

LOG: [InstCombine] Handle a bitreverse idiom which ends with a bswap (#77677)

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

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
    llvm/lib/Transforms/Utils/Local.cpp
    llvm/test/Transforms/InstCombine/bitreverse.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 40b48699f75851..64fbd5543a9e20 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 c76cc9db16d7e7..b9cad764aaef8b 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -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;

diff  --git a/llvm/test/Transforms/InstCombine/bitreverse.ll b/llvm/test/Transforms/InstCombine/bitreverse.ll
index 7d122297c11b2d..cbe9695c48690b 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)


        


More information about the llvm-commits mailing list