sepavloff created this revision. sepavloff added reviewers: rsmith, rjmccall.
Type in the LLVM IR may have names but only for the purpose of human readability (see discussions in https://reviews.llvm.org/D40567, http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20171127/210816.html and http://lists.llvm.org/pipermail/llvm-dev/2017-December/119585.html). In the case when the resulting IR is not proposed for reading, for instance, when compilation produces machine code, the type names are waste of memory. In some cases, when types are nested in other types, the memory expenses may be really large. This change implements new clang option, '--ir-type-names=', which controls if IR types should be given human readable names. The option may have values 'use' or 'none', which turn names on or off correspondently. If no such option was specified, compiler assign names when output may be read by a human, namely when IR is saved beyond compilation or in debug builds. Repository: rC Clang https://reviews.llvm.org/D43805 Files: include/clang/Driver/Options.td include/clang/Frontend/CodeGenOptions.def include/clang/Frontend/CodeGenOptions.h lib/CodeGen/CodeGenAction.cpp lib/CodeGen/CodeGenTypes.cpp lib/Driver/ToolChains/Clang.cpp lib/Frontend/CompilerInvocation.cpp test/CodeGenCXX/pr29160.cpp test/CodeGenCXX/type-names.cpp
Index: test/CodeGenCXX/type-names.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/type-names.cpp @@ -0,0 +1,65 @@ +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm --ir-type-names=use -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm --ir-type-names=none -o - %s | FileCheck %s --check-prefix=UNNAMED + +struct C1 { + int a; + int *b; +}; + +C1 var_C1_a; +C1 var_C1_b[10]; +C1 *var_C1_c; +int (*var_C1_d)(const C1 &); + +struct C1A { + int a; + int *b; +}; + +C1A var_C1A_a; + +template<typename T> struct C2 { + C1 a; + T b; + struct Inner { + }; +}; + +C2<short> var_C2_a; +C2<long long> var_C2_b; +C2<int>::Inner var_C2_c; + +struct C3 { + double a; + struct C4 { + int a; + float b; + }; +}; + +C3::C4 var_c4; + +namespace { +struct C5 { + int *a; +}; +} + +C5 var_C5_a; +void *var_C5_b = &var_C5_a; + +// CHECK: %struct.C1 = type { i32, i32* } +// CHECK: %struct.C1A = type { i32, i32* } +// CHECK: %struct.C2 = type { %struct.C1, i16 } +// CHECK: %struct.C2.0 = type { %struct.C1, i64 } +// CHECK: %"struct.C2<int>::Inner" = type { i8 } +// CHECK: %"struct.C3::C4" = type { i32, float } +// CHECK: %"struct.(anonymous namespace)::C5" = type { i32* } + +// UNNAMED: %0 = type { i32, i32* } +// UNNAMED: %1 = type { i32, i32* } +// UNNAMED: %2 = type { %0, i16 } +// UNNAMED: %3 = type { %0, i64 } +// UNNAMED: %4 = type { i8 } +// UNNAMED: %5 = type { i32, float } +// UNNAMED: %6 = type { i32* } Index: test/CodeGenCXX/pr29160.cpp =================================================================== --- test/CodeGenCXX/pr29160.cpp +++ test/CodeGenCXX/pr29160.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++11 -triple i686-linux-gnu %s -o /dev/null -S -emit-llvm +// RUN: %clang_cc1 -std=c++11 -triple i686-linux-gnu -DNAMELESS --ir-type-names=none %s -o /dev/null -S -emit-llvm // // This test's failure mode is running ~forever. (For some value of "forever" // that's greater than 25 minutes on my machine) @@ -8,6 +9,7 @@ template <typename... T> static void ignore() {} Foo() { ignore<Ts...>(); } + struct ABC {}; }; struct Base { @@ -39,3 +41,9 @@ STAMP(Q, P); int main() { Q q; } + +#ifdef NAMELESS +// Without '--ir-type-names=none' compiler tries to create name for Q::ABC, +// which is really huge, so compilation never ends. +Q::ABC var; +#endif Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -804,6 +804,19 @@ } } + if (Arg *A = Args.getLastArg(OPT_ir_type_names_EQ)) { + StringRef Name = A->getValue(); + auto Info = llvm::StringSwitch<CodeGenOptions::IRNameKind>(Name) + .Case("none", CodeGenOptions::IRNameKind::None) + .Case("use", CodeGenOptions::IRNameKind::Use) + .Default(CodeGenOptions::IRNameKind::Unspecified); + if (Info == CodeGenOptions::IRNameKind::Unspecified) { + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; + Success = false; + } else + Opts.setIRTypeNames(Info); + } + Opts.PreserveVec3Type = Args.hasArg(OPT_fpreserve_vec3_type); Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions); Opts.InstrumentFunctionsAfterInlining = Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -3279,6 +3279,8 @@ if (C.getDriver().embedBitcodeMarkerOnly() && !C.getDriver().isUsingLTO()) CmdArgs.push_back("-fembed-bitcode=marker"); + Args.AddLastArg(CmdArgs, options::OPT_ir_type_names_EQ); + // We normally speed up the clang process a bit by skipping destructors at // exit, but when we're generating diagnostics we can rely on some of the // cleanup. Index: lib/CodeGen/CodeGenTypes.cpp =================================================================== --- lib/CodeGen/CodeGenTypes.cpp +++ lib/CodeGen/CodeGenTypes.cpp @@ -51,10 +51,13 @@ void CodeGenTypes::addRecordTypeName(const RecordDecl *RD, llvm::StructType *Ty, StringRef suffix) { + if (getCodeGenOpts().getIRTypeNames() == CodeGenOptions::IRNameKind::None) + return; + SmallString<256> TypeName; llvm::raw_svector_ostream OS(TypeName); OS << RD->getKindName() << '.'; - + // Name the codegen type after the typedef name // if there is no tag type name available if (RD->getIdentifier()) { Index: lib/CodeGen/CodeGenAction.cpp =================================================================== --- lib/CodeGen/CodeGenAction.cpp +++ lib/CodeGen/CodeGenAction.cpp @@ -884,6 +884,22 @@ std::unique_ptr<PPCallbacks>(CoverageInfo)); } + // Specify names for IR types in the cases: + // - if it requested explicitly, by option '--ir-type-names=use', + // - if compilation produces IR representation, or + // - in Debug build. + if (CI.getCodeGenOpts().getIRTypeNames() + == CodeGenOptions::IRNameKind::Unspecified) { +#ifdef NDEBUG + if ((BA == Backend_EmitBC || + BA == Backend_EmitLL || + (BA == Backend_EmitObj && + CI.getCodeGenOpts().getEmbedBitcode() != CodeGenOptions::Embed_Off) || + !LinkModules.empty())) +#endif + CI.getCodeGenOpts().setIRTypeNames(CodeGenOptions::IRNameKind::Use); + } + std::unique_ptr<BackendConsumer> Result(new BackendConsumer( BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), Index: include/clang/Frontend/CodeGenOptions.h =================================================================== --- include/clang/Frontend/CodeGenOptions.h +++ include/clang/Frontend/CodeGenOptions.h @@ -107,6 +107,14 @@ Embed_Marker // Embed a marker as a placeholder for bitcode. }; + /// Should LLVM types be given human-readable names? + /// + enum class IRNameKind { + Unspecified, ///< No special option was passed. + None, ///< No type names. + Use ///< Types must be named. + }; + /// The code model to use (-mcmodel). std::string CodeModel; Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -72,6 +72,11 @@ CODEGENOPT(EmulatedTLS , 1, 0) ///< Set when -femulated-tls is enabled. /// \brief Embed Bitcode mode (off/all/bitcode/marker). ENUM_CODEGENOPT(EmbedBitcode, EmbedBitcodeKind, 2, Embed_Off) + +/// Should LLVM IR types be given human-readable names? +/// \see CodeGenOptions::IRNameKind. +ENUM_CODEGENOPT(IRTypeNames, IRNameKind, 4, IRNameKind::Unspecified) + CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables ///< are required. CODEGENOPT(FunctionSections , 1, 0) ///< Set when -ffunction-sections is enabled. Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1729,6 +1729,10 @@ MetaVarName<"<file>">, HelpText<"Include file before parsing">, Flags<[CC1Option]>; def include_pch : Separate<["-"], "include-pch">, Group<clang_i_Group>, Flags<[CC1Option]>, HelpText<"Include precompiled header file">, MetaVarName<"<file>">; +def ir_type_names_EQ : Joined<["--"], "ir-type-names=">, + Flags<[CC1Option, HelpHidden]>, + HelpText<"Whether to use IR type names (option: none, use)">, + Values<"none,use">; def relocatable_pch : Flag<["-", "--"], "relocatable-pch">, Flags<[CC1Option]>, HelpText<"Whether to build a relocatable precompiled header">; def verify_pch : Flag<["-"], "verify-pch">, Group<Action_Group>, Flags<[CC1Option]>,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits