Skip to content

Commit c31e665

Browse files
committed
[AArch64][llvm] Armv9.7-A: Add support for SVE2p3 CVT operations
Add instructions for SVE2p3 CVT operations: - FCVTZSN - FCVTZUN - SCVTF - SCVTFLT - UCVTF - UCVTFLT as documented here: * https://developer.arm.com/documentation/ddi0602/2025-09/ * https://developer.arm.com/documentation/109697/2025_09/2025-Architecture-Extensions
1 parent f7e40b5 commit c31e665

File tree

8 files changed

+591
-0
lines changed

8 files changed

+591
-0
lines changed

llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4639,6 +4639,15 @@ let Predicates = [HasSVE2p3_or_SME2p3] in {
46394639
def SDOT_ZZZI_BtoH : sve_intx_dot_by_indexed_elem_x<0b0, "sdot">;
46404640
def UDOT_ZZZI_BtoH : sve_intx_dot_by_indexed_elem_x<0b1, "udot">;
46414641

4642+
// SVE2 fp convert, narrow and interleave to integer, rounding toward zero
4643+
defm FCVTZSN_Z2Z : sve2_fp_to_int_downcvt<"fcvtzsn", 0b0>;
4644+
defm FCVTZUN_Z2Z : sve2_fp_to_int_downcvt<"fcvtzun", 0b1>;
4645+
4646+
// SVE2 signed/unsigned integer convert to floating-point
4647+
defm SCVTF_ZZ : sve2_int_to_fp_upcvt<"scvtf", 0b00>;
4648+
defm SCVTFLT_ZZ : sve2_int_to_fp_upcvt<"scvtflt", 0b10>;
4649+
defm UCVTF_ZZ : sve2_int_to_fp_upcvt<"ucvtf", 0b01>;
4650+
defm UCVTFLT_ZZ : sve2_int_to_fp_upcvt<"ucvtflt", 0b11>;
46424651
} // End HasSME2p3orSVE2p3
46434652

46444653
//===----------------------------------------------------------------------===//

llvm/lib/Target/AArch64/SVEInstrFormats.td

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11300,3 +11300,49 @@ class sve_int_mla_cpa<string asm>
1130011300

1130111301
let ElementSize = ZPR64.ElementSize;
1130211302
}
11303+
11304+
//===----------------------------------------------------------------------===//
11305+
// FCVTZSN
11306+
//===----------------------------------------------------------------------===//
11307+
class sve2_fp_to_int_downcvt<string asm, ZPRRegOp ZdRC, RegisterOperand ZSrcOp, bits<2> size, bit U>
11308+
: I<(outs ZdRC:$Zd), (ins ZSrcOp:$Zn),
11309+
asm, "\t$Zd, $Zn", "", []>, Sched<[]> {
11310+
bits<5> Zd;
11311+
bits<4> Zn;
11312+
let Inst{31-24} = 0b01100101;
11313+
let Inst{23-22} = size;
11314+
let Inst{21-11} = 0b00110100110;
11315+
let Inst{10} = U;
11316+
let Inst{9-6} = Zn;
11317+
let Inst{5} = 0b0;
11318+
let Inst{4-0} = Zd;
11319+
}
11320+
11321+
multiclass sve2_fp_to_int_downcvt<string asm, bit U> {
11322+
def _HtoB : sve2_fp_to_int_downcvt<asm, ZPR8, ZZ_h_mul_r, 0b01, U>;
11323+
def _StoH : sve2_fp_to_int_downcvt<asm, ZPR16, ZZ_s_mul_r, 0b10, U>;
11324+
def _DtoS : sve2_fp_to_int_downcvt<asm, ZPR32, ZZ_d_mul_r, 0b11, U>;
11325+
}
11326+
11327+
//===----------------------------------------------------------------------===//
11328+
// SCVTF
11329+
//===----------------------------------------------------------------------===//
11330+
class sve2_int_to_fp_upcvt<string asm, ZPRRegOp ZdRC, ZPRRegOp ZnRC,
11331+
bits<2> size, bits<2> U>
11332+
: I<(outs ZdRC:$Zd), (ins ZnRC:$Zn),
11333+
asm, "\t$Zd, $Zn", "", []>, Sched<[]> {
11334+
bits<5> Zd;
11335+
bits<5> Zn;
11336+
let Inst{31-24} = 0b01100101;
11337+
let Inst{23-22} = size;
11338+
let Inst{21-12} = 0b0011000011;
11339+
let Inst{11-10} = U;
11340+
let Inst{9-5} = Zn;
11341+
let Inst{4-0} = Zd;
11342+
}
11343+
11344+
multiclass sve2_int_to_fp_upcvt<string asm, bits<2> U> {
11345+
def _BtoH : sve2_int_to_fp_upcvt<asm, ZPR16, ZPR8, 0b01, U>;
11346+
def _HtoS : sve2_int_to_fp_upcvt<asm, ZPR32, ZPR16, 0b10, U>;
11347+
def _StoD : sve2_int_to_fp_upcvt<asm, ZPR64, ZPR32, 0b11, U>;
11348+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p3 2>&1 < %s| FileCheck %s
2+
3+
// --------------------------------------------------------------------------//
4+
// Invalid operand for instruction
5+
6+
fcvtzsn z0.b, { z0.b, z1.b }
7+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
8+
// CHECK-NEXT: fcvtzsn z0.b, { z0.b, z1.b }
9+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
10+
11+
fcvtzsn z0.h, { z0.h, z1.h }
12+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
13+
// CHECK-NEXT: fcvtzsn z0.h, { z0.h, z1.h }
14+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
15+
16+
fcvtzsn z0.s, { z0.s, z1.s }
17+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
18+
// CHECK-NEXT: fcvtzsn z0.s, { z0.s, z1.s }
19+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
20+
21+
// --------------------------------------------------------------------------//
22+
// Negative tests for instructions that are incompatible with movprfx
23+
24+
movprfx z0, z7
25+
fcvtzsn z0.b, { z0.h, z1.h }
26+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov
27+
// CHECK-NEXT: fcvtzsn z0.b, { z0.h, z1.h }
28+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
29+
30+
// --------------------------------------------------------------------------//
31+
// Invalid operand for instruction
32+
33+
fcvtzun z0.b, { z0.b, z1.b }
34+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
35+
// CHECK-NEXT: fcvtzun z0.b, { z0.b, z1.b }
36+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
37+
38+
fcvtzun z0.h, { z0.h, z1.h }
39+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
40+
// CHECK-NEXT: fcvtzun z0.h, { z0.h, z1.h }
41+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
42+
43+
fcvtzun z0.s, { z0.s, z1.s }
44+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction
45+
// CHECK-NEXT: fcvtzun z0.s, { z0.s, z1.s }
46+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
47+
48+
// --------------------------------------------------------------------------//
49+
// Negative tests for instructions that are incompatible with movprfx
50+
51+
movprfx z0, z7
52+
fcvtzun z0.b, { z0.h, z1.h }
53+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov
54+
// CHECK-NEXT: fcvtzun z0.b, { z0.h, z1.h }
55+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p3 < %s \
2+
// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
3+
// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2p3 < %s \
4+
// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
5+
// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \
6+
// RUN: | FileCheck %s --check-prefix=CHECK-ERROR
7+
// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2p3 < %s \
8+
// RUN: | llvm-objdump -d --mattr=+sve2p3 --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-INST
9+
// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2p3 < %s \
10+
// RUN: | llvm-objdump -d --mattr=-sve2p3 --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-UNKNOWN
11+
// Disassemble encoding and check the re-encoding (-show-encoding) matches.
12+
// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p3 < %s \
13+
// RUN: | sed '/.text/d' | sed 's/.*encoding: //g' \
14+
// RUN: | llvm-mc -triple=aarch64 -mattr=+sve2p3 -disassemble -show-encoding \
15+
// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
16+
17+
// -------------------------------------------------------------
18+
// Floating-point convert, narrow and interleave to signed integer, rounding toward zero
19+
20+
fcvtzsn z0.b, { z0.h, z1.h }
21+
// CHECK-INST: fcvtzsn z0.b, { z0.h, z1.h }
22+
// CHECK-ENCODING: encoding: [0x00,0x30,0x4d,0x65]
23+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
24+
// CHECK-UNKNOWN: 654d3000 <unknown>
25+
26+
fcvtzsn z31.b, { z0.h, z1.h }
27+
// CHECK-INST: fcvtzsn z31.b, { z0.h, z1.h }
28+
// CHECK-ENCODING: encoding: [0x1f,0x30,0x4d,0x65]
29+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
30+
// CHECK-UNKNOWN: 654d301f <unknown>
31+
32+
fcvtzsn z0.b, { z30.h, z31.h }
33+
// CHECK-INST: fcvtzsn z0.b, { z30.h, z31.h }
34+
// CHECK-ENCODING: encoding: [0xc0,0x33,0x4d,0x65]
35+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
36+
// CHECK-UNKNOWN: 654d33c0 <unknown>
37+
38+
fcvtzsn z31.b, { z30.h, z31.h }
39+
// CHECK-INST: fcvtzsn z31.b, { z30.h, z31.h }
40+
// CHECK-ENCODING: encoding: [0xdf,0x33,0x4d,0x65]
41+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
42+
// CHECK-UNKNOWN: 654d33df <unknown>
43+
44+
fcvtzsn z0.h, { z0.s, z1.s }
45+
// CHECK-INST: fcvtzsn z0.h, { z0.s, z1.s }
46+
// CHECK-ENCODING: encoding: [0x00,0x30,0x8d,0x65]
47+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
48+
// CHECK-UNKNOWN: 658d3000 <unknown>
49+
50+
fcvtzsn z31.h, { z0.s, z1.s }
51+
// CHECK-INST: fcvtzsn z31.h, { z0.s, z1.s }
52+
// CHECK-ENCODING: encoding: [0x1f,0x30,0x8d,0x65]
53+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
54+
// CHECK-UNKNOWN: 658d301f <unknown>
55+
56+
fcvtzsn z0.h, { z30.s, z31.s }
57+
// CHECK-INST: fcvtzsn z0.h, { z30.s, z31.s }
58+
// CHECK-ENCODING: encoding: [0xc0,0x33,0x8d,0x65]
59+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
60+
// CHECK-UNKNOWN: 658d33c0 <unknown>
61+
62+
fcvtzsn z31.h, { z30.s, z31.s }
63+
// CHECK-INST: fcvtzsn z31.h, { z30.s, z31.s }
64+
// CHECK-ENCODING: encoding: [0xdf,0x33,0x8d,0x65]
65+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
66+
// CHECK-UNKNOWN: 658d33df <unknown>
67+
68+
fcvtzsn z0.s, { z0.d, z1.d }
69+
// CHECK-INST: fcvtzsn z0.s, { z0.d, z1.d }
70+
// CHECK-ENCODING: encoding: [0x00,0x30,0xcd,0x65]
71+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
72+
// CHECK-UNKNOWN: 65cd3000 <unknown>
73+
74+
fcvtzsn z31.s, { z0.d, z1.d }
75+
// CHECK-INST: fcvtzsn z31.s, { z0.d, z1.d }
76+
// CHECK-ENCODING: encoding: [0x1f,0x30,0xcd,0x65]
77+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
78+
// CHECK-UNKNOWN: 65cd301f <unknown>
79+
80+
fcvtzsn z0.s, { z30.d, z31.d }
81+
// CHECK-INST: fcvtzsn z0.s, { z30.d, z31.d }
82+
// CHECK-ENCODING: encoding: [0xc0,0x33,0xcd,0x65]
83+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
84+
// CHECK-UNKNOWN: 65cd33c0 <unknown>
85+
86+
fcvtzsn z31.s, { z30.d, z31.d }
87+
// CHECK-INST: fcvtzsn z31.s, { z30.d, z31.d }
88+
// CHECK-ENCODING: encoding: [0xdf,0x33,0xcd,0x65]
89+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
90+
// CHECK-UNKNOWN: 65cd33df <unknown>
91+
92+
// -------------------------------------------------------------
93+
// Floating-point convert, narrow and interleave to unsigned integer, rounding toward zero
94+
95+
fcvtzun z0.b, { z0.h, z1.h }
96+
// CHECK-INST: fcvtzun z0.b, { z0.h, z1.h }
97+
// CHECK-ENCODING: encoding: [0x00,0x34,0x4d,0x65]
98+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
99+
// CHECK-UNKNOWN: 654d3400 <unknown>
100+
101+
fcvtzun z31.b, { z0.h, z1.h }
102+
// CHECK-INST: fcvtzun z31.b, { z0.h, z1.h }
103+
// CHECK-ENCODING: encoding: [0x1f,0x34,0x4d,0x65]
104+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
105+
// CHECK-UNKNOWN: 654d341f <unknown>
106+
107+
fcvtzun z0.b, { z30.h, z31.h }
108+
// CHECK-INST: fcvtzun z0.b, { z30.h, z31.h }
109+
// CHECK-ENCODING: encoding: [0xc0,0x37,0x4d,0x65]
110+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
111+
// CHECK-UNKNOWN: 654d37c0 <unknown>
112+
113+
fcvtzun z31.b, { z30.h, z31.h }
114+
// CHECK-INST: fcvtzun z31.b, { z30.h, z31.h }
115+
// CHECK-ENCODING: encoding: [0xdf,0x37,0x4d,0x65]
116+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
117+
// CHECK-UNKNOWN: 654d37df <unknown>
118+
119+
fcvtzun z0.h, { z0.s, z1.s }
120+
// CHECK-INST: fcvtzun z0.h, { z0.s, z1.s }
121+
// CHECK-ENCODING: encoding: [0x00,0x34,0x8d,0x65]
122+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
123+
// CHECK-UNKNOWN: 658d3400 <unknown>
124+
125+
fcvtzun z31.h, { z0.s, z1.s }
126+
// CHECK-INST: fcvtzun z31.h, { z0.s, z1.s }
127+
// CHECK-ENCODING: encoding: [0x1f,0x34,0x8d,0x65]
128+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
129+
// CHECK-UNKNOWN: 658d341f <unknown>
130+
131+
fcvtzun z0.h, { z30.s, z31.s }
132+
// CHECK-INST: fcvtzun z0.h, { z30.s, z31.s }
133+
// CHECK-ENCODING: encoding: [0xc0,0x37,0x8d,0x65]
134+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
135+
// CHECK-UNKNOWN: 658d37c0 <unknown>
136+
137+
fcvtzun z31.h, { z30.s, z31.s }
138+
// CHECK-INST: fcvtzun z31.h, { z30.s, z31.s }
139+
// CHECK-ENCODING: encoding: [0xdf,0x37,0x8d,0x65]
140+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
141+
// CHECK-UNKNOWN: 658d37df <unknown>
142+
143+
fcvtzun z0.s, { z0.d, z1.d }
144+
// CHECK-INST: fcvtzun z0.s, { z0.d, z1.d }
145+
// CHECK-ENCODING: encoding: [0x00,0x34,0xcd,0x65]
146+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
147+
// CHECK-UNKNOWN: 65cd3400 <unknown>
148+
149+
fcvtzun z31.s, { z0.d, z1.d }
150+
// CHECK-INST: fcvtzun z31.s, { z0.d, z1.d }
151+
// CHECK-ENCODING: encoding: [0x1f,0x34,0xcd,0x65]
152+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
153+
// CHECK-UNKNOWN: 65cd341f <unknown>
154+
155+
fcvtzun z0.s, { z30.d, z31.d }
156+
// CHECK-INST: fcvtzun z0.s, { z30.d, z31.d }
157+
// CHECK-ENCODING: encoding: [0xc0,0x37,0xcd,0x65]
158+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
159+
// CHECK-UNKNOWN: 65cd37c0 <unknown>
160+
161+
fcvtzun z31.s, { z30.d, z31.d }
162+
// CHECK-INST: fcvtzun z31.s, { z30.d, z31.d }
163+
// CHECK-ENCODING: encoding: [0xdf,0x37,0xcd,0x65]
164+
// CHECK-ERROR: instruction requires: sme2p3 or sve2p3
165+
// CHECK-UNKNOWN: 65cd37df <unknown>
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p3 2>&1 < %s| FileCheck %s
2+
3+
// --------------------------------------------------------------------------//
4+
// Invalid element width
5+
6+
scvtf z0.b, z0.b
7+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
8+
// CHECK-NEXT: scvtf z0.b, z0.b
9+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
10+
11+
scvtf z0.h, z0.h
12+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
13+
// CHECK-NEXT: scvtf z0.h, z0.h
14+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
15+
16+
scvtf z0.s, z0.s
17+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
18+
// CHECK-NEXT: scvtf z0.s, z0.s
19+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
20+
21+
scvtf z0.d, z0.d
22+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
23+
// CHECK-NEXT: scvtf z0.d, z0.d
24+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
25+
26+
// --------------------------------------------------------------------------//
27+
// Negative tests for instructions that are incompatible with movprfx
28+
29+
movprfx z0, z7
30+
scvtf z0.h, z0.b
31+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov
32+
// CHECK-NEXT: scvtf z0.h, z0.b
33+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
34+
35+
// --------------------------------------------------------------------------//
36+
// Invalid element width
37+
38+
scvtflt z0.b, z0.b
39+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
40+
// CHECK-NEXT: scvtflt z0.b, z0.b
41+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
42+
43+
scvtflt z0.h, z0.h
44+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
45+
// CHECK-NEXT: scvtflt z0.h, z0.h
46+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
47+
48+
scvtflt z0.s, z0.s
49+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
50+
// CHECK-NEXT: scvtflt z0.s, z0.s
51+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
52+
53+
scvtflt z0.d, z0.d
54+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width
55+
// CHECK-NEXT: scvtflt z0.d, z0.d
56+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:
57+
58+
// --------------------------------------------------------------------------//
59+
// Negative tests for instructions that are incompatible with movprfx
60+
61+
movprfx z0, z7
62+
scvtflt z0.h, z0.b
63+
// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov
64+
// CHECK-NEXT: scvtflt z0.h, z0.b
65+
// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}:

0 commit comments

Comments
 (0)