[AArch64][v8.5A] Add FRINT[32,64][Z,X] instructions

These are some new variants of the "Floating-point Round to Integral"
family of instructions, which round to the nearest floating-point value
which fits in a 32- or 64-bit integer.

Patch by Pablo Barrio!

Differential revision: https://reviews.llvm.org/D52475

llvm-svn: 343209
This commit is contained in:
Oliver Stannard 2018-09-27 13:32:06 +00:00
parent 30183093ab
commit ddb7d46aa5
7 changed files with 301 additions and 8 deletions

View File

@ -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

View File

@ -4433,6 +4433,22 @@ multiclass SingleOperandFPData<bits<4> opcode, string asm,
}
}
multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
SDPatternOperator node = null_frag>{
def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
let Inst{23-22} = 0b00; // 32-bit registers
}
def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
let Inst{23-22} = 0b01; // 64-bit registers
}
}
// FRInt[32|64][Z|N] instructions
multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
//---
// Two operand floating point data processing
//---
@ -5308,7 +5324,7 @@ multiclass SIMDTwoVectorBH<bit U, bits<5> 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<bit U, bit S, bits<5> opc, string asm,
SDPatternOperator OpNode> {
@ -5331,6 +5347,25 @@ multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
[(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
}
// Supports only S and D element sizes
multiclass SIMDTwoVectorSD<bit U, bits<5> 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<bit U, bit op, string asm,
SDPatternOperator OpNode = null_frag> :
SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
// Supports only S element size.
multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
SDPatternOperator OpNode> {

View File

@ -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",

View File

@ -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; }

View File

@ -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

View File

@ -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

View File

@ -1,5 +1,6 @@
# 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]
@ -10,3 +11,91 @@
# 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]