Skip to content

Commit 25c43d8

Browse files
committed
[DAGCombiner] Turn (neg (max x, (neg x))) into (min x, (neg x))
We already have a rule to turn `(neg (abs x))` into `(min x, (neg x))`. But in some cases `(neg (max x, (neg x)))` is formed by an expanded `abs` followed by a `neg` that is only generated after the expansion. This patch adds a separate pattern to match this kind of cases.
1 parent abf6f85 commit 25c43d8

File tree

2 files changed

+18
-8
lines changed

2 files changed

+18
-8
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3949,6 +3949,20 @@ SDValue DAGCombiner::visitSUB(SDNode *N) {
39493949
if (SDValue Result = TLI.expandABS(N1.getNode(), DAG, true))
39503950
return Result;
39513951

3952+
// Similar to the previous rule, but this time targeting an expanded abs.
3953+
// (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
3954+
// Note that this is applicable to both signed and unsigned min/max.
3955+
SDValue X;
3956+
if (LegalOperations &&
3957+
sd_match(N1,
3958+
m_OneUse(m_AnyOf(m_SMax(m_Value(X), m_Neg(m_Deferred(X))),
3959+
m_UMax(m_Value(X), m_Neg(m_Deferred(X))))))) {
3960+
unsigned MinOpc = N1->getOpcode() == ISD::SMAX ? ISD::SMIN : ISD::UMIN;
3961+
if (hasOperation(MinOpc, VT))
3962+
return DAG.getNode(MinOpc, DL, VT, X,
3963+
DAG.getNode(ISD::SUB, DL, VT, N0, X));
3964+
}
3965+
39523966
// Fold neg(splat(neg(x)) -> splat(x)
39533967
if (VT.isVector()) {
39543968
SDValue N1S = DAG.getSplatValue(N1, true);

llvm/test/CodeGen/RISCV/neg-abs.ll

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -273,8 +273,7 @@ define i32 @expanded_neg_abs32(i32 %x) {
273273
; RV32ZBB-LABEL: expanded_neg_abs32:
274274
; RV32ZBB: # %bb.0:
275275
; RV32ZBB-NEXT: neg a1, a0
276-
; RV32ZBB-NEXT: max a0, a1, a0
277-
; RV32ZBB-NEXT: neg a0, a0
276+
; RV32ZBB-NEXT: min a0, a0, a1
278277
; RV32ZBB-NEXT: ret
279278
;
280279
; RV64I-LABEL: expanded_neg_abs32:
@@ -315,8 +314,7 @@ define i32 @expanded_neg_abs32_unsigned(i32 %x) {
315314
; RV32ZBB-LABEL: expanded_neg_abs32_unsigned:
316315
; RV32ZBB: # %bb.0:
317316
; RV32ZBB-NEXT: neg a1, a0
318-
; RV32ZBB-NEXT: maxu a0, a1, a0
319-
; RV32ZBB-NEXT: neg a0, a0
317+
; RV32ZBB-NEXT: minu a0, a0, a1
320318
; RV32ZBB-NEXT: ret
321319
;
322320
; RV64I-LABEL: expanded_neg_abs32_unsigned:
@@ -405,8 +403,7 @@ define i64 @expanded_neg_abs64(i64 %x) {
405403
; RV64ZBB-LABEL: expanded_neg_abs64:
406404
; RV64ZBB: # %bb.0:
407405
; RV64ZBB-NEXT: neg a1, a0
408-
; RV64ZBB-NEXT: max a0, a1, a0
409-
; RV64ZBB-NEXT: neg a0, a0
406+
; RV64ZBB-NEXT: min a0, a0, a1
410407
; RV64ZBB-NEXT: ret
411408
%n = sub i64 0, %x
412409
%t = call i64 @llvm.smax.i64(i64 %n, i64 %x)
@@ -476,8 +473,7 @@ define i64 @expanded_neg_abs64_unsigned(i64 %x) {
476473
; RV64ZBB-LABEL: expanded_neg_abs64_unsigned:
477474
; RV64ZBB: # %bb.0:
478475
; RV64ZBB-NEXT: neg a1, a0
479-
; RV64ZBB-NEXT: maxu a0, a1, a0
480-
; RV64ZBB-NEXT: neg a0, a0
476+
; RV64ZBB-NEXT: minu a0, a0, a1
481477
; RV64ZBB-NEXT: ret
482478
%n = sub i64 0, %x
483479
%t = call i64 @llvm.umax.i64(i64 %n, i64 %x)

0 commit comments

Comments
 (0)