From dde8423f21fb09c77b83d1ec50d5fff6bb940586 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Mon, 14 Nov 2022 19:37:04 -0800 Subject: [PATCH] [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. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 46 +++++++++++------------------ llvm/lib/Target/RISCV/RISCVISelLowering.h | 4 +++ llvm/lib/Target/RISCV/RISCVInstrInfoZb.td | 4 +++ llvm/test/CodeGen/RISCV/iabs.ll | 10 +++---- llvm/test/CodeGen/RISCV/neg-abs.ll | 2 +- llvm/test/CodeGen/RISCV/rv64zbb.ll | 2 +- 6 files changed, 32 insertions(+), 36 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 687a89e..287800b 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(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 4f07d9e..a02107e 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 bb38c6f..3ea19ea 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; def : PatGpr; 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 6f88335..9ab9290 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 4659e7a..723ab42 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 d5dc0ec..d4ab229 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) -- 2.7.4