mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 00:46:05 +00:00
[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:
parent
d0eeeab557
commit
0fcbf148df
60
llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s
Normal file
60
llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s
Normal 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'
|
@ -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: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user