[llvm] dde8423 - [RISCV] Expand i32 abs to negw+max at isel.
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 14 19:48:20 PST 2022
Author: Craig Topper
Date: 2022-11-14T19:44:05-08:00
New Revision: dde8423f21fb09c77b83d1ec50d5fff6bb940586
URL: https://github.com/llvm/llvm-project/commit/dde8423f21fb09c77b83d1ec50d5fff6bb940586
DIFF: https://github.com/llvm/llvm-project/commit/dde8423f21fb09c77b83d1ec50d5fff6bb940586.diff
LOG: [RISCV] Expand i32 abs to negw+max at isel.
This adds a RISCVISD::ABSW to remember that we started with an i32
abs. Previously we used a DAG combine of (sext_inreg (abs)) to
delay emitting a freeze from type legalization in order to make
ComputeNumSignBits optimizations work on other promoted nodes.
This new approach always uses negw+max even if the result doesn't
need to be sign extended. This helps the RISCVSExtWRemoval pass
if the sext.w is in another basic block.
Added:
Modified:
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/lib/Target/RISCV/RISCVISelLowering.h
llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
llvm/test/CodeGen/RISCV/iabs.ll
llvm/test/CodeGen/RISCV/neg-abs.ll
llvm/test/CodeGen/RISCV/rv64zbb.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 687a89e290e3..287800b1fb22 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -294,11 +294,11 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
MVT::i32, Custom);
} else {
setOperationAction({ISD::CTTZ, ISD::CTLZ, ISD::CTPOP}, XLenVT, Expand);
-
- if (Subtarget.is64Bit())
- setOperationAction(ISD::ABS, MVT::i32, Custom);
}
+ if (Subtarget.is64Bit())
+ setOperationAction(ISD::ABS, MVT::i32, Custom);
+
setOperationAction(ISD::SELECT, XLenVT, Custom);
static const unsigned FPLegalNodeTypes[] = {
@@ -999,7 +999,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
if (Subtarget.hasStdExtZbkb())
setTargetDAGCombine(ISD::BITREVERSE);
- if (Subtarget.hasStdExtZfh() || Subtarget.hasStdExtZbb())
+ if (Subtarget.hasStdExtZfh())
setTargetDAGCombine(ISD::SIGN_EXTEND_INREG);
if (Subtarget.hasStdExtF())
setTargetDAGCombine({ISD::ZERO_EXTEND, ISD::FP_TO_SINT, ISD::FP_TO_UINT,
@@ -7616,8 +7616,18 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
"Unexpected custom legalisation");
- // Expand abs to Y = (sraiw X, 31); subw(xor(X, Y), Y)
+ if (Subtarget.hasStdExtZbb()) {
+ // Emit a special ABSW node that will be expanded to NEGW+MAX at isel.
+ // This allows us to remember that the result is sign extended. Expanding
+ // to NEGW+MAX here requires a Freeze which breaks ComputeNumSignBits.
+ SDValue Src = DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64,
+ N->getOperand(0));
+ SDValue Abs = DAG.getNode(RISCVISD::ABSW, DL, MVT::i64, Src);
+ Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, Abs));
+ return;
+ }
+ // Expand abs to Y = (sraiw X, 31); subw(xor(X, Y), Y)
SDValue Src = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(0));
// Freeze the source so we can increase it's use count.
@@ -8354,30 +8364,6 @@ performSIGN_EXTEND_INREGCombine(SDNode *N, SelectionDAG &DAG,
return DAG.getNode(RISCVISD::FMV_X_SIGNEXTH, SDLoc(N), VT,
Src.getOperand(0));
- // Fold (i64 (sext_inreg (abs X), i32)) ->
- // (i64 (smax (sext_inreg (neg X), i32), X)) if X has more than 32 sign bits.
- // The (sext_inreg (neg X), i32) will be selected to negw by isel. This
- // pattern occurs after type legalization of (i32 (abs X)) on RV64 if the user
- // of the (i32 (abs X)) is a sext or setcc or something else that causes type
- // legalization to add a sext_inreg after the abs. The (i32 (abs X)) will have
- // been type legalized to (i64 (abs (sext_inreg X, i32))), but the sext_inreg
- // may get combined into an earlier operation so we need to use
- // ComputeNumSignBits.
- // NOTE: (i64 (sext_inreg (abs X), i32)) can also be created for
- // (i64 (ashr (shl (abs X), 32), 32)) without any type legalization so
- // we can't assume that X has 33 sign bits. We must check.
- if (Subtarget.hasStdExtZbb() && Subtarget.is64Bit() &&
- Src.getOpcode() == ISD::ABS && Src.hasOneUse() && VT == MVT::i64 &&
- cast<VTSDNode>(N->getOperand(1))->getVT() == MVT::i32 &&
- DAG.ComputeNumSignBits(Src.getOperand(0)) > 32) {
- SDLoc DL(N);
- SDValue Freeze = DAG.getFreeze(Src.getOperand(0));
- SDValue Neg = DAG.getNegative(Freeze, DL, VT);
- Neg = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, Neg,
- DAG.getValueType(MVT::i32));
- return DAG.getNode(ISD::SMAX, DL, MVT::i64, Freeze, Neg);
- }
-
return SDValue();
}
@@ -10237,6 +10223,7 @@ unsigned RISCVTargetLowering::ComputeNumSignBitsForTargetNode(
case RISCVISD::REMUW:
case RISCVISD::ROLW:
case RISCVISD::RORW:
+ case RISCVISD::ABSW:
case RISCVISD::FCVT_W_RV64:
case RISCVISD::FCVT_WU_RV64:
case RISCVISD::STRICT_FCVT_W_RV64:
@@ -12413,6 +12400,7 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
NODE_NAME_CASE(RORW)
NODE_NAME_CASE(CLZW)
NODE_NAME_CASE(CTZW)
+ NODE_NAME_CASE(ABSW)
NODE_NAME_CASE(FMV_H_X)
NODE_NAME_CASE(FMV_X_ANYEXTH)
NODE_NAME_CASE(FMV_X_SIGNEXTH)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index 4f07d9ece8f3..a02107ed2a74 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -78,6 +78,10 @@ enum NodeType : unsigned {
// named RISC-V instructions.
CLZW,
CTZW,
+
+ // RV64IZbb absolute value for i32. Expanded to (max (negw X), X) during isel.
+ ABSW,
+
// FPR<->GPR transfer operations when the FPR is smaller than XLEN, needed as
// XLEN is the only legal integer width.
//
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
index bb38c6f87f2d..3ea19eafd0a5 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td
@@ -37,6 +37,7 @@ def riscv_brev8 : SDNode<"RISCVISD::BREV8", SDTIntUnaryOp>;
def riscv_orc_b : SDNode<"RISCVISD::ORC_B", SDTIntUnaryOp>;
def riscv_zip : SDNode<"RISCVISD::ZIP", SDTIntUnaryOp>;
def riscv_unzip : SDNode<"RISCVISD::UNZIP", SDTIntUnaryOp>;
+def riscv_absw : SDNode<"RISCVISD::ABSW", SDTIntUnaryOp>;
def UImmLog2XLenHalfAsmOperand : AsmOperandClass {
let Name = "UImmLog2XLenHalf";
@@ -609,6 +610,9 @@ let Predicates = [HasStdExtZbb, IsRV64] in {
def : PatGpr<riscv_clzw, CLZW>;
def : PatGpr<riscv_ctzw, CTZW>;
def : Pat<(i64 (ctpop (i64 (zexti32 (i64 GPR:$rs1))))), (CPOPW GPR:$rs1)>;
+
+def : Pat<(i64 (riscv_absw GPR:$rs1)),
+ (MAX GPR:$rs1, (SUBW X0, GPR:$rs1))>;
} // Predicates = [HasStdExtZbb, IsRV64]
let Predicates = [HasStdExtZbb] in {
diff --git a/llvm/test/CodeGen/RISCV/iabs.ll b/llvm/test/CodeGen/RISCV/iabs.ll
index 6f883353f1d9..9ab9290f0d37 100644
--- a/llvm/test/CodeGen/RISCV/iabs.ll
+++ b/llvm/test/CodeGen/RISCV/iabs.ll
@@ -178,7 +178,7 @@ define i32 @abs32(i32 %x) {
; RV64ZBB-LABEL: abs32:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: sext.w a0, a0
-; RV64ZBB-NEXT: neg a1, a0
+; RV64ZBB-NEXT: negw a1, a0
; RV64ZBB-NEXT: max a0, a0, a1
; RV64ZBB-NEXT: ret
%abs = tail call i32 @llvm.abs.i32(i32 %x, i1 true)
@@ -209,7 +209,7 @@ define i32 @select_abs32(i32 %x) {
; RV64ZBB-LABEL: select_abs32:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: sext.w a0, a0
-; RV64ZBB-NEXT: neg a1, a0
+; RV64ZBB-NEXT: negw a1, a0
; RV64ZBB-NEXT: max a0, a0, a1
; RV64ZBB-NEXT: ret
%1 = icmp slt i32 %x, 0
@@ -501,9 +501,9 @@ define i64 @zext_abs32(i32 %x) {
;
; RV64ZBB-LABEL: zext_abs32:
; RV64ZBB: # %bb.0:
-; RV64ZBB-NEXT: sext.w a1, a0
-; RV64ZBB-NEXT: negw a0, a0
-; RV64ZBB-NEXT: max a0, a1, a0
+; RV64ZBB-NEXT: sext.w a0, a0
+; RV64ZBB-NEXT: negw a1, a0
+; RV64ZBB-NEXT: max a0, a0, a1
; RV64ZBB-NEXT: ret
%abs = tail call i32 @llvm.abs.i32(i32 %x, i1 true)
%zext = zext i32 %abs to i64
diff --git a/llvm/test/CodeGen/RISCV/neg-abs.ll b/llvm/test/CodeGen/RISCV/neg-abs.ll
index 4659e7a17f23..723ab42cde62 100644
--- a/llvm/test/CodeGen/RISCV/neg-abs.ll
+++ b/llvm/test/CodeGen/RISCV/neg-abs.ll
@@ -187,7 +187,7 @@ define i32 @neg_abs32_multiuse(i32 %x, i32* %y) {
; RV64ZBB-LABEL: neg_abs32_multiuse:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: sext.w a0, a0
-; RV64ZBB-NEXT: neg a2, a0
+; RV64ZBB-NEXT: negw a2, a0
; RV64ZBB-NEXT: max a2, a0, a2
; RV64ZBB-NEXT: negw a0, a2
; RV64ZBB-NEXT: sw a2, 0(a1)
diff --git a/llvm/test/CodeGen/RISCV/rv64zbb.ll b/llvm/test/CodeGen/RISCV/rv64zbb.ll
index d5dc0ec5d6ac..d4ab229d5574 100644
--- a/llvm/test/CodeGen/RISCV/rv64zbb.ll
+++ b/llvm/test/CodeGen/RISCV/rv64zbb.ll
@@ -870,7 +870,7 @@ define i32 @abs_i32(i32 %x) {
; RV64ZBB-LABEL: abs_i32:
; RV64ZBB: # %bb.0:
; RV64ZBB-NEXT: sext.w a0, a0
-; RV64ZBB-NEXT: neg a1, a0
+; RV64ZBB-NEXT: negw a1, a0
; RV64ZBB-NEXT: max a0, a0, a1
; RV64ZBB-NEXT: ret
%abs = tail call i32 @llvm.abs.i32(i32 %x, i1 true)
More information about the llvm-commits
mailing list