diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -6490,19 +6490,23 @@ // Make sure everything beyond the low halfword gets set to zero since the SRL // 16 will clear the top bits. unsigned OpSizeInBits = VT.getSizeInBits(); - if (DemandHighBits && OpSizeInBits > 16) { + if (OpSizeInBits > 16) { // If the left-shift isn't masked out then the only way this is a bswap is // if all bits beyond the low 8 are 0. In that case the entire pattern // reduces to a left shift anyway: leave it for other parts of the combiner. - if (!LookPassAnd0) + if (DemandHighBits && !LookPassAnd0) return SDValue(); // However, if the right shift isn't masked out then it might be because - // it's not needed. See if we can spot that too. - if (!LookPassAnd1 && - !DAG.MaskedValueIsZero( - N10, APInt::getHighBitsSet(OpSizeInBits, OpSizeInBits - 16))) - return SDValue(); + // it's not needed. See if we can spot that too. If the high bits aren't + // demanded, we only need bits 23:16 to be zero. Otherwise, we need all + // upper bits to be zero. + if (!LookPassAnd1) { + unsigned HighBit = DemandHighBits ? OpSizeInBits : 24; + if (!DAG.MaskedValueIsZero(N10, + APInt::getBitsSet(OpSizeInBits, 16, HighBit))) + return SDValue(); + } } SDValue Res = DAG.getNode(ISD::BSWAP, SDLoc(N), VT, N00); diff --git a/llvm/test/CodeGen/AArch64/arm64-rev.ll b/llvm/test/CodeGen/AArch64/arm64-rev.ll --- a/llvm/test/CodeGen/AArch64/arm64-rev.ll +++ b/llvm/test/CodeGen/AArch64/arm64-rev.ll @@ -953,8 +953,9 @@ define i32 @pr55484(i32 %0) { ; CHECK-LABEL: pr55484: ; CHECK: // %bb.0: -; CHECK-NEXT: rev w8, w0 -; CHECK-NEXT: asr w0, w8, #16 +; CHECK-NEXT: lsr w8, w0, #8 +; CHECK-NEXT: orr w8, w8, w0, lsl #8 +; CHECK-NEXT: sxth w0, w8 ; CHECK-NEXT: ret ; ; GISEL-LABEL: pr55484: diff --git a/llvm/test/CodeGen/ARM/rev.ll b/llvm/test/CodeGen/ARM/rev.ll --- a/llvm/test/CodeGen/ARM/rev.ll +++ b/llvm/test/CodeGen/ARM/rev.ll @@ -183,10 +183,27 @@ } define i32 @pr55484(i32 %0) { -; CHECK-LABEL: pr55484: -; CHECK: @ %bb.0: -; CHECK-NEXT: revsh r0, r0 -; CHECK-NEXT: bx lr +; CHECK-ARM-LABEL: pr55484: +; CHECK-ARM: @ %bb.0: +; CHECK-ARM-NEXT: lsr r1, r0, #8 +; CHECK-ARM-NEXT: orr r0, r1, r0, lsl #8 +; CHECK-ARM-NEXT: sxth r0, r0 +; CHECK-ARM-NEXT: bx lr +; +; CHECK-V6-LABEL: pr55484: +; CHECK-V6: @ %bb.0: +; CHECK-V6-NEXT: lsls r1, r0, #8 +; CHECK-V6-NEXT: lsrs r0, r0, #8 +; CHECK-V6-NEXT: orrs r0, r1 +; CHECK-V6-NEXT: sxth r0, r0 +; CHECK-V6-NEXT: bx lr +; +; CHECK-V7-LABEL: pr55484: +; CHECK-V7: @ %bb.0: +; CHECK-V7-NEXT: lsrs r1, r0, #8 +; CHECK-V7-NEXT: orr.w r0, r1, r0, lsl #8 +; CHECK-V7-NEXT: sxth r0, r0 +; CHECK-V7-NEXT: bx lr %2 = lshr i32 %0, 8 %3 = shl i32 %0, 8 %4 = or i32 %2, %3 diff --git a/llvm/test/CodeGen/RISCV/bswap-bitreverse.ll b/llvm/test/CodeGen/RISCV/bswap-bitreverse.ll --- a/llvm/test/CodeGen/RISCV/bswap-bitreverse.ll +++ b/llvm/test/CodeGen/RISCV/bswap-bitreverse.ll @@ -1657,14 +1657,18 @@ ; ; RV32ZBB-LABEL: pr55484: ; RV32ZBB: # %bb.0: -; RV32ZBB-NEXT: rev8 a0, a0 -; RV32ZBB-NEXT: srai a0, a0, 16 +; RV32ZBB-NEXT: srli a1, a0, 8 +; RV32ZBB-NEXT: slli a0, a0, 8 +; RV32ZBB-NEXT: or a0, a1, a0 +; RV32ZBB-NEXT: sext.h a0, a0 ; RV32ZBB-NEXT: ret ; ; RV64ZBB-LABEL: pr55484: ; RV64ZBB: # %bb.0: -; RV64ZBB-NEXT: rev8 a0, a0 -; RV64ZBB-NEXT: srai a0, a0, 48 +; RV64ZBB-NEXT: srli a1, a0, 8 +; RV64ZBB-NEXT: slli a0, a0, 8 +; RV64ZBB-NEXT: or a0, a1, a0 +; RV64ZBB-NEXT: sext.h a0, a0 ; RV64ZBB-NEXT: ret ; ; RV32ZBKB-LABEL: pr55484: diff --git a/llvm/test/CodeGen/Thumb/rev.ll b/llvm/test/CodeGen/Thumb/rev.ll --- a/llvm/test/CodeGen/Thumb/rev.ll +++ b/llvm/test/CodeGen/Thumb/rev.ll @@ -67,7 +67,10 @@ define i32 @pr55484(i32 %0) { ; CHECK-LABEL: pr55484: ; CHECK: @ %bb.0: -; CHECK-NEXT: revsh r0, r0 +; CHECK-NEXT: lsls r1, r0, #8 +; CHECK-NEXT: lsrs r0, r0, #8 +; CHECK-NEXT: orrs r0, r1 +; CHECK-NEXT: sxth r0, r0 ; CHECK-NEXT: bx lr %2 = lshr i32 %0, 8 %3 = shl i32 %0, 8 diff --git a/llvm/test/CodeGen/X86/bswap.ll b/llvm/test/CodeGen/X86/bswap.ll --- a/llvm/test/CodeGen/X86/bswap.ll +++ b/llvm/test/CodeGen/X86/bswap.ll @@ -395,15 +395,20 @@ ; CHECK-LABEL: pr55484: ; CHECK: # %bb.0: ; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax -; CHECK-NEXT: bswapl %eax -; CHECK-NEXT: sarl $16, %eax +; CHECK-NEXT: movl %eax, %ecx +; CHECK-NEXT: shrl $8, %ecx +; CHECK-NEXT: shll $8, %eax +; CHECK-NEXT: orl %ecx, %eax +; CHECK-NEXT: cwtl ; CHECK-NEXT: retl ; ; CHECK64-LABEL: pr55484: ; CHECK64: # %bb.0: ; CHECK64-NEXT: movl %edi, %eax -; CHECK64-NEXT: bswapl %eax -; CHECK64-NEXT: sarl $16, %eax +; CHECK64-NEXT: shrl $8, %eax +; CHECK64-NEXT: shll $8, %edi +; CHECK64-NEXT: orl %eax, %edi +; CHECK64-NEXT: movswl %di, %eax ; CHECK64-NEXT: retq %2 = lshr i32 %0, 8 %3 = shl i32 %0, 8