-
Notifications
You must be signed in to change notification settings - Fork 14.2k
[Exegesis] Implemented strategy for load operation #113458
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-tools-llvm-exegesis Author: None (AnastasiyaChernikova) ChangesThis 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. Full diff: https://github.com/llvm/llvm-project/pull/113458.diff 1 Files Affected:
diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
index 7100b51bbb7298..ac4881f298618d 100644
--- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
@@ -113,7 +113,51 @@ 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;
+ auto &ET = State.getExegesisTarget();
+ auto ScratchMemoryRegister = ET.getScratchMemoryRegister(
+ State.getTargetMachine().getTargetTriple());
+ auto &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;
+ if (CT.ScratchSpacePointerInReg == 0)
+ CT.ScratchSpacePointerInReg = ScratchMemoryRegister;
+
+ CT.Info = std::string(ExecutionClassDescription);
+ CT.Instructions.push_back(std::move(Variant));
+ CT.PreinitScratchMemory.emplace_back(ScratchMemoryRegister,
+ /* Offset */ 0);
+ CodeTemplates.push_back(std::move(CT));
+ }
+
+ // TODO: implement more cases
return;
}
case ExecutionMode::SERIAL_VIA_EXPLICIT_REGS: {
|
016057e
to
52cad46
Compare
@legrosbuffle @mshockwave @topperc @boomanaiden154 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have any test? Or does this depend on #89047
Yes, this is part of #89047, which was asked to be discussed in this comment (#89047 (comment)). This only affects boot support for riscv, it doesn't change anything on other platforms (I looked at the --opcode-index=-1 entries in the add code for all supported architectures). Since the commit with riscv support hasn't been pushed yet, I can't add tests here. |
Is it possible to write test with other platforms, like ARM? If not, could you add a line in the PR description that this PR is stacked on top of #89047 ? |
auto DefOpIt = find_if(I.Operands, [](Operand const &op) { | ||
return op.isDef() && op.isReg(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auto DefOpIt = find_if(I.Operands, [](Operand const &op) { | |
return op.isDef() && op.isReg(); | |
}); | |
auto DefOpIt = find_if(I.Operands, [](Operand const &Op) { | |
return Op.isDef() && Op.isReg(); | |
}); |
Uppercase
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
|
||
CodeTemplate CT; | ||
CT.Execution = ExecutionModeBit; | ||
if (CT.ScratchSpacePointerInReg == 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You just created CT
a few lines back, is it possible that ScratchSpacePointerInReg
is not zero at this point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
auto &ET = State.getExegesisTarget(); | ||
auto ScratchMemoryRegister = ET.getScratchMemoryRegister( | ||
State.getTargetMachine().getTargetTriple()); | ||
auto &RegClass = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please spell out the auto here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
@@ -132,6 +132,9 @@ struct CodeTemplate { | |||
// If the template uses the provided scratch memory, the register in which | |||
// the pointer to this memory is passed in to the function. | |||
unsigned ScratchSpacePointerInReg = 0; | |||
// Require to pre-store value of a given register (fisrt) | |||
// to scratch memory with given offset (second) | |||
SmallVector<std::pair<unsigned, unsigned>, 2> PreinitScratchMemory; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this field is populated, but where is it used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed
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.
52cad46
to
3508c76
Compare
@mshockwave @legrosbuffle @topperc @boomanaiden154 I answered all the comments, please take a look |
@mshockwave @legrosbuffle @topperc @boomanaiden154 I look forward to further review |
@mshockwave @legrosbuffle @topperc @boomanaiden154 Please take a look |
@mshockwave, do you have any objections for this? |
It's been a month and there was no objections and this patch is LGTM, so I would say that it is good to merge. I'll wait till the end of this week though, so original reviews may take a look once more @mshockwave @legrosbuffle @topperc @boomanaiden154 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for being late. I only have one comment on the test file. LGTM now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One nit, otherwise seems reasonable enough to me.
const ExegesisTarget &ET = State.getExegesisTarget(); | ||
unsigned ScratchMemoryRegister = ET.getScratchMemoryRegister( | ||
State.getTargetMachine().getTargetTriple()); | ||
const llvm::MCRegisterClass &RegClass = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: We can drop the llvm::
here.
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 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.