[llvm] Adding support in llvm-exegesis for Aarch64 for handling FPR64/128, PPR16 and ZPR128 reg class. (PR #127564)

via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 20 03:47:41 PST 2025


https://github.com/lakshayk-nv updated https://github.com/llvm/llvm-project/pull/127564

>From 624a7eeeb08df37b2cb7349dc3ce9bfa198d2abe Mon Sep 17 00:00:00 2001
From: Lakshay Kumar <lakshayk at nvidia.com>
Date: Mon, 17 Feb 2025 02:25:29 -0800
Subject: [PATCH 1/3] Adding support for FPR64/128, PPR16 and ZPR128 in setReg
 of llvm-exegesis for Aarch64

---
 .../llvm-exegesis/lib/AArch64/Target.cpp      | 57 ++++++++++++++++++-
 1 file changed, 56 insertions(+), 1 deletion(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 5a7cc6f5e30d3..806565a26f19b 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -35,6 +35,48 @@ static MCInst loadImmediate(MCRegister Reg, unsigned RegBitWidth,
       .addImm(Value.getZExtValue());
 }
 
+static MCInst loadZPRImmediate(MCRegister Reg, unsigned RegBitWidth,
+                               const APInt &Value) {
+  if (Value.getBitWidth() > RegBitWidth)
+    llvm_unreachable("Value must fit in the ZPR Register");
+  // For ZPR, we typically use DUPM instruction to load immediate values
+  return MCInstBuilder(AArch64::DUPM_ZI)
+      .addReg(Reg)
+      .addImm(Value.getZExtValue());
+}
+
+static MCInst loadPPRImmediate(MCRegister Reg, unsigned RegBitWidth,
+                               const APInt &Value) {
+  if (Value.getBitWidth() > RegBitWidth)
+    llvm_unreachable("Value must fit in the PPR Register");
+  // For PPR, we typically use PTRUE instruction to set predicate registers
+  return MCInstBuilder(AArch64::PTRUE_B)
+      .addReg(Reg)
+      .addImm(31); // All lanes true
+}
+
+// Generates instruction to load an FP immediate value into a register.
+static unsigned getLoadFPImmediateOpcode(unsigned RegBitWidth) {
+  switch (RegBitWidth) {
+  case 64:
+    return AArch64::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) {
+  if (Value.getBitWidth() > RegBitWidth)
+    llvm_unreachable("Value must fit in the FP Register");
+  return MCInstBuilder(getLoadFPImmediateOpcode(RegBitWidth))
+      .addReg(Reg)
+      .addImm(Value.getZExtValue());
+}
+
 #include "AArch64GenExegesis.inc"
 
 namespace {
@@ -49,8 +91,21 @@ class ExegesisAArch64Target : public ExegesisTarget {
                                const APInt &Value) const override {
     if (AArch64::GPR32RegClass.contains(Reg))
       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 {};
   }
@@ -77,4 +132,4 @@ void InitializeAArch64ExegesisTarget() {
 }
 
 } // namespace exegesis
-} // namespace llvm
+} // namespace llvm
\ No newline at end of file

>From 4c4d605ba2aa3a4b1f510bac246d7ff75eb2993a Mon Sep 17 00:00:00 2001
From: Lakshay Kumar <lakshayk at nvidia.com>
Date: Mon, 17 Feb 2025 19:51:16 -0800
Subject: [PATCH 2/3] Adding support for FPR64/128, PPR16 and ZPR128 in setReg
 of llvm-exegesis for Aarch64

---
 llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 806565a26f19b..dc312f4916703 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -91,7 +91,6 @@ class ExegesisAArch64Target : public ExegesisTarget {
                                const APInt &Value) const override {
     if (AArch64::GPR32RegClass.contains(Reg))
       return {loadImmediate(Reg, 32, Value)};
-    
     if (AArch64::GPR64RegClass.contains(Reg))
       return {loadImmediate(Reg, 64, Value)};
 

>From d34cb6d157ccc8b1abf55c71494144a42b5bb546 Mon Sep 17 00:00:00 2001
From: Lakshay Kumar <lakshayk at nvidia.com>
Date: Thu, 20 Feb 2025 02:27:00 -0800
Subject: [PATCH 3/3] Added assert that Value is in range for the generated
 instructions and testcases for patch FPR64/128, PPR, ZPR128

---
 .../AArch64/reg_based/reg_fpr128.s             |  8 ++++++++
 .../AArch64/reg_based/reg_fpr64.s              |  7 +++++++
 .../llvm-exegesis/AArch64/reg_based/reg_ppr.s  |  8 ++++++++
 .../llvm-exegesis/AArch64/reg_based/reg_zpr.s  |  8 ++++++++
 .../tools/llvm-exegesis/lib/AArch64/Target.cpp | 18 +++++++-----------
 5 files changed, 38 insertions(+), 11 deletions(-)
 create mode 100644 llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_fpr128.s
 create mode 100644 llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_fpr64.s
 create mode 100644 llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_ppr.s
 create mode 100644 llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_zpr.s

diff --git a/llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_fpr128.s b/llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_fpr128.s
new file mode 100644
index 0000000000000..210ea563b85f5
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_fpr128.s
@@ -0,0 +1,8 @@
+# RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency -opcode-name=ADDVv16i8v | FileCheck %s
+# REQUIRES: aarch64-registered-target
+
+# Check that warning of not initializing registers is not printed
+# CHECK-NOT: setRegTo is not implemented, results will be unreliable
+
+# Check that we add ret (bx lr) instr to snippet
+# CHECK: assembled_snippet: {{.*}}C0035FD6
\ No newline at end of file
diff --git a/llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_fpr64.s b/llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_fpr64.s
new file mode 100644
index 0000000000000..0a08dcc2b7715
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_fpr64.s
@@ -0,0 +1,7 @@
+# RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency -opcode-name=ADDVv4i16v 2>&1 | FileCheck %s
+
+# Check that warning of not initializing registers is not printed
+# CHECK-NOT: setRegTo is not implemented, results will be unreliable
+
+# Check that we add ret (bx lr) instr to snippet
+# CHECK: assembled_snippet: {{.*}}C0035FD6
\ No newline at end of file
diff --git a/llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_ppr.s b/llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_ppr.s
new file mode 100644
index 0000000000000..79ed1d3aaeb84
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_ppr.s
@@ -0,0 +1,8 @@
+# RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency -opcode-name=FADDV_VPZ_D | FileCheck %s
+# REQUIRES: aarch64-registered-target
+
+# Check that warning of not initializing registers is not printed
+# CHECK-NOT: setRegTo is not implemented, results will be unreliable
+
+# Check that we add ret (bx lr) instr to snippet
+# CHECK: assembled_snippet: {{.*}}C0035FD6
\ No newline at end of file
diff --git a/llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_zpr.s b/llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_zpr.s
new file mode 100644
index 0000000000000..e0d308f16c0f9
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/AArch64/reg_based/reg_zpr.s
@@ -0,0 +1,8 @@
+# RUN: llvm-exegesis -mcpu=neoverse-v2 -mode=latency -opcode-name=FADDV_VPZ_S | FileCheck %s
+# REQUIRES: aarch64-registered-target
+
+# Check that warning of not initializing registers is not printed
+# CHECK-NOT: setRegTo is not implemented, results will be unreliable
+
+# Check that we add ret (bx lr) instr to snippet
+# CHECK: assembled_snippet: {{.*}}C0035FD6
\ No newline at end of file
diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index dc312f4916703..3b0265cd22ffc 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -28,8 +28,7 @@ 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());
@@ -37,22 +36,20 @@ static MCInst loadImmediate(MCRegister Reg, unsigned RegBitWidth,
 
 static MCInst loadZPRImmediate(MCRegister Reg, unsigned RegBitWidth,
                                const APInt &Value) {
-  if (Value.getBitWidth() > RegBitWidth)
-    llvm_unreachable("Value must fit in the ZPR Register");
+  assert(Value.getBitWidth() <= RegBitWidth && "Value must fit in the PPR Register");
   // For ZPR, we typically use DUPM instruction to load immediate values
   return MCInstBuilder(AArch64::DUPM_ZI)
       .addReg(Reg)
-      .addImm(Value.getZExtValue());
+      .addImm(0x1);
 }
 
 static MCInst loadPPRImmediate(MCRegister Reg, unsigned RegBitWidth,
                                const APInt &Value) {
-  if (Value.getBitWidth() > RegBitWidth)
-    llvm_unreachable("Value must fit in the PPR Register");
+  assert(Value.getBitWidth() <= RegBitWidth && "Value must fit in the PPR Register"); 
   // For PPR, we typically use PTRUE instruction to set predicate registers
   return MCInstBuilder(AArch64::PTRUE_B)
       .addReg(Reg)
-      .addImm(31); // All lanes true
+      .addImm(0xFFFF); // All lanes true for 16 bits
 }
 
 // Generates instruction to load an FP immediate value into a register.
@@ -70,8 +67,7 @@ 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) {
-  if (Value.getBitWidth() > RegBitWidth)
-    llvm_unreachable("Value must fit in the FP Register");
+  assert(Value.getBitWidth() <= RegBitWidth && "Value must fit in the FP Register");
   return MCInstBuilder(getLoadFPImmediateOpcode(RegBitWidth))
       .addReg(Reg)
       .addImm(Value.getZExtValue());
@@ -131,4 +127,4 @@ void InitializeAArch64ExegesisTarget() {
 }
 
 } // namespace exegesis
-} // namespace llvm
\ No newline at end of file
+} // namespace llvm



More information about the llvm-commits mailing list