[llvm] 088bb8a - [RISCV] Add more SHXADD patterns where the input is (and (shl/shr X, C2), C1)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 5 16:22:22 PDT 2022


Author: Craig Topper
Date: 2022-07-05T16:21:47-07:00
New Revision: 088bb8a328e030dfdc74fe464b564e0eb9b3411c

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

LOG: [RISCV] Add more SHXADD patterns where the input is (and (shl/shr X, C2), C1)

It might be possible to rewrite (and (shl/shr X, C2), C1) in a way
that gives us a left shift that can be folded into a SHXADD.

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
    llvm/test/CodeGen/RISCV/rv64zba.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 1b9a5fdf30bf..a73422ab9526 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -2041,15 +2041,62 @@ bool RISCVDAGToDAGISel::selectZExti32(SDValue N, SDValue &Val) {
 /// SHXADD we are trying to match.
 bool RISCVDAGToDAGISel::selectSHXADDOp(SDValue N, unsigned ShAmt,
                                        SDValue &Val) {
+  if (N.getOpcode() == ISD::AND && isa<ConstantSDNode>(N.getOperand(1))) {
+    SDValue N0 = N.getOperand(0);
+
+    bool LeftShift = N0.getOpcode() == ISD::SHL;
+    if ((LeftShift || N0.getOpcode() == ISD::SRL) &&
+        isa<ConstantSDNode>(N0.getOperand(1))) {
+      uint64_t Mask = N.getConstantOperandVal(1);
+      unsigned C2 = N0.getConstantOperandVal(1);
+
+      unsigned XLen = Subtarget->getXLen();
+      if (LeftShift)
+        Mask &= maskTrailingZeros<uint64_t>(C2);
+      else
+        Mask &= maskTrailingOnes<uint64_t>(XLen - C2);
+
+      // Look for (and (shl y, c2), c1) where c1 is a shifted mask with no
+      // leading zeros and c3 trailing zeros. We can use an SRLI by c2+c3
+      // followed by a SHXADD with c3 for the X amount.
+      if (isShiftedMask_64(Mask)) {
+        unsigned Leading = XLen - (64 - countLeadingZeros(Mask));
+        unsigned Trailing = countTrailingZeros(Mask);
+        if (LeftShift && Leading == 0 && C2 < Trailing && Trailing == ShAmt) {
+          SDLoc DL(N);
+          EVT VT = N.getValueType();
+          Val = SDValue(CurDAG->getMachineNode(
+                            RISCV::SRLI, DL, VT, N0.getOperand(0),
+                            CurDAG->getTargetConstant(Trailing - C2, DL, VT)),
+                        0);
+          return true;
+        }
+        // Look for (and (shr y, c2), c1) where c1 is a shifted mask with c2
+        // leading zeros and c3 trailing zeros. We can use an SRLI by C3
+        // followed by a SHXADD using c3 for the X amount.
+        if (!LeftShift && Leading == C2 && Trailing == ShAmt) {
+          SDLoc DL(N);
+          EVT VT = N.getValueType();
+          Val = SDValue(
+              CurDAG->getMachineNode(
+                  RISCV::SRLI, DL, VT, N0.getOperand(0),
+                  CurDAG->getTargetConstant(Leading + Trailing, DL, VT)),
+              0);
+          return true;
+        }
+      }
+    }
+  }
+
   bool LeftShift = N.getOpcode() == ISD::SHL;
   if ((LeftShift || N.getOpcode() == ISD::SRL) &&
       isa<ConstantSDNode>(N.getOperand(1))) {
-    unsigned C1 = N.getConstantOperandVal(1);
     SDValue N0 = N.getOperand(0);
     if (N0.getOpcode() == ISD::AND && N0.hasOneUse() &&
         isa<ConstantSDNode>(N0.getOperand(1))) {
       uint64_t Mask = N0.getConstantOperandVal(1);
       if (isShiftedMask_64(Mask)) {
+        unsigned C1 = N.getConstantOperandVal(1);
         unsigned XLen = Subtarget->getXLen();
         unsigned Leading = XLen - (64 - countLeadingZeros(Mask));
         unsigned Trailing = countTrailingZeros(Mask);

diff  --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll
index 1b92377865bc..4e8f5ad33992 100644
--- a/llvm/test/CodeGen/RISCV/rv64zba.ll
+++ b/llvm/test/CodeGen/RISCV/rv64zba.ll
@@ -1444,13 +1444,20 @@ define i64 @srliw_4_sh3add(i64* %0, i32 signext %1) {
 }
 
 define signext i32 @srli_1_sh2add(i32* %0, i64 %1) {
-; CHECK-LABEL: srli_1_sh2add:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    slli a1, a1, 1
-; CHECK-NEXT:    andi a1, a1, -4
-; CHECK-NEXT:    add a0, a0, a1
-; CHECK-NEXT:    lw a0, 0(a0)
-; CHECK-NEXT:    ret
+; RV64I-LABEL: srli_1_sh2add:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    slli a1, a1, 1
+; RV64I-NEXT:    andi a1, a1, -4
+; RV64I-NEXT:    add a0, a0, a1
+; RV64I-NEXT:    lw a0, 0(a0)
+; RV64I-NEXT:    ret
+;
+; RV64ZBA-LABEL: srli_1_sh2add:
+; RV64ZBA:       # %bb.0:
+; RV64ZBA-NEXT:    srli a1, a1, 1
+; RV64ZBA-NEXT:    sh2add a0, a1, a0
+; RV64ZBA-NEXT:    lw a0, 0(a0)
+; RV64ZBA-NEXT:    ret
   %3 = lshr i64 %1, 1
   %4 = getelementptr inbounds i32, i32* %0, i64 %3
   %5 = load i32, i32* %4, align 4
@@ -1458,13 +1465,20 @@ define signext i32 @srli_1_sh2add(i32* %0, i64 %1) {
 }
 
 define i64 @srli_2_sh3add(i64* %0, i64 %1) {
-; CHECK-LABEL: srli_2_sh3add:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    slli a1, a1, 1
-; CHECK-NEXT:    andi a1, a1, -8
-; CHECK-NEXT:    add a0, a0, a1
-; CHECK-NEXT:    ld a0, 0(a0)
-; CHECK-NEXT:    ret
+; RV64I-LABEL: srli_2_sh3add:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    slli a1, a1, 1
+; RV64I-NEXT:    andi a1, a1, -8
+; RV64I-NEXT:    add a0, a0, a1
+; RV64I-NEXT:    ld a0, 0(a0)
+; RV64I-NEXT:    ret
+;
+; RV64ZBA-LABEL: srli_2_sh3add:
+; RV64ZBA:       # %bb.0:
+; RV64ZBA-NEXT:    srli a1, a1, 2
+; RV64ZBA-NEXT:    sh3add a0, a1, a0
+; RV64ZBA-NEXT:    ld a0, 0(a0)
+; RV64ZBA-NEXT:    ret
   %3 = lshr i64 %1, 2
   %4 = getelementptr inbounds i64, i64* %0, i64 %3
   %5 = load i64, i64* %4, align 8
@@ -1472,13 +1486,20 @@ define i64 @srli_2_sh3add(i64* %0, i64 %1) {
 }
 
 define signext i16 @srli_2_sh1add(i16* %0, i64 %1) {
-; CHECK-LABEL: srli_2_sh1add:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    srli a1, a1, 1
-; CHECK-NEXT:    andi a1, a1, -2
-; CHECK-NEXT:    add a0, a0, a1
-; CHECK-NEXT:    lh a0, 0(a0)
-; CHECK-NEXT:    ret
+; RV64I-LABEL: srli_2_sh1add:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    srli a1, a1, 1
+; RV64I-NEXT:    andi a1, a1, -2
+; RV64I-NEXT:    add a0, a0, a1
+; RV64I-NEXT:    lh a0, 0(a0)
+; RV64I-NEXT:    ret
+;
+; RV64ZBA-LABEL: srli_2_sh1add:
+; RV64ZBA:       # %bb.0:
+; RV64ZBA-NEXT:    srli a1, a1, 2
+; RV64ZBA-NEXT:    sh1add a0, a1, a0
+; RV64ZBA-NEXT:    lh a0, 0(a0)
+; RV64ZBA-NEXT:    ret
   %3 = lshr i64 %1, 2
   %4 = getelementptr inbounds i16, i16* %0, i64 %3
   %5 = load i16, i16* %4, align 2
@@ -1486,13 +1507,20 @@ define signext i16 @srli_2_sh1add(i16* %0, i64 %1) {
 }
 
 define signext i32 @srli_3_sh2add(i32* %0, i64 %1) {
-; CHECK-LABEL: srli_3_sh2add:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    srli a1, a1, 1
-; CHECK-NEXT:    andi a1, a1, -4
-; CHECK-NEXT:    add a0, a0, a1
-; CHECK-NEXT:    lw a0, 0(a0)
-; CHECK-NEXT:    ret
+; RV64I-LABEL: srli_3_sh2add:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    srli a1, a1, 1
+; RV64I-NEXT:    andi a1, a1, -4
+; RV64I-NEXT:    add a0, a0, a1
+; RV64I-NEXT:    lw a0, 0(a0)
+; RV64I-NEXT:    ret
+;
+; RV64ZBA-LABEL: srli_3_sh2add:
+; RV64ZBA:       # %bb.0:
+; RV64ZBA-NEXT:    srli a1, a1, 3
+; RV64ZBA-NEXT:    sh2add a0, a1, a0
+; RV64ZBA-NEXT:    lw a0, 0(a0)
+; RV64ZBA-NEXT:    ret
   %3 = lshr i64 %1, 3
   %4 = getelementptr inbounds i32, i32* %0, i64 %3
   %5 = load i32, i32* %4, align 4
@@ -1500,13 +1528,20 @@ define signext i32 @srli_3_sh2add(i32* %0, i64 %1) {
 }
 
 define i64 @srli_4_sh3add(i64* %0, i64 %1) {
-; CHECK-LABEL: srli_4_sh3add:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    srli a1, a1, 1
-; CHECK-NEXT:    andi a1, a1, -8
-; CHECK-NEXT:    add a0, a0, a1
-; CHECK-NEXT:    ld a0, 0(a0)
-; CHECK-NEXT:    ret
+; RV64I-LABEL: srli_4_sh3add:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    srli a1, a1, 1
+; RV64I-NEXT:    andi a1, a1, -8
+; RV64I-NEXT:    add a0, a0, a1
+; RV64I-NEXT:    ld a0, 0(a0)
+; RV64I-NEXT:    ret
+;
+; RV64ZBA-LABEL: srli_4_sh3add:
+; RV64ZBA:       # %bb.0:
+; RV64ZBA-NEXT:    srli a1, a1, 4
+; RV64ZBA-NEXT:    sh3add a0, a1, a0
+; RV64ZBA-NEXT:    ld a0, 0(a0)
+; RV64ZBA-NEXT:    ret
   %3 = lshr i64 %1, 4
   %4 = getelementptr inbounds i64, i64* %0, i64 %3
   %5 = load i64, i64* %4, align 8


        


More information about the llvm-commits mailing list