Skip to content

Commit 52cad46

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 eb9af19 commit 52cad46

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
@@ -113,7 +113,51 @@ static void appendCodeTemplates(const LLVMState &State,
113113
}
114114
case ExecutionMode::SERIAL_VIA_MEMORY_INSTR: {
115115
// Select back-to-back memory instruction.
116-
// TODO: Implement me.
116+
117+
auto &I = Variant.getInstr();
118+
if (I.Description.mayLoad()) {
119+
// If instruction is load, we can self-alias it in case when instruction
120+
// overrides whole address register. For that we use provided scratch
121+
// memory.
122+
123+
// TODO: now it is not checked if load writes the whole register.
124+
125+
auto DefOpIt = find_if(I.Operands, [](Operand const &op) {
126+
return op.isDef() && op.isReg();
127+
});
128+
129+
if (DefOpIt == I.Operands.end())
130+
return;
131+
132+
const Operand &DefOp = *DefOpIt;
133+
auto &ET = State.getExegesisTarget();
134+
auto ScratchMemoryRegister = ET.getScratchMemoryRegister(
135+
State.getTargetMachine().getTargetTriple());
136+
auto &RegClass =
137+
State.getTargetMachine().getMCRegisterInfo()->getRegClass(
138+
DefOp.getExplicitOperandInfo().RegClass);
139+
140+
// Register classes of def operand and memory operand must be the same
141+
// to perform aliasing.
142+
if (!RegClass.contains(ScratchMemoryRegister))
143+
return;
144+
145+
ET.fillMemoryOperands(Variant, ScratchMemoryRegister, 0);
146+
Variant.getValueFor(DefOp) = MCOperand::createReg(ScratchMemoryRegister);
147+
148+
CodeTemplate CT;
149+
CT.Execution = ExecutionModeBit;
150+
if (CT.ScratchSpacePointerInReg == 0)
151+
CT.ScratchSpacePointerInReg = ScratchMemoryRegister;
152+
153+
CT.Info = std::string(ExecutionClassDescription);
154+
CT.Instructions.push_back(std::move(Variant));
155+
CT.PreinitScratchMemory.emplace_back(ScratchMemoryRegister,
156+
/* Offset */ 0);
157+
CodeTemplates.push_back(std::move(CT));
158+
}
159+
160+
// TODO: implement more cases
117161
return;
118162
}
119163
case ExecutionMode::SERIAL_VIA_EXPLICIT_REGS: {

0 commit comments

Comments
 (0)