[llvm] e32cf69 - [RISCV] Optimize (add (mul r, c0), c1)

Ben Shi via llvm-commits llvm-commits at lists.llvm.org
Sun Nov 7 18:58:59 PST 2021


Author: Ben Shi
Date: 2021-11-08T02:58:25Z
New Revision: e32cf690dfdcf41255022c075beac20c141e1419

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

LOG: [RISCV] Optimize (add (mul r, c0), c1)

Optimize (add (mul x, c0), c1) ->
         (add (mul (add x, c1/c0+1), c0), c1%c0-c0),
if c1/c0+1 and c1%c0-c0 are simm12, while c1 is not.

Optimize (add (mul x, c0), c1) ->
         (add (mul (add x, c1/c0-1), c0), c1%c0+c0),
if c1/c0-1 and c1%c0+c0 are simm12, while c1 is not.

Reviewed By: craig.topper, asb

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

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVISelLowering.cpp
    llvm/test/CodeGen/RISCV/addimm-mulimm.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 193c5b4c91db3..372685d4b1e98 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -6439,7 +6439,19 @@ static SDValue combineSelectAndUseCommutative(SDNode *N, SelectionDAG &DAG,
 
 // Transform (add (mul x, c0), c1) ->
 //           (add (mul (add x, c1/c0), c0), c1%c0).
-// if c1/c0 and c1%c0 are simm12, while c1 is not.
+// if c1/c0 and c1%c0 are simm12, while c1 is not. A special corner case
+// that should be excluded is when c0*(c1/c0) is simm12, which will lead
+// to an infinite loop in DAGCombine if transformed.
+// Or transform (add (mul x, c0), c1) ->
+//              (add (mul (add x, c1/c0+1), c0), c1%c0-c0),
+// if c1/c0+1 and c1%c0-c0 are simm12, while c1 is not. A special corner
+// case that should be excluded is when c0*(c1/c0+1) is simm12, which will
+// lead to an infinite loop in DAGCombine if transformed.
+// Or transform (add (mul x, c0), c1) ->
+//              (add (mul (add x, c1/c0-1), c0), c1%c0+c0),
+// if c1/c0-1 and c1%c0+c0 are simm12, while c1 is not. A special corner
+// case that should be excluded is when c0*(c1/c0-1) is simm12, which will
+// lead to an infinite loop in DAGCombine if transformed.
 // Or transform (add (mul x, c0), c1) ->
 //              (mul (add x, c1/c0), c0).
 // if c1%c0 is zero, and c1/c0 is simm12 while c1 is not.
@@ -6460,35 +6472,37 @@ static SDValue transformAddImmMulImm(SDNode *N, SelectionDAG &DAG,
     return SDValue();
   int64_t C0 = N0C->getSExtValue();
   int64_t C1 = N1C->getSExtValue();
-  if (C0 == -1 || C0 == 0 || C0 == 1 || (C1 / C0) == 0 || isInt<12>(C1) ||
-      !isInt<12>(C1 % C0) || !isInt<12>(C1 / C0))
+  int64_t CA, CB;
+  if (C0 == -1 || C0 == 0 || C0 == 1 || isInt<12>(C1))
     return SDValue();
-  // If C0 * (C1 / C0) is a 12-bit integer, this transform will be reversed.
-  if (isInt<12>(C0 * (C1 / C0)))
+  // Search for proper CA (non-zero) and CB that both are simm12.
+  if ((C1 / C0) != 0 && isInt<12>(C1 / C0) && isInt<12>(C1 % C0) &&
+      !isInt<12>(C0 * (C1 / C0))) {
+    CA = C1 / C0;
+    CB = C1 % C0;
+  } else if ((C1 / C0 + 1) != 0 && isInt<12>(C1 / C0 + 1) &&
+             isInt<12>(C1 % C0 - C0) && !isInt<12>(C0 * (C1 / C0 + 1))) {
+    CA = C1 / C0 + 1;
+    CB = C1 % C0 - C0;
+  } else if ((C1 / C0 - 1) != 0 && isInt<12>(C1 / C0 - 1) &&
+             isInt<12>(C1 % C0 + C0) && !isInt<12>(C0 * (C1 / C0 - 1))) {
+    CA = C1 / C0 - 1;
+    CB = C1 % C0 + C0;
+  } else
     return SDValue();
   // Build new nodes (add (mul (add x, c1/c0), c0), c1%c0).
   SDLoc DL(N);
   SDValue New0 = DAG.getNode(ISD::ADD, DL, VT, N0->getOperand(0),
-                             DAG.getConstant(C1 / C0, DL, VT));
+                             DAG.getConstant(CA, DL, VT));
   SDValue New1 =
       DAG.getNode(ISD::MUL, DL, VT, New0, DAG.getConstant(C0, DL, VT));
-  if ((C1 % C0) == 0)
-    return New1;
-  return DAG.getNode(ISD::ADD, DL, VT, New1, DAG.getConstant(C1 % C0, DL, VT));
+  return DAG.getNode(ISD::ADD, DL, VT, New1, DAG.getConstant(CB, DL, VT));
 }
 
 static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG,
                                  const RISCVSubtarget &Subtarget) {
-  // Transform (add (mul x, c0), c1) ->
-  //           (add (mul (add x, c1/c0), c0), c1%c0).
-  // if c1/c0 and c1%c0 are simm12, while c1 is not.
-  // Or transform (add (mul x, c0), c1) ->
-  //              (mul (add x, c1/c0), c0).
-  // if c1%c0 is zero, and c1/c0 is simm12 while c1 is not.
   if (SDValue V = transformAddImmMulImm(N, DAG, Subtarget))
     return V;
-  // 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) ->

diff  --git a/llvm/test/CodeGen/RISCV/addimm-mulimm.ll b/llvm/test/CodeGen/RISCV/addimm-mulimm.ll
index 761a20e957a45..399361e7fb39e 100644
--- a/llvm/test/CodeGen/RISCV/addimm-mulimm.ll
+++ b/llvm/test/CodeGen/RISCV/addimm-mulimm.ll
@@ -559,9 +559,9 @@ define i64 @add_mul_combine_infinite_loop(i64 %x) {
 ;
 ; RV64IMB-LABEL: add_mul_combine_infinite_loop:
 ; RV64IMB:       # %bb.0:
+; RV64IMB-NEXT:    addi a0, a0, 86
 ; RV64IMB-NEXT:    sh1add a0, a0, a0
-; RV64IMB-NEXT:    lui a1, 1
-; RV64IMB-NEXT:    addiw a1, a1, -2048
+; RV64IMB-NEXT:    addi a1, zero, -16
 ; RV64IMB-NEXT:    sh3add a0, a0, a1
 ; RV64IMB-NEXT:    ret
   %tmp0 = mul i64 %x, 24
@@ -572,22 +572,20 @@ define i64 @add_mul_combine_infinite_loop(i64 %x) {
 define i32 @mul3000_add8990_a(i32 %x) {
 ; RV32IMB-LABEL: mul3000_add8990_a:
 ; RV32IMB:       # %bb.0:
+; RV32IMB-NEXT:    addi a0, a0, 3
 ; RV32IMB-NEXT:    lui a1, 1
 ; RV32IMB-NEXT:    addi a1, a1, -1096
 ; RV32IMB-NEXT:    mul a0, a0, a1
-; RV32IMB-NEXT:    lui a1, 2
-; RV32IMB-NEXT:    addi a1, a1, 798
-; RV32IMB-NEXT:    add a0, a0, a1
+; RV32IMB-NEXT:    addi a0, a0, -10
 ; RV32IMB-NEXT:    ret
 ;
 ; RV64IMB-LABEL: mul3000_add8990_a:
 ; RV64IMB:       # %bb.0:
+; RV64IMB-NEXT:    addiw a0, a0, 3
 ; RV64IMB-NEXT:    lui a1, 1
 ; RV64IMB-NEXT:    addiw a1, a1, -1096
 ; RV64IMB-NEXT:    mulw a0, a0, a1
-; RV64IMB-NEXT:    lui a1, 2
-; RV64IMB-NEXT:    addiw a1, a1, 798
-; RV64IMB-NEXT:    addw a0, a0, a1
+; RV64IMB-NEXT:    addiw a0, a0, -10
 ; RV64IMB-NEXT:    ret
   %tmp0 = mul i32 %x, 3000
   %tmp1 = add i32 %tmp0, 8990
@@ -597,22 +595,20 @@ define i32 @mul3000_add8990_a(i32 %x) {
 define signext i32 @mul3000_add8990_b(i32 signext %x) {
 ; RV32IMB-LABEL: mul3000_add8990_b:
 ; RV32IMB:       # %bb.0:
+; RV32IMB-NEXT:    addi a0, a0, 3
 ; RV32IMB-NEXT:    lui a1, 1
 ; RV32IMB-NEXT:    addi a1, a1, -1096
 ; RV32IMB-NEXT:    mul a0, a0, a1
-; RV32IMB-NEXT:    lui a1, 2
-; RV32IMB-NEXT:    addi a1, a1, 798
-; RV32IMB-NEXT:    add a0, a0, a1
+; RV32IMB-NEXT:    addi a0, a0, -10
 ; RV32IMB-NEXT:    ret
 ;
 ; RV64IMB-LABEL: mul3000_add8990_b:
 ; RV64IMB:       # %bb.0:
+; RV64IMB-NEXT:    addiw a0, a0, 3
 ; RV64IMB-NEXT:    lui a1, 1
 ; RV64IMB-NEXT:    addiw a1, a1, -1096
 ; RV64IMB-NEXT:    mulw a0, a0, a1
-; RV64IMB-NEXT:    lui a1, 2
-; RV64IMB-NEXT:    addiw a1, a1, 798
-; RV64IMB-NEXT:    addw a0, a0, a1
+; RV64IMB-NEXT:    addiw a0, a0, -10
 ; RV64IMB-NEXT:    ret
   %tmp0 = mul i32 %x, 3000
   %tmp1 = add i32 %tmp0, 8990
@@ -637,12 +633,11 @@ define i64 @mul3000_add8990_c(i64 %x) {
 ;
 ; RV64IMB-LABEL: mul3000_add8990_c:
 ; RV64IMB:       # %bb.0:
+; RV64IMB-NEXT:    addi a0, a0, 3
 ; RV64IMB-NEXT:    lui a1, 1
 ; RV64IMB-NEXT:    addiw a1, a1, -1096
 ; RV64IMB-NEXT:    mul a0, a0, a1
-; RV64IMB-NEXT:    lui a1, 2
-; RV64IMB-NEXT:    addiw a1, a1, 798
-; RV64IMB-NEXT:    add a0, a0, a1
+; RV64IMB-NEXT:    addi a0, a0, -10
 ; RV64IMB-NEXT:    ret
   %tmp0 = mul i64 %x, 3000
   %tmp1 = add i64 %tmp0, 8990
@@ -652,22 +647,20 @@ define i64 @mul3000_add8990_c(i64 %x) {
 define i32 @mul3000_sub8990_a(i32 %x) {
 ; RV32IMB-LABEL: mul3000_sub8990_a:
 ; RV32IMB:       # %bb.0:
+; RV32IMB-NEXT:    addi a0, a0, -3
 ; RV32IMB-NEXT:    lui a1, 1
 ; RV32IMB-NEXT:    addi a1, a1, -1096
 ; RV32IMB-NEXT:    mul a0, a0, a1
-; RV32IMB-NEXT:    lui a1, 1048574
-; RV32IMB-NEXT:    addi a1, a1, -798
-; RV32IMB-NEXT:    add a0, a0, a1
+; RV32IMB-NEXT:    addi a0, a0, 10
 ; RV32IMB-NEXT:    ret
 ;
 ; RV64IMB-LABEL: mul3000_sub8990_a:
 ; RV64IMB:       # %bb.0:
+; RV64IMB-NEXT:    addiw a0, a0, -3
 ; RV64IMB-NEXT:    lui a1, 1
 ; RV64IMB-NEXT:    addiw a1, a1, -1096
 ; RV64IMB-NEXT:    mulw a0, a0, a1
-; RV64IMB-NEXT:    lui a1, 1048574
-; RV64IMB-NEXT:    addiw a1, a1, -798
-; RV64IMB-NEXT:    addw a0, a0, a1
+; RV64IMB-NEXT:    addiw a0, a0, 10
 ; RV64IMB-NEXT:    ret
   %tmp0 = mul i32 %x, 3000
   %tmp1 = add i32 %tmp0, -8990
@@ -677,22 +670,20 @@ define i32 @mul3000_sub8990_a(i32 %x) {
 define signext i32 @mul3000_sub8990_b(i32 signext %x) {
 ; RV32IMB-LABEL: mul3000_sub8990_b:
 ; RV32IMB:       # %bb.0:
+; RV32IMB-NEXT:    addi a0, a0, -3
 ; RV32IMB-NEXT:    lui a1, 1
 ; RV32IMB-NEXT:    addi a1, a1, -1096
 ; RV32IMB-NEXT:    mul a0, a0, a1
-; RV32IMB-NEXT:    lui a1, 1048574
-; RV32IMB-NEXT:    addi a1, a1, -798
-; RV32IMB-NEXT:    add a0, a0, a1
+; RV32IMB-NEXT:    addi a0, a0, 10
 ; RV32IMB-NEXT:    ret
 ;
 ; RV64IMB-LABEL: mul3000_sub8990_b:
 ; RV64IMB:       # %bb.0:
+; RV64IMB-NEXT:    addiw a0, a0, -3
 ; RV64IMB-NEXT:    lui a1, 1
 ; RV64IMB-NEXT:    addiw a1, a1, -1096
 ; RV64IMB-NEXT:    mulw a0, a0, a1
-; RV64IMB-NEXT:    lui a1, 1048574
-; RV64IMB-NEXT:    addiw a1, a1, -798
-; RV64IMB-NEXT:    addw a0, a0, a1
+; RV64IMB-NEXT:    addiw a0, a0, 10
 ; RV64IMB-NEXT:    ret
   %tmp0 = mul i32 %x, 3000
   %tmp1 = add i32 %tmp0, -8990
@@ -718,12 +709,11 @@ define i64 @mul3000_sub8990_c(i64 %x) {
 ;
 ; RV64IMB-LABEL: mul3000_sub8990_c:
 ; RV64IMB:       # %bb.0:
+; RV64IMB-NEXT:    addi a0, a0, -3
 ; RV64IMB-NEXT:    lui a1, 1
 ; RV64IMB-NEXT:    addiw a1, a1, -1096
 ; RV64IMB-NEXT:    mul a0, a0, a1
-; RV64IMB-NEXT:    lui a1, 1048574
-; RV64IMB-NEXT:    addiw a1, a1, -798
-; RV64IMB-NEXT:    add a0, a0, a1
+; RV64IMB-NEXT:    addi a0, a0, 10
 ; RV64IMB-NEXT:    ret
   %tmp0 = mul i64 %x, 3000
   %tmp1 = add i64 %tmp0, -8990
@@ -733,22 +723,20 @@ define i64 @mul3000_sub8990_c(i64 %x) {
 define i32 @mulneg3000_add8990_a(i32 %x) {
 ; RV32IMB-LABEL: mulneg3000_add8990_a:
 ; RV32IMB:       # %bb.0:
+; RV32IMB-NEXT:    addi a0, a0, -3
 ; RV32IMB-NEXT:    lui a1, 1048575
 ; RV32IMB-NEXT:    addi a1, a1, 1096
 ; RV32IMB-NEXT:    mul a0, a0, a1
-; RV32IMB-NEXT:    lui a1, 2
-; RV32IMB-NEXT:    addi a1, a1, 798
-; RV32IMB-NEXT:    add a0, a0, a1
+; RV32IMB-NEXT:    addi a0, a0, -10
 ; RV32IMB-NEXT:    ret
 ;
 ; RV64IMB-LABEL: mulneg3000_add8990_a:
 ; RV64IMB:       # %bb.0:
+; RV64IMB-NEXT:    addiw a0, a0, -3
 ; RV64IMB-NEXT:    lui a1, 1048575
 ; RV64IMB-NEXT:    addiw a1, a1, 1096
 ; RV64IMB-NEXT:    mulw a0, a0, a1
-; RV64IMB-NEXT:    lui a1, 2
-; RV64IMB-NEXT:    addiw a1, a1, 798
-; RV64IMB-NEXT:    addw a0, a0, a1
+; RV64IMB-NEXT:    addiw a0, a0, -10
 ; RV64IMB-NEXT:    ret
   %tmp0 = mul i32 %x, -3000
   %tmp1 = add i32 %tmp0, 8990
@@ -758,22 +746,20 @@ define i32 @mulneg3000_add8990_a(i32 %x) {
 define signext i32 @mulneg3000_add8990_b(i32 signext %x) {
 ; RV32IMB-LABEL: mulneg3000_add8990_b:
 ; RV32IMB:       # %bb.0:
+; RV32IMB-NEXT:    addi a0, a0, -3
 ; RV32IMB-NEXT:    lui a1, 1048575
 ; RV32IMB-NEXT:    addi a1, a1, 1096
 ; RV32IMB-NEXT:    mul a0, a0, a1
-; RV32IMB-NEXT:    lui a1, 2
-; RV32IMB-NEXT:    addi a1, a1, 798
-; RV32IMB-NEXT:    add a0, a0, a1
+; RV32IMB-NEXT:    addi a0, a0, -10
 ; RV32IMB-NEXT:    ret
 ;
 ; RV64IMB-LABEL: mulneg3000_add8990_b:
 ; RV64IMB:       # %bb.0:
+; RV64IMB-NEXT:    addiw a0, a0, -3
 ; RV64IMB-NEXT:    lui a1, 1048575
 ; RV64IMB-NEXT:    addiw a1, a1, 1096
 ; RV64IMB-NEXT:    mulw a0, a0, a1
-; RV64IMB-NEXT:    lui a1, 2
-; RV64IMB-NEXT:    addiw a1, a1, 798
-; RV64IMB-NEXT:    addw a0, a0, a1
+; RV64IMB-NEXT:    addiw a0, a0, -10
 ; RV64IMB-NEXT:    ret
   %tmp0 = mul i32 %x, -3000
   %tmp1 = add i32 %tmp0, 8990
@@ -799,12 +785,11 @@ define i64 @mulneg3000_add8990_c(i64 %x) {
 ;
 ; RV64IMB-LABEL: mulneg3000_add8990_c:
 ; RV64IMB:       # %bb.0:
+; RV64IMB-NEXT:    addi a0, a0, -3
 ; RV64IMB-NEXT:    lui a1, 1048575
 ; RV64IMB-NEXT:    addiw a1, a1, 1096
 ; RV64IMB-NEXT:    mul a0, a0, a1
-; RV64IMB-NEXT:    lui a1, 2
-; RV64IMB-NEXT:    addiw a1, a1, 798
-; RV64IMB-NEXT:    add a0, a0, a1
+; RV64IMB-NEXT:    addi a0, a0, -10
 ; RV64IMB-NEXT:    ret
   %tmp0 = mul i64 %x, -3000
   %tmp1 = add i64 %tmp0, 8990
@@ -814,22 +799,20 @@ define i64 @mulneg3000_add8990_c(i64 %x) {
 define i32 @mulneg3000_sub8990_a(i32 %x) {
 ; RV32IMB-LABEL: mulneg3000_sub8990_a:
 ; RV32IMB:       # %bb.0:
+; RV32IMB-NEXT:    addi a0, a0, 3
 ; RV32IMB-NEXT:    lui a1, 1048575
 ; RV32IMB-NEXT:    addi a1, a1, 1096
 ; RV32IMB-NEXT:    mul a0, a0, a1
-; RV32IMB-NEXT:    lui a1, 1048574
-; RV32IMB-NEXT:    addi a1, a1, -798
-; RV32IMB-NEXT:    add a0, a0, a1
+; RV32IMB-NEXT:    addi a0, a0, 10
 ; RV32IMB-NEXT:    ret
 ;
 ; RV64IMB-LABEL: mulneg3000_sub8990_a:
 ; RV64IMB:       # %bb.0:
+; RV64IMB-NEXT:    addiw a0, a0, 3
 ; RV64IMB-NEXT:    lui a1, 1048575
 ; RV64IMB-NEXT:    addiw a1, a1, 1096
 ; RV64IMB-NEXT:    mulw a0, a0, a1
-; RV64IMB-NEXT:    lui a1, 1048574
-; RV64IMB-NEXT:    addiw a1, a1, -798
-; RV64IMB-NEXT:    addw a0, a0, a1
+; RV64IMB-NEXT:    addiw a0, a0, 10
 ; RV64IMB-NEXT:    ret
   %tmp0 = mul i32 %x, -3000
   %tmp1 = add i32 %tmp0, -8990
@@ -839,22 +822,20 @@ define i32 @mulneg3000_sub8990_a(i32 %x) {
 define signext i32 @mulneg3000_sub8990_b(i32 signext %x) {
 ; RV32IMB-LABEL: mulneg3000_sub8990_b:
 ; RV32IMB:       # %bb.0:
+; RV32IMB-NEXT:    addi a0, a0, 3
 ; RV32IMB-NEXT:    lui a1, 1048575
 ; RV32IMB-NEXT:    addi a1, a1, 1096
 ; RV32IMB-NEXT:    mul a0, a0, a1
-; RV32IMB-NEXT:    lui a1, 1048574
-; RV32IMB-NEXT:    addi a1, a1, -798
-; RV32IMB-NEXT:    add a0, a0, a1
+; RV32IMB-NEXT:    addi a0, a0, 10
 ; RV32IMB-NEXT:    ret
 ;
 ; RV64IMB-LABEL: mulneg3000_sub8990_b:
 ; RV64IMB:       # %bb.0:
+; RV64IMB-NEXT:    addiw a0, a0, 3
 ; RV64IMB-NEXT:    lui a1, 1048575
 ; RV64IMB-NEXT:    addiw a1, a1, 1096
 ; RV64IMB-NEXT:    mulw a0, a0, a1
-; RV64IMB-NEXT:    lui a1, 1048574
-; RV64IMB-NEXT:    addiw a1, a1, -798
-; RV64IMB-NEXT:    addw a0, a0, a1
+; RV64IMB-NEXT:    addiw a0, a0, 10
 ; RV64IMB-NEXT:    ret
   %tmp0 = mul i32 %x, -3000
   %tmp1 = add i32 %tmp0, -8990
@@ -881,12 +862,11 @@ define i64 @mulneg3000_sub8990_c(i64 %x) {
 ;
 ; RV64IMB-LABEL: mulneg3000_sub8990_c:
 ; RV64IMB:       # %bb.0:
+; RV64IMB-NEXT:    addi a0, a0, 3
 ; RV64IMB-NEXT:    lui a1, 1048575
 ; RV64IMB-NEXT:    addiw a1, a1, 1096
 ; RV64IMB-NEXT:    mul a0, a0, a1
-; RV64IMB-NEXT:    lui a1, 1048574
-; RV64IMB-NEXT:    addiw a1, a1, -798
-; RV64IMB-NEXT:    add a0, a0, a1
+; RV64IMB-NEXT:    addi a0, a0, 10
 ; RV64IMB-NEXT:    ret
   %tmp0 = mul i64 %x, -3000
   %tmp1 = add i64 %tmp0, -8990


        


More information about the llvm-commits mailing list