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
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);
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);
}
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
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()">;
// 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>;
//===----------------------------------------------------------------------===//
// 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]>;
-; 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
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
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
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
}
-