Skip to content

Commit d61d219

Browse files
authored
Adding support in llvm-exegesis for Aarch64 for handling FPR64/128, PPR16 and ZPR128 reg class. (#127564)
Current implementation (for Aarch64) in llvm-exegesis only supports GRP32 and GPR64 bit register class, thus for opcodes variants which used FPR64/128, PPR16 and ZPR128, llvm-exegesis throws warning "setReg is not implemented". This code will handle the above register class and initialize the registers using appropriate base instruction class.
1 parent a2b0576 commit d61d219

File tree

2 files changed

+89
-2
lines changed

2 files changed

+89
-2
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
REQUIRES: aarch64-registered-target
2+
3+
## PPR Register Class Initialization Testcase
4+
## Ideally, we should use PTRUE_{B/H/S/D} instead of FADDV_VPZ_D for an isolated test case;
5+
## However, exegesis does not yet support PTRUE_{B/H/S/D}.
6+
RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=FADDV_VPZ_D 2>&1
7+
RUN: llvm-objdump -d %d > %t.s
8+
RUN: FileCheck %s --check-prefix=PPR_ASM < %t.s
9+
PPR_ASM: <foo>:
10+
PPR_ASM: ptrue p{{[0-9]+}}.b
11+
PPR_ASM-NEXT: mov z{{[0-9]+}}.d, #0x0
12+
PPR_ASM-NEXT: faddv d{{[0-9]+}}, p{{[0-9]+}}, z{{[0-9]+}}
13+
14+
## ZPR Register Class Initialization Testcase
15+
## Ideally, we should use DUP_ZI_{B/H/S/D} instead of FADDV_VPZ_D for an isolated test case;
16+
## However, exegesis does not yet support DUP_ZI_{B/H/S/D}.
17+
RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=FADDV_VPZ_D 2>&1
18+
RUN: llvm-objdump -d %d > %t.s
19+
RUN: FileCheck %s --check-prefix=ZPR_ASM < %t.s
20+
ZPR_ASM: <foo>:
21+
ZPR_ASM: ptrue p{{[0-9]+}}.b
22+
ZPR_ASM-NEXT: mov z{{[0-9]+}}.d, #0x0
23+
ZPR_ASM-NEXT: faddv d{{[0-9]+}}, p{{[0-9]+}}, z{{[0-9]+}}
24+
25+
## FPR128 Register Class Initialization Testcase
26+
RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=ADDVv16i8v 2>&1
27+
RUN: llvm-objdump -d %d > %t.s
28+
RUN: FileCheck %s --check-prefix=FPR128-ASM < %t.s
29+
FPR128-ASM: <foo>:
30+
FPR128-ASM: movi v{{[0-9]+}}.2d, #0000000000000000
31+
FPR128-ASM-NEXT: addv b{{[0-9]+}}, v{{[0-9]+}}.16b
32+
33+
## FPR64 Register Class Initialization Testcase
34+
RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=ADDVv4i16v 2>&1
35+
RUN: llvm-objdump -d %d > %t.s
36+
RUN: FileCheck %s --check-prefix=FPR64-ASM < %t.s
37+
FPR64-ASM: <foo>:
38+
FPR64-ASM: movi d{{[0-9]+}}, #0000000000000000
39+
FPR64-ASM-NEXT: addv h{{[0-9]+}}, v{{[0-9]+}}.4h

llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,52 @@ static unsigned getLoadImmediateOpcode(unsigned RegBitWidth) {
2828
// Generates instruction to load an immediate value into a register.
2929
static MCInst loadImmediate(MCRegister Reg, unsigned RegBitWidth,
3030
const APInt &Value) {
31-
if (Value.getBitWidth() > RegBitWidth)
32-
llvm_unreachable("Value must fit in the Register");
31+
assert (Value.getBitWidth() <= RegBitWidth &&
32+
"Value must fit in the Register");
3333
return MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
3434
.addReg(Reg)
3535
.addImm(Value.getZExtValue());
3636
}
3737

38+
static MCInst loadZPRImmediate(MCRegister Reg, unsigned RegBitWidth,
39+
const APInt &Value) {
40+
assert(Value.getZExtValue() < (1 << 7) &&
41+
"Value must be in the range of the immediate opcode");
42+
return MCInstBuilder(AArch64::DUP_ZI_D)
43+
.addReg(Reg)
44+
.addImm(Value.getZExtValue())
45+
.addImm(0);
46+
}
47+
48+
static MCInst loadPPRImmediate(MCRegister Reg, unsigned RegBitWidth,
49+
const APInt &Value) {
50+
// For PPR, we typically use PTRUE instruction to set predicate registers
51+
return MCInstBuilder(AArch64::PTRUE_B)
52+
.addReg(Reg)
53+
.addImm(31); // All lanes true for 16 bits
54+
}
55+
56+
// Fetch base-instruction to load an FP immediate value into a register.
57+
static unsigned getLoadFPImmediateOpcode(unsigned RegBitWidth) {
58+
switch (RegBitWidth) {
59+
case 64:
60+
return AArch64::MOVID; //FMOVDi;
61+
case 128:
62+
return AArch64::MOVIv2d_ns;
63+
}
64+
llvm_unreachable("Invalid Value Width");
65+
}
66+
67+
// Generates instruction to load an FP immediate value into a register.
68+
static MCInst loadFPImmediate(MCRegister Reg, unsigned RegBitWidth,
69+
const APInt &Value) {
70+
assert(Value.getZExtValue() == 0 &&
71+
"Expected initialisation value 0");
72+
return MCInstBuilder(getLoadFPImmediateOpcode(RegBitWidth))
73+
.addReg(Reg)
74+
.addImm(Value.getZExtValue());
75+
}
76+
3877
#include "AArch64GenExegesis.inc"
3978

4079
namespace {
@@ -51,6 +90,15 @@ class ExegesisAArch64Target : public ExegesisTarget {
5190
return {loadImmediate(Reg, 32, Value)};
5291
if (AArch64::GPR64RegClass.contains(Reg))
5392
return {loadImmediate(Reg, 64, Value)};
93+
if (AArch64::PPRRegClass.contains(Reg))
94+
return {loadPPRImmediate(Reg, 16, Value)};
95+
if (AArch64::FPR64RegClass.contains(Reg))
96+
return {loadFPImmediate(Reg, 64, Value)};
97+
if (AArch64::FPR128RegClass.contains(Reg))
98+
return {loadFPImmediate(Reg, 128, Value)};
99+
if (AArch64::ZPRRegClass.contains(Reg))
100+
return {loadZPRImmediate(Reg, 128, Value)};
101+
54102
errs() << "setRegTo is not implemented, results will be unreliable\n";
55103
return {};
56104
}

0 commit comments

Comments
 (0)