diff --git a/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s b/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s new file mode 100644 index 0000000000000..1b69ac68a2b30 --- /dev/null +++ b/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s @@ -0,0 +1,39 @@ +REQUIRES: aarch64-registered-target + +## PPR Register Class Initialization Testcase +## Ideally, we should use PTRUE_{B/H/S/D} instead of FADDV_VPZ_D for an isolated test case; +## However, exegesis does not yet support PTRUE_{B/H/S/D}. +RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=FADDV_VPZ_D 2>&1 +RUN: llvm-objdump -d %d > %t.s +RUN: FileCheck %s --check-prefix=PPR_ASM < %t.s +PPR_ASM: : +PPR_ASM: ptrue p{{[0-9]+}}.b +PPR_ASM-NEXT: mov z{{[0-9]+}}.d, #0x0 +PPR_ASM-NEXT: faddv d{{[0-9]+}}, p{{[0-9]+}}, z{{[0-9]+}} + +## ZPR Register Class Initialization Testcase +## Ideally, we should use DUP_ZI_{B/H/S/D} instead of FADDV_VPZ_D for an isolated test case; +## However, exegesis does not yet support DUP_ZI_{B/H/S/D}. +RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=FADDV_VPZ_D 2>&1 +RUN: llvm-objdump -d %d > %t.s +RUN: FileCheck %s --check-prefix=ZPR_ASM < %t.s +ZPR_ASM: : +ZPR_ASM: ptrue p{{[0-9]+}}.b +ZPR_ASM-NEXT: mov z{{[0-9]+}}.d, #0x0 +ZPR_ASM-NEXT: faddv d{{[0-9]+}}, p{{[0-9]+}}, z{{[0-9]+}} + +## FPR128 Register Class Initialization Testcase +RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=ADDVv16i8v 2>&1 +RUN: llvm-objdump -d %d > %t.s +RUN: FileCheck %s --check-prefix=FPR128-ASM < %t.s +FPR128-ASM: : +FPR128-ASM: movi v{{[0-9]+}}.2d, #0000000000000000 +FPR128-ASM-NEXT: addv b{{[0-9]+}}, v{{[0-9]+}}.16b + +## FPR64 Register Class Initialization Testcase +RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=ADDVv4i16v 2>&1 +RUN: llvm-objdump -d %d > %t.s +RUN: FileCheck %s --check-prefix=FPR64-ASM < %t.s +FPR64-ASM: : +FPR64-ASM: movi d{{[0-9]+}}, #0000000000000000 +FPR64-ASM-NEXT: addv h{{[0-9]+}}, v{{[0-9]+}}.4h diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp index 5a7cc6f5e30d3..ed36cb2f75d5b 100644 --- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp @@ -28,13 +28,52 @@ static unsigned getLoadImmediateOpcode(unsigned RegBitWidth) { // Generates instruction to load an immediate value into a register. static MCInst loadImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) { - if (Value.getBitWidth() > RegBitWidth) - llvm_unreachable("Value must fit in the Register"); + assert (Value.getBitWidth() <= RegBitWidth && + "Value must fit in the Register"); return MCInstBuilder(getLoadImmediateOpcode(RegBitWidth)) .addReg(Reg) .addImm(Value.getZExtValue()); } +static MCInst loadZPRImmediate(MCRegister Reg, unsigned RegBitWidth, + const APInt &Value) { + assert(Value.getZExtValue() < (1 << 7) && + "Value must be in the range of the immediate opcode"); + return MCInstBuilder(AArch64::DUP_ZI_D) + .addReg(Reg) + .addImm(Value.getZExtValue()) + .addImm(0); +} + +static MCInst loadPPRImmediate(MCRegister Reg, unsigned RegBitWidth, + const APInt &Value) { + // For PPR, we typically use PTRUE instruction to set predicate registers + return MCInstBuilder(AArch64::PTRUE_B) + .addReg(Reg) + .addImm(31); // All lanes true for 16 bits +} + +// Fetch base-instruction to load an FP immediate value into a register. +static unsigned getLoadFPImmediateOpcode(unsigned RegBitWidth) { + switch (RegBitWidth) { + case 64: + return AArch64::MOVID; //FMOVDi; + case 128: + return AArch64::MOVIv2d_ns; + } + llvm_unreachable("Invalid Value Width"); +} + +// Generates instruction to load an FP immediate value into a register. +static MCInst loadFPImmediate(MCRegister Reg, unsigned RegBitWidth, + const APInt &Value) { + assert(Value.getZExtValue() == 0 && + "Expected initialisation value 0"); + return MCInstBuilder(getLoadFPImmediateOpcode(RegBitWidth)) + .addReg(Reg) + .addImm(Value.getZExtValue()); +} + #include "AArch64GenExegesis.inc" namespace { @@ -51,6 +90,15 @@ class ExegesisAArch64Target : public ExegesisTarget { return {loadImmediate(Reg, 32, Value)}; if (AArch64::GPR64RegClass.contains(Reg)) return {loadImmediate(Reg, 64, Value)}; + if (AArch64::PPRRegClass.contains(Reg)) + return {loadPPRImmediate(Reg, 16, Value)}; + if (AArch64::FPR64RegClass.contains(Reg)) + return {loadFPImmediate(Reg, 64, Value)}; + if (AArch64::FPR128RegClass.contains(Reg)) + return {loadFPImmediate(Reg, 128, Value)}; + if (AArch64::ZPRRegClass.contains(Reg)) + return {loadZPRImmediate(Reg, 128, Value)}; + errs() << "setRegTo is not implemented, results will be unreliable\n"; return {}; }