[AArch64] lower abs intrinsic to new ABS instruction in SelDag
authorTies Stuij <ties.stuij@arm.com>
Tue, 6 Dec 2022 10:44:05 +0000 (10:44 +0000)
committerTies Stuij <ties@stuij.se>
Tue, 6 Dec 2022 10:48:21 +0000 (10:48 +0000)
When feature CSSC is available, the SelectionDag abs intrinsic should map to the
new scalar ABS instruction.

Additionally, the SIMDTwoScalarD tablegen defm includes a pattern match for
scalar i64, which we don't want to use when CSSC is enabled.

spec:
https://developer.arm.com/documentation/ddi0602/2022-09/Base-Instructions/ABS--Absolute-value-

Reviewed By: lenary

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

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
llvm/lib/Target/AArch64/AArch64InstrFormats.td
llvm/lib/Target/AArch64/AArch64InstrInfo.td
llvm/test/CodeGen/AArch64/iabs.ll

index a3b82d0..862ed37 100644 (file)
@@ -545,10 +545,15 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
     setOperationAction(ISD::CTPOP, MVT::i32, Legal);
     setOperationAction(ISD::CTPOP, MVT::i64, Legal);
     setOperationAction(ISD::CTPOP, MVT::i128, Expand);
+
     setOperationAction(ISD::PARITY, MVT::i128, Expand);
+
     setOperationAction(ISD::CTTZ, MVT::i32, Legal);
     setOperationAction(ISD::CTTZ, MVT::i64, Legal);
     setOperationAction(ISD::CTTZ, MVT::i128, Expand);
+
+    setOperationAction(ISD::ABS, MVT::i32, Legal);
+    setOperationAction(ISD::ABS, MVT::i64, Legal);
   } else {
     setOperationAction(ISD::CTPOP, MVT::i32, Custom);
     setOperationAction(ISD::CTPOP, MVT::i64, Custom);
@@ -556,10 +561,10 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
 
     setOperationAction(ISD::PARITY, MVT::i64, Custom);
     setOperationAction(ISD::PARITY, MVT::i128, Custom);
-  }
 
-  setOperationAction(ISD::ABS, MVT::i32, Custom);
-  setOperationAction(ISD::ABS, MVT::i64, Custom);
+    setOperationAction(ISD::ABS, MVT::i32, Custom);
+    setOperationAction(ISD::ABS, MVT::i64, Custom);
+  }
 
   setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
   setOperationAction(ISD::SDIVREM, MVT::i64, Expand);
index ee3761f..016563c 100644 (file)
@@ -7265,12 +7265,15 @@ multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
 }
 
 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
-                          SDPatternOperator OpNode = null_frag> {
+                          SDPatternOperator OpNode = null_frag,
+                          list<Predicate> preds = []> {
   def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
 
+  let Predicates = preds in {
   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
+  }
 }
 
 let mayRaiseFPException = 1, Uses = [FPCR] in
index 409c9a9..55f88f4 100644 (file)
@@ -115,8 +115,9 @@ def HasDotProd       : Predicate<"Subtarget->hasDotProd()">,
                                  AssemblerPredicateWithAll<(all_of FeatureDotProd), "dotprod">;
 def HasCRC           : Predicate<"Subtarget->hasCRC()">,
                                  AssemblerPredicateWithAll<(all_of FeatureCRC), "crc">;
-def HasCSSC           : Predicate<"Subtarget->hasCSSC()">,
+def HasCSSC          : Predicate<"Subtarget->hasCSSC()">,
                                  AssemblerPredicateWithAll<(all_of FeatureCSSC), "cssc">;
+def HasNoCSSC        : Predicate<"!Subtarget->hasCSSC()">;
 def HasLSE           : Predicate<"Subtarget->hasLSE()">,
                                  AssemblerPredicateWithAll<(all_of FeatureLSE), "lse">;
 def HasNoLSE         : Predicate<"!Subtarget->hasLSE()">;
@@ -5092,7 +5093,7 @@ def : Pat<(i64 (int_aarch64_neon_sqsub (i64 FPR64:$Rd),
 // Advanced SIMD two scalar instructions.
 //===----------------------------------------------------------------------===//
 
-defm ABS    : SIMDTwoScalarD<    0, 0b01011, "abs", abs>;
+defm ABS    : SIMDTwoScalarD<    0, 0b01011, "abs", abs, [HasNoCSSC]>;
 defm CMEQ   : SIMDCmpTwoScalarD< 0, 0b01001, "cmeq", AArch64cmeqz>;
 defm CMGE   : SIMDCmpTwoScalarD< 1, 0b01000, "cmge", AArch64cmgez>;
 defm CMGT   : SIMDCmpTwoScalarD< 0, 0b01000, "cmgt", AArch64cmgtz>;
@@ -8554,7 +8555,7 @@ defm RCWSWP  : ReadCheckWriteOperation<0b010, "swp">;
 //===----------------------------------------------------------------------===//
 // General Data-Processing Instructions (FEAT_V94_DP)
 //===----------------------------------------------------------------------===//
-defm ABS : OneOperandData<0b001000, "abs">, Requires<[HasCSSC]>;
+defm ABS : OneOperandData<0b001000, "abs", abs>, Requires<[HasCSSC]>;
 defm CNT : OneOperandData<0b000111, "cnt", ctpop>, Requires<[HasCSSC]>;
 defm CTZ : OneOperandData<0b000110, "ctz", cttz>, Requires<[HasCSSC]>;
 
index dbcd922..bbb04c7 100644 (file)
@@ -1,12 +1,20 @@
-; RUN: llc < %s -mtriple=arm64-eabi -aarch64-neon-syntax=apple | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=arm64-eabi | FileCheck %s
+; RUN: llc < %s -mtriple=arm64-eabi -mattr=+cssc | FileCheck %s -check-prefix=CHECK-CSSC
 
 define i8 @test_i8(i8 %a) nounwind {
 ; CHECK-LABEL: test_i8:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:  sxtb w8, w0
-; CHECK-NEXT:  cmp w8, #0
-; CHECK-NEXT:  cneg w0, w8, mi
-; CHECK-NEXT:  ret
+; CHECK-NEXT:    sxtb w8, w0
+; CHECK-NEXT:    cmp w8, #0
+; CHECK-NEXT:    cneg w0, w8, mi
+; CHECK-NEXT:    ret
+;
+; CHECK-CSSC-LABEL: test_i8:
+; CHECK-CSSC:       // %bb.0:
+; CHECK-CSSC-NEXT:    sxtb w8, w0
+; CHECK-CSSC-NEXT:    abs w0, w8
+; CHECK-CSSC-NEXT:    ret
   %tmp1neg = sub i8 0, %a
   %b = icmp sgt i8 %a, -1
   %abs = select i1 %b, i8 %a, i8 %tmp1neg
@@ -16,10 +24,16 @@ define i8 @test_i8(i8 %a) nounwind {
 define i16 @test_i16(i16 %a) nounwind {
 ; CHECK-LABEL: test_i16:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:  sxth w8, w0
-; CHECK-NEXT:  cmp w8, #0
-; CHECK-NEXT:  cneg w0, w8, mi
-; CHECK-NEXT:  ret
+; CHECK-NEXT:    sxth w8, w0
+; CHECK-NEXT:    cmp w8, #0
+; CHECK-NEXT:    cneg w0, w8, mi
+; CHECK-NEXT:    ret
+;
+; CHECK-CSSC-LABEL: test_i16:
+; CHECK-CSSC:       // %bb.0:
+; CHECK-CSSC-NEXT:    sxth w8, w0
+; CHECK-CSSC-NEXT:    abs w0, w8
+; CHECK-CSSC-NEXT:    ret
   %tmp1neg = sub i16 0, %a
   %b = icmp sgt i16 %a, -1
   %abs = select i1 %b, i16 %a, i16 %tmp1neg
@@ -29,9 +43,14 @@ define i16 @test_i16(i16 %a) nounwind {
 define i32 @test_i32(i32 %a) nounwind {
 ; CHECK-LABEL: test_i32:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:  cmp w0, #0
-; CHECK-NEXT:  cneg w0, w0, mi
-; CHECK-NEXT:  ret
+; CHECK-NEXT:    cmp w0, #0
+; CHECK-NEXT:    cneg w0, w0, mi
+; CHECK-NEXT:    ret
+;
+; CHECK-CSSC-LABEL: test_i32:
+; CHECK-CSSC:       // %bb.0:
+; CHECK-CSSC-NEXT:    abs w0, w0
+; CHECK-CSSC-NEXT:    ret
   %tmp1neg = sub i32 0, %a
   %b = icmp sgt i32 %a, -1
   %abs = select i1 %b, i32 %a, i32 %tmp1neg
@@ -41,12 +60,16 @@ define i32 @test_i32(i32 %a) nounwind {
 define i64 @test_i64(i64 %a) nounwind {
 ; CHECK-LABEL: test_i64:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:  cmp x0, #0
-; CHECK-NEXT:  cneg x0, x0, mi
-; CHECK-NEXT:  ret
+; CHECK-NEXT:    cmp x0, #0
+; CHECK-NEXT:    cneg x0, x0, mi
+; CHECK-NEXT:    ret
+;
+; CHECK-CSSC-LABEL: test_i64:
+; CHECK-CSSC:       // %bb.0:
+; CHECK-CSSC-NEXT:    abs x0, x0
+; CHECK-CSSC-NEXT:    ret
   %tmp1neg = sub i64 0, %a
   %b = icmp sgt i64 %a, -1
   %abs = select i1 %b, i64 %a, i64 %tmp1neg
   ret i64 %abs
 }
-