[llvm] [VectorCombine] Fold bitcast(bitreverse.v8i8(bitcast(IntTy))) into bswap+bitreverse (PR #209037)
Deepak Shirke via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 18 06:35:47 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;
-
----------------
deepakshirkem wrote:
@dtcxzyw Yes. After running clang-format, when I commit the file, those lines get removed.
https://github.com/llvm/llvm-project/pull/209037
More information about the llvm-commits
mailing list