@@ -652,6 +652,149 @@ in the future. The expected roadmap for Reduced BMIs as of Clang 19.x is:
652652 comes, the term BMI will refer to the Reduced BMI and the Full BMI will only
653653 be meaningful to build systems which elect to support two-phase compilation.
654654
655+ Experimental Non-Cascading Changes
656+ ----------------------------------
657+
658+ This section is primarily for build system vendors. For end compiler users,
659+ if you don't want to read it all, this is helpful to reduce recompilations.
660+ We encourage build system vendors and end users try this out and bring feedback.
661+
662+ Before Clang 19, a change in BMI of any (transitive) dependency would cause the
663+ outputs of the BMI to change. Starting with Clang 19, changes to non-direct
664+ dependencies should not directly affect the output BMI, unless they affect the
665+ results of the compilations. We expect that there are many more opportunities
666+ for this optimization than we currently have realized and would appreaciate
667+ feedback about missed optimization opportunities. For example,
668+
669+ .. code-block :: c++
670+
671+ // m-partA.cppm
672+ export module m:partA;
673+
674+ // m-partB.cppm
675+ export module m:partB;
676+ export int getB() { return 44; }
677+
678+ // m.cppm
679+ export module m;
680+ export import :partA;
681+ export import :partB;
682+
683+ // useBOnly.cppm
684+ export module useBOnly;
685+ import m;
686+ export int B() {
687+ return getB();
688+ }
689+
690+ // Use.cc
691+ import useBOnly;
692+ int get() {
693+ return B();
694+ }
695+
696+ To compile the project (for brevity, some commands are omitted.):
697+
698+ .. code-block :: console
699+
700+ $ clang++ -std=c++20 m-partA.cppm --precompile -o m-partA.pcm
701+ $ clang++ -std=c++20 m-partB.cppm --precompile -o m-partB.pcm
702+ $ clang++ -std=c++20 m.cppm --precompile -o m.pcm -fprebuilt-module-path=.
703+ $ clang++ -std=c++20 useBOnly.cppm --precompile -o useBOnly.pcm -fprebuilt-module-path=.
704+ $ md5sum useBOnly.pcm
705+ 07656bf4a6908626795729295f9608da useBOnly.pcm
706+
707+ If the interface of ``m-partA.cppm `` is changed to:
708+
709+ .. code-block :: c++
710+
711+ // m-partA.v1.cppm
712+ export module m:partA;
713+ export int getA() { return 43; }
714+
715+ and the BMI for ``useBOnly `` is recompiled as in:
716+
717+ .. code-block :: console
718+
719+ $ clang++ -std=c++20 m-partA.cppm --precompile -o m-partA.pcm
720+ $ clang++ -std=c++20 m-partB.cppm --precompile -o m-partB.pcm
721+ $ clang++ -std=c++20 m.cppm --precompile -o m.pcm -fprebuilt-module-path=.
722+ $ clang++ -std=c++20 useBOnly.cppm --precompile -o useBOnly.pcm -fprebuilt-module-path=.
723+ $ md5sum useBOnly.pcm
724+ 07656bf4a6908626795729295f9608da useBOnly.pcm
725+
726+ then the contents of ``useBOnly.pcm `` remain unchanged.
727+ Consequently, if the build system only bases recompilation decisions on directly imported modules,
728+ it becomes possible to skip the recompilation of ``Use.cc ``.
729+ It should be fine because the altered interfaces do not affect ``Use.cc `` in any way;
730+ the changes do not cascade.
731+
732+ When ``Clang `` generates a BMI, it records the hash values of all potentially contributory BMIs
733+ for the BMI being produced. This ensures that build systems are not required to consider
734+ transitively imported modules when deciding whether to recompile.
735+
736+ What is considered to be a potential contributory BMIs is currently unspecified.
737+ However, it is a severe bug for a BMI to remain unchanged following an observable change
738+ that affects its consumers.
739+
740+ Build systems may utilize this optimization by doing an update-if-changed operation to the BMI
741+ that is consumed from the BMI that is output by the compiler.
742+
743+ We encourage build systems to add an experimental mode that
744+ reuses the cached BMI when **direct ** dependencies did not change,
745+ even if **transitive ** dependencies did change.
746+
747+ Given there are potential compiler bugs, we recommend that build systems
748+ support this feature as a configurable option so that users
749+ can go back to the transitive change mode safely at any time.
750+
751+ Interactions with Reduced BMI
752+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
753+
754+ With reduced BMI, non-cascading changes can be more powerful. For example,
755+
756+ .. code-block :: c++
757+
758+ // A.cppm
759+ export module A;
760+ export int a() { return 44; }
761+
762+ // B.cppm
763+ export module B;
764+ import A;
765+ export int b() { return a(); }
766+
767+ .. code-block :: console
768+
769+ $ clang++ -std=c++20 A.cppm -c -fmodule-output=A.pcm -fexperimental-modules-reduced-bmi -o A.o
770+ $ clang++ -std=c++20 B.cppm -c -fmodule-output=B.pcm -fexperimental-modules-reduced-bmi -o B.o -fmodule-file=A=A.pcm
771+ $ md5sum B.pcm
772+ 6c2bd452ca32ab418bf35cd141b060b9 B.pcm
773+
774+ And let's change the implementation for ``A.cppm `` into:
775+
776+ .. code-block :: c++
777+
778+ export module A;
779+ int a_impl() { return 99; }
780+ export int a() { return a_impl(); }
781+
782+ and recompile the example:
783+
784+ .. code-block :: console
785+
786+ $ clang++ -std=c++20 A.cppm -c -fmodule-output=A.pcm -fexperimental-modules-reduced-bmi -o A.o
787+ $ clang++ -std=c++20 B.cppm -c -fmodule-output=B.pcm -fexperimental-modules-reduced-bmi -o B.o -fmodule-file=A=A.pcm
788+ $ md5sum B.pcm
789+ 6c2bd452ca32ab418bf35cd141b060b9 B.pcm
790+
791+ We should find the contents of ``B.pcm `` remains the same. In this case, the build system is
792+ allowed to skip recompilations of TUs which solely and directly depend on module ``B ``.
793+
794+ This only happens with a reduced BMI. With reduced BMIs, we won't record the function body
795+ of ``int b() `` in the BMI for ``B `` so that the module ``A `` doesn't contribute to the BMI of ``B ``
796+ and we have less dependencies.
797+
655798Performance Tips
656799----------------
657800
0 commit comments