Skip to content

Make Ownership of MachineModuleInfo in Its Wrapper Pass External #110443

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

Open
wants to merge 21 commits into
base: main
Choose a base branch
from

Conversation

matinraayai
Copy link
Contributor

Following up on discussions in #105541, this PR is the first part of #105541, which removes ownership of the llvm::MachineModuleInfoWrapperPass over its encapsulated llvm::MachineModuleInfo, allowing better control over the MMI's lifetime.

After this PR is merged, I plan to:

  1. Move the MC emission functions in TargetMachine to LLVMTargetMachine. With the changes in this PR, we explicitly assume in both addPassesToEmitFile and addPassesToEmitMC that the TargetMachine is an LLVMTargetMachine; Hence it does not make sense for these functions to be present in the TargetMachine interface.
  2. Make MMI only take external context, which originally was the second part of Make MMIWP not have ownership over MMI + Make MMI Only Use an External MCContext #105541.

cc @aeubanks @arsenm

Copy link

⚠️ We detected that you are using a GitHub private e-mail address to contribute to the repo.
Please turn off Keep my email addresses private setting in your account.
See LLVM Discourse for more information.

Copy link

github-actions bot commented Sep 29, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@arsenm
Copy link
Contributor

arsenm commented Sep 30, 2024

  • Move the MC emission functions in TargetMachine to LLVMTargetMachine. With the changes in this PR, we explicitly assume in both addPassesToEmitFile and addPassesToEmitMC that the TargetMachine is an LLVMTargetMachine; Hence it does not make sense for these functions to be present in the TargetMachine interface.

Was this already implicitly assumed? IIRC there was some layering reason why this is the way it was. There were previous attempts to merge these before, which were abandoned:

https://lists.llvm.org/pipermail/llvm-dev/2017-October/117907.html

https://reviews.llvm.org/D38482
https://reviews.llvm.org/D38489

@matinraayai
Copy link
Contributor Author

matinraayai commented Sep 30, 2024

  • Move the MC emission functions in TargetMachine to LLVMTargetMachine. With the changes in this PR, we explicitly assume in both addPassesToEmitFile and addPassesToEmitMC that the TargetMachine is an LLVMTargetMachine; Hence it does not make sense for these functions to be present in the TargetMachine interface.

Was this already implicitly assumed? IIRC there was some layering reason why this is the way it was. There were previous attempts to merge these before, which were abandoned:

https://lists.llvm.org/pipermail/llvm-dev/2017-October/117907.html

https://reviews.llvm.org/D38482 https://reviews.llvm.org/D38489

@arsenm Initially I was going to move the MC file emission functions to LLVMTargetMachine but I decided against it, as it would make the PR harder to review.

I don't intend on merging the two interfaces together; I only think the MC file emission functions addPassesToEmitFile and addPassesToEmitMC need to be moved to LLVMTargetMachine. This is because creating an MMI requires the TargetMachine to be an LLVMTargetMachine in the first place. Other functions in TargetMachine that are not MC-related should remain the way it was, which I think should respect the original layering.

…ings in the C-API + linked any libraries that depends on MC file emission to CodeGen.
@matinraayai
Copy link
Contributor Author

@MatzeB @arsenm in the latest commit I had to fix the issue you ran into in the following links @arsenm mentioned earlier:
https://lists.llvm.org/pipermail/llvm-dev/2017-October/117907.html

https://reviews.llvm.org/D38482
https://reviews.llvm.org/D38489

I can live with TargetMachine and LLVMTargetMachine being separate entities, with TargetMachine being the "frontend" and LLVMTargetMachine being any concrete subclass with codegen support as @MatzeB explained in the past.

With this patch, if any library requires MC code emission of any kind, it has to explicitly link to libCodeGen, since it has to be able to access the MMI constructor/destructor. I still believe that addPassesToEmitMC and addPassesToEmitFile need to be moved to LLVMTargetMachine to further enforce the distinction between LLVMTargetMachine and TargetMachine, as well as any other interface that explicitly uses CodeGen or MC primitives (e.g. MachineFunctionInfoYaml things).

Copy link
Contributor

@aeubanks aeubanks left a comment

Choose a reason for hiding this comment

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

I'm still trying to wrap my head around LLVMTargetMachine vs TargetMachine, let me do some reading

@@ -1162,6 +1165,7 @@ void EmitAssemblyHelper::RunCodegenPipeline(
// does not work with the codegen pipeline.
// FIXME: make the new PM work with the codegen pipeline.
legacy::PassManager CodeGenPasses;
std::unique_ptr<MachineModuleInfo> MMI;
Copy link
Contributor

Choose a reason for hiding this comment

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

can this just be MachineModuleInfo MMI; below?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll change it to a normal construction with the TM.

@@ -106,16 +106,18 @@ class MachineModuleInfo {
const Function *LastRequest = nullptr; ///< Used for shortcut/cache.
MachineFunction *LastResult = nullptr; ///< Used for shortcut/cache.

MachineModuleInfo &operator=(MachineModuleInfo &&MMII) = delete;
/// Deleted copy constructor
Copy link
Contributor

Choose a reason for hiding this comment

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

comment is not useful, I'd either say why it's deleted or just remove the comment

Copy link
Contributor

@aeubanks aeubanks left a comment

Choose a reason for hiding this comment

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

ah there's more context in https://reviews.llvm.org/D123964

Copy link
Contributor

@aeubanks aeubanks left a comment

Choose a reason for hiding this comment

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

I see that MMI really is a Codegen concept and not a Target concept, so that's why it takes an LLVMTargetMachine instead of TargetMachine. However, the static_casts everywhere are extremely unfortunate. And it doesn't make sense to make the return type of Target::createTargetMachine() LLVMTargetMachine instead of TargetMachine. Perhaps alternatively we make the MMI constructor take TargetMachine and cast it inside the constructor to LLVMTargetMachine, so we only pay the cost of this weird distinction in one place rather than everywhere? wdyt?

@matinraayai
Copy link
Contributor Author

I dug up the commit that introduced LLVMTargetMachine: 12e9730. It dates back to before when the MC layer was created. It seems the motivation was to allow a hypothetical target to generate code using whatever code generator it wants internally (be it the one provided by LLVM at the time or some other external library). The MC stuff was later on added on top of it around 2010, which I think made this abstraction a bit pointless, since MC and CodeGen integrate tightly together, and there's no point to have support for only one layer.

Given the issues faced when joining TM and LLVMTM, I think this abstraction should be respected. The key takeaway from this abstraction is that TM must have a function that generates object files/MC; It's just that those interface functions should be void of any CodeGen related constructs (even the MMIWP). TLDR: We should follow this rule of thumb: If it uses LLVM's CodeGen it belongs to the LLVMTM class, otherwise it belongs to TM (The same goes for all the MachineFunctionInfo stuff; They should be moved to LLVMTM).

This is a cause of concern for managing the lifetime of MMI: For TM interfaces, MMI's lifetime should be managed by the MMIWP pass, otherwise it will get deleted when it goes out of the scope of the pass building function. For LLVMTM interface, however, MMI should be managed externally by the interface user. I think both should exist.

This also relates to a question that I had regarding the new PM codegen interface buildCodeGenPipeline @aeubanks: how exactly is the MMI's lifetime managed after calling this function? If it's possible I want to talk more about it offline (You can find me on LLVM's Discord).

I see that MMI really is a Codegen concept and not a Target concept, so that's why it takes an LLVMTargetMachine instead of TargetMachine. However, the static_casts everywhere are extremely unfortunate. And it doesn't make sense to make the return type of Target::createTargetMachine() LLVMTargetMachine instead of TargetMachine. Perhaps alternatively we make the MMI constructor take TargetMachine and cast it inside the constructor to LLVMTargetMachine, so we only pay the cost of this weird distinction in one place rather than everywhere? wdyt?

To get back to your question @aeubanks I don't think we should force any casts in the MMI constructor; Instead we should address the TM/LLVMTM abstraction issue. The casting will then take care of itself. Also there should be a Target::createLLVMTargetMachine() for those who want to explicitly manage MMI's lifetime and want to use LLVm CodeGen.

arsenm pushed a commit that referenced this pull request Nov 14, 2024
Following discussions in #110443, and the following earlier discussions
in https://lists.llvm.org/pipermail/llvm-dev/2017-October/117907.html,
https://reviews.llvm.org/D38482, https://reviews.llvm.org/D38489, this
PR attempts to overhaul the `TargetMachine` and `LLVMTargetMachine`
interface classes. More specifically:
1. Makes `TargetMachine` the only class implemented under
`TargetMachine.h` in the `Target` library.
2. `TargetMachine` contains target-specific interface functions that
relate to IR/CodeGen/MC constructs, whereas before (at least on paper)
it was supposed to have only IR/MC constructs. Any Target that doesn't
want to use the independent code generator simply does not implement
them, and returns either `false` or `nullptr`.
3. Renames `LLVMTargetMachine` to `CodeGenCommonTMImpl`. This renaming
aims to make the purpose of `LLVMTargetMachine` clearer. Its interface
was moved under the CodeGen library, to further emphasis its usage in
Targets that use CodeGen directly.
4. Makes `TargetMachine` the only interface used across LLVM and its
projects. With these changes, `CodeGenCommonTMImpl` is simply a set of
shared function implementations of `TargetMachine`, and CodeGen users
don't need to static cast to `LLVMTargetMachine` every time they need a
CodeGen-specific feature of the `TargetMachine`.
5. More importantly, does not change any requirements regarding library
linking.

cc @arsenm @aeubanks
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.

3 participants