Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
624a7ee
Adding support for FPR64/128, PPR16 and ZPR128 in setReg of llvm-exeg…
lakshayk-nv Feb 17, 2025
4c4d605
Adding support for FPR64/128, PPR16 and ZPR128 in setReg of llvm-exeg…
lakshayk-nv Feb 18, 2025
f8ce0cc
Merge branch 'main' into llvm-exegesis-setreg
lakshayk-nv Feb 18, 2025
d34cb6d
Added assert that Value is in range for the generated instructions an…
lakshayk-nv Feb 20, 2025
566081a
Merge branch 'llvm:main' into llvm-exegesis-setreg
lakshayk-nv Feb 20, 2025
803b9e9
Merge branch 'llvm:main' into llvm-exegesis-setreg
lakshayk-nv Feb 20, 2025
3589838
Merge branch 'llvm-exegesis-setreg' of github.com:lakshayk-nv/llvm-pr…
lakshayk-nv Feb 20, 2025
53b9f0b
Added combined testfile for register initialization (PPR,ZPR,FPR64/12…
lakshayk-nv Feb 21, 2025
caebb7b
Deleted Indvidual testfiles
lakshayk-nv Feb 21, 2025
230aade
Modified: requirement(aarch64) check only required once for a test
lakshayk-nv Feb 24, 2025
aab854b
Modified: PPR register class should be set with immediate value 31 fo…
lakshayk-nv Feb 24, 2025
f1e561c
Modified: Testcases to check disassembly, apart from setReg warning a…
lakshayk-nv Feb 27, 2025
25b02b6
Modified: Fixed Typo in assertion message
lakshayk-nv Feb 27, 2025
b83b52d
Modified: Simplified regex checks for disassembly
lakshayk-nv Feb 27, 2025
433b62e
Modified: Testcases to strictly check correct order of instruction in…
lakshayk-nv Feb 28, 2025
482a0a3
Modified: Stricter asserts for checking immediate (Value) to be set i…
lakshayk-nv Mar 4, 2025
951e05e
Modified: Base-instruction of FPR64 reg class to MOVID & ZPR reg clas…
lakshayk-nv Mar 5, 2025
ea8b28b
Modified: Updated testcases checks for disassembly as be base instruc…
lakshayk-nv Mar 5, 2025
b5853a9
Modified: reverted headers
lakshayk-nv Mar 5, 2025
2c16af6
Modified: Simplified testfile to check only disassembly.
lakshayk-nv Mar 5, 2025
c21ee8b
Modified: Removed redundant comments and asserts.
lakshayk-nv Mar 5, 2025
5cda550
Modified: Revert back to asserting bit width for GPR Register classes
lakshayk-nv Mar 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions llvm/test/tools/llvm-exegesis/AArch64/setReg_init_check.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
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 | FileCheck %s --check-prefix=PPR
RUN: llvm-objdump -d %d > %t.s
RUN: FileCheck %s --check-prefix=PPR_ASM < %t.s
PPR-NOT: setRegTo is not implemented, results will be unreliable
PPR: assembled_snippet: {{.*}}C0035FD6
PPR_ASM: {{<foo>:}}
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]+}}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a nitpick, but I think we are testing the same things with:

setRegTo is not implemented, results will be unreliable

and

PPR_ASM-NEXT: dupm z{{[0-9]+}}.s, #0x1

So I think we can just test one thing, and the best thing to check is the assembly.
I also don't know what this means or is testing:

PPR: assembled_snippet: {{.*}}C0035FD6

Here's my suggestion for this test just to clean this up, and with a bit of extra formatting and spacing to make it slightly more easy to read (in my opinion):

    ## 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 | FileCheck %s --check-prefix=PPR
    RUN: llvm-objdump -d %d > %t.s
    RUN: FileCheck %s --check-prefix=PPR_ASM < %t.s

    PPR_ASM:       {{<foo>:}}
    PPR_ASM:       ptrue p{{[0-9]+}}.b
    PPR_ASM-NEXT:  dupm z{{[0-9]+}}.s, #0x1
    PPR_ASM-NEXT:  faddv d{{[0-9]+}}, p{{[0-9]+}}, z{{[0-9]+}}

Can you give the other tests below a similar treatment?

Copy link
Contributor Author

@lakshayk-nv lakshayk-nv Mar 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give the other tests below a similar treatment?

Cleaned up format in testfile. Only checking required assembly checks.

PPR: assembled_snippet: {{.*}}C0035FD6

No needed, Removed.
Just for reference, this checks for assembly snippet to end with return statement (C0035FD6 is return instruction for aarch64) i.e "Check that we add ret instr to snippet" as one of the exegesis existing test case used, took inspiration from there.

setRegTo is not implemented, results will be unreliable

and

PPR_ASM-NEXT: dupm z{{[0-9]+}}.s, #0x1

They check the same things using different commands. Thus removed.

Thanks!


## 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 | FileCheck %s --check-prefix=ZPR
RUN: llvm-objdump -d %d > %t.s
RUN: FileCheck %s --check-prefix=ZPR_ASM < %t.s
ZPR-NOT: setRegTo is not implemented, results will be unreliable
ZPR: assembled_snippet: {{.*}}C0035FD6
ZPR_ASM: {{<foo>:}}
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 | FileCheck %s --check-prefix=FPR128
RUN: llvm-objdump -d %d > %t.s
RUN: FileCheck %s --check-prefix=FPR128-ASM < %t.s
FPR128-NOT: setRegTo is not implemented, results will be unreliable
FPR128: assembled_snippet: {{.*}}C0035FD6
FPR128-ASM: {{<foo>:}}
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 | FileCheck %s --check-prefix=FPR64
RUN: llvm-objdump -d %d > %t.s
RUN: FileCheck %s --check-prefix=FPR64-ASM < %t.s
FPR64-NOT: setRegTo is not implemented, results will be unreliable
FPR64: assembled_snippet: {{.*}}C0035FD6
FPR64-ASM: {{<foo>:}}
## For FMOVDi base-instruction : fmov d{{[0-9]+}}, {{#2.0+|#2\.000000000000000000e\+00}}
FPR64-ASM: movi d{{[0-9]+}}, #0000000000000000
FPR64-ASM-NEXT: addv h{{[0-9]+}}, v{{[0-9]+}}.4h
58 changes: 56 additions & 2 deletions llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,58 @@ 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");
// 0 <= Value.getZExtValue() < 2**16
assert(Value.getZExtValue() < (1 << 16) &&
"Value must be in the range of the immediate opcode");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MOVi32imm and MOVi64imm are pseudo's that should be able to handle any immedated AFAIU. They should be expanded later into a series of MOVs if needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, MOVi32imm and MOVi64imm are pseudo-instructions that decompose into the MOV instruction, such as mov w21, #0x0, as seen in disassembly using GPR32/64 for opcodes like LSRVWr.
The assertion primarily ensures codebase consistency. In practice, setRegTo is almost always used to set a register to zero.
Since the MOV instruction accepts a 16-bit immediate, the upper bound check is set to 2^16 accordingly. [Referred ISA doc here].

PS: I tried with larger value setting using the pseudo, it works for larger values than 2^16. In my opinion, we can skip the assert. What do you think ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah removing this assert sounds OK to me.

return MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
.addReg(Reg)
.addImm(Value.getZExtValue());
}

static MCInst loadZPRImmediate(MCRegister Reg, unsigned RegBitWidth,
const APInt &Value) {
// -127 <= Value.getZExtValue() < 128
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) {
// 0 <= Value.getZExtValue() < 2**8 (int Value)
// -31.0 <= Value.getZExtValue() < 31.0 (frac Value)
assert(Value.getZExtValue() == 0 &&
"Value should be zero, temporary fix for now");
assert(Value.getZExtValue() < (1 << 8) &&
"Value must be in the range of the immediate opcode");
return MCInstBuilder(getLoadFPImmediateOpcode(RegBitWidth))
.addReg(Reg)
.addImm(Value.getZExtValue());
}

#include "AArch64GenExegesis.inc"

namespace {
Expand All @@ -51,6 +96,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 {};
}
Expand Down