diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 52d161703f965e..62e50a807f4f6e 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1834,6 +1834,18 @@ def fprofile_selected_function_group : Visibility<[ClangOption, CC1Option]>, MetaVarName<"">, HelpText<"Partition functions into N groups using -fprofile-function-groups and select only functions in group i to be instrumented. The valid range is 0 to N-1 inclusive">, MarshallingInfoInt>; +def fcodegen_data_generate : Joined<["-"], "fcodegen-data-generate">, + Group, Visibility<[ClangOption, CC1Option]>, + HelpText<"Emit codegen data into object file. LLD for MachO (for now) merges them into default.cgdata">; +def fcodegen_data_generate_EQ : Joined<["-"], "fcodegen-data-generate=">, + Group, Visibility<[ClangOption, CC1Option]>, MetaVarName<"">, + HelpText<"Emit codegen data into object file. LLD for MachO (for now) merges them into /default.cgdata">; +def fcodegen_data_use : Joined<["-"], "fcodegen-data-use">, + Group, Visibility<[ClangOption, CC1Option]>, + HelpText<"Use codegen data read from default.cgdata to optimize the binary">; +def fcodegen_data_use_EQ : Joined<["-"], "fcodegen-data-use=">, + Group, Visibility<[ClangOption, CC1Option]>, MetaVarName<"">, + HelpText<"Use codegen data read from /default.cgdata to optimize the binary">; def fswift_async_fp_EQ : Joined<["-"], "fswift-async-fp=">, Group, Visibility<[ClangOption, CC1Option, CC1AsOption, CLOption]>, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index b65b96db16bd79..8490955a5ae82c 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -2752,6 +2752,33 @@ void tools::addMachineOutlinerArgs(const Driver &D, addArg(Twine("-enable-machine-outliner=never")); } } + + auto *CodeGenDataGenArg = + Args.getLastArg(options::OPT_fcodegen_data_generate, + options::OPT_fcodegen_data_generate_EQ); + auto *CodeGenDataUseArg = Args.getLastArg(options::OPT_fcodegen_data_use, + options::OPT_fcodegen_data_use_EQ); + + // We only allow one of them to be specified. + if (CodeGenDataGenArg && CodeGenDataUseArg) + D.Diag(diag::err_drv_argument_not_allowed_with) + << CodeGenDataGenArg->getAsString(Args) + << CodeGenDataUseArg->getAsString(Args); + + // For codegen data gen, the output file is passed to the linker + // while a boolean flag is passed to the LLVM backend. + if (CodeGenDataGenArg) + addArg(Twine("-codegen-data-generate")); + + // For codegen data use, the input file is passed to the LLVM backend. + if (CodeGenDataUseArg) { + SmallString<128> Path(CodeGenDataUseArg->getNumValues() == 0 + ? "" + : CodeGenDataUseArg->getValue()); + if (Path.empty() || llvm::sys::fs::is_directory(Path)) + llvm::sys::path::append(Path, "default.cgdata"); + addArg(Twine("-codegen-data-use-path=" + Path.str())); + } } void tools::addOpenMPDeviceRTL(const Driver &D, diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index caf6c4a444fdce..85407ea5c69dfc 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -476,6 +476,19 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args, llvm::sys::path::append(Path, "default.profdata"); CmdArgs.push_back(Args.MakeArgString(Twine("--cs-profile-path=") + Path)); } + + auto *CodeGenDataGenArg = + Args.getLastArg(options::OPT_fcodegen_data_generate, + options::OPT_fcodegen_data_generate_EQ); + if (CodeGenDataGenArg) { + SmallString<128> Path(CodeGenDataGenArg->getNumValues() == 0 + ? "" + : CodeGenDataGenArg->getValue()); + if (Path.empty() || llvm::sys::fs::is_directory(Path)) + llvm::sys::path::append(Path, "default.cgdata"); + CmdArgs.push_back( + Args.MakeArgString(Twine("--codegen-data-generate-path=") + Path)); + } } } @@ -633,6 +646,39 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-mllvm"); CmdArgs.push_back("-enable-linkonceodr-outlining"); + // Propagate codegen data flags to the linker for the LLVM backend. + auto *CodeGenDataGenArg = + Args.getLastArg(options::OPT_fcodegen_data_generate, + options::OPT_fcodegen_data_generate_EQ); + auto *CodeGenDataUseArg = Args.getLastArg(options::OPT_fcodegen_data_use, + options::OPT_fcodegen_data_use_EQ); + + // We only allow one of them to be specified. + const Driver &D = getToolChain().getDriver(); + if (CodeGenDataGenArg && CodeGenDataUseArg) + D.Diag(diag::err_drv_argument_not_allowed_with) + << CodeGenDataGenArg->getAsString(Args) + << CodeGenDataUseArg->getAsString(Args); + + // For codegen data gen, the output file is passed to the linker + // while a boolean flag is passed to the LLVM backend. + if (CodeGenDataGenArg) { + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back("-codegen-data-generate"); + } + + // For codegen data use, the input file is passed to the LLVM backend. + if (CodeGenDataUseArg) { + SmallString<128> Path(CodeGenDataUseArg->getNumValues() == 0 + ? "" + : CodeGenDataUseArg->getValue()); + if (Path.empty() || llvm::sys::fs::is_directory(Path)) + llvm::sys::path::append(Path, "default.cgdata"); + CmdArgs.push_back("-mllvm"); + CmdArgs.push_back( + Args.MakeArgString("-codegen-data-use-path=" + Path.str())); + } + // Setup statistics file output. SmallString<128> StatsFile = getStatsFileName(Args, Output, Inputs[0], getToolChain().getDriver()); diff --git a/clang/test/Driver/codegen-data.c b/clang/test/Driver/codegen-data.c new file mode 100644 index 00000000000000..a72850afc59736 --- /dev/null +++ b/clang/test/Driver/codegen-data.c @@ -0,0 +1,42 @@ +// Verify only one of codegen-data flag is passed. +// RUN: not %clang -### -S --target=aarch64-linux-gnu -fcodegen-data-generate -fcodegen-data-use %s 2>&1 | FileCheck %s --check-prefix=CONFLICT +// RUN: not %clang -### -S --target=arm64-apple-darwin -fcodegen-data-generate -fcodegen-data-use %s 2>&1 | FileCheck %s --check-prefix=CONFLICT +// CONFLICT: error: invalid argument '-fcodegen-data-generate' not allowed with '-fcodegen-data-use' + +// Verify the codegen-data-generate (boolean) flag is passed to LLVM +// RUN: %clang -### -S --target=aarch64-linux-gnu -fcodegen-data-generate %s 2>&1| FileCheck %s --check-prefix=GENERATE +// RUN: %clang -### -S --target=arm64-apple-darwin -fcodegen-data-generate %s 2>&1| FileCheck %s --check-prefix=GENERATE +// GENERATE: "-mllvm" "-codegen-data-generate" + +// Verify the codegen-data-use-path flag (with a default value) is passed to LLVM. +// RUN: %clang -### -S --target=aarch64-linux-gnu -fcodegen-data-use %s 2>&1| FileCheck %s --check-prefix=USE +// RUN: %clang -### -S --target=arm64-apple-darwin -fcodegen-data-use %s 2>&1| FileCheck %s --check-prefix=USE +// RUN: mkdir -p %t.d/some/dir +// RUN: %clang -### -S --target=aarch64-linux-gnu -fcodegen-data-use=%t.d/some/dir %s 2>&1 | FileCheck %s --check-prefix=USE-DIR +// RUN: %clang -### -S --target=arm64-apple-darwin -fcodegen-data-use=%t.d/some/dir %s 2>&1 | FileCheck %s --check-prefix=USE-DIR +// RUN: %clang -### -S --target=aarch64-linux-gnu -fcodegen-data-use=file %s 2>&1 | FileCheck %s --check-prefix=USE-FILE +// RUN: %clang -### -S --target=arm64-apple-darwin -fcodegen-data-use=file %s 2>&1 | FileCheck %s --check-prefix=USE-FILE +// USE: "-mllvm" "-codegen-data-use-path=default.cgdata" +// USE-DIR: "-mllvm" "-codegen-data-use-path={{.*}}.d/some/dir{{/|\\\\}}default.cgdata" +// USE-FILE: "-mllvm" "-codegen-data-use-path=file" + +// Verify the codegen-data-generate (boolean) flag with a LTO. +// RUN: %clang -### -flto --target=aarch64-linux-gnu -fcodegen-data-generate %s 2>&1 | FileCheck %s --check-prefix=GENERATE-LTO +// GENERATE-LTO: {{ld(.exe)?"}} +// GENERATE-LTO-SAME: "-plugin-opt=-codegen-data-generate" +// RUN: %clang -### -flto --target=arm64-apple-darwin -fcodegen-data-generate %s 2>&1 | FileCheck %s --check-prefix=GENERATE-LTO-DARWIN +// GENERATE-LTO-DARWIN: {{ld(.exe)?"}} +// GENERATE-LTO-DARWIN-SAME: "-mllvm" "-codegen-data-generate" + +// Verify the codegen-data-use-path flag with a LTO is passed to LLVM. +// RUN: %clang -### -flto=thin --target=aarch64-linux-gnu -fcodegen-data-use %s 2>&1 | FileCheck %s --check-prefix=USE-LTO +// USE-LTO: {{ld(.exe)?"}} +// USE-LTO-SAME: "-plugin-opt=-codegen-data-use-path=default.cgdata" +// RUN: %clang -### -flto=thin --target=arm64-apple-darwin -fcodegen-data-use %s 2>&1 | FileCheck %s --check-prefix=USE-LTO-DARWIN +// USE-LTO-DARWIN: {{ld(.exe)?"}} +// USE-LTO-DARWIN-SAME: "-mllvm" "-codegen-data-use-path=default.cgdata" + +// For now, LLD MachO supports for generating the codegen data at link time. +// RUN: %clang -### -fuse-ld=lld -B%S/Inputs/lld --target=arm64-apple-darwin -fcodegen-data-generate %s 2>&1 | FileCheck %s --check-prefix=GENERATE-LLD-DARWIN +// GENERATE-LLD-DARWIN: {{ld(.exe)?"}} +// GENERATE-LLD-DARWIN-SAME: "--codegen-data-generate-path=default.cgdata"