[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