[llvm] c8bd534 - [DAGCombiner][RISCV] Pre-promote (zext (abs X)) to (abs (sext X)) when X has an illegal type.

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 13 10:41:42 PST 2023


Author: Craig Topper
Date: 2023-01-13T10:40:25-08:00
New Revision: c8bd5343df642f98966cea7aabc6b26144ec87e1

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

LOG: [DAGCombiner][RISCV] Pre-promote (zext (abs X)) to (abs (sext X)) when X has an illegal type.

Type legalization will insert a sign extend anyway. By doing it
early we can remove the zext. ComputeNumSignBits can't spot it
after type legalization because type legalization may expand
the abs to sra+xor+sub.

If the zext result type is larger than the type to be promoted to,
we'll promote to a legal type and then zext the rest of the way.
If the legal type is larger than the destination type we can promote
and then truncate.

Reviewed By: asb

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

Added: 
    

Modified: 
    llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
    llvm/test/CodeGen/RISCV/iabs.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 278d82c26b5f6..b8eb279ae7fe2 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -12602,6 +12602,33 @@ static SDValue widenCtPop(SDNode *Extend, SelectionDAG &DAG) {
   return DAG.getNode(ISD::CTPOP, DL, VT, NewZext);
 }
 
+// If we have (zext (abs X)) where X is a type that will be promoted by type
+// legalization, convert to (abs (sext X)). But don't extend past a legal type.
+static SDValue widenAbs(SDNode *Extend, SelectionDAG &DAG) {
+  assert(Extend->getOpcode() == ISD::ZERO_EXTEND && "Expected zero extend.");
+
+  EVT VT = Extend->getValueType(0);
+  if (VT.isVector())
+    return SDValue();
+
+  SDValue Abs = Extend->getOperand(0);
+  if (Abs.getOpcode() != ISD::ABS || !Abs.hasOneUse())
+    return SDValue();
+
+  EVT AbsVT = Abs.getValueType();
+  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+  if (TLI.getTypeAction(*DAG.getContext(), AbsVT) !=
+      TargetLowering::TypePromoteInteger)
+    return SDValue();
+
+  EVT LegalVT = TLI.getTypeToTransformTo(*DAG.getContext(), AbsVT);
+
+  SDValue SExt =
+      DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Abs), LegalVT, Abs.getOperand(0));
+  SDValue NewAbs = DAG.getNode(ISD::ABS, SDLoc(Abs), LegalVT, SExt);
+  return DAG.getZExtOrTrunc(NewAbs, SDLoc(Extend), VT);
+}
+
 SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
   SDValue N0 = N->getOperand(0);
   EVT VT = N->getValueType(0);
@@ -12866,6 +12893,9 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
   if (SDValue NewCtPop = widenCtPop(N, DAG))
     return NewCtPop;
 
+  if (SDValue V = widenAbs(N, DAG))
+    return V;
+
   if (SDValue Res = tryToFoldExtendSelectLoad(N, TLI, DAG))
     return Res;
 

diff  --git a/llvm/test/CodeGen/RISCV/iabs.ll b/llvm/test/CodeGen/RISCV/iabs.ll
index 5c7636d15906a..7a1d57ecad3d8 100644
--- a/llvm/test/CodeGen/RISCV/iabs.ll
+++ b/llvm/test/CodeGen/RISCV/iabs.ll
@@ -513,32 +513,28 @@ define i64 @zext_abs32(i32 %x) {
 define signext i32 @zext_abs8(i8 signext %x) {
 ; RV32I-LABEL: zext_abs8:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    srai a1, a0, 7
+; RV32I-NEXT:    srai a1, a0, 31
 ; RV32I-NEXT:    xor a0, a0, a1
 ; RV32I-NEXT:    sub a0, a0, a1
-; RV32I-NEXT:    andi a0, a0, 255
 ; RV32I-NEXT:    ret
 ;
 ; RV32ZBB-LABEL: zext_abs8:
 ; RV32ZBB:       # %bb.0:
 ; RV32ZBB-NEXT:    neg a1, a0
 ; RV32ZBB-NEXT:    max a0, a0, a1
-; RV32ZBB-NEXT:    andi a0, a0, 255
 ; RV32ZBB-NEXT:    ret
 ;
 ; RV64I-LABEL: zext_abs8:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srai a1, a0, 7
+; RV64I-NEXT:    srai a1, a0, 63
 ; RV64I-NEXT:    xor a0, a0, a1
-; RV64I-NEXT:    subw a0, a0, a1
-; RV64I-NEXT:    andi a0, a0, 255
+; RV64I-NEXT:    sub a0, a0, a1
 ; RV64I-NEXT:    ret
 ;
 ; RV64ZBB-LABEL: zext_abs8:
 ; RV64ZBB:       # %bb.0:
 ; RV64ZBB-NEXT:    neg a1, a0
 ; RV64ZBB-NEXT:    max a0, a0, a1
-; RV64ZBB-NEXT:    andi a0, a0, 255
 ; RV64ZBB-NEXT:    ret
   %a = call i8 @llvm.abs.i8(i8 %x, i1 false)
   %b = zext i8 %a to i32
@@ -548,34 +544,28 @@ define signext i32 @zext_abs8(i8 signext %x) {
 define signext i32 @zext_abs16(i16 signext %x) {
 ; RV32I-LABEL: zext_abs16:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    srai a1, a0, 15
+; RV32I-NEXT:    srai a1, a0, 31
 ; RV32I-NEXT:    xor a0, a0, a1
 ; RV32I-NEXT:    sub a0, a0, a1
-; RV32I-NEXT:    slli a0, a0, 16
-; RV32I-NEXT:    srli a0, a0, 16
 ; RV32I-NEXT:    ret
 ;
 ; RV32ZBB-LABEL: zext_abs16:
 ; RV32ZBB:       # %bb.0:
 ; RV32ZBB-NEXT:    neg a1, a0
 ; RV32ZBB-NEXT:    max a0, a0, a1
-; RV32ZBB-NEXT:    zext.h a0, a0
 ; RV32ZBB-NEXT:    ret
 ;
 ; RV64I-LABEL: zext_abs16:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srai a1, a0, 15
+; RV64I-NEXT:    srai a1, a0, 63
 ; RV64I-NEXT:    xor a0, a0, a1
-; RV64I-NEXT:    subw a0, a0, a1
-; RV64I-NEXT:    slli a0, a0, 48
-; RV64I-NEXT:    srli a0, a0, 48
+; RV64I-NEXT:    sub a0, a0, a1
 ; RV64I-NEXT:    ret
 ;
 ; RV64ZBB-LABEL: zext_abs16:
 ; RV64ZBB:       # %bb.0:
 ; RV64ZBB-NEXT:    neg a1, a0
 ; RV64ZBB-NEXT:    max a0, a0, a1
-; RV64ZBB-NEXT:    zext.h a0, a0
 ; RV64ZBB-NEXT:    ret
   %a = call i16 @llvm.abs.i16(i16 %x, i1 false)
   %b = zext i16 %a to i32
@@ -585,10 +575,9 @@ define signext i32 @zext_abs16(i16 signext %x) {
 define i64 @zext64_abs8(i8 signext %x) {
 ; RV32I-LABEL: zext64_abs8:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    srai a1, a0, 7
+; RV32I-NEXT:    srai a1, a0, 31
 ; RV32I-NEXT:    xor a0, a0, a1
 ; RV32I-NEXT:    sub a0, a0, a1
-; RV32I-NEXT:    andi a0, a0, 255
 ; RV32I-NEXT:    li a1, 0
 ; RV32I-NEXT:    ret
 ;
@@ -596,23 +585,20 @@ define i64 @zext64_abs8(i8 signext %x) {
 ; RV32ZBB:       # %bb.0:
 ; RV32ZBB-NEXT:    neg a1, a0
 ; RV32ZBB-NEXT:    max a0, a0, a1
-; RV32ZBB-NEXT:    andi a0, a0, 255
 ; RV32ZBB-NEXT:    li a1, 0
 ; RV32ZBB-NEXT:    ret
 ;
 ; RV64I-LABEL: zext64_abs8:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srai a1, a0, 7
+; RV64I-NEXT:    srai a1, a0, 63
 ; RV64I-NEXT:    xor a0, a0, a1
-; RV64I-NEXT:    subw a0, a0, a1
-; RV64I-NEXT:    andi a0, a0, 255
+; RV64I-NEXT:    sub a0, a0, a1
 ; RV64I-NEXT:    ret
 ;
 ; RV64ZBB-LABEL: zext64_abs8:
 ; RV64ZBB:       # %bb.0:
 ; RV64ZBB-NEXT:    neg a1, a0
 ; RV64ZBB-NEXT:    max a0, a0, a1
-; RV64ZBB-NEXT:    andi a0, a0, 255
 ; RV64ZBB-NEXT:    ret
   %a = call i8 @llvm.abs.i8(i8 %x, i1 false)
   %b = zext i8 %a to i64
@@ -622,11 +608,9 @@ define i64 @zext64_abs8(i8 signext %x) {
 define i64 @zext64_abs16(i16 signext %x) {
 ; RV32I-LABEL: zext64_abs16:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    srai a1, a0, 15
+; RV32I-NEXT:    srai a1, a0, 31
 ; RV32I-NEXT:    xor a0, a0, a1
 ; RV32I-NEXT:    sub a0, a0, a1
-; RV32I-NEXT:    slli a0, a0, 16
-; RV32I-NEXT:    srli a0, a0, 16
 ; RV32I-NEXT:    li a1, 0
 ; RV32I-NEXT:    ret
 ;
@@ -634,24 +618,20 @@ define i64 @zext64_abs16(i16 signext %x) {
 ; RV32ZBB:       # %bb.0:
 ; RV32ZBB-NEXT:    neg a1, a0
 ; RV32ZBB-NEXT:    max a0, a0, a1
-; RV32ZBB-NEXT:    zext.h a0, a0
 ; RV32ZBB-NEXT:    li a1, 0
 ; RV32ZBB-NEXT:    ret
 ;
 ; RV64I-LABEL: zext64_abs16:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    srai a1, a0, 15
+; RV64I-NEXT:    srai a1, a0, 63
 ; RV64I-NEXT:    xor a0, a0, a1
-; RV64I-NEXT:    subw a0, a0, a1
-; RV64I-NEXT:    slli a0, a0, 48
-; RV64I-NEXT:    srli a0, a0, 48
+; RV64I-NEXT:    sub a0, a0, a1
 ; RV64I-NEXT:    ret
 ;
 ; RV64ZBB-LABEL: zext64_abs16:
 ; RV64ZBB:       # %bb.0:
 ; RV64ZBB-NEXT:    neg a1, a0
 ; RV64ZBB-NEXT:    max a0, a0, a1
-; RV64ZBB-NEXT:    zext.h a0, a0
 ; RV64ZBB-NEXT:    ret
   %a = call i16 @llvm.abs.i16(i16 %x, i1 false)
   %b = zext i16 %a to i64
@@ -661,11 +641,11 @@ define i64 @zext64_abs16(i16 signext %x) {
 define void @zext16_abs8(i8 %x, ptr %p) {
 ; RV32I-LABEL: zext16_abs8:
 ; RV32I:       # %bb.0:
-; RV32I-NEXT:    slli a2, a0, 24
-; RV32I-NEXT:    srai a2, a2, 31
+; RV32I-NEXT:    slli a0, a0, 24
+; RV32I-NEXT:    srai a0, a0, 24
+; RV32I-NEXT:    srai a2, a0, 31
 ; RV32I-NEXT:    xor a0, a0, a2
 ; RV32I-NEXT:    sub a0, a0, a2
-; RV32I-NEXT:    andi a0, a0, 255
 ; RV32I-NEXT:    sh a0, 0(a1)
 ; RV32I-NEXT:    ret
 ;
@@ -674,17 +654,16 @@ define void @zext16_abs8(i8 %x, ptr %p) {
 ; RV32ZBB-NEXT:    sext.b a0, a0
 ; RV32ZBB-NEXT:    neg a2, a0
 ; RV32ZBB-NEXT:    max a0, a0, a2
-; RV32ZBB-NEXT:    andi a0, a0, 255
 ; RV32ZBB-NEXT:    sh a0, 0(a1)
 ; RV32ZBB-NEXT:    ret
 ;
 ; RV64I-LABEL: zext16_abs8:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    slli a2, a0, 56
-; RV64I-NEXT:    srai a2, a2, 63
+; RV64I-NEXT:    slli a0, a0, 56
+; RV64I-NEXT:    srai a0, a0, 56
+; RV64I-NEXT:    srai a2, a0, 63
 ; RV64I-NEXT:    xor a0, a0, a2
 ; RV64I-NEXT:    subw a0, a0, a2
-; RV64I-NEXT:    andi a0, a0, 255
 ; RV64I-NEXT:    sh a0, 0(a1)
 ; RV64I-NEXT:    ret
 ;
@@ -693,7 +672,6 @@ define void @zext16_abs8(i8 %x, ptr %p) {
 ; RV64ZBB-NEXT:    sext.b a0, a0
 ; RV64ZBB-NEXT:    neg a2, a0
 ; RV64ZBB-NEXT:    max a0, a0, a2
-; RV64ZBB-NEXT:    andi a0, a0, 255
 ; RV64ZBB-NEXT:    sh a0, 0(a1)
 ; RV64ZBB-NEXT:    ret
   %a = call i8 @llvm.abs.i8(i8 %x, i1 false)


        


More information about the llvm-commits mailing list