Most emitters are irrelevant to generate files in the critical path, intrinsics_gen and RISCVTargetParserTableGen. If those emitters could be separated, the critical path might be reduced.
Move each cl::opt definition to corresponding Emitter.cpp.
Implement the capability to build each emitter as loadable module.
Make llvm-tblgen recognize an unknown (unlinked) generator and load it dynamically.
-gen-unknown-foo will load libtblgen-unknown-foo.so
Make add_tablegen to append dependency to emitter module.
I don’t intend to move to plugin-ization. This may be optional.
When they will be made, LLVMSupport:ItaniumManglingCanonicalizer.cpp will be the next critical path.
Split out some files in LLVMSupport
The most effective way is to split files required by tblgen to dedicated module, like “LLVMSupportLite”. But I am afraid that it would make LLVM less maintainancible.
Could we move ItaniumManglingCanonicalizer.cpp out of LLVMSupport?
Move dependency on LLVMTargetParser
I haven’t had any idea yet, since it is new to me.
Random notes
I expect ninja-build to schedule along critical path. May be depth-based, at least.
In test-depends (check-clang), SemaExpr-clang-ast-dump-ASTNodeAPI.json-ToolingTests:SourceCodeTest.cpp is the longest critical path.
FYI, the attached test-depends.json is generated by my experimental ninja-build. It implements duration-based scheduler with previous build log.
Even if we could optimize scheduling llvm-tblgen, we would still see idle time due to starvation. Could we fill tasks into the gap?
Some files will be dissolved from dependency on llvm-tblgen. This will require lots of works in CMake side.
Loosen dependency to add_custom_command. I did, in past, with target_link_libraries(INTERFACE).
Discover the real dependency on generated headers with clang-scan-deps and add deps with ninja’s dyndep.
Not sure how much of saving this is but ItaniumManglingCanonicalizer/SymbolRemappingReader looks like they’d be better off in ProfileData - I think that’d only affect llvm-cxxmap ?
I’ve long wanted to be able to unify MachineValueType.h and ValueTypes.td to avoid the duplication and the hard-coding of constants that makes adding MVTs in a fork annoying for merge conflicts. Currently llvm-tblgen depends on MachineValueType.h as some of the GISel backends need to know about MVTs, but moving to a plugin-based approach could allow that to be decoupled and break the circular dependency. I don’t know how you would propose loading plugins for a statically-linked llvm-tblgen though given dlopen only works in dynamically-linked binaries on some OSes (e.g. FreeBSD), as a attractive as it seems for resolving this problem, and I doubt we want to have one full binary per backend.
I would go the other direction. Instead of the llvm-tblgen bottleneck, I would turn tblgen into a library and each subproject can create its own tblgen tool.
We already do that anyway; llvm-tblgen is for llvm/, clang-tblgen is for clang/, lld-tblgen is for lldb/, and they each provide their backends that link against libLLVMTableGen. Unless you mean one binary per backend, which would mean going from 1 to 30-40 executables for llvm/ alone; though perhaps statically linking libLLVMTableGen and its dependencies doesn’t need all that much disk space, on my Mac it seems to be ~5M, so 200M wouldn’t be absurd in the grand scheme of LLVM build requirements.
+1 for turning TG backends (emitters) into plugins that will be built on-demand
Actually I think it’s a good time to do so since plugin-ization shares lots of infrastructure with the solution you described. Plus, it helps TG as a language in general for out-of-tree applications since creating a custom TG backend becomes a lot easier (you don’t have to create your own driver tool or modify llvm-tblgen).
Would you mean “TG binaries” as “plugin modules of tblgen”?
I think we could split out specific emitters, but I would like to introduce more generic way.
Then, “llvm-tblgen” (and LLVMTableGen+LLVMSupportLite.so) will handle almost all emitters. I expect it would make easier for 3rd parties to implement emitters out of LLVM tree.
dlopen is not fun. I was thinking of an llvm-globalisel-tblgen executable and an llvm-tblgen executable. Maybe the TG infrastructure can be exported as a library to make it easer to write custom out of tree TGs and in-tree.
A lot of it already is exported, though a bunch of CodeGen-specific stuff is missing for that plan. Basically, add a libLLVMTableGenCodeGen in addition to the already existing libLLVMTableGen, where the new library contains CodeGenTarget.cpp and potentially others.
I’ve thought the opposite of having multiple tablegen tools, but have one tablegen invocation perform all of the generators at once and in parallel. There’s a lot of time spent in common building target information paths, only some of which gets used depending in the output type.
Also there’s probably low hanging fruit to speed up GlobalISelEmitter. I’ve never looked at the profile for it.
If we add more tablegen-* binaries, do we also need to increase the default number of parallel link jobs? Will adding more binaries make the build slower on systems with fewer cores?
In 2021, I took an option to plugin-ize tblgen, since I wanted to avoid intrusive changes in the tree. Then I didn’t think I could add other tblgen executables.
As I read comments, I think it would be yet another option to add specific tblgen(s), if it would be acceptable.
Although decoupling GISelEmitter would be effective, I think introducing “CodeGen’s tblgen” would be better. I will work if I have my time.
@jrtc27 I have looked around llvm-tblgen and MVT.
I expected CodeGen stuff could be split out easily, but I knew also intrinsics_gen depends on MVT.
Could we use ValueTypes.td directly from other td(s) to avoid using MachineValueType.h, at least for IntrinsicsEmitter?
I guess it would not be easy to rewrite all emitters since we would have to rewrite many emitters.
For now, I suspend considering ValueTypes.td.
@tschuett@nhaehnle Let me know why you don’t prefer plugin.
(As I said before, it should be an option)
@tstellar tblgen executables would be expected smaller.
With a few libraries to link each tblgen executable.
If we would build plugins, each plugin module would be a few object files with a few dynamic libraries.
I think it would not be a problem unless we would try linking hundred of tblgen(s).