[llvm] r334553 - [DAGCombiner] Recognize more patterns for ABS

Krzysztof Parzyszek via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 12 14:51:49 PDT 2018


Author: kparzysz
Date: Tue Jun 12 14:51:49 2018
New Revision: 334553

URL: http://llvm.org/viewvc/llvm-project?rev=334553&view=rev
Log:
[DAGCombiner] Recognize more patterns for ABS

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

Modified:
    llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
    llvm/trunk/lib/Target/ARM/ARMInstrNEON.td
    llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp
    llvm/trunk/lib/Target/Hexagon/HexagonPatterns.td
    llvm/trunk/test/CodeGen/Hexagon/abs.ll

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=334553&r1=334552&r2=334553&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Tue Jun 12 14:51:49 2018
@@ -2555,6 +2555,20 @@ SDValue DAGCombiner::visitSUB(SDNode *N)
   if (N1.isUndef())
     return N1;
 
+  // fold Y = sra (X, size(X)-1); sub (xor (X, Y), Y) -> (abs X)
+  if (TLI.isOperationLegalOrCustom(ISD::ABS, VT)) {
+    if (N0.getOpcode() == ISD::XOR && N1.getOpcode() == ISD::SRA) {
+      SDValue X0 = N0.getOperand(0), X1 = N0.getOperand(1);
+      SDValue S0 = N1.getOperand(0);
+      if ((X0 == S0 && X1 == N1) || (X0 == N1 && X1 == S0)) {
+        unsigned OpSizeInBits = VT.getScalarSizeInBits();
+        if (ConstantSDNode *C = isConstOrConstSplat(N1.getOperand(1)))
+          if (C->getAPIntValue() == (OpSizeInBits - 1))
+            return DAG.getNode(ISD::ABS, SDLoc(N), VT, S0);
+      }
+    }
+  }
+
   // If the relocation model supports it, consider symbol offsets.
   if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(N0))
     if (!LegalOperations && TLI.isOffsetFoldingLegal(GA)) {
@@ -5660,13 +5674,19 @@ SDValue DAGCombiner::visitXOR(SDNode *N)
   }
 
   // fold Y = sra (X, size(X)-1); xor (add (X, Y), Y) -> (abs X)
-  unsigned OpSizeInBits = VT.getScalarSizeInBits();
-  if (N0.getOpcode() == ISD::ADD && N0.getOperand(1) == N1 &&
-      N1.getOpcode() == ISD::SRA && N1.getOperand(0) == N0.getOperand(0) &&
-      TLI.isOperationLegalOrCustom(ISD::ABS, VT)) {
-    if (ConstantSDNode *C = isConstOrConstSplat(N1.getOperand(1)))
-      if (C->getAPIntValue() == (OpSizeInBits - 1))
-        return DAG.getNode(ISD::ABS, SDLoc(N), VT, N0.getOperand(0));
+  if (TLI.isOperationLegalOrCustom(ISD::ABS, VT)) {
+    SDValue A = N0.getOpcode() == ISD::ADD ? N0 : N1;
+    SDValue S = N0.getOpcode() == ISD::SRA ? N0 : N1;
+    if (A.getOpcode() == ISD::ADD && S.getOpcode() == ISD::SRA) {
+      SDValue A0 = A.getOperand(0), A1 = A.getOperand(1);
+      SDValue S0 = S.getOperand(0);
+      if ((A0 == S && A1 == S0) || (A1 == S && A0 == S0)) {
+        unsigned OpSizeInBits = VT.getScalarSizeInBits();
+        if (ConstantSDNode *C = isConstOrConstSplat(S.getOperand(1)))
+          if (C->getAPIntValue() == (OpSizeInBits - 1))
+            return DAG.getNode(ISD::ABS, SDLoc(N), VT, S0);
+      }
+    }
   }
 
   // fold (xor x, x) -> 0

Modified: llvm/trunk/lib/Target/ARM/ARMInstrNEON.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrNEON.td?rev=334553&r1=334552&r2=334553&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrNEON.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrNEON.td Tue Jun 12 14:51:49 2018
@@ -5392,23 +5392,19 @@ defm VABDLs   : N3VLIntExt_QHS<0,1,0b011
 defm VABDLu   : N3VLIntExt_QHS<1,1,0b0111,0, IIC_VSUBi4Q,
                                "vabdl", "u", int_arm_neon_vabdu, zext, 1>;
 
+def : Pat<(v8i16 (abs (sub (zext (v8i8 DPR:$opA)), (zext (v8i8 DPR:$opB))))),
+          (VABDLuv8i16 DPR:$opA, DPR:$opB)>;
+def : Pat<(v4i32 (abs (sub (zext (v4i16 DPR:$opA)), (zext (v4i16 DPR:$opB))))),
+          (VABDLuv4i32 DPR:$opA, DPR:$opB)>;
+
+// ISD::ABS is not legal for v2i64, so VABDL needs to be matched from the
+// shift/xor pattern for ABS.
+
 def abd_shr :
     PatFrag<(ops node:$in1, node:$in2, node:$shift),
             (NEONvshrs (sub (zext node:$in1),
                             (zext node:$in2)), (i32 $shift))>;
 
-def : Pat<(xor (v4i32 (bitconvert (v8i16 (abd_shr (v8i8 DPR:$opA), (v8i8 DPR:$opB), 15)))),
-               (v4i32 (bitconvert (v8i16 (add (sub (zext (v8i8 DPR:$opA)),
-                                                   (zext (v8i8 DPR:$opB))),
-                                              (v8i16 (abd_shr (v8i8 DPR:$opA), (v8i8 DPR:$opB), 15))))))),
-          (VABDLuv8i16 DPR:$opA, DPR:$opB)>;
-
-def : Pat<(xor (v4i32 (abd_shr (v4i16 DPR:$opA), (v4i16 DPR:$opB), 31)),
-               (v4i32 (add (sub (zext (v4i16 DPR:$opA)),
-                                (zext (v4i16 DPR:$opB))),
-                           (abd_shr (v4i16 DPR:$opA), (v4i16 DPR:$opB), 31)))),
-          (VABDLuv4i32 DPR:$opA, DPR:$opB)>;
-
 def : Pat<(xor (v4i32 (bitconvert (v2i64 (abd_shr (v2i32 DPR:$opA), (v2i32 DPR:$opB), 63)))),
                (v4i32 (bitconvert (v2i64 (add (sub (zext (v2i32 DPR:$opA)),
                                                    (zext (v2i32 DPR:$opB))),

Modified: llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp?rev=334553&r1=334552&r2=334553&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp Tue Jun 12 14:51:49 2018
@@ -1327,6 +1327,9 @@ HexagonTargetLowering::HexagonTargetLowe
     setMinimumJumpTableEntries(std::numeric_limits<int>::max());
   setOperationAction(ISD::BR_JT, MVT::Other, Expand);
 
+  setOperationAction(ISD::ABS, MVT::i32, Legal);
+  setOperationAction(ISD::ABS, MVT::i64, Legal);
+
   // Hexagon has A4_addp_c and A4_subp_c that take and generate a carry bit,
   // but they only operate on i64.
   for (MVT VT : MVT::integer_valuetypes()) {

Modified: llvm/trunk/lib/Target/Hexagon/HexagonPatterns.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonPatterns.td?rev=334553&r1=334552&r2=334553&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonPatterns.td (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonPatterns.td Tue Jun 12 14:51:49 2018
@@ -1194,22 +1194,6 @@ let Predicates = [HasV5T] in {
                      (i32 (LoReg $Rs)))>;
 }
 
-let AddedComplexity = 50 in
-multiclass Abs_pat<InstHexagon MI, PatFrag RsPred, int Sh> {
-  // Let y = x >> 31 (for 32-bit), i.e. the sign bit repeated.
-  // abs(x) = (x + y) ^ y
-  def: Pat<(xor (add (sra RsPred:$Rs, (i32 Sh)), RsPred:$Rs),
-                (sra RsPred:$Rs, (i32 Sh))),
-           (MI RsPred:$Rs)>;
-  // abs(x) = (x ^ y) - y
-  def: Pat<(sub (xor RsPred:$Rs, (sra RsPred:$Rs, (i32 Sh))),
-                (sra RsPred:$Rs, (i32 Sh))),
-           (MI RsPred:$Rs)>;
-}
-
-defm: Abs_pat<A2_abs,  I32, 31>;
-defm: Abs_pat<A2_absp, I64, 63>;
-
 def: Pat<(add I32:$Rs, anyimm:$s16),   (A2_addi   I32:$Rs,  imm:$s16)>;
 def: Pat<(or  I32:$Rs, anyimm:$s10),   (A2_orir   I32:$Rs,  imm:$s10)>;
 def: Pat<(and I32:$Rs, anyimm:$s10),   (A2_andir  I32:$Rs,  imm:$s10)>;

Modified: llvm/trunk/test/CodeGen/Hexagon/abs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Hexagon/abs.ll?rev=334553&r1=334552&r2=334553&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Hexagon/abs.ll (original)
+++ llvm/trunk/test/CodeGen/Hexagon/abs.ll Tue Jun 12 14:51:49 2018
@@ -54,4 +54,30 @@ define i64 @f5(i64 %a0) #0 {
   ret i64 %v2
 }
 
-attributes #0 = { nounwind readnone "target-cpu"="hexagonv60" }
+; CHECK-LABEL: f6:
+; CHECK: r[[R60:[0-9]+]] = abs(r0)
+; CHECK: r[[R61:[0-9]+]] = asr(r0,#31)
+; CHECK: r0 = addasl(r[[R61]],r[[R60]],#1)
+define i32 @f6(i32 %a0) #0 {
+  %v0 = ashr i32 %a0, 31
+  %v1 = add i32 %a0, %v0
+  %v2 = xor i32 %v0, %v1
+  %v3 = mul i32 %v2, 2
+  %v4 = add i32 %v0, %v3
+  ret i32 %v4
+}
+
+; CHECK-LABEL: f7:
+; CHECK: r[[R70:[0-9]+]] = abs(r0)
+; CHECK: r[[R71:[0-9]+]] = asr(r0,#31)
+; CHECK: r0 = addasl(r[[R71]],r[[R70]],#1)
+define i32 @f7(i32 %a0) #0 {
+  %v0 = ashr i32 %a0, 31
+  %v1 = add i32 %v0, %a0
+  %v2 = xor i32 %v0, %v1
+  %v3 = shl i32 %v2, 1
+  %v4 = add i32 %v0, %v3
+  ret i32 %v4
+}
+
+attributes #0 = { nounwind readnone "target-cpu"="hexagonv60" "target-features"="-packets" }




More information about the llvm-commits mailing list