[llvm] [VectorCombine] Fold bitcast(bitreverse.v8i8(bitcast(IntTy))) into bswap+bitreverse (PR #209037)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 18 05:47:24 PDT 2026


================
@@ -6114,49 +6114,88 @@ bool VectorCombine::foldBitcastOfVPLoad(Instruction &I) {
 
 /// Fold the following cases into a single byte-level bit-reverse operation
 /// and accepts bswap and bitreverse intrinsics:
-///   bswap(bitreverse(x)) --> bitcast(bitreverse(bitcast(x)))
-///   bitreverse(bswap(x)) --> bitcast(bitreverse(bitcast(x)))
+///   bswap(bitreverse(x)) <--> bitcast(bitreverse(bitcast(x)))
+///   bitreverse(bswap(x)) <--> bitcast(bitreverse(bitcast(x)))
+/// The direction of the fold is cost-model driven.
 bool VectorCombine::foldBitOrderReverseAndSwap(Instruction &I) {
   Value *X;
+
+  if (match(&I, m_BitCast(m_BitReverse(m_BitCast(m_Value(X)))))) {
+    Type *Ty = X->getType();
+    Type *VecTy = cast<BitCastInst>(&I)->getOperand(0)->getType();
+    // Only handle integer scalar types with even byte count (bswap requirement)
+    // and fixed-length byte vectors.
+    if (Ty->isIntegerTy() && Ty == I.getType() && isa<FixedVectorType>(VecTy) &&
+        cast<FixedVectorType>(VecTy)->getElementType()->isIntegerTy(8) &&
+        Ty->getIntegerBitWidth() % 16 == 0) {
+      auto *OuterBitCast = cast<BitCastInst>(&I);
+      auto *InnerCall = dyn_cast<Instruction>(OuterBitCast->getOperand(0));
+      if (!InnerCall)
+        return false;
+      auto *InnerBitCast = dyn_cast<BitCastInst>(InnerCall->getOperand(0));
+      if (!InnerBitCast)
+        return false;
+      InstructionCost OldCost = TTI.getInstructionCost(InnerBitCast, CostKind) +
+                                TTI.getInstructionCost(InnerCall, CostKind) +
+                                TTI.getInstructionCost(OuterBitCast, CostKind);
+      // NewCost = bswap + bitreverse on integer type.
+      // If the bitreverse vector has other uses we cannot remove it,
+      // so add its cost to NewCost.
+      IntrinsicCostAttributes ICABSwap(Intrinsic::bswap, Ty, {Ty});
+      IntrinsicCostAttributes ICABRev(Intrinsic::bitreverse, Ty, {Ty});
+      InstructionCost NewCost = TTI.getIntrinsicInstrCost(ICABSwap, CostKind) +
+                                TTI.getIntrinsicInstrCost(ICABRev, CostKind);
+      if (!InnerCall->hasOneUse())
+        NewCost += TTI.getInstructionCost(InnerCall, CostKind);
+      LLVM_DEBUG(dbgs() << "Found bitreverse vector roundtrip: " << I
+                        << "\n  OldCost: " << OldCost
+                        << " vs NewCost: " << NewCost << "\n");
+      if (NewCost.isValid() && NewCost < OldCost) {
+        Builder.SetInsertPoint(&I);
+        Value *BSwap = Builder.CreateUnaryIntrinsic(Intrinsic::bswap, X);
+        Worklist.pushValue(BSwap);
+        Value *BRev =
+            Builder.CreateUnaryIntrinsic(Intrinsic::bitreverse, BSwap);
+        replaceValue(I, *BRev);
+        return true;
+      }
+    }
+  }
+
+  // Forward direction: bswap(bitreverse(x)) or bitreverse(bswap(x))
+  // --> bitcast(bitreverse(<N x i8>)(bitcast(x)))
   if (!match(&I, m_BitReverse(m_BSwap(m_Value(X)))) &&
       !match(&I, m_BSwap(m_BitReverse(m_Value(X)))))
     return false;
-
----------------
dtcxzyw wrote:

I don't understand at all. Did clang-format still remove these lines after you recovered these changes?


https://github.com/llvm/llvm-project/pull/209037


More information about the llvm-commits mailing list