Skip to content

[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

Merged
merged 3 commits into from
Mar 4, 2025

Conversation

AnastasiyaChernikova
Copy link
Contributor

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.

@llvmbot
Copy link
Member

llvmbot commented Oct 23, 2024

@llvm/pr-subscribers-tools-llvm-exegesis

Author: None (AnastasiyaChernikova)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/113458.diff

1 Files Affected:

  • (modified) llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp (+45-1)
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: {

@AnastasiyaChernikova
Copy link
Contributor Author

AnastasiyaChernikova commented Oct 28, 2024

@legrosbuffle @mshockwave @topperc @boomanaiden154
Please take a look

Copy link
Member

@mshockwave mshockwave left a 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

@AnastasiyaChernikova
Copy link
Contributor Author

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.

@mshockwave
Copy link
Member

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 ?

Comment on lines 125 to 118
auto DefOpIt = find_if(I.Operands, [](Operand const &op) {
return op.isDef() && op.isReg();
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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

Copy link
Contributor Author

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)
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed

Comment on lines 133 to 136
auto &ET = State.getExegesisTarget();
auto ScratchMemoryRegister = ET.getScratchMemoryRegister(
State.getTargetMachine().getTargetTriple());
auto &RegClass =
Copy link
Member

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

Copy link
Contributor Author

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;
Copy link
Member

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?

Copy link
Contributor Author

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.
@AnastasiyaChernikova
Copy link
Contributor Author

@mshockwave @legrosbuffle @topperc @boomanaiden154 I answered all the comments, please take a look

@AnastasiyaChernikova
Copy link
Contributor Author

@mshockwave @legrosbuffle @topperc @boomanaiden154 I look forward to further review

@AnastasiyaChernikova
Copy link
Contributor Author

@mshockwave @legrosbuffle @topperc @boomanaiden154 Please take a look

@dybv-sc
Copy link
Contributor

dybv-sc commented Feb 4, 2025

@mshockwave, do you have any objections for this?

@dybv-sc
Copy link
Contributor

dybv-sc commented Mar 3, 2025

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

Copy link
Member

@mshockwave mshockwave left a 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

Copy link
Contributor

@boomanaiden154 boomanaiden154 left a 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 =
Copy link
Contributor

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.

@dybv-sc dybv-sc merged commit 0fcbf14 into llvm:main Mar 4, 2025
8 checks passed
jph-13 pushed a commit to jph-13/llvm-project that referenced this pull request Mar 21, 2025
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants