Skip to content

Commit 2e8ecf7

Browse files
authored
[llvm-exegesis] [AArch64] Resolving "not all operands are initialized by snippet generator" (#142529)
Exegesis for AArch64 arch, before this patch only handles/initialise Immediate and Register Operands. For opcodes requiring rest operand types exegesis exits with Error: `"not all operands are initialised by snippet generator"`. To resolve a given error we have to initialise required operand types. i.e., For `"not all operands are initialised by snippet generator"` init `OPERAND_SHIFT_MSL`, `OPERAND_PCREL`, And For `"targets with target-specific operands should implement this"` init `OPERAND_FIRST_TARGET`. This PR adds support to the following opcodes:- - OPERAND_SHIFT_MSL: `[MOVI|MVNI]_[2s|4s]_msl`. - OPERAND_PCREL: `LDR[R|X|W|SW|D|S|Q]l` - OPERAND_IMPLICIT_IMM_0: `[UMOV|SMOV]v[i8|i16|i32|i64|i8to32|i8to64|i16to32|i32to64|i16to64]_idx0` --- ### [Experiment/Learnings] Moreover, We found out we can similarly omit `OPERAND_UNKNOWN` with immediate value of 0. This brute force fix helps us get major part of (`~1000`) opcodes which throw un-init operands error. But, The correct way to resolve is to introduce `OperandType` in AArch64 tablegen files for opcode which have `OPERND_UNKNOWN` in `AArch64GenInstrInfo.inc`. And add switch case for those `OperandType` in the `randomizeTargetMCOperand()`. As, side-effect to this temporary fix that we explored is listed below system-level instructions throws `illegal instruction` i.e. for`MRS, MSR, MSRpstatesvcrImm1, SYSLxt, SYSxt, UDF`. This patch in `--mode=inverse_throughput` for opcodes `MRS, MSR, MSRpstatesvcrImm1, SYSLxt, SYSxt, UDF` exits with handled error of `snippet crashed while running: Illegal instruction`, they previously used to exits with error `not all operands initialized by snippet generator`. [For completeness] Additionally, exegesis beforehand and with this patch too, throws illegal instruction in throughput mode, for these opcodes too (`APAS, DCPS1, DCPS2, DCPS3, HLT, HVC, SMC, STGM, STZGM`). Will look into them later. --- ### [Summary] Thus, Only introduced changes in implementation of `randomizeTargetMCOperand()` for AArch64 that omitting `OPERAND_SHIFT_MSL`, `OPERAND_PCREL` to an immediate value of 264 and 8 respectively. PS: Omitting `MCOI::OPERAND_FIRST_TARGET`/`llvm:AArch64:OPERAND_IMPLICIT_IMM_0` similarly, to value 0. It was low hanging change thus added in this PR only. For any future operand type of AArch64 if not initialised will exit with error `"Unimplemented operand type: MCOI::OperandType:<#Number>"`.
1 parent 020dff4 commit 2e8ecf7

File tree

5 files changed

+141
-2
lines changed

5 files changed

+141
-2
lines changed

llvm/lib/Target/AArch64/AArch64InstrFormats.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,6 +1327,8 @@ def move_vec_shift : Operand<i32> {
13271327
let PrintMethod = "printShifter";
13281328
let EncoderMethod = "getMoveVecShifterOpValue";
13291329
let ParserMatchClass = MoveVecShifterOperand;
1330+
let OperandType = "OPERAND_SHIFT_MSL";
1331+
let OperandNamespace = "AArch64";
13301332
}
13311333

13321334
let DiagnosticType = "AddSubSecondSource" in {

llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCTargetDesc.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,16 @@ void initLLVMToCVRegMapping(MCRegisterInfo *MRI);
6565
bool isHForm(const MCInst &MI, const MCInstrInfo *MCII);
6666
bool isQForm(const MCInst &MI, const MCInstrInfo *MCII);
6767
bool isFpOrNEON(const MCInst &MI, const MCInstrInfo *MCII);
68-
}
68+
} // namespace AArch64_MC
6969

7070
namespace AArch64 {
7171
enum OperandType {
7272
OPERAND_IMPLICIT_IMM_0 = MCOI::OPERAND_FIRST_TARGET,
73+
OPERAND_SHIFT_MSL,
7374
};
7475
} // namespace AArch64
7576

76-
} // End llvm namespace
77+
} // namespace llvm
7778

7879
// Defines symbolic names for AArch64 registers. This defines a mapping from
7980
// register name to register number.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# REQUIRES: aarch64-registered-target
2+
3+
4+
5+
// Test for omitting OperandType::OPERAND_SHIFT_MSL
6+
7+
// MOVIv2s_msl: MOVI vd, #imm{, shift}
8+
# RUN: llvm-exegesis --mtriple=aarch64 --mcpu=neoverse-v2 --mode=latency --benchmark-phase=prepare-and-assemble-snippet --opcode-name=MOVIv4s_msl 2>&1 | FileCheck %s --check-prefix=MOVIv4s_msl_latency
9+
# RUN: llvm-exegesis --mtriple=aarch64 --mcpu=neoverse-v2 --mode=inverse_throughput --benchmark-phase=prepare-and-assemble-snippet --opcode-name=MOVIv4s_msl 2>&1 | FileCheck %s --check-prefix=MOVIv4s_msl_throughput
10+
# MOVIv4s_msl_latency-NOT: Not all operands were initialized by the snippet generator for MOVIv4s_msl opcode
11+
12+
// TODO: Add test to check if the immediate value is correct when serial execution strategy is added for MOVIv4s_msl
13+
14+
15+
# MOVIv4s_msl_throughput-NOT: Not all operands were initialized by the snippet generator for MOVIv4s_msl opcode
16+
# MOVIv4s_msl_throughput: ---
17+
# MOVIv4s_msl_throughput-NEXT: mode: inverse_throughput
18+
# MOVIv4s_msl_throughput-NEXT: key:
19+
# MOVIv4s_msl_throughput-NEXT: instructions:
20+
# MOVIv4s_msl_throughput-NEXT: MOVIv4s_msl [[REG1:Q[0-9]+|LR]] i_0x1 i_0x108
21+
# MOVIv4s_msl_throughput: ...
22+
23+
// MOVIv2s_msl: MOVI vd, #imm{, shift}
24+
# RUN: llvm-exegesis --mtriple=aarch64 --mcpu=neoverse-v2 --mode=latency --benchmark-phase=prepare-and-assemble-snippet --opcode-name=MOVIv2s_msl 2>&1 | FileCheck %s --check-prefix=MOVIv2s_msl_latency
25+
# RUN: llvm-exegesis --mtriple=aarch64 --mcpu=neoverse-v2 --mode=inverse_throughput --benchmark-phase=prepare-and-assemble-snippet --opcode-name=MOVIv2s_msl 2>&1 | FileCheck %s --check-prefix=MOVIv2s_msl_throughput
26+
# MOVIv2s_msl_latency-NOT: Not all operands were initialized by the snippet generator for MOVIv2s_msl opcode
27+
28+
// TODO: Add test to check if the immediate value is correct when serial execution strategy is added for MOVIv2s_msl
29+
30+
31+
# MOVIv2s_msl_throughput-NOT: Not all operands were initialized by the snippet generator for MOVIv2s_msl opcode
32+
# MOVIv2s_msl_throughput: ---
33+
# MOVIv2s_msl_throughput-NEXT: mode: inverse_throughput
34+
# MOVIv2s_msl_throughput-NEXT: key:
35+
# MOVIv2s_msl_throughput-NEXT: instructions:
36+
# MOVIv2s_msl_throughput-NEXT: MOVIv2s_msl [[REG1:D[0-9]+|LR]] i_0x1 i_0x108
37+
# MOVIv2s_msl_throughput: ...
38+
39+
40+
41+
// Test for omitting OperandType::OPERAND_PCREL
42+
// LDRDl: LDRD ldr1, ldr2, [pc, #imm]
43+
# RUN: llvm-exegesis --mtriple=aarch64 --mcpu=neoverse-v2 --mode=latency --benchmark-phase=prepare-and-assemble-snippet --opcode-name=LDRDl 2>&1 | FileCheck %s --check-prefix=LDRDl_latency
44+
# RUN: llvm-exegesis --mtriple=aarch64 --mcpu=neoverse-v2 --mode=inverse_throughput --benchmark-phase=prepare-and-assemble-snippet --opcode-name=LDRDl 2>&1 | FileCheck %s --check-prefix=LDRDl_throughput
45+
46+
# LDRDl_latency-NOT: Not all operands were initialized by the snippet generator for LDRDl opcodes
47+
# LDRDl_throughput-NOT: Not all operands were initialized by the snippet generator for LDRDl opcodes
48+
49+
# LDRDl_throughput: ---
50+
# LDRDl_throughput-NEXT: mode: inverse_throughput
51+
# LDRDl_throughput-NEXT: key:
52+
# LDRDl_throughput-NEXT: instructions:
53+
# LDRDl_throughput-NEXT: LDRDl [[REG1:D[0-9]+|LR]] i_0x8
54+
# LDRDl_throughput: ...
55+
56+
57+
58+
// Test for omitting OperandType::OPERAND_IMPLICIT_IMM_0
59+
60+
// UMOVvi16_idx0: UMOV wd, vn.h[index]
61+
# RUN: llvm-exegesis --mtriple=aarch64 --mcpu=neoverse-v2 --mode=latency --benchmark-phase=prepare-and-assemble-snippet --opcode-name=UMOVvi16_idx0 2>&1 | FileCheck %s --check-prefix=UMOVvi16_idx0_latency
62+
# RUN: llvm-exegesis --mtriple=aarch64 --mcpu=neoverse-v2 --mode=inverse_throughput --benchmark-phase=prepare-and-assemble-snippet --opcode-name=UMOVvi16_idx0 2>&1 | FileCheck %s --check-prefix=UMOVvi16_idx0_throughput
63+
64+
# UMOVvi16_idx0_latency-NOT: Not all operands were initialized by the snippet generator for UMOVvi16_idx0 opcode
65+
# UMOVvi16_idx0_latency: ---
66+
# UMOVvi16_idx0_latency-NEXT: mode: latency
67+
# UMOVvi16_idx0_latency-NEXT: key:
68+
# UMOVvi16_idx0_latency-NEXT: instructions:
69+
# UMOVvi16_idx0_latency-NEXT: UMOVvi16_idx0 [[REG1:W[0-9]+|LR]] [[REG2:Q[0-9]+|LR]] i_0x0
70+
# UMOVvi16_idx0_latency: ...
71+
72+
# UMOVvi16_idx0_throughput-NOT: Not all operands were initialized by the snippet generator for UMOVvi16_idx0 opcode
73+
# UMOVvi16_idx0_throughput: ---
74+
# UMOVvi16_idx0_throughput-NEXT: mode: inverse_throughput
75+
# UMOVvi16_idx0_throughput-NEXT: key:
76+
# UMOVvi16_idx0_throughput-NEXT: instructions:
77+
# UMOVvi16_idx0_throughput-NEXT: UMOVvi16_idx0 [[REG1:W[0-9]+|LR]] [[REG2:Q[0-9]+|LR]] i_0x0
78+
# UMOVvi16_idx0_throughput: ...

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

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ class ExegesisAArch64Target : public ExegesisTarget {
119119
ExegesisAArch64Target()
120120
: ExegesisTarget(AArch64CpuPfmCounters, AArch64_MC::isOpcodeAvailable) {}
121121

122+
Error randomizeTargetMCOperand(const Instruction &Instr, const Variable &Var,
123+
MCOperand &AssignedValue,
124+
const BitVector &ForbiddenRegs) const override;
125+
122126
private:
123127
std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, MCRegister Reg,
124128
const APInt &Value) const override {
@@ -182,6 +186,56 @@ class ExegesisAArch64Target : public ExegesisTarget {
182186
}
183187
};
184188

189+
Error ExegesisAArch64Target::randomizeTargetMCOperand(
190+
const Instruction &Instr, const Variable &Var, MCOperand &AssignedValue,
191+
const BitVector &ForbiddenRegs) const {
192+
const Operand &Op = Instr.getPrimaryOperand(Var);
193+
const auto OperandType = Op.getExplicitOperandInfo().OperandType;
194+
// NOTE: To resolve "Not all operands were initialized by snippet generator"
195+
// Requires OperandType to be defined for such opcode's operands in AArch64
196+
// tablegen files. And omit introduced OperandType(s).
197+
198+
// Hacky temporary fix works by defaulting all OPERAND_UNKNOWN to
199+
// immediate value 0, but this introduce illegal instruction error for below
200+
// system instructions will need to be omitted with OperandType or opcode
201+
// specific values to avoid generating invalid encodings or unreliable
202+
// benchmark results for these system-level instructions.
203+
// Implement opcode-specific immediate value handling for system instrs:
204+
// - MRS/MSR: Use valid system register encodings (e.g., NZCV, FPCR, FPSR)
205+
// - MSRpstatesvcrImm1: Use valid PSTATE field encodings (e.g., SPSel,
206+
// DAIFSet)
207+
// - SYSLxt/SYSxt: Use valid system instruction encodings with proper
208+
// CRn/CRm/op values
209+
// - UDF: Use valid undefined instruction immediate ranges (0-65535)
210+
211+
switch (OperandType) {
212+
// MSL (Masking Shift Left) imm operand for 32-bit splatted SIMD constants
213+
// Correspond to AArch64InstructionSelector::tryAdvSIMDModImm321s()
214+
case llvm::AArch64::OPERAND_SHIFT_MSL: {
215+
// There are two valid encodings:
216+
// - Type 7: imm at [15:8], [47:40], shift = 264 (0x108) → msl #8
217+
// - Type 8: imm at [23:16], [55:48], shift = 272 (0x110) → msl #16
218+
// Corresponds AArch64_AM::encodeAdvSIMDModImmType7()
219+
// But, v2s_msl and v4s_msl instructions accept either form,
220+
// Thus, Arbitrarily chosing 264 (msl #8) for simplicity.
221+
AssignedValue = MCOperand::createImm(264);
222+
return Error::success();
223+
}
224+
case llvm::AArch64::OPERAND_IMPLICIT_IMM_0:
225+
AssignedValue = MCOperand::createImm(0);
226+
return Error::success();
227+
case MCOI::OperandType::OPERAND_PCREL:
228+
AssignedValue = MCOperand::createImm(8);
229+
return Error::success();
230+
default:
231+
break;
232+
}
233+
234+
return make_error<Failure>(
235+
Twine("Unimplemented operand type: MCOI::OperandType:")
236+
.concat(Twine(static_cast<int>(OperandType))));
237+
}
238+
185239
} // namespace
186240

187241
static ExegesisTarget *getTheExegesisAArch64Target() {

llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,10 @@ static Error randomizeMCOperand(const LLVMState &State,
276276
AssignedValue = MCOperand::createReg(randomBit(AllowedRegs));
277277
break;
278278
}
279+
/// Omit pc-relative operands to imm value based on the instruction
280+
case MCOI::OperandType::OPERAND_PCREL:
281+
return State.getExegesisTarget().randomizeTargetMCOperand(
282+
Instr, Var, AssignedValue, ForbiddenRegs);
279283
default:
280284
break;
281285
}

0 commit comments

Comments
 (0)