[llvm] d6a9eec - [AARCH64][DAGCombine] Add combine for negation of CSEL absolute value pattern.

David Green via llvm-commits llvm-commits at lists.llvm.org
Tue Feb 22 01:59:41 PST 2022


Author: Sunho Kim
Date: 2022-02-22T09:59:36Z
New Revision: d6a9eec2382559aeae3bb87761afa1b6d351e9a5

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

LOG: [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 https://github.com/llvm/llvm-project/issues/51558.

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

Added: 
    

Modified: 
    llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
    llvm/test/CodeGen/AArch64/neg-abs.ll
    llvm/test/CodeGen/AArch64/neg-selects.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 30d30e88f2740..5678029be376e 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -14893,6 +14893,49 @@ static SDValue performAddDotCombine(SDNode *N, SelectionDAG &DAG) {
                      Dot.getOperand(2));
 }
 
+static bool isNegatedInteger(SDValue Op) {
+  return Op.getOpcode() == ISD::SUB && isNullConstant(Op.getOperand(0));
+}
+
+static SDValue getNegatedInteger(SDValue Op, SelectionDAG &DAG) {
+  SDLoc DL(Op);
+  EVT VT = Op.getValueType();
+  SDValue Zero = DAG.getConstant(0, DL, VT);
+  return DAG.getNode(ISD::SUB, DL, VT, Zero, Op);
+}
+
+// Try to fold
+//
+// (neg (csel X, Y)) -> (csel (neg X), (neg Y))
+//
+// The folding helps csel to be matched with csneg without generating
+// redundant neg instruction, which includes negation of the csel expansion
+// of abs node lowered by lowerABS.
+static SDValue performNegCSelCombine(SDNode *N, SelectionDAG &DAG) {
+  if (!isNegatedInteger(SDValue(N, 0)))
+    return SDValue();
+
+  SDValue CSel = N->getOperand(1);
+  if (CSel.getOpcode() != AArch64ISD::CSEL || !CSel->hasOneUse())
+    return SDValue();
+
+  SDValue N0 = CSel.getOperand(0);
+  SDValue N1 = CSel.getOperand(1);
+
+  // If both of them is not negations, it's not worth the folding as it
+  // introduces two additional negations while reducing one negation.
+  if (!isNegatedInteger(N0) && !isNegatedInteger(N1))
+    return SDValue();
+
+  SDValue N0N = getNegatedInteger(N0, DAG);
+  SDValue N1N = getNegatedInteger(N1, DAG);
+
+  SDLoc DL(N);
+  EVT VT = CSel.getValueType();
+  return DAG.getNode(AArch64ISD::CSEL, DL, VT, N0N, N1N, CSel.getOperand(2),
+                     CSel.getOperand(3));
+}
+
 // The basic add/sub long vector instructions have variants with "2" on the end
 // which act on the high-half of their inputs. They are normally matched by
 // patterns like:
@@ -14956,6 +14999,8 @@ static SDValue performAddSubCombine(SDNode *N,
     return Val;
   if (SDValue Val = performAddCSelIntoCSinc(N, DAG))
     return Val;
+  if (SDValue Val = performNegCSelCombine(N, DAG))
+    return Val;
 
   return performAddSubLongCombine(N, DCI, DAG);
 }

diff  --git a/llvm/test/CodeGen/AArch64/neg-abs.ll b/llvm/test/CodeGen/AArch64/neg-abs.ll
index 71a320e98398a..7f691c9b694c4 100644
--- a/llvm/test/CodeGen/AArch64/neg-abs.ll
+++ b/llvm/test/CodeGen/AArch64/neg-abs.ll
@@ -8,8 +8,7 @@ define i64 @neg_abs64(i64 %x) {
 ; CHECK-LABEL: neg_abs64:
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    cmp x0, #0
-; CHECK-NEXT:    cneg x8, x0, mi
-; CHECK-NEXT:    neg x0, x8
+; CHECK-NEXT:    cneg x0, x0, pl
 ; CHECK-NEXT:    ret
   %abs = tail call i64 @llvm.abs.i64(i64 %x, i1 true)
   %neg = sub nsw i64 0, %abs
@@ -22,8 +21,7 @@ define i32 @neg_abs32(i32 %x) {
 ; CHECK-LABEL: neg_abs32:
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    cmp w0, #0
-; CHECK-NEXT:    cneg w8, w0, mi
-; CHECK-NEXT:    neg w0, w8
+; CHECK-NEXT:    cneg w0, w0, pl
 ; CHECK-NEXT:    ret
   %abs = tail call i32 @llvm.abs.i32(i32 %x, i1 true)
   %neg = sub nsw i32 0, %abs

diff  --git a/llvm/test/CodeGen/AArch64/neg-selects.ll b/llvm/test/CodeGen/AArch64/neg-selects.ll
index e0f0efdcc2d3f..114300a79b909 100644
--- a/llvm/test/CodeGen/AArch64/neg-selects.ll
+++ b/llvm/test/CodeGen/AArch64/neg-selects.ll
@@ -31,8 +31,7 @@ define i32 @neg_select_nega(i32 %a, i32 %b, i1 %bb) {
 ; CHECK-LABEL: neg_select_nega:
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    tst w2, #0x1
-; CHECK-NEXT:    csneg w8, w1, w0, eq
-; CHECK-NEXT:    neg w0, w8
+; CHECK-NEXT:    csneg w0, w0, w1, ne
 ; CHECK-NEXT:    ret
   %nega = sub i32 0, %a
   %sel = select i1 %bb, i32 %nega, i32 %b
@@ -44,8 +43,7 @@ define i32 @neg_select_negb(i32 %a, i32 %b, i1 %bb) {
 ; CHECK-LABEL: neg_select_negb:
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    tst w2, #0x1
-; CHECK-NEXT:    csneg w8, w0, w1, ne
-; CHECK-NEXT:    neg w0, w8
+; CHECK-NEXT:    csneg w0, w1, w0, eq
 ; CHECK-NEXT:    ret
   %negb = sub i32 0, %b
   %sel = select i1 %bb, i32 %a, i32 %negb


        


More information about the llvm-commits mailing list