[Exegesis] Implemented strategy for load operation (#113458)

This fix helps to map operand memory to destination registers. If
instruction is load, we can self-alias it in case when instruction
overrides whole address register. For that we use provided scratch
memory.
This commit is contained in:
AnastasiyaChernikova 2025-03-04 13:16:55 +03:00 committed by GitHub
parent d0eeeab557
commit 0fcbf148df
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 102 additions and 1 deletions

View File

@ -0,0 +1,60 @@
# RUN: llvm-exegesis -mode=latency --benchmark-phase=assemble-measured-code -mtriple=riscv64-unknown-linux-gnu --mcpu=generic -opcode-name=LD 2>&1 | FileCheck --check-prefix=TEST1 %s
TEST1: ---
TEST1-NEXT: mode: latency
TEST1-NEXT: key:
TEST1-NEXT: instructions:
TEST1-NEXT: - 'LD X10 X10 i_0x0'
# RUN: llvm-exegesis -mode=latency --benchmark-phase=assemble-measured-code -mtriple=riscv64-unknown-linux-gnu --mcpu=generic -opcode-name=LW 2>&1 | FileCheck --check-prefix=TEST2 %s
TEST2: ---
TEST2-NEXT: mode: latency
TEST2-NEXT: key:
TEST2-NEXT: instructions:
TEST2-NEXT: - 'LW X10 X10 i_0x0'
# RUN: llvm-exegesis -mode=latency --benchmark-phase=assemble-measured-code -mtriple=riscv64-unknown-linux-gnu --mcpu=generic -opcode-name=LH 2>&1 | FileCheck --check-prefix=TEST3 %s
TEST3: ---
TEST3-NEXT: mode: latency
TEST3-NEXT: key:
TEST3-NEXT: instructions:
TEST3-NEXT: - 'LH X10 X10 i_0x0'
# RUN: llvm-exegesis -mode=latency --benchmark-phase=assemble-measured-code -mtriple=riscv64-unknown-linux-gnu --mcpu=generic -opcode-name=LWU 2>&1 | FileCheck --check-prefix=TEST4 %s
TEST4: ---
TEST4-NEXT: mode: latency
TEST4-NEXT: key:
TEST4-NEXT: instructions:
TEST4-NEXT: - 'LWU X10 X10 i_0x0'
# RUN: llvm-exegesis -mode=latency --benchmark-phase=assemble-measured-code -mtriple=riscv64-unknown-linux-gnu --mcpu=generic -opcode-name=LBU 2>&1 | FileCheck --check-prefix=TEST5 %s
TEST5: ---
TEST5-NEXT: mode: latency
TEST5-NEXT: key:
TEST5-NEXT: instructions:
TEST5-NEXT: - 'LBU X10 X10 i_0x0'
# RUN: llvm-exegesis -mode=latency --benchmark-phase=assemble-measured-code -mtriple=riscv64-unknown-linux-gnu --mcpu=generic -opcode-name=LUI 2>&1 | FileCheck --check-prefix=TEST6 %s
TEST6: LUI: No strategy found to make the execution serial
# RUN: llvm-exegesis -mode=latency --benchmark-phase=assemble-measured-code -mtriple=riscv64-unknown-linux-gnu --mcpu=generic -opcode-name=LB 2>&1 | FileCheck --check-prefix=TEST7 %s
TEST7: ---
TEST7-NEXT: mode: latency
TEST7-NEXT: key:
TEST7-NEXT: instructions:
TEST7-NEXT: - 'LB X10 X10 i_0x0'
# RUN: llvm-exegesis -mode=latency --benchmark-phase=assemble-measured-code -mtriple=riscv64-unknown-linux-gnu --mcpu=generic -mattr=+a -opcode-name=LR_W_RL 2>&1 | FileCheck --check-prefix=TEST8 %s
TEST8: ---
TEST8-NEXT: mode: latency
TEST8-NEXT: key:
TEST8-NEXT: instructions:
TEST8-NEXT: - 'LR_W_RL X10 X10'

View File

@ -106,7 +106,48 @@ static void appendCodeTemplates(const LLVMState &State,
}
case ExecutionMode::SERIAL_VIA_MEMORY_INSTR: {
// Select back-to-back memory instruction.
// TODO: Implement me.
auto &I = Variant.getInstr();
if (I.Description.mayLoad()) {
// If instruction is load, we can self-alias it in case when instruction
// overrides whole address register. For that we use provided scratch
// memory.
// TODO: now it is not checked if load writes the whole register.
auto DefOpIt = find_if(I.Operands, [](Operand const &Op) {
return Op.isDef() && Op.isReg();
});
if (DefOpIt == I.Operands.end())
return;
const Operand &DefOp = *DefOpIt;
const ExegesisTarget &ET = State.getExegesisTarget();
unsigned ScratchMemoryRegister = ET.getScratchMemoryRegister(
State.getTargetMachine().getTargetTriple());
const llvm::MCRegisterClass &RegClass =
State.getTargetMachine().getMCRegisterInfo()->getRegClass(
DefOp.getExplicitOperandInfo().RegClass);
// Register classes of def operand and memory operand must be the same
// to perform aliasing.
if (!RegClass.contains(ScratchMemoryRegister))
return;
ET.fillMemoryOperands(Variant, ScratchMemoryRegister, 0);
Variant.getValueFor(DefOp) = MCOperand::createReg(ScratchMemoryRegister);
CodeTemplate CT;
CT.Execution = ExecutionModeBit;
CT.ScratchSpacePointerInReg = ScratchMemoryRegister;
CT.Info = std::string(ExecutionClassDescription);
CT.Instructions.push_back(std::move(Variant));
CodeTemplates.push_back(std::move(CT));
}
// TODO: implement more cases
return;
}
case ExecutionMode::SERIAL_VIA_EXPLICIT_REGS: {