ChuanqiXu created this revision.
ChuanqiXu added reviewers: iains, Bigcheese, dblaikie.
ChuanqiXu added a project: clang-modules.
Herald added a project: All.
ChuanqiXu requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay.
Herald added a project: clang.

Close https://github.com/llvm/llvm-project/issues/61015
Close https://github.com/llvm/llvm-project/issues/60996

Clang will import the function definitions from other module unit within
optimizations by default to get the best performance. But there are
cases users prefer faster compilation speed than the best performance.

Although we may not agree such ideas, we should offer an option for the
users to give them the right to choose.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D144844

Files:
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/module-no-import-from-other-tu.cppm
  clang/test/Modules/inter-module-imports-function-defs.cppm

Index: clang/test/Modules/inter-module-imports-function-defs.cppm
===================================================================
--- /dev/null
+++ clang/test/Modules/inter-module-imports-function-defs.cppm
@@ -0,0 +1,57 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm \
+// RUN:     -emit-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cppm \
+// RUN:     -emit-module-interface -fprebuilt-module-path=%t -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/c.cppm \
+// RUN:     -emit-module-interface -fprebuilt-module-path=%t -o %t/c.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/c.pcm -S \
+// RUN:     -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cppm --check-prefix=NO-IMPORT
+//
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -O3 %t/a.cppm \
+// RUN:     -emit-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -O3 %t/b.cppm \
+// RUN:     -emit-module-interface -fprebuilt-module-path=%t -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -O3 %t/c.cppm \
+// RUN:     -emit-module-interface -fprebuilt-module-path=%t -o %t/c.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -O3 %t/c.pcm \
+// RUN:     -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cppm --check-prefix=IMPORT
+//
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -O3 \
+// RUN:     %t/a.cppm -emit-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -O3 \
+// RUN:     %t/b.cppm -emit-module-interface -fprebuilt-module-path=%t -o %t/b.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -O3 \
+// RUN:     %t/c.cppm -emit-module-interface -fprebuilt-module-path=%t -o %t/c.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -O3 \
+// RUN:     -fno-import-inter-module-function-defs %t/c.pcm \
+// RUN:     -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/c.cppm --check-prefix=NO-IMPORT
+
+//--- a.cppm
+export module a;
+export int a() {
+    return 43;
+}
+
+//--- b.cppm
+export module b;
+export import a;
+export int b() {
+    return 43 + a();
+}
+
+//--- c.cppm
+export module c;
+export import b;
+export int c() {
+    return 43 + b() + a();
+}
+
+// NO-IMPORT: declare{{.*}}@_ZW1b1bv
+// NO-IMPORT: declare{{.*}}@_ZW1a1av
+
+// IMPORT: define available_externally{{.*}}@_ZW1b1bv
+// IMPORT: define available_externally{{.*}}@_ZW1a1av
Index: clang/test/Driver/module-no-import-from-other-tu.cppm
===================================================================
--- /dev/null
+++ clang/test/Driver/module-no-import-from-other-tu.cppm
@@ -0,0 +1,6 @@
+// RUN: %clang -O3 -fno-import-inter-module-function-defs -std=c++20 \
+// RUN:     %s -### 2>&1 | FileCheck %s
+
+export module x;
+
+// CHECK: -fno-import-inter-module-function-defs
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -3850,6 +3850,10 @@
   Args.ClaimAllArgs(options::OPT_fmodule_output);
   Args.ClaimAllArgs(options::OPT_fmodule_output_EQ);
 
+  if (Args.hasFlag(options::OPT_fno_import_inter_module_function_defs,
+                   options::OPT_fimport_inter_module_function_defs, false))
+    CmdArgs.push_back("-fno-import-inter-module-function-defs");
+
   return HaveModules;
 }
 
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3541,7 +3541,8 @@
   if (getFunctionLinkage(GD) != llvm::Function::AvailableExternallyLinkage)
     return true;
   const auto *F = cast<FunctionDecl>(GD.getDecl());
-  if (CodeGenOpts.OptimizationLevel == 0 && !F->hasAttr<AlwaysInlineAttr>())
+  if (!CodeGenOpts.ImportInterModuleFunctionDefs &&
+      !F->hasAttr<AlwaysInlineAttr>())
     return false;
 
   if (F->hasAttr<DLLImportAttr>() && !F->hasAttr<AlwaysInlineAttr>()) {
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -545,6 +545,8 @@
 
 defvar std = !strconcat("LangStandard::getLangStandardForKind(", lang_std.KeyPath, ")");
 
+defvar opt_level = CodeGenOpts<"OptimizationLevel">;
+
 /////////
 // Options
 
@@ -2355,6 +2357,11 @@
 def fmodule_output : Flag<["-"], "fmodule-output">, Flags<[NoXarchOption, CC1Option]>,
   HelpText<"Save intermediate module file results when compiling a standard C++ module unit.">;
 
+defm import_inter_module_function_defs : BoolOption<"f", "import-inter-module-function-defs",
+  CodeGenOpts<"ImportInterModuleFunctionDefs">, Default<!strconcat(opt_level.KeyPath, "!= 0")>,
+  PosFlag<SetTrue, [], "Import function definitions from other module units">,
+  NegFlag<SetFalse, [CC1Option], "Don't import function definitions from other module units">>;
+
 def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, Group<i_Group>,
   Flags<[CC1Option]>, MetaVarName<"<seconds>">,
   HelpText<"Specify the interval (in seconds) between attempts to prune the module cache">,
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -506,6 +506,10 @@
 /// non-deleting destructors. (No effect on Microsoft ABI.)
 CODEGENOPT(CtorDtorReturnThis, 1, 0)
 
+/// Whether to import function definitions from inter module function
+/// definitions.
+CODEGENOPT(ImportInterModuleFunctionDefs, 1, 0)
+
 #undef CODEGENOPT
 #undef ENUM_CODEGENOPT
 #undef VALUE_CODEGENOPT
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to