[llvm] dee5a8c - [RISCV] Optimize (add (shl x, c0), (shl y, c1)) with SH*ADD

Ben Shi via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 19 01:35:30 PDT 2021


Author: Ben Shi
Date: 2021-09-19T16:35:12+08:00
New Revision: dee5a8ca325f3c752534442233cb601910e918c4

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

LOG: [RISCV] Optimize (add (shl x, c0), (shl y, c1)) with SH*ADD

Optimize (add (shl x, c0), (shl y, c1)) ->
         (SLLI (SH*ADD x, y), c1), if c0-c1 == 1/2/3.

Reviewed By: craig.topper, luismarques

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

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index e9ac4bbfd270f..f7969bdd27e41 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -5913,6 +5913,52 @@ static SDValue combineORToSHFL(SDValue Op, SelectionDAG &DAG,
                      DAG.getConstant(Match1->ShAmt, DL, VT));
 }
 
+// Optimize (add (shl x, c0), (shl y, c1)) ->
+//          (SLLI (SH*ADD x, y), c0), if c1-c0 equals to [1|2|3].
+static SDValue transformAddShlImm(SDNode *N, SelectionDAG &DAG,
+                                  const RISCVSubtarget &Subtarget) {
+  // Perform this optimization only in the zba extension.
+  if (!Subtarget.hasStdExtZba())
+    return SDValue();
+
+  // Skip for vector types and larger types.
+  EVT VT = N->getValueType(0);
+  if (VT.isVector() || VT.getSizeInBits() > Subtarget.getXLen())
+    return SDValue();
+
+  // The two operand nodes must be SHL and have no other use.
+  SDValue N0 = N->getOperand(0);
+  SDValue N1 = N->getOperand(1);
+  if (N0->getOpcode() != ISD::SHL || N1->getOpcode() != ISD::SHL ||
+      !N0->hasOneUse() || !N1->hasOneUse())
+    return SDValue();
+
+  // Check c0 and c1.
+  auto *N0C = dyn_cast<ConstantSDNode>(N0->getOperand(1));
+  auto *N1C = dyn_cast<ConstantSDNode>(N1->getOperand(1));
+  if (!N0C || !N1C)
+    return SDValue();
+  int64_t C0 = N0C->getSExtValue();
+  int64_t C1 = N1C->getSExtValue();
+  if (C0 <= 0 || C1 <= 0)
+    return SDValue();
+
+  // Skip if SH1ADD/SH2ADD/SH3ADD are not applicable.
+  int64_t Bits = std::min(C0, C1);
+  int64_t Diff = std::abs(C0 - C1);
+  if (Diff != 1 && Diff != 2 && Diff != 3)
+    return SDValue();
+
+  // Build nodes.
+  SDLoc DL(N);
+  SDValue NS = (C0 < C1) ? N0->getOperand(0) : N1->getOperand(0);
+  SDValue NL = (C0 > C1) ? N0->getOperand(0) : N1->getOperand(0);
+  SDValue NA0 =
+      DAG.getNode(ISD::SHL, DL, VT, NL, DAG.getConstant(Diff, DL, VT));
+  SDValue NA1 = DAG.getNode(ISD::ADD, DL, VT, NA0, NS);
+  return DAG.getNode(ISD::SHL, DL, VT, NA1, DAG.getConstant(Bits, DL, VT));
+}
+
 // Combine (GREVI (GREVI x, C2), C1) -> (GREVI x, C1^C2) when C1^C2 is
 // non-zero, and to x when it is. Any repeated GREVI stage undoes itself.
 // Combine (GORCI (GORCI x, C2), C1) -> (GORCI x, C1|C2). Repeated stage does
@@ -6017,7 +6063,12 @@ static SDValue combineSelectAndUseCommutative(SDNode *N, SelectionDAG &DAG,
   return SDValue();
 }
 
-static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG) {
+static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG,
+                                 const RISCVSubtarget &Subtarget) {
+  // Fold (add (shl x, c0), (shl y, c1)) ->
+  //      (SLLI (SH*ADD x, y), c0), if c1-c0 equals to [1|2|3].
+  if (SDValue V = transformAddShlImm(N, DAG, Subtarget))
+    return V;
   // fold (add (select lhs, rhs, cc, 0, y), x) ->
   //      (select lhs, rhs, cc, x, (add x, y))
   return combineSelectAndUseCommutative(N, DAG, /*AllOnes*/ false);
@@ -6330,7 +6381,7 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
                        DAG.getConstant(~SignBit, DL, VT));
   }
   case ISD::ADD:
-    return performADDCombine(N, DAG);
+    return performADDCombine(N, DAG, Subtarget);
   case ISD::SUB:
     return performSUBCombine(N, DAG);
   case ISD::AND:

diff  --git a/llvm/test/CodeGen/RISCV/rv32zba.ll b/llvm/test/CodeGen/RISCV/rv32zba.ll
index 2423691a2bf0a..9e1eb48228a5d 100644
--- a/llvm/test/CodeGen/RISCV/rv32zba.ll
+++ b/llvm/test/CodeGen/RISCV/rv32zba.ll
@@ -796,16 +796,14 @@ define i32 @addshl_5_6(i32 %a, i32 %b) {
 ;
 ; RV32B-LABEL: addshl_5_6:
 ; RV32B:       # %bb.0:
+; RV32B-NEXT:    sh1add a0, a1, a0
 ; RV32B-NEXT:    slli a0, a0, 5
-; RV32B-NEXT:    slli a1, a1, 6
-; RV32B-NEXT:    add a0, a0, a1
 ; RV32B-NEXT:    ret
 ;
 ; RV32ZBA-LABEL: addshl_5_6:
 ; RV32ZBA:       # %bb.0:
+; RV32ZBA-NEXT:    sh1add a0, a1, a0
 ; RV32ZBA-NEXT:    slli a0, a0, 5
-; RV32ZBA-NEXT:    slli a1, a1, 6
-; RV32ZBA-NEXT:    add a0, a0, a1
 ; RV32ZBA-NEXT:    ret
   %c = shl i32 %a, 5
   %d = shl i32 %b, 6
@@ -823,16 +821,14 @@ define i32 @addshl_5_7(i32 %a, i32 %b) {
 ;
 ; RV32B-LABEL: addshl_5_7:
 ; RV32B:       # %bb.0:
+; RV32B-NEXT:    sh2add a0, a1, a0
 ; RV32B-NEXT:    slli a0, a0, 5
-; RV32B-NEXT:    slli a1, a1, 7
-; RV32B-NEXT:    add a0, a0, a1
 ; RV32B-NEXT:    ret
 ;
 ; RV32ZBA-LABEL: addshl_5_7:
 ; RV32ZBA:       # %bb.0:
+; RV32ZBA-NEXT:    sh2add a0, a1, a0
 ; RV32ZBA-NEXT:    slli a0, a0, 5
-; RV32ZBA-NEXT:    slli a1, a1, 7
-; RV32ZBA-NEXT:    add a0, a0, a1
 ; RV32ZBA-NEXT:    ret
   %c = shl i32 %a, 5
   %d = shl i32 %b, 7
@@ -850,16 +846,14 @@ define i32 @addshl_5_8(i32 %a, i32 %b) {
 ;
 ; RV32B-LABEL: addshl_5_8:
 ; RV32B:       # %bb.0:
+; RV32B-NEXT:    sh3add a0, a1, a0
 ; RV32B-NEXT:    slli a0, a0, 5
-; RV32B-NEXT:    slli a1, a1, 8
-; RV32B-NEXT:    add a0, a0, a1
 ; RV32B-NEXT:    ret
 ;
 ; RV32ZBA-LABEL: addshl_5_8:
 ; RV32ZBA:       # %bb.0:
+; RV32ZBA-NEXT:    sh3add a0, a1, a0
 ; RV32ZBA-NEXT:    slli a0, a0, 5
-; RV32ZBA-NEXT:    slli a1, a1, 8
-; RV32ZBA-NEXT:    add a0, a0, a1
 ; RV32ZBA-NEXT:    ret
   %c = shl i32 %a, 5
   %d = shl i32 %b, 8

diff  --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll
index c418ce6823616..32689d223a1a3 100644
--- a/llvm/test/CodeGen/RISCV/rv64zba.ll
+++ b/llvm/test/CodeGen/RISCV/rv64zba.ll
@@ -1407,16 +1407,14 @@ define signext i32 @addshl32_5_6(i32 signext %a, i32 signext %b) {
 ;
 ; RV64B-LABEL: addshl32_5_6:
 ; RV64B:       # %bb.0:
+; RV64B-NEXT:    sh1add a0, a1, a0
 ; RV64B-NEXT:    slliw a0, a0, 5
-; RV64B-NEXT:    slliw a1, a1, 6
-; RV64B-NEXT:    addw a0, a0, a1
 ; RV64B-NEXT:    ret
 ;
 ; RV64ZBA-LABEL: addshl32_5_6:
 ; RV64ZBA:       # %bb.0:
+; RV64ZBA-NEXT:    sh1add a0, a1, a0
 ; RV64ZBA-NEXT:    slliw a0, a0, 5
-; RV64ZBA-NEXT:    slliw a1, a1, 6
-; RV64ZBA-NEXT:    addw a0, a0, a1
 ; RV64ZBA-NEXT:    ret
   %c = shl i32 %a, 5
   %d = shl i32 %b, 6
@@ -1434,16 +1432,14 @@ define i64 @addshl64_5_6(i64 %a, i64 %b) {
 ;
 ; RV64B-LABEL: addshl64_5_6:
 ; RV64B:       # %bb.0:
+; RV64B-NEXT:    sh1add a0, a1, a0
 ; RV64B-NEXT:    slli a0, a0, 5
-; RV64B-NEXT:    slli a1, a1, 6
-; RV64B-NEXT:    add a0, a0, a1
 ; RV64B-NEXT:    ret
 ;
 ; RV64ZBA-LABEL: addshl64_5_6:
 ; RV64ZBA:       # %bb.0:
+; RV64ZBA-NEXT:    sh1add a0, a1, a0
 ; RV64ZBA-NEXT:    slli a0, a0, 5
-; RV64ZBA-NEXT:    slli a1, a1, 6
-; RV64ZBA-NEXT:    add a0, a0, a1
 ; RV64ZBA-NEXT:    ret
   %c = shl i64 %a, 5
   %d = shl i64 %b, 6
@@ -1461,16 +1457,14 @@ define signext i32 @addshl32_5_7(i32 signext %a, i32 signext %b) {
 ;
 ; RV64B-LABEL: addshl32_5_7:
 ; RV64B:       # %bb.0:
+; RV64B-NEXT:    sh2add a0, a1, a0
 ; RV64B-NEXT:    slliw a0, a0, 5
-; RV64B-NEXT:    slliw a1, a1, 7
-; RV64B-NEXT:    addw a0, a0, a1
 ; RV64B-NEXT:    ret
 ;
 ; RV64ZBA-LABEL: addshl32_5_7:
 ; RV64ZBA:       # %bb.0:
+; RV64ZBA-NEXT:    sh2add a0, a1, a0
 ; RV64ZBA-NEXT:    slliw a0, a0, 5
-; RV64ZBA-NEXT:    slliw a1, a1, 7
-; RV64ZBA-NEXT:    addw a0, a0, a1
 ; RV64ZBA-NEXT:    ret
   %c = shl i32 %a, 5
   %d = shl i32 %b, 7
@@ -1488,16 +1482,14 @@ define i64 @addshl64_5_7(i64 %a, i64 %b) {
 ;
 ; RV64B-LABEL: addshl64_5_7:
 ; RV64B:       # %bb.0:
+; RV64B-NEXT:    sh2add a0, a1, a0
 ; RV64B-NEXT:    slli a0, a0, 5
-; RV64B-NEXT:    slli a1, a1, 7
-; RV64B-NEXT:    add a0, a0, a1
 ; RV64B-NEXT:    ret
 ;
 ; RV64ZBA-LABEL: addshl64_5_7:
 ; RV64ZBA:       # %bb.0:
+; RV64ZBA-NEXT:    sh2add a0, a1, a0
 ; RV64ZBA-NEXT:    slli a0, a0, 5
-; RV64ZBA-NEXT:    slli a1, a1, 7
-; RV64ZBA-NEXT:    add a0, a0, a1
 ; RV64ZBA-NEXT:    ret
   %c = shl i64 %a, 5
   %d = shl i64 %b, 7
@@ -1515,16 +1507,14 @@ define signext i32 @addshl32_5_8(i32 signext %a, i32 signext %b) {
 ;
 ; RV64B-LABEL: addshl32_5_8:
 ; RV64B:       # %bb.0:
+; RV64B-NEXT:    sh3add a0, a1, a0
 ; RV64B-NEXT:    slliw a0, a0, 5
-; RV64B-NEXT:    slliw a1, a1, 8
-; RV64B-NEXT:    addw a0, a0, a1
 ; RV64B-NEXT:    ret
 ;
 ; RV64ZBA-LABEL: addshl32_5_8:
 ; RV64ZBA:       # %bb.0:
+; RV64ZBA-NEXT:    sh3add a0, a1, a0
 ; RV64ZBA-NEXT:    slliw a0, a0, 5
-; RV64ZBA-NEXT:    slliw a1, a1, 8
-; RV64ZBA-NEXT:    addw a0, a0, a1
 ; RV64ZBA-NEXT:    ret
   %c = shl i32 %a, 5
   %d = shl i32 %b, 8
@@ -1542,16 +1532,14 @@ define i64 @addshl64_5_8(i64 %a, i64 %b) {
 ;
 ; RV64B-LABEL: addshl64_5_8:
 ; RV64B:       # %bb.0:
+; RV64B-NEXT:    sh3add a0, a1, a0
 ; RV64B-NEXT:    slli a0, a0, 5
-; RV64B-NEXT:    slli a1, a1, 8
-; RV64B-NEXT:    add a0, a0, a1
 ; RV64B-NEXT:    ret
 ;
 ; RV64ZBA-LABEL: addshl64_5_8:
 ; RV64ZBA:       # %bb.0:
+; RV64ZBA-NEXT:    sh3add a0, a1, a0
 ; RV64ZBA-NEXT:    slli a0, a0, 5
-; RV64ZBA-NEXT:    slli a1, a1, 8
-; RV64ZBA-NEXT:    add a0, a0, a1
 ; RV64ZBA-NEXT:    ret
   %c = shl i64 %a, 5
   %d = shl i64 %b, 8


        


More information about the llvm-commits mailing list