[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