[llvm] f468907 - [RISCV] Custom type legalize i32 ISD::ABS on RV64 without Zbb.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 28 09:40:12 PST 2022


Author: Craig Topper
Date: 2022-02-28T09:30:27-08:00
New Revision: f46890711f03dfb02722ec18dc332753967700e8

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

LOG: [RISCV] Custom type legalize i32 ISD::ABS on RV64 without Zbb.

Default type legalization will create sext_inreg+abs, but we may
not be able to remove the sext_inreg.

Instead this patch expands abs during type legalization to
Y = sraiw X, 31; subw(xor X, Y), Y) which doesn't require the input
to be sign extended.

This gives a big improvement for some neg-abs tests where the
abs is used more than the the neg. Previously the abs was expanded
a different way before and after type legalization. Now they are
expanded in a similar way enabling more CSE.

Reviewed By: asb

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

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVISelLowering.cpp
    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 ebcf3f8dea425..6261b6a5aee80 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -303,6 +303,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::CTTZ, XLenVT, Expand);
     setOperationAction(ISD::CTLZ, XLenVT, Expand);
     setOperationAction(ISD::CTPOP, XLenVT, Expand);
+
+    if (Subtarget.is64Bit())
+      setOperationAction(ISD::ABS, MVT::i32, Custom);
   }
 
   if (Subtarget.hasStdExtZbt()) {
@@ -6622,6 +6625,34 @@ void RISCVTargetLowering::ReplaceNodeResults(SDNode *N,
     Results.push_back(expandAddSubSat(N, DAG));
     return;
   }
+  case ISD::ABS: {
+    assert(N->getValueType(0) == MVT::i32 && Subtarget.is64Bit() &&
+           "Unexpected custom legalisation");
+          DAG.getNode(ISD::SIGN_EXTEND, DL, MVT::i64, N->getOperand(0));
+
+    // 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.
+    Src = DAG.getFreeze(Src);
+
+    // Copy sign bit to all bits using the sraiw pattern.
+    SDValue SignFill = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, Src,
+                                   DAG.getValueType(MVT::i32));
+    SignFill = DAG.getNode(ISD::SRA, DL, MVT::i64, SignFill,
+                           DAG.getConstant(31, DL, MVT::i64));
+
+    SDValue NewRes = DAG.getNode(ISD::XOR, DL, MVT::i64, Src, SignFill);
+    NewRes = DAG.getNode(ISD::SUB, DL, MVT::i64, NewRes, SignFill);
+
+    // NOTE: The result is only required to be anyextended, but sext is
+    // consistent with type legalization of sub.
+    NewRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i64, NewRes,
+                         DAG.getValueType(MVT::i32));
+    Results.push_back(DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, NewRes));
+    return;
+  }
   case ISD::BITCAST: {
     EVT VT = N->getValueType(0);
     assert(VT.isInteger() && !VT.isVector() && "Unexpected VT!");

diff  --git a/llvm/test/CodeGen/RISCV/neg-abs.ll b/llvm/test/CodeGen/RISCV/neg-abs.ll
index 2651db6f4653b..9dfa533ebcadc 100644
--- a/llvm/test/CodeGen/RISCV/neg-abs.ll
+++ b/llvm/test/CodeGen/RISCV/neg-abs.ll
@@ -255,15 +255,11 @@ define i32 @neg_abs32_multiuse(i32 %x, i32* %y) {
 ;
 ; RV64I-LABEL: neg_abs32_multiuse:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sext.w a3, a0
 ; RV64I-NEXT:    sraiw a2, a0, 31
-; RV64I-NEXT:    xor a4, a0, a2
-; RV64I-NEXT:    subw a2, a2, a4
-; RV64I-NEXT:    srai a3, a3, 63
-; RV64I-NEXT:    xor a0, a0, a3
-; RV64I-NEXT:    subw a0, a0, a3
-; RV64I-NEXT:    sw a0, 0(a1)
-; RV64I-NEXT:    mv a0, a2
+; RV64I-NEXT:    xor a3, a0, a2
+; RV64I-NEXT:    subw a0, a2, a3
+; RV64I-NEXT:    subw a2, a3, a2
+; RV64I-NEXT:    sw a2, 0(a1)
 ; RV64I-NEXT:    ret
 ;
 ; RV64ZBB-LABEL: neg_abs32_multiuse:
@@ -279,15 +275,11 @@ define i32 @neg_abs32_multiuse(i32 %x, i32* %y) {
 ;
 ; RV64IBT-LABEL: neg_abs32_multiuse:
 ; RV64IBT:       # %bb.0:
-; RV64IBT-NEXT:    sext.w a3, a0
 ; RV64IBT-NEXT:    sraiw a2, a0, 31
-; RV64IBT-NEXT:    xor a4, a0, a2
-; RV64IBT-NEXT:    subw a2, a2, a4
-; RV64IBT-NEXT:    srai a3, a3, 63
-; RV64IBT-NEXT:    xor a0, a0, a3
-; RV64IBT-NEXT:    subw a0, a0, a3
-; RV64IBT-NEXT:    sw a0, 0(a1)
-; RV64IBT-NEXT:    mv a0, a2
+; RV64IBT-NEXT:    xor a3, a0, a2
+; RV64IBT-NEXT:    subw a0, a2, a3
+; RV64IBT-NEXT:    subw a2, a3, a2
+; RV64IBT-NEXT:    sw a2, 0(a1)
 ; RV64IBT-NEXT:    ret
   %abs = tail call i32 @llvm.abs.i32(i32 %x, i1 true)
   store i32 %abs, i32* %y

diff  --git a/llvm/test/CodeGen/RISCV/rv64zbb.ll b/llvm/test/CodeGen/RISCV/rv64zbb.ll
index 0127ac4d33a5b..1b5396e8592a0 100644
--- a/llvm/test/CodeGen/RISCV/rv64zbb.ll
+++ b/llvm/test/CodeGen/RISCV/rv64zbb.ll
@@ -945,10 +945,9 @@ declare i32 @llvm.abs.i32(i32, i1 immarg)
 define i32 @abs_i32(i32 %x) {
 ; RV64I-LABEL: abs_i32:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    sext.w a0, a0
-; RV64I-NEXT:    srai a1, a0, 63
+; RV64I-NEXT:    sraiw a1, a0, 31
 ; RV64I-NEXT:    xor a0, a0, a1
-; RV64I-NEXT:    sub a0, a0, a1
+; RV64I-NEXT:    subw a0, a0, a1
 ; RV64I-NEXT:    ret
 ;
 ; RV64ZBB-LABEL: abs_i32:
@@ -965,7 +964,7 @@ define i32 @abs_i32(i32 %x) {
 define signext i32 @abs_i32_sext(i32 signext %x) {
 ; RV64I-LABEL: abs_i32_sext:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srai a1, a0, 63
+; RV64I-NEXT:    sraiw a1, a0, 31
 ; RV64I-NEXT:    xor a0, a0, a1
 ; RV64I-NEXT:    subw a0, a0, a1
 ; RV64I-NEXT:    ret


        


More information about the llvm-commits mailing list