[llvm] [llvm-exegesis] Adding in llvm-exegesis for Aarch64 for handling FPR8/16/32 and FPCR setReg warning (PR #130595)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Mar 11 06:30:37 PDT 2025
https://github.com/lakshayk-nv updated https://github.com/llvm/llvm-project/pull/130595
>From 5f3de2201dadbb6de8f37203d5f771adbe324925 Mon Sep 17 00:00:00 2001
From: Lakshay Kumar <lakshayk at nvidia.com>
Date: Mon, 10 Mar 2025 05:45:26 -0700
Subject: [PATCH 1/4] [llvm-exegesis] Adding support for FPR8/16/32 and FPCR
for setReg warning in Aarch64.
Current implementation (for Aarch64) in llvm-exegesis only supports
GRP32, GPR64, FPR64/128, PPR16 and ZPR128 register class, thus for
opcodes variants which used llvm-exegesis throws warning "setReg is not
implemented". This code will handle the all rest floating point register
classes and initialize the registers using appropriate base instruction. And appropriate testcases for the four register classes.
---
.../llvm-exegesis/AArch64/setReg_init_check.s | 37 ++++++++++++
.../llvm-exegesis/lib/AArch64/Target.cpp | 58 ++++++++++++++++---
2 files changed, 88 insertions(+), 7 deletions(-)
diff --git a/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s b/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s
index da28388c96094..a5ae91e6ebb3a 100644
--- a/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s
+++ b/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s
@@ -37,3 +37,40 @@ RUN: FileCheck %s --check-prefix=FPR64-ASM < %t.s
FPR64-ASM: <foo>:
FPR64-ASM: movi d{{[0-9]+}}, #0000000000000000
FPR64-ASM-NEXT: addv h{{[0-9]+}}, v{{[0-9]+}}.4h
+
+## FPR32 Register Class Initialization Testcase
+RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=FABSSr --benchmark-phase=assemble-measured-code 2>&1
+RUN: llvm-objdump -d %d > %t.s
+RUN: FileCheck %s --check-prefix=FPR32-ASM < %t.s
+FPR32-ASM: <foo>:
+FPR32-ASM: movi d{{[0-9]+}}, #0000000000000000
+FPR32-ASM-NEXT: fabs s{{[0-9]+}}, s{{[0-9]+}}
+
+
+## FPR16 Register Class Initialization Testcase
+RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=FABSHr --benchmark-phase=assemble-measured-code 2>&1
+RUN: llvm-objdump -d %d > %t.s
+RUN: FileCheck %s --check-prefix=FPR16-ASM < %t.s
+FPR16-ASM: <foo>:
+FPR16-ASM: movi d{{[0-9]+}}, #0000000000000000
+FPR16-ASM-NEXT: fabs h{{[0-9]+}}, h{{[0-9]+}}
+
+## FPR8 Register Class Initialization Testcase
+RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=SQABSv1i8 --benchmark-phase=assemble-measured-code 2>&1
+RUN: llvm-objdump -d %d > %t.s
+RUN: FileCheck %s --check-prefix=FPR8-ASM < %t.s
+FPR8-ASM: <foo>:
+FPR8-ASM: mov w{{[0-9]+}}, #0x0
+FPR8-ASM-NEXT: fmov h{{[0-9]+}}, w{{[0-9]+}}
+FPR8-ASM-NEXT: sqabs b{{[0-9]+}}, b{{[0-9]+}}
+
+
+## FPCR Register Class Initialization Testcase
+RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --opcode-name=BFCVT --benchmark-phase=assemble-measured-code 2>&1
+RUN: llvm-objdump -d %d > %t.s
+RUN: FileCheck %s --check-prefix=FPCR-ASM < %t.s
+FPCR-ASM: <foo>:
+FPCR-ASM: movi d{{[0-9]+}}, #0000000000000000
+FPCR-ASM-NEXT: mov x{{[0-9]+}}, #0x0
+FPCR-ASM-NEXT: msr FPCR, x{{[0-9]+}}
+FPCR-ASM-NEXT: bfcvt h{{[0-9]+}}, s{{[0-9]+}}
diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index ed36cb2f75d5b..026dd240708ab 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -28,8 +28,8 @@ 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) {
- assert (Value.getBitWidth() <= RegBitWidth &&
- "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());
@@ -53,9 +53,44 @@ static MCInst loadPPRImmediate(MCRegister Reg, unsigned RegBitWidth,
.addImm(31); // All lanes true for 16 bits
}
+// Generates instructions to load an immediate value into an FPCR register.
+static std::vector<MCInst>
+loadFPCRImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
+ MCRegister TempReg = AArch64::X8;
+ MCInst LoadImm = MCInstBuilder(AArch64::MOVi64imm).addReg(TempReg).addImm(0);
+ MCInst MoveToFPCR =
+ MCInstBuilder(AArch64::MSR).addImm(AArch64SysReg::FPCR).addReg(TempReg);
+ return {LoadImm, MoveToFPCR};
+}
+
+// Generates instructions to load an immediate value into an FPR8 register.
+static std::vector<MCInst>
+loadFP8Immediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
+ assert(Value.getBitWidth() <= 8 && "Value must fit in 8 bits");
+
+ // Use a temporary general-purpose register (W8) to hold the 8-bit value
+ MCRegister TempReg = AArch64::W8;
+
+ // Load the 8-bit value into a general-purpose register (W8)
+ MCInst LoadImm = MCInstBuilder(AArch64::MOVi32imm)
+ .addReg(TempReg)
+ .addImm(Value.getZExtValue());
+
+ // Move the value from the general-purpose register to the FPR16 register
+ // Convert the FPR8 register to an FPR16 register
+ MCRegister FPR16Reg = Reg + (AArch64::H0 - AArch64::B0);
+ MCInst MoveToFPR =
+ MCInstBuilder(AArch64::FMOVWHr).addReg(FPR16Reg).addReg(TempReg);
+ return {LoadImm, MoveToFPR};
+}
+
// Fetch base-instruction to load an FP immediate value into a register.
static unsigned getLoadFPImmediateOpcode(unsigned RegBitWidth) {
switch (RegBitWidth) {
+ case 16:
+ return AArch64::FMOVH0; //FMOVHi;
+ case 32:
+ return AArch64::FMOVS0; //FMOVSi;
case 64:
return AArch64::MOVID; //FMOVDi;
case 128:
@@ -67,11 +102,12 @@ static unsigned getLoadFPImmediateOpcode(unsigned RegBitWidth) {
// 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());
+ assert(Value.getZExtValue() == 0 && "Expected initialisation value 0");
+ MCInst Instructions =
+ MCInstBuilder(getLoadFPImmediateOpcode(RegBitWidth)).addReg(Reg);
+ if (RegBitWidth >= 64)
+ Instructions.addOperand(MCOperand::createImm(Value.getZExtValue()));
+ return Instructions;
}
#include "AArch64GenExegesis.inc"
@@ -92,12 +128,20 @@ class ExegesisAArch64Target : public ExegesisTarget {
return {loadImmediate(Reg, 64, Value)};
if (AArch64::PPRRegClass.contains(Reg))
return {loadPPRImmediate(Reg, 16, Value)};
+ if (AArch64::FPR8RegClass.contains(Reg))
+ return loadFP8Immediate(Reg, 8, Value);
+ if (AArch64::FPR16RegClass.contains(Reg))
+ return {loadFPImmediate(Reg, 16, Value)};
+ if (AArch64::FPR32RegClass.contains(Reg))
+ return {loadFPImmediate(Reg, 32, 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)};
+ if (Reg == AArch64::FPCR)
+ return {loadFPCRImmediate(Reg, 32, Value)};
errs() << "setRegTo is not implemented, results will be unreliable\n";
return {};
>From 62e8e36b796d6ecfae405dc7082d4741745a2411 Mon Sep 17 00:00:00 2001
From: Lakshay Kumar <lakshayk at nvidia.com>
Date: Mon, 10 Mar 2025 06:08:19 -0700
Subject: [PATCH 2/4] Modified: clang formatter changes
---
llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 026dd240708ab..abe8b24a4b541 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -88,11 +88,11 @@ loadFP8Immediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
static unsigned getLoadFPImmediateOpcode(unsigned RegBitWidth) {
switch (RegBitWidth) {
case 16:
- return AArch64::FMOVH0; //FMOVHi;
+ return AArch64::FMOVH0; // FMOVHi;
case 32:
- return AArch64::FMOVS0; //FMOVSi;
+ return AArch64::FMOVS0; // FMOVSi;
case 64:
- return AArch64::MOVID; //FMOVDi;
+ return AArch64::MOVID; // FMOVDi;
case 128:
return AArch64::MOVIv2d_ns;
}
>From b684c97ecd6e5394fb01b419a8c5d6a970fbfe3f Mon Sep 17 00:00:00 2001
From: lakshayk-nv <lakshayk at nvidia.com>
Date: Tue, 11 Mar 2025 04:46:19 -0700
Subject: [PATCH 3/4] [llvm-exegesis] Simplifying the FPR8 setReg
implementation and corresponding test cases.
---
.../llvm-exegesis/AArch64/setReg_init_check.s | 7 +++---
.../llvm-exegesis/lib/AArch64/Target.cpp | 23 +------------------
2 files changed, 4 insertions(+), 26 deletions(-)
diff --git a/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s b/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s
index a5ae91e6ebb3a..4b4fa453da709 100644
--- a/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s
+++ b/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s
@@ -60,8 +60,7 @@ RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --op
RUN: llvm-objdump -d %d > %t.s
RUN: FileCheck %s --check-prefix=FPR8-ASM < %t.s
FPR8-ASM: <foo>:
-FPR8-ASM: mov w{{[0-9]+}}, #0x0
-FPR8-ASM-NEXT: fmov h{{[0-9]+}}, w{{[0-9]+}}
+FPR8-ASM: movi d{{[0-9]+}}, #0000000000000000
FPR8-ASM-NEXT: sqabs b{{[0-9]+}}, b{{[0-9]+}}
@@ -71,6 +70,6 @@ RUN: llvm-objdump -d %d > %t.s
RUN: FileCheck %s --check-prefix=FPCR-ASM < %t.s
FPCR-ASM: <foo>:
FPCR-ASM: movi d{{[0-9]+}}, #0000000000000000
-FPCR-ASM-NEXT: mov x{{[0-9]+}}, #0x0
-FPCR-ASM-NEXT: msr FPCR, x{{[0-9]+}}
+FPCR-ASM-NEXT: mov x8, #0x0
+FPCR-ASM-NEXT: msr FPCR, x8
FPCR-ASM-NEXT: bfcvt h{{[0-9]+}}, s{{[0-9]+}}
diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index abe8b24a4b541..bf2b053003ce3 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -63,27 +63,6 @@ loadFPCRImmediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
return {LoadImm, MoveToFPCR};
}
-// Generates instructions to load an immediate value into an FPR8 register.
-static std::vector<MCInst>
-loadFP8Immediate(MCRegister Reg, unsigned RegBitWidth, const APInt &Value) {
- assert(Value.getBitWidth() <= 8 && "Value must fit in 8 bits");
-
- // Use a temporary general-purpose register (W8) to hold the 8-bit value
- MCRegister TempReg = AArch64::W8;
-
- // Load the 8-bit value into a general-purpose register (W8)
- MCInst LoadImm = MCInstBuilder(AArch64::MOVi32imm)
- .addReg(TempReg)
- .addImm(Value.getZExtValue());
-
- // Move the value from the general-purpose register to the FPR16 register
- // Convert the FPR8 register to an FPR16 register
- MCRegister FPR16Reg = Reg + (AArch64::H0 - AArch64::B0);
- MCInst MoveToFPR =
- MCInstBuilder(AArch64::FMOVWHr).addReg(FPR16Reg).addReg(TempReg);
- return {LoadImm, MoveToFPR};
-}
-
// Fetch base-instruction to load an FP immediate value into a register.
static unsigned getLoadFPImmediateOpcode(unsigned RegBitWidth) {
switch (RegBitWidth) {
@@ -129,7 +108,7 @@ class ExegesisAArch64Target : public ExegesisTarget {
if (AArch64::PPRRegClass.contains(Reg))
return {loadPPRImmediate(Reg, 16, Value)};
if (AArch64::FPR8RegClass.contains(Reg))
- return loadFP8Immediate(Reg, 8, Value);
+ return {loadFPImmediate(Reg - AArch64::B0 + AArch64::D0, 64, Value)};
if (AArch64::FPR16RegClass.contains(Reg))
return {loadFPImmediate(Reg, 16, Value)};
if (AArch64::FPR32RegClass.contains(Reg))
>From fae356f858d4e0005b267a308becefa3562d6463 Mon Sep 17 00:00:00 2001
From: lakshayk-nv <lakshayk at nvidia.com>
Date: Tue, 11 Mar 2025 06:29:50 -0700
Subject: [PATCH 4/4] [llvm-exegesis] Style nits for testcase.
---
llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s b/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s
index 4b4fa453da709..a4350fc6dc2cb 100644
--- a/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s
+++ b/llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s
@@ -60,7 +60,7 @@ RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --op
RUN: llvm-objdump -d %d > %t.s
RUN: FileCheck %s --check-prefix=FPR8-ASM < %t.s
FPR8-ASM: <foo>:
-FPR8-ASM: movi d{{[0-9]+}}, #0000000000000000
+FPR8-ASM: movi d{{[0-9]+}}, #0000000000000000
FPR8-ASM-NEXT: sqabs b{{[0-9]+}}, b{{[0-9]+}}
@@ -69,7 +69,7 @@ RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency --dump-object-to-disk=%d --op
RUN: llvm-objdump -d %d > %t.s
RUN: FileCheck %s --check-prefix=FPCR-ASM < %t.s
FPCR-ASM: <foo>:
-FPCR-ASM: movi d{{[0-9]+}}, #0000000000000000
+FPCR-ASM: movi d{{[0-9]+}}, #0000000000000000
FPCR-ASM-NEXT: mov x8, #0x0
FPCR-ASM-NEXT: msr FPCR, x8
FPCR-ASM-NEXT: bfcvt h{{[0-9]+}}, s{{[0-9]+}}
More information about the llvm-commits
mailing list