-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[RFC][Clang] Allow plugins to hook into back-end #165257
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
base: users/aengelke/spr/main.rfcclang-allow-plugins-to-hook-into-back-end
Are you sure you want to change the base?
Conversation
Created using spr 1.3.5-bogner
|
I'm okay with this, though I believe @weliveindetail was hoping for something that works cross-frontend. But probably this is a better starting point. |
|
Can you clarify: do you use a plugin to swap clang's CodeGen and why the standard plugin system does not work well there? |
We swap LLVM's CodeGen (the machine code generation part), but want to keep Clang's CodeGen (the part that generates LLVM IR and optimizes that). We want the front-end and middle-end optimizations to behave as usual and only replace the back-end with our own back-end.
The standard front-end plugins permit replacing, e.g., the CodeGenAction with something else. But we do want Clang's CodeGen to work normally. CodeGenAction and emitBackendOutput are very inflexible; adding a custom back-end through a PluginASTAction would essentially require us to copy large parts of CodeGenAction.cpp and BackendUtil.cpp, which is not maintainable. |
Would it make more sense to make the CodeGenAction and emitBackendOutput more flexible? Maybe checking if the It would be great to enhance the existing clang plugin system rather than adding a new plugin extension point. cc: @lhames. |
Do you mean that you will need to wrap clang's |
Maybe? emitBackendOutput (EmitAssemblyHelper) could call back into some new virtual method in BackendConsumer. This would leave the problem of inserting a new different (subclass of) BackendConsumer. But as a PluginASTAction cannot be a CodeGenAction, I would assume that at the very least the plugin action has to wrap all the virtual methods that CodeGenAction uses? This doesn't seem to be particularly viable, especially as some of the methods are protected. Duplicating CodeGenAction methods is also not a good option.
I generally agree, but... I spent a few days trying to come up with a PluginASTAction that achieves something similar... and gave up (=> this patch). (I've not much experience with Clang plugins, but the code is rather complicated and sparsely documented, which doesn't help, either.)
Ideally, I don't want to swap emitBackendOutput, because I don't want to duplicate that logic... |
|
I think we can use the opportunity to improve that part of the plugin support but let's see what others have to say. Independently, have you considered uploading the tpde-llvm to the llvm project itself? It does not seem a lot of code and it shows quite useful results for the JIT cases? |
Yes, and we concluded that we'd rather not pursue it at this point. Quoting from tpde2/tpde#6 (comment):
|
|
@aengelke Thanks for taking the initiative! I got derailed from my backend swapping research after I settled with this downstream patch "for the moment". It was surprisingly small and effective, but no solid upstreamable implementation.
Yes, that's right. Adding a frontend-specific mechanism doesn't seem like the best approach to me. Populating and running the codegen pipeline is an inherent responsibility of LLVM. If we provided a generic way to make it configurable without breaking the interface, then all frontends would profit. So what options do we have? Looking at different frontends, we see that all of them invoke
This seems to be a good place to add a hook and it's just two hops away from the entry-point proposed in this patch: The notable difference is, that we only populate the codegen pipeline here and execute it later via Let's look at the code: I like the approach with the
I think it's worth investigating, if we can keep the proposed approach, move the hook into On the side, we should note the second entry-point
I agree and there are more people who want to load alternative backends and/or configure the codegen pipeline @ashermancinelli @jwillbold @vadorovsky Let's see if we can improve the plugin story instead! 🙏 |
If we consider LLVM as a library that generates code and an alternative back-end as a different library that generates code, then it's up to the front-end to decide which library to use. No alternative back-end will be a fully compatible and transparent drop-in replacement for LLVM. The front-end should be in full control of which back-end it uses and any "LLVM plugin" (which is not a thing right now) should merely be able to change defaults. For example, a JIT compiler we would want to enable/disable an alternative back-end in ORC JIT through a runtime switch for every compilation (e.g., baseline vs. later optimized code generation). (Well ok, that's not quite accurate in the TPDE-LLVM case -- here, users will likely want to avoid ORC JITLink entirely and use TPDE's faster JIT mapper instead.)
It would almost certainly need a new API if fallback is to be supported (which, for TPDE-LLVM, would be a fairly important requirement). While I think that our current addPassesToEmitX + PM.run API is not good, it's there and used.. a new API would need to be picked up by front-ends and it's not very likely that we'd deprecate the existing API? |
Yes, as a pure backend selection feature in the frontend, this is fair. It doesn't fit my use-case where a pass plugin requires a different/modified codegen backend, but that might just be a different story. I think we should wait for feedback from clang maintainers then.
The switch to the new pass manager might actually be a good opportunity to revisit the interface. It follows the same approach to split populate and run, but it wouldn't need to be exposed that way. llc implements it here and calls into TargetMachine's new |
|
ping -- are there further opinions or any objections to this direction? |
Add a mechanism to permit plugins running code between optimizations and
the back-end passes.
The primary motivation for this point is TPDE-LLVM, which substitutes
the LLVM back-end (optionally falling back to it for unsupported IR). We
have been distributing a Clang patch; but requiring a custom-build
toolchain is impracticable for many users.
I'm not sure whether this is the best way to achieve the goal. Front-end
plugins are not viable. Any kind of pass manager plugin is not an
option, as the entire pass pipeline needs to be (optionally) skipped.
Tests are currently missing; I will add them once there's consensus that
this is the way to go.