diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td index 592c7e07b947..67b475de65a4 100644 --- a/llvm/lib/Target/AArch64/AArch64.td +++ b/llvm/lib/Target/AArch64/AArch64.td @@ -207,6 +207,10 @@ def FeatureAggressiveFMA : def FeatureAltFPCmp : SubtargetFeature<"altnzcv", "HasAlternativeNZCV", "true", "Enable alternative NZCV format for floating point comparisons">; +def FeatureFRInt3264 : SubtargetFeature<"fptoint", "HasFRInt3264", "true", + "Enable FRInt[32|64][Z|X] instructions that round a floating-point number to " + "an integer (in FP format) forcing it to fit into a 32- or 64-bit int" >; + //===----------------------------------------------------------------------===// // Architectures. // @@ -223,8 +227,10 @@ def HasV8_3aOps : SubtargetFeature<"v8.3a", "HasV8_3aOps", "true", def HasV8_4aOps : SubtargetFeature<"v8.4a", "HasV8_4aOps", "true", "Support ARM v8.4a instructions", [HasV8_3aOps, FeatureDotProd]>; -def HasV8_5aOps : SubtargetFeature<"v8.5a", "HasV8_5aOps", "true", - "Support ARM v8.5a instructions", [HasV8_4aOps, FeatureAltFPCmp]>; +def HasV8_5aOps : SubtargetFeature< + "v8.5a", "HasV8_5aOps", "true", "Support ARM v8.5a instructions", + [HasV8_4aOps, FeatureAltFPCmp, FeatureFRInt3264] +>; //===----------------------------------------------------------------------===// // Register File Description diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td index 1ad87558b639..8a24650610eb 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -4433,6 +4433,22 @@ multiclass SingleOperandFPData opcode, string asm, } } +multiclass SingleOperandFPNo16 opcode, string asm, + SDPatternOperator node = null_frag>{ + + def Sr : BaseSingleOperandFPData { + let Inst{23-22} = 0b00; // 32-bit registers + } + + def Dr : BaseSingleOperandFPData { + let Inst{23-22} = 0b01; // 64-bit registers + } +} + +// FRInt[32|64][Z|N] instructions +multiclass FRIntNNT opcode, string asm, SDPatternOperator node = null_frag> : + SingleOperandFPNo16<{0b0100,opcode}, asm, node>; + //--- // Two operand floating point data processing //--- @@ -5308,7 +5324,7 @@ multiclass SIMDTwoVectorBH opc, string asm, [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>; } -// Supports only S and D element sizes, uses high bit of the size field +// Supports H, S and D element sizes, uses high bit of the size field // as an extra opcode bit. multiclass SIMDTwoVectorFP opc, string asm, SDPatternOperator OpNode> { @@ -5331,6 +5347,25 @@ multiclass SIMDTwoVectorFP opc, string asm, [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>; } +// Supports only S and D element sizes +multiclass SIMDTwoVectorSD opc, string asm, + SDPatternOperator OpNode = null_frag> { + + def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64, + asm, ".2s", ".2s", + [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>; + def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128, + asm, ".4s", ".4s", + [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>; + def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128, + asm, ".2d", ".2d", + [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>; +} + +multiclass FRIntNNTVector : + SIMDTwoVectorSD; + // Supports only S element size. multiclass SIMDTwoVectorS opc, string asm, SDPatternOperator OpNode> { diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 83bec32da795..d1daf6d7f764 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -64,6 +64,8 @@ def HasRCPC : Predicate<"Subtarget->hasRCPC()">, AssemblerPredicate<"FeatureRCPC", "rcpc">; def HasAltNZCV : Predicate<"Subtarget->hasAlternativeNZCV()">, AssemblerPredicate<"FeatureAltFPCmp", "altnzcv">; +def HasFRInt3264 : Predicate<"Subtarget->hasFRInt3264()">, + AssemblerPredicate<"FeatureFRInt3264", "frint3264">; def IsLE : Predicate<"Subtarget->isLittleEndian()">; def IsBE : Predicate<"!Subtarget->isLittleEndian()">; def UseAlternateSExtLoadCVTF32 @@ -2939,6 +2941,13 @@ let SchedRW = [WriteFDiv] in { defm FSQRT : SingleOperandFPData<0b0011, "fsqrt", fsqrt>; } +let Predicates = [HasFRInt3264] in { + defm FRINT32Z : FRIntNNT<0b00, "frint32z">; + defm FRINT64Z : FRIntNNT<0b10, "frint64z">; + defm FRINT32X : FRIntNNT<0b01, "frint32x">; + defm FRINT64X : FRIntNNT<0b11, "frint64x">; +} // HasFRInt3264 + //===----------------------------------------------------------------------===// // Floating point two operand instructions. //===----------------------------------------------------------------------===// @@ -3157,6 +3166,14 @@ defm FRINTN : SIMDTwoVectorFP<0, 0, 0b11000, "frintn", int_aarch64_neon_frintn>; defm FRINTP : SIMDTwoVectorFP<0, 1, 0b11000, "frintp", fceil>; defm FRINTX : SIMDTwoVectorFP<1, 0, 0b11001, "frintx", frint>; defm FRINTZ : SIMDTwoVectorFP<0, 1, 0b11001, "frintz", ftrunc>; + +let Predicates = [HasFRInt3264] in { + defm FRINT32Z : FRIntNNTVector<0, 0, "frint32z">; + defm FRINT64Z : FRIntNNTVector<0, 1, "frint64z">; + defm FRINT32X : FRIntNNTVector<1, 0, "frint32x">; + defm FRINT64X : FRIntNNTVector<1, 1, "frint64x">; +} // HasFRInt3264 + defm FRSQRTE: SIMDTwoVectorFP<1, 1, 0b11101, "frsqrte", int_aarch64_neon_frsqrte>; defm FSQRT : SIMDTwoVectorFP<1, 1, 0b11111, "fsqrt", fsqrt>; defm NEG : SIMDTwoVectorBHSD<1, 0b01011, "neg", diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h index bf60a0fd269f..fec338c1ab38 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -96,6 +96,7 @@ protected: // Armv8.5-A Extensions bool HasAlternativeNZCV = false; + bool HasFRInt3264 = false; // HasZeroCycleRegMove - Has zero-cycle register mov instructions. bool HasZeroCycleRegMove = false; @@ -310,6 +311,7 @@ public: bool hasRCPC() const { return HasRCPC; } bool hasAggressiveFMA() const { return HasAggressiveFMA; } bool hasAlternativeNZCV() const { return HasAlternativeNZCV; } + bool hasFRInt3264() const { return HasFRInt3264; } bool isLittleEndian() const { return IsLittle; } diff --git a/llvm/test/MC/AArch64/armv8.5a-frint-error.s b/llvm/test/MC/AArch64/armv8.5a-frint-error.s new file mode 100644 index 000000000000..61f3ed00759e --- /dev/null +++ b/llvm/test/MC/AArch64/armv8.5a-frint-error.s @@ -0,0 +1,52 @@ +// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.5a < %s 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR + +// FP-to-int rounding, vector, illegal +frint32z v0.4h, v0.4h +frint32z v0.8b, v0.8b +frint32z v0.8h, v0.8h +frint32z v0.16b, v0.16b +frint64z v0.4h, v0.4h +frint64z v0.8b, v0.8b +frint64z v0.8h, v0.8h +frint64z v0.16b, v0.16b +frint32x v0.4h, v0.4h +frint32x v0.8b, v0.8b +frint32x v0.8h, v0.8h +frint32x v0.16b, v0.16b +frint64x v0.4h, v0.4h +frint64x v0.8b, v0.8b +frint64x v0.8h, v0.8h +frint64x v0.16b, v0.16b + +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint32z v0.4h, v0.4h +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint32z v0.8b, v0.8b +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint32z v0.8h, v0.8h +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint32z v0.16b, v0.16b +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint64z v0.4h, v0.4h +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint64z v0.8b, v0.8b +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint64z v0.8h, v0.8h +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint64z v0.16b, v0.16b +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint32x v0.4h, v0.4h +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint32x v0.8b, v0.8b +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint32x v0.8h, v0.8h +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint32x v0.16b, v0.16b +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint64x v0.4h, v0.4h +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint64x v0.8b, v0.8b +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint64x v0.8h, v0.8h +// CHECK-ERROR: invalid operand for instruction +// CHECK-ERROR-NEXT: frint64x v0.16b, v0.16b diff --git a/llvm/test/MC/AArch64/armv8.5a-frint.s b/llvm/test/MC/AArch64/armv8.5a-frint.s new file mode 100644 index 000000000000..da46baebeb99 --- /dev/null +++ b/llvm/test/MC/AArch64/armv8.5a-frint.s @@ -0,0 +1,92 @@ +// RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.5a < %s | FileCheck %s +// RUN: llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.4a,+fptoint < %s | FileCheck %s +// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.4a,-v8.5a < %s 2>&1 | FileCheck %s --check-prefix=NOFRINT +// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=-v8.5a < %s 2>&1 | FileCheck %s --check-prefix=NOFRINT + +// FP-to-int rounding, scalar +frint32z s0, s1 +frint32z d0, d1 +frint64z s2, s3 +frint64z d2, d3 +frint32x s4, s5 +frint32x d4, d5 +frint64x s6, s7 +frint64x d6, d7 + +// CHECK: frint32z s0, s1 // encoding: [0x20,0x40,0x28,0x1e] +// CHECK: frint32z d0, d1 // encoding: [0x20,0x40,0x68,0x1e] +// CHECK: frint64z s2, s3 // encoding: [0x62,0x40,0x29,0x1e] +// CHECK: frint64z d2, d3 // encoding: [0x62,0x40,0x69,0x1e] +// CHECK: frint32x s4, s5 // encoding: [0xa4,0xc0,0x28,0x1e] +// CHECK: frint32x d4, d5 // encoding: [0xa4,0xc0,0x68,0x1e] +// CHECK: frint64x s6, s7 // encoding: [0xe6,0xc0,0x29,0x1e] +// CHECK: frint64x d6, d7 // encoding: [0xe6,0xc0,0x69,0x1e] + +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint32z s0, s1 +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint32z d0, d1 +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint64z s2, s3 +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint64z d2, d3 +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint32x s4, s5 +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint32x d4, d5 +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint64x s6, s7 +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint64x d6, d7 + +// FP-to-int rounding, vector +frint32z v0.2s, v1.2s +frint32z v0.2d, v1.2d +frint32z v0.4s, v1.4s +frint64z v2.2s, v3.2s +frint64z v2.2d, v3.2d +frint64z v2.4s, v3.4s +frint32x v4.2s, v5.2s +frint32x v4.2d, v5.2d +frint32x v4.4s, v5.4s +frint64x v6.2s, v7.2s +frint64x v6.2d, v7.2d +frint64x v6.4s, v7.4s + +// CHECK: frint32z v0.2s, v1.2s // encoding: [0x20,0xe8,0x21,0x0e] +// CHECK: frint32z v0.2d, v1.2d // encoding: [0x20,0xe8,0x61,0x4e] +// CHECK: frint32z v0.4s, v1.4s // encoding: [0x20,0xe8,0x21,0x4e] +// CHECK: frint64z v2.2s, v3.2s // encoding: [0x62,0xf8,0x21,0x0e] +// CHECK: frint64z v2.2d, v3.2d // encoding: [0x62,0xf8,0x61,0x4e] +// CHECK: frint64z v2.4s, v3.4s // encoding: [0x62,0xf8,0x21,0x4e] +// CHECK: frint32x v4.2s, v5.2s // encoding: [0xa4,0xe8,0x21,0x2e] +// CHECK: frint32x v4.2d, v5.2d // encoding: [0xa4,0xe8,0x61,0x6e] +// CHECK: frint32x v4.4s, v5.4s // encoding: [0xa4,0xe8,0x21,0x6e] +// CHECK: frint64x v6.2s, v7.2s // encoding: [0xe6,0xf8,0x21,0x2e] +// CHECK: frint64x v6.2d, v7.2d // encoding: [0xe6,0xf8,0x61,0x6e] +// CHECK: frint64x v6.4s, v7.4s // encoding: [0xe6,0xf8,0x21,0x6e] + +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint32z v0.2s, v1.2s +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint32z v0.2d, v1.2d +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint32z v0.4s, v1.4s +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint64z v2.2s, v3.2s +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint64z v2.2d, v3.2d +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint64z v2.4s, v3.4s +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint32x v4.2s, v5.2s +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint32x v4.2d, v5.2d +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint32x v4.4s, v5.4s +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint64x v6.2s, v7.2s +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint64x v6.2d, v7.2d +// NOFRINT: instruction requires: frint3264 +// NOFRINT-NEXT: frint64x v6.4s, v7.4s diff --git a/llvm/test/MC/Disassembler/AArch64/armv8.5a-dataproc.txt b/llvm/test/MC/Disassembler/AArch64/armv8.5a-dataproc.txt index 1932b5f42412..29899bd83408 100644 --- a/llvm/test/MC/Disassembler/AArch64/armv8.5a-dataproc.txt +++ b/llvm/test/MC/Disassembler/AArch64/armv8.5a-dataproc.txt @@ -1,12 +1,101 @@ # RUN: llvm-mc -triple aarch64-none-linux-gnu -mattr=+v8.5a --disassemble < %s | FileCheck %s -# RUN: llvm-mc -triple aarch64-none-linux-gnu -mattr=-v8.5a --disassemble < %s 2>&1 | FileCheck %s --check-prefix=CHECK-NOV85 +# RUN: not llvm-mc -triple aarch64-none-linux-gnu -mattr=-v8.5a --disassemble < %s 2>%t | FileCheck %s --check-prefix=CHECK-NOV85 +# RUN: FileCheck %s --check-prefix=CHECK-NOV85-ERROR < %t # Flag manipulation [0x3f,0x40,0x00,0xd5] [0x5f,0x40,0x00,0xd5] -#CHECK: xaflag -#CHECK: axflag +# CHECK: xaflag +# CHECK: axflag -#CHECK-NOV85: msr S0_0_C4_C0_1, xzr -#CHECK-NOV85: msr S0_0_C4_C0_2, xzr +# CHECK-NOV85: msr S0_0_C4_C0_1, xzr +# CHECK-NOV85: msr S0_0_C4_C0_2, xzr + +# FP-to-int rounding, scalar +[0x20,0x40,0x28,0x1e] +[0x20,0x40,0x68,0x1e] +[0x62,0x40,0x29,0x1e] +[0x62,0x40,0x69,0x1e] +[0xa4,0xc0,0x28,0x1e] +[0xa4,0xc0,0x68,0x1e] +[0xe6,0xc0,0x29,0x1e] +[0xe6,0xc0,0x69,0x1e] + +# CHECK: frint32z s0, s1 +# CHECK: frint32z d0, d1 +# CHECK: frint64z s2, s3 +# CHECK: frint64z d2, d3 +# CHECK: frint32x s4, s5 +# CHECK: frint32x d4, d5 +# CHECK: frint64x s6, s7 +# CHECK: frint64x d6, d7 + +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0x20,0x40,0x28,0x1e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0x20,0x40,0x68,0x1e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0x62,0x40,0x29,0x1e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0x62,0x40,0x69,0x1e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0xa4,0xc0,0x28,0x1e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0xa4,0xc0,0x68,0x1e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0xe6,0xc0,0x29,0x1e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0xe6,0xc0,0x69,0x1e] + +# FP-to-int rounding, vector +[0x20,0xe8,0x21,0x0e] +[0x20,0xe8,0x61,0x4e] +[0x20,0xe8,0x21,0x4e] +[0x62,0xf8,0x21,0x0e] +[0x62,0xf8,0x61,0x4e] +[0x62,0xf8,0x21,0x4e] +[0xa4,0xe8,0x21,0x2e] +[0xa4,0xe8,0x61,0x6e] +[0xa4,0xe8,0x21,0x6e] +[0xe6,0xf8,0x21,0x2e] +[0xe6,0xf8,0x61,0x6e] +[0xe6,0xf8,0x21,0x6e] + +#CHECK: frint32z v0.2s, v1.2s +#CHECK: frint32z v0.2d, v1.2d +#CHECK: frint32z v0.4s, v1.4s +#CHECK: frint64z v2.2s, v3.2s +#CHECK: frint64z v2.2d, v3.2d +#CHECK: frint64z v2.4s, v3.4s +#CHECK: frint32x v4.2s, v5.2s +#CHECK: frint32x v4.2d, v5.2d +#CHECK: frint32x v4.4s, v5.4s +#CHECK: frint64x v6.2s, v7.2s +#CHECK: frint64x v6.2d, v7.2d +#CHECK: frint64x v6.4s, v7.4s + +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0x20,0xe8,0x21,0x0e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0x20,0xe8,0x61,0x4e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0x20,0xe8,0x21,0x4e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0x62,0xf8,0x21,0x0e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0x62,0xf8,0x61,0x4e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0x62,0xf8,0x21,0x4e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0xa4,0xe8,0x21,0x2e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0xa4,0xe8,0x61,0x6e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0xa4,0xe8,0x21,0x6e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0xe6,0xf8,0x21,0x2e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0xe6,0xf8,0x61,0x6e] +# CHECK-NOV85-ERROR: invalid instruction encoding +# CHECK-NOV85-ERROR-NEXT: [0xe6,0xf8,0x21,0x6e]