Skip to content

Commit d6a9eec

Browse files
sunhodavemgreen
authored andcommitted
[AARCH64][DAGCombine] Add combine for negation of CSEL absolute value pattern.
This folds a negation through a csel, which can come up during the lowering of negative abs. Fixes #51558. Differential Revision: https://reviews.llvm.org/D112204
1 parent 9c72025 commit d6a9eec

File tree

3 files changed

+49
-8
lines changed

3 files changed

+49
-8
lines changed

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14893,6 +14893,49 @@ static SDValue performAddDotCombine(SDNode *N, SelectionDAG &DAG) {
1489314893
Dot.getOperand(2));
1489414894
}
1489514895

14896+
static bool isNegatedInteger(SDValue Op) {
14897+
return Op.getOpcode() == ISD::SUB && isNullConstant(Op.getOperand(0));
14898+
}
14899+
14900+
static SDValue getNegatedInteger(SDValue Op, SelectionDAG &DAG) {
14901+
SDLoc DL(Op);
14902+
EVT VT = Op.getValueType();
14903+
SDValue Zero = DAG.getConstant(0, DL, VT);
14904+
return DAG.getNode(ISD::SUB, DL, VT, Zero, Op);
14905+
}
14906+
14907+
// Try to fold
14908+
//
14909+
// (neg (csel X, Y)) -> (csel (neg X), (neg Y))
14910+
//
14911+
// The folding helps csel to be matched with csneg without generating
14912+
// redundant neg instruction, which includes negation of the csel expansion
14913+
// of abs node lowered by lowerABS.
14914+
static SDValue performNegCSelCombine(SDNode *N, SelectionDAG &DAG) {
14915+
if (!isNegatedInteger(SDValue(N, 0)))
14916+
return SDValue();
14917+
14918+
SDValue CSel = N->getOperand(1);
14919+
if (CSel.getOpcode() != AArch64ISD::CSEL || !CSel->hasOneUse())
14920+
return SDValue();
14921+
14922+
SDValue N0 = CSel.getOperand(0);
14923+
SDValue N1 = CSel.getOperand(1);
14924+
14925+
// If both of them is not negations, it's not worth the folding as it
14926+
// introduces two additional negations while reducing one negation.
14927+
if (!isNegatedInteger(N0) && !isNegatedInteger(N1))
14928+
return SDValue();
14929+
14930+
SDValue N0N = getNegatedInteger(N0, DAG);
14931+
SDValue N1N = getNegatedInteger(N1, DAG);
14932+
14933+
SDLoc DL(N);
14934+
EVT VT = CSel.getValueType();
14935+
return DAG.getNode(AArch64ISD::CSEL, DL, VT, N0N, N1N, CSel.getOperand(2),
14936+
CSel.getOperand(3));
14937+
}
14938+
1489614939
// The basic add/sub long vector instructions have variants with "2" on the end
1489714940
// which act on the high-half of their inputs. They are normally matched by
1489814941
// patterns like:
@@ -14956,6 +14999,8 @@ static SDValue performAddSubCombine(SDNode *N,
1495614999
return Val;
1495715000
if (SDValue Val = performAddCSelIntoCSinc(N, DAG))
1495815001
return Val;
15002+
if (SDValue Val = performNegCSelCombine(N, DAG))
15003+
return Val;
1495915004

1496015005
return performAddSubLongCombine(N, DCI, DAG);
1496115006
}

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ define i64 @neg_abs64(i64 %x) {
88
; CHECK-LABEL: neg_abs64:
99
; CHECK: // %bb.0:
1010
; CHECK-NEXT: cmp x0, #0
11-
; CHECK-NEXT: cneg x8, x0, mi
12-
; CHECK-NEXT: neg x0, x8
11+
; CHECK-NEXT: cneg x0, x0, pl
1312
; CHECK-NEXT: ret
1413
%abs = tail call i64 @llvm.abs.i64(i64 %x, i1 true)
1514
%neg = sub nsw i64 0, %abs
@@ -22,8 +21,7 @@ define i32 @neg_abs32(i32 %x) {
2221
; CHECK-LABEL: neg_abs32:
2322
; CHECK: // %bb.0:
2423
; CHECK-NEXT: cmp w0, #0
25-
; CHECK-NEXT: cneg w8, w0, mi
26-
; CHECK-NEXT: neg w0, w8
24+
; CHECK-NEXT: cneg w0, w0, pl
2725
; CHECK-NEXT: ret
2826
%abs = tail call i32 @llvm.abs.i32(i32 %x, i1 true)
2927
%neg = sub nsw i32 0, %abs

llvm/test/CodeGen/AArch64/neg-selects.ll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,7 @@ define i32 @neg_select_nega(i32 %a, i32 %b, i1 %bb) {
3131
; CHECK-LABEL: neg_select_nega:
3232
; CHECK: // %bb.0:
3333
; CHECK-NEXT: tst w2, #0x1
34-
; CHECK-NEXT: csneg w8, w1, w0, eq
35-
; CHECK-NEXT: neg w0, w8
34+
; CHECK-NEXT: csneg w0, w0, w1, ne
3635
; CHECK-NEXT: ret
3736
%nega = sub i32 0, %a
3837
%sel = select i1 %bb, i32 %nega, i32 %b
@@ -44,8 +43,7 @@ define i32 @neg_select_negb(i32 %a, i32 %b, i1 %bb) {
4443
; CHECK-LABEL: neg_select_negb:
4544
; CHECK: // %bb.0:
4645
; CHECK-NEXT: tst w2, #0x1
47-
; CHECK-NEXT: csneg w8, w0, w1, ne
48-
; CHECK-NEXT: neg w0, w8
46+
; CHECK-NEXT: csneg w0, w1, w0, eq
4947
; CHECK-NEXT: ret
5048
%negb = sub i32 0, %b
5149
%sel = select i1 %bb, i32 %a, i32 %negb

0 commit comments

Comments
 (0)