Skip to content

Commit 4acd123

Browse files
[Exegesis] Implemented strategy for load operation
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.
1 parent b2073fb commit 4acd123

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

llvm/tools/llvm-exegesis/lib/CodeTemplate.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ struct CodeTemplate {
132132
// If the template uses the provided scratch memory, the register in which
133133
// the pointer to this memory is passed in to the function.
134134
unsigned ScratchSpacePointerInReg = 0;
135+
// Require to pre-store value of a given register (fisrt)
136+
// to scratch memory with given offset (second)
137+
SmallVector<std::pair<unsigned, unsigned>, 2> PreinitScratchMemory;
135138

136139
#if defined(__GNUC__) && (defined(__clang__) || LLVM_GNUC_PREREQ(8, 0, 0))
137140
// FIXME: GCC7 bug workaround. Drop #if after GCC7 no longer supported.

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

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,51 @@ static void appendCodeTemplates(const LLVMState &State,
104104
}
105105
case ExecutionMode::SERIAL_VIA_MEMORY_INSTR: {
106106
// Select back-to-back memory instruction.
107-
// TODO: Implement me.
107+
108+
auto &I = Variant.getInstr();
109+
if (I.Description.mayLoad()) {
110+
// If instruction is load, we can self-alias it in case when instruction
111+
// overrides whole address register. For that we use provided scratch
112+
// memory.
113+
114+
// TODO: now it is not checked if load writes the whole register.
115+
116+
auto DefOpIt = find_if(I.Operands, [](Operand const &op) {
117+
return op.isDef() && op.isReg();
118+
});
119+
120+
if (DefOpIt == I.Operands.end())
121+
return;
122+
123+
const Operand &DefOp = *DefOpIt;
124+
auto &ET = State.getExegesisTarget();
125+
auto ScratchMemoryRegister = ET.getScratchMemoryRegister(
126+
State.getTargetMachine().getTargetTriple());
127+
auto &RegClass =
128+
State.getTargetMachine().getMCRegisterInfo()->getRegClass(
129+
DefOp.getExplicitOperandInfo().RegClass);
130+
131+
// Register classes of def operand and memory operand must be the same
132+
// to perform aliasing.
133+
if (!RegClass.contains(ScratchMemoryRegister))
134+
return;
135+
136+
ET.fillMemoryOperands(Variant, ScratchMemoryRegister, 0);
137+
Variant.getValueFor(DefOp) = MCOperand::createReg(ScratchMemoryRegister);
138+
139+
CodeTemplate CT;
140+
CT.Execution = ExecutionModeBit;
141+
if (CT.ScratchSpacePointerInReg == 0)
142+
CT.ScratchSpacePointerInReg = ScratchMemoryRegister;
143+
144+
CT.Info = std::string(ExecutionClassDescription);
145+
CT.Instructions.push_back(std::move(Variant));
146+
CT.PreinitScratchMemory.emplace_back(ScratchMemoryRegister,
147+
/* Offset */ 0);
148+
CodeTemplates.push_back(std::move(CT));
149+
}
150+
151+
// TODO: implement more cases
108152
return;
109153
}
110154
case ExecutionMode::SERIAL_VIA_EXPLICIT_REGS: {

0 commit comments

Comments
 (0)