[llvm] f30f8b4 - [RISCV] Lower i8/i16 bswap/bitreverse to grevi/greviw with Zbp.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 7 10:32:10 PDT 2021


Author: Craig Topper
Date: 2021-06-07T10:31:51-07:00
New Revision: f30f8b4f12b762a054800aaa7b60461fd177fa96

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

LOG: [RISCV] Lower i8/i16 bswap/bitreverse to grevi/greviw with Zbp.

Include known bits support so we know we don't need to zext the
output if the input was already zero extended.

Reviewed By: luismarques

Differential Revision: https://reviews.llvm.org/D103757

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVISelLowering.cpp
    llvm/test/CodeGen/RISCV/rv32zbp.ll
    llvm/test/CodeGen/RISCV/rv64zbp.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 0b2c79b2e915d..ef748ce6adc6e 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -250,12 +250,16 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
   if (Subtarget.hasStdExtZbp()) {
     // Custom lower bswap/bitreverse so we can convert them to GREVI to enable
     // more combining.
-    setOperationAction(ISD::BITREVERSE, XLenVT, Custom);
-    setOperationAction(ISD::BSWAP, XLenVT, Custom);
+    setOperationAction(ISD::BITREVERSE, XLenVT,   Custom);
+    setOperationAction(ISD::BSWAP,      XLenVT,   Custom);
+    setOperationAction(ISD::BITREVERSE, MVT::i8,  Custom);
+    // BSWAP i8 doesn't exist.
+    setOperationAction(ISD::BITREVERSE, MVT::i16, Custom);
+    setOperationAction(ISD::BSWAP,      MVT::i16, Custom);
 
     if (Subtarget.is64Bit()) {
       setOperationAction(ISD::BITREVERSE, MVT::i32, Custom);
-      setOperationAction(ISD::BSWAP, MVT::i32, Custom);
+      setOperationAction(ISD::BSWAP,      MVT::i32, Custom);
     }
   } else {
     // With Zbb we have an XLen rev8 instruction, but not GREVI. So we'll
@@ -4861,16 +4865,22 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
   }
   case ISD::BSWAP:
   case ISD::BITREVERSE: {
-    assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
+    MVT VT = N->getSimpleValueType(0);
+    MVT XLenVT = Subtarget.getXLenVT();
+    assert((VT == MVT::i8 || VT == MVT::i16 ||
+            (VT == MVT::i32 && Subtarget.is64Bit())) &&
            Subtarget.hasStdExtZbp() && "Unexpected custom legalisation");
-    SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64,
-                                 N->getOperand(0));
-    unsigned Imm = N->getOpcode() == ISD::BITREVERSE ? 31 : 24;
-    SDValue GREVIW = DAG.getNode(RISCVISD::GREVW, DL, MVT::i64, NewOp0,
-                                 DAG.getConstant(Imm, DL, MVT::i64));
+    SDValue NewOp0 = DAG.getNode(ISD::ANY_EXTEND, DL, XLenVT, N->getOperand(0));
+    unsigned Imm = VT.getSizeInBits() - 1;
+    // If this is BSWAP rather than BITREVERSE, clear the lower 3 bits.
+    if (N->getOpcode() == ISD::BSWAP)
+      Imm &= ~0x7U;
+    unsigned Opc = Subtarget.is64Bit() ? RISCVISD::GREVW : RISCVISD::GREV;
+    SDValue GREVI =
+        DAG.getNode(Opc, DL, XLenVT, NewOp0, DAG.getConstant(Imm, DL, XLenVT));
     // ReplaceNodeResults requires we maintain the same type for the return
     // value.
-    Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, GREVIW));
+    Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, VT, GREVI));
     break;
   }
   case ISD::FSHL:
@@ -6066,6 +6076,24 @@ bool RISCVTargetLowering::targetShrinkDemandedConstant(
   return UseMask(NewMask);
 }
 
+static void computeGREV(APInt &Src, unsigned ShAmt) {
+  ShAmt &= Src.getBitWidth() - 1;
+  uint64_t x = Src.getZExtValue();
+  if (ShAmt & 1)
+    x = ((x & 0x5555555555555555LL) << 1) | ((x & 0xAAAAAAAAAAAAAAAALL) >> 1);
+  if (ShAmt & 2)
+    x = ((x & 0x3333333333333333LL) << 2) | ((x & 0xCCCCCCCCCCCCCCCCLL) >> 2);
+  if (ShAmt & 4)
+    x = ((x & 0x0F0F0F0F0F0F0F0FLL) << 4) | ((x & 0xF0F0F0F0F0F0F0F0LL) >> 4);
+  if (ShAmt & 8)
+    x = ((x & 0x00FF00FF00FF00FFLL) << 8) | ((x & 0xFF00FF00FF00FF00LL) >> 8);
+  if (ShAmt & 16)
+    x = ((x & 0x0000FFFF0000FFFFLL) << 16) | ((x & 0xFFFF0000FFFF0000LL) >> 16);
+  if (ShAmt & 32)
+    x = ((x & 0x00000000FFFFFFFFLL) << 32) | ((x & 0xFFFFFFFF00000000LL) >> 32);
+  Src = x;
+}
+
 void RISCVTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
                                                         KnownBits &Known,
                                                         const APInt &DemandedElts,
@@ -6128,6 +6156,20 @@ void RISCVTargetLowering::computeKnownBitsForTargetNode(const SDValue Op,
     Known.Zero.setBitsFrom(LowBits);
     break;
   }
+  case RISCVISD::GREV:
+  case RISCVISD::GREVW: {
+    if (auto *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
+      Known = DAG.computeKnownBits(Op.getOperand(0), Depth + 1);
+      if (Opc == RISCVISD::GREVW)
+        Known = Known.trunc(32);
+      unsigned ShAmt = C->getZExtValue();
+      computeGREV(Known.Zero, ShAmt);
+      computeGREV(Known.One, ShAmt);
+      if (Opc == RISCVISD::GREVW)
+        Known = Known.sext(BitWidth);
+    }
+    break;
+  }
   case RISCVISD::READ_VLENB:
     // We assume VLENB is at least 16 bytes.
     Known.Zero.setLowBits(4);

diff  --git a/llvm/test/CodeGen/RISCV/rv32zbp.ll b/llvm/test/CodeGen/RISCV/rv32zbp.ll
index 2b3e112bcf1ed..6b32f993251bd 100644
--- a/llvm/test/CodeGen/RISCV/rv32zbp.ll
+++ b/llvm/test/CodeGen/RISCV/rv32zbp.ll
@@ -2353,14 +2353,12 @@ define zeroext i16 @bswap_i16(i16 zeroext %a) nounwind {
 ;
 ; RV32IB-LABEL: bswap_i16:
 ; RV32IB:       # %bb.0:
-; RV32IB-NEXT:    rev8 a0, a0
-; RV32IB-NEXT:    srli a0, a0, 16
+; RV32IB-NEXT:    rev8.h a0, a0
 ; RV32IB-NEXT:    ret
 ;
 ; RV32IBP-LABEL: bswap_i16:
 ; RV32IBP:       # %bb.0:
-; RV32IBP-NEXT:    rev8 a0, a0
-; RV32IBP-NEXT:    srli a0, a0, 16
+; RV32IBP-NEXT:    rev8.h a0, a0
 ; RV32IBP-NEXT:    ret
   %1 = tail call i16 @llvm.bswap.i16(i16 %a)
   ret i16 %1
@@ -2467,14 +2465,12 @@ define zeroext i8 @bitreverse_i8(i8 zeroext %a) nounwind {
 ;
 ; RV32IB-LABEL: bitreverse_i8:
 ; RV32IB:       # %bb.0:
-; RV32IB-NEXT:    rev a0, a0
-; RV32IB-NEXT:    srli a0, a0, 24
+; RV32IB-NEXT:    rev.b a0, a0
 ; RV32IB-NEXT:    ret
 ;
 ; RV32IBP-LABEL: bitreverse_i8:
 ; RV32IBP:       # %bb.0:
-; RV32IBP-NEXT:    rev a0, a0
-; RV32IBP-NEXT:    srli a0, a0, 24
+; RV32IBP-NEXT:    rev.b a0, a0
 ; RV32IBP-NEXT:    ret
   %1 = tail call i8 @llvm.bitreverse.i8(i8 %a)
   ret i8 %1
@@ -2519,14 +2515,12 @@ define zeroext i16 @bitreverse_i16(i16 zeroext %a) nounwind {
 ;
 ; RV32IB-LABEL: bitreverse_i16:
 ; RV32IB:       # %bb.0:
-; RV32IB-NEXT:    rev a0, a0
-; RV32IB-NEXT:    srli a0, a0, 16
+; RV32IB-NEXT:    rev.h a0, a0
 ; RV32IB-NEXT:    ret
 ;
 ; RV32IBP-LABEL: bitreverse_i16:
 ; RV32IBP:       # %bb.0:
-; RV32IBP-NEXT:    rev a0, a0
-; RV32IBP-NEXT:    srli a0, a0, 16
+; RV32IBP-NEXT:    rev.h a0, a0
 ; RV32IBP-NEXT:    ret
   %1 = tail call i16 @llvm.bitreverse.i16(i16 %a)
   ret i16 %1

diff  --git a/llvm/test/CodeGen/RISCV/rv64zbp.ll b/llvm/test/CodeGen/RISCV/rv64zbp.ll
index e911c6356f7c1..00d3278a3283d 100644
--- a/llvm/test/CodeGen/RISCV/rv64zbp.ll
+++ b/llvm/test/CodeGen/RISCV/rv64zbp.ll
@@ -2679,14 +2679,12 @@ define zeroext i16 @bswap_i16(i16 zeroext %a) nounwind {
 ;
 ; RV64IB-LABEL: bswap_i16:
 ; RV64IB:       # %bb.0:
-; RV64IB-NEXT:    rev8 a0, a0
-; RV64IB-NEXT:    srli a0, a0, 48
+; RV64IB-NEXT:    greviw a0, a0, 8
 ; RV64IB-NEXT:    ret
 ;
 ; RV64IBP-LABEL: bswap_i16:
 ; RV64IBP:       # %bb.0:
-; RV64IBP-NEXT:    rev8 a0, a0
-; RV64IBP-NEXT:    srli a0, a0, 48
+; RV64IBP-NEXT:    greviw a0, a0, 8
 ; RV64IBP-NEXT:    ret
   %1 = tail call i16 @llvm.bswap.i16(i16 %a)
   ret i16 %1
@@ -2832,14 +2830,12 @@ define zeroext i8 @bitreverse_i8(i8 zeroext %a) nounwind {
 ;
 ; RV64IB-LABEL: bitreverse_i8:
 ; RV64IB:       # %bb.0:
-; RV64IB-NEXT:    rev a0, a0
-; RV64IB-NEXT:    srli a0, a0, 56
+; RV64IB-NEXT:    greviw a0, a0, 7
 ; RV64IB-NEXT:    ret
 ;
 ; RV64IBP-LABEL: bitreverse_i8:
 ; RV64IBP:       # %bb.0:
-; RV64IBP-NEXT:    rev a0, a0
-; RV64IBP-NEXT:    srli a0, a0, 56
+; RV64IBP-NEXT:    greviw a0, a0, 7
 ; RV64IBP-NEXT:    ret
   %1 = tail call i8 @llvm.bitreverse.i8(i8 %a)
   ret i8 %1
@@ -2884,14 +2880,12 @@ define zeroext i16 @bitreverse_i16(i16 zeroext %a) nounwind {
 ;
 ; RV64IB-LABEL: bitreverse_i16:
 ; RV64IB:       # %bb.0:
-; RV64IB-NEXT:    rev a0, a0
-; RV64IB-NEXT:    srli a0, a0, 48
+; RV64IB-NEXT:    greviw a0, a0, 15
 ; RV64IB-NEXT:    ret
 ;
 ; RV64IBP-LABEL: bitreverse_i16:
 ; RV64IBP:       # %bb.0:
-; RV64IBP-NEXT:    rev a0, a0
-; RV64IBP-NEXT:    srli a0, a0, 48
+; RV64IBP-NEXT:    greviw a0, a0, 15
 ; RV64IBP-NEXT:    ret
   %1 = tail call i16 @llvm.bitreverse.i16(i16 %a)
   ret i16 %1


        


More information about the llvm-commits mailing list