-
Notifications
You must be signed in to change notification settings - Fork 11.5k
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
[C++20][Modules] Missed optimization: Unnecessary code emitted for empty module initializers #67582
Comments
@llvm/issue-subscribers-clang-modules
Given
a.cpp: export module a; and b.cpp: import a; Then after compiling with clang++ -std=c++20 -O3 -x c++-module -fmodule-output=a.pcm --precompile -c a.cpp
clang++ -std=c++20 -O3 -fmodule-file=a=a.pcm -S b.cpp -emit-llvm We end up with the generated code for
The module initializer for It actually seems to be significantly worse than this. For instance, in my local compiler explorer instance I have an umbrella module import bounded; In my compiler explorer output I see _GLOBAL__sub_I_example.cpp: # @<!-- -->_GLOBAL__sub_I_example.cpp
push rax
call initializer for module bounded@<!-- -->PLT
call initializer for module bounded.arithmetic.operators@<!-- -->PLT
call initializer for module bounded.arithmetic.operators_builtin@<!-- -->PLT
call initializer for module bounded.arithmetic.round_up_divide@<!-- -->PLT
call initializer for module bounded.abs@<!-- -->PLT
call initializer for module bounded.builtin_min_max_value@<!-- -->PLT
call initializer for module bounded.cast@<!-- -->PLT
call initializer for module bounded.check_in_range@<!-- -->PLT
call initializer for module bounded.clamp@<!-- -->PLT
call initializer for module bounded.comparison@<!-- -->PLT
call initializer for module bounded.comparison_builtin@<!-- -->PLT
call initializer for module bounded.construct@<!-- -->PLT
call initializer for module bounded.construct_at@<!-- -->PLT
call initializer for module bounded.copy@<!-- -->PLT
call initializer for module bounded.hash@<!-- -->PLT
call initializer for module bounded.integer@<!-- -->PLT
call initializer for module bounded.integer_tombstone_traits@<!-- -->PLT
call initializer for module bounded.is_bounded_integer@<!-- -->PLT
call initializer for module bounded.lazy_init@<!-- -->PLT
call initializer for module bounded.literal@<!-- -->PLT
call initializer for module bounded.log@<!-- -->PLT
call initializer for module bounded.minmax@<!-- -->PLT
call initializer for module bounded.normalize@<!-- -->PLT
call initializer for module bounded.number_of@<!-- -->PLT
call initializer for module bounded.pow@<!-- -->PLT
call initializer for module bounded.representation_digits@<!-- -->PLT
call initializer for module bounded.size_of@<!-- -->PLT
call initializer for module bounded.std_iterator@<!-- -->PLT
call initializer for module bounded.stream@<!-- -->PLT
pop rax
jmp initializer for module bounded.to_integer@<!-- -->PLT # TAILCALL |
Thanks for the report. And this is duplicated with #56794 |
…t init anything Close llvm#56794 And see llvm#67582 for a detailed backgrond for the issue. As required by the Itanium ABI, the module units have to generate the initialization function. However, the importers are allowed to elide the call to the initialization function if they are sure the initialization function doesn't do anything. This patch implemented this semantics.
… init anything (#67638) Close #56794 And see #67582 for a detailed backgrond for the issue. As required by the Itanium ABI, the module units have to generate the initialization function. However, the importers are allowed to elide the call to the initialization function if they are sure the initialization function doesn't do anything. This patch implemented this semantics.
… init anything (llvm#67638) Close llvm#56794 And see llvm#67582 for a detailed backgrond for the issue. As required by the Itanium ABI, the module units have to generate the initialization function. However, the importers are allowed to elide the call to the initialization function if they are sure the initialization function doesn't do anything. This patch implemented this semantics.
Given
a.cpp:
and
b.cpp:
Then after compiling with
We end up with the generated code for
b
as:The module initializer for
a
is empty, yet we still do a tail call to it. I would expect there to be no reference to the initializer of modulea
anywhere in the generated code forb
.It actually seems to be significantly worse than this. For instance, in my local compiler explorer instance I have an umbrella module
bounded
that imports various sub-modules. I see an unnecessary initializer of the umbrella module (which internally has unnecessary initializers for all its imports), and then I see unnecessary initializers of all of those sub-modules:In my compiler explorer output I see
The text was updated successfully, but these errors were encountered: