From dea290db815830c7a356771f98a05054204643c2 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 5 Aug 2026 05:52:24 -0700 Subject: [PATCH] Only lower files we are going to emit. (#7611) Move `--output-last-file-only` and output filename synthesis logic out of the general-purpose compile driver and into the `carbon compile` subcommand, which is the only thing that should be using them. Track on CompilationUnit whether it is being lowered, or whether it exists only to be imported into other units. `carbon compile` now never lowers inputs that it discovered for itself, only inputs that were specified on the command line. In particular, it doesn't lower (and throw away the result of lowering) the prelude any more. This makes the toolchain tests about 10% faster in my crude measurements. Also, we now do not create a clang `CodeGenerator` for input files that we are not lowering, similarly saving compilation time for units that exist only to be imported, not lowered. One minor change: we use the same mechanism to determine whether an input is being lowered and to determine what the output filename is. This means that `--phase=lower` and `--phase=optimize`, which lower but don't produce an output file, still need an output filename to be specified now in some cases. Given those are just debugging tools, I think that's fine. Assisted-by: Gemini via Antigravity --- toolchain/check/check.cpp | 6 +- toolchain/check/check.h | 1 + toolchain/check/cpp/domain.h | 5 + toolchain/check/cpp/generate_ast.cpp | 4 + toolchain/driver/compile_driver.cpp | 55 +++-------- toolchain/driver/compile_driver.h | 9 +- toolchain/driver/compile_options.cpp | 11 --- toolchain/driver/compile_options.h | 1 - toolchain/driver/compile_subcommand.cpp | 84 ++++++++++++++++- toolchain/driver/compile_subcommand.h | 12 +++ toolchain/driver/testdata/stdin.carbon | 2 +- .../generic/call_different_specific.carbon | 10 +- .../testdata/interop/cpp/operators.carbon | 94 +++++++++---------- .../interop/cpp/std_initializer_list.carbon | 6 +- 14 files changed, 181 insertions(+), 119 deletions(-) diff --git a/toolchain/check/check.cpp b/toolchain/check/check.cpp index 899ae21eb7b9..b6de302f1077 100644 --- a/toolchain/check/check.cpp +++ b/toolchain/check/check.cpp @@ -513,7 +513,8 @@ auto CheckParseTrees( continue; } inputs.push_back({.check_ir_id = unit_info.unit->sem_ir->check_ir_id(), - .filename = unit_info.unit->sem_ir->filename()}); + .filename = unit_info.unit->sem_ir->filename(), + .is_lowered = unit_info.unit->is_lowered}); } // TODO: Remove dependence on properties of the first unit here. if (auto cpp_domain = InitializeCppDomain( @@ -534,7 +535,8 @@ auto CheckParseTrees( if (auto cpp_domain = InitializeCppDomain( unit_info.err_tracker, {{.check_ir_id = unit_info.unit->sem_ir->check_ir_id(), - .filename = unit_info.unit->sem_ir->filename()}}, + .filename = unit_info.unit->sem_ir->filename(), + .is_lowered = unit_info.unit->is_lowered}}, fs, unit_info.unit->llvm_context, clang_invocation)) { cpp_domains.push_back(std::move(cpp_domain)); unit_info.cpp_domain = cpp_domains.back().get(); diff --git a/toolchain/check/check.h b/toolchain/check/check.h index 927c57c831b4..21a460fbbf6f 100644 --- a/toolchain/check/check.h +++ b/toolchain/check/check.h @@ -28,6 +28,7 @@ struct Unit { // The unit's SemIR, provided as empty and filled in by CheckParseTrees. SemIR::File* sem_ir; llvm::LLVMContext* llvm_context; + bool is_lowered; // The total number of files. int total_ir_count; }; diff --git a/toolchain/check/cpp/domain.h b/toolchain/check/cpp/domain.h index 1b586f7e4565..a2fd38b2f6bc 100644 --- a/toolchain/check/cpp/domain.h +++ b/toolchain/check/cpp/domain.h @@ -26,8 +26,13 @@ namespace Carbon::Check { // An input Carbon file and its CheckIRId for C++ domain code generation. struct CppInputFile { + // The ID used to identify this file within SemIR. SemIR::CheckIRId check_ir_id; + // The Carbon source filename for this input. llvm::StringRef filename; + // Whether this input IR will be lowered. If not, we don't need to build a + // Clang CodeGenerator for it. + bool is_lowered; }; // A C++ compilation domain, including a live Clang instance that can be used to diff --git a/toolchain/check/cpp/generate_ast.cpp b/toolchain/check/cpp/generate_ast.cpp index e46a03b2eb00..8f02c78a3dad 100644 --- a/toolchain/check/cpp/generate_ast.cpp +++ b/toolchain/check/cpp/generate_ast.cpp @@ -743,6 +743,10 @@ class GenerateASTAction : public clang::ASTFrontendAction { // a single object file, for a faster `carbon build` mode. std::vector> consumers; for (const auto& input : inputs_) { + if (!input.is_lowered) { + code_generators_.push_back(nullptr); + continue; + } // TODO: Filter what goes into each code generator. If there are strong // external C++ definitions in a Carbon file (for example, in inline C++ // code), they should be emitted only in that one file. diff --git a/toolchain/driver/compile_driver.cpp b/toolchain/driver/compile_driver.cpp index a5f1d3ce3981..881f3d334b4b 100644 --- a/toolchain/driver/compile_driver.cpp +++ b/toolchain/driver/compile_driver.cpp @@ -154,6 +154,7 @@ auto CompilationUnit::GetCheckUnit() -> Check::Unit { .timings = timings_ ? &*timings_ : nullptr, .sem_ir = &*sem_ir_, .llvm_context = llvm_context_, + .is_lowered = is_lowered(), .total_ir_count = total_ir_count_}; } @@ -175,6 +176,8 @@ auto CompilationUnit::PostCheck() -> void { } auto CompilationUnit::RunLower() -> void { + CARBON_CHECK(is_lowered(), "Should not lower this compilation unit"); + LogCall("Lower::LowerToLLVM", "lower", [&] { Lower::LowerToLLVMOptions options; options.llvm_verifier_stream = @@ -364,27 +367,10 @@ auto CompilationUnit::RunCodeGenHelper() -> bool { } } } else { - llvm::SmallString<256> output_filename = llvm::StringRef(output_filename_); - if (output_filename.empty()) { - if (!source_->is_regular_file()) { - // Don't invent file names like `-.o` or `/dev/stdin.o`. - // TODO: Consider rephrasing the diagnostic to use the file as the - // `Emit` location. - CARBON_DIAGNOSTIC(CompileInputNotRegularFile, Error, - "output file name must be specified for input `{0}` " - "that is not a regular file", - std::string); - driver_env_->emitter.Emit(CompileInputNotRegularFile, input_filename_); - return false; - } - output_filename = input_filename_; - llvm::sys::path::replace_extension(output_filename, - options_->asm_output ? ".s" : ".o"); - } - CARBON_VLOG("Writing output to: {0}\n", output_filename); + CARBON_VLOG("Writing output to: {0}\n", output_filename_); std::error_code ec; - llvm::raw_fd_ostream output_file(output_filename, ec, + llvm::raw_fd_ostream output_file(output_filename_, ec, llvm::sys::fs::OF_None); if (ec) { // TODO: Consider rephrasing the diagnostic to use the file as the `Emit` @@ -392,8 +378,8 @@ auto CompilationUnit::RunCodeGenHelper() -> bool { CARBON_DIAGNOSTIC(CompileOutputFileOpenError, Error, "could not open output file `{0}`: {1}", std::string, std::string); - driver_env_->emitter.Emit(CompileOutputFileOpenError, - output_filename.str().str(), ec.message()); + driver_env_->emitter.Emit(CompileOutputFileOpenError, output_filename_, + ec.message()); return false; } if (options_->asm_output) { @@ -647,6 +633,10 @@ auto CompileDriver::Compile(DriverEnv& driver_env) -> DriverResult { // Lower and optimize. for (const auto& unit : units_) { + if (!unit->is_lowered()) { + continue; + } + unit->RunLower(); if (options_->phase != CompileOptions::Phase::Lower) { @@ -662,28 +652,9 @@ auto CompileDriver::Compile(DriverEnv& driver_env) -> DriverResult { CARBON_CHECK(options_->phase == CompileOptions::Phase::CodeGen, "CodeGen should be the last stage"); - bool output_last_input_only = options_->output_last_input_only; - if (!output_last_input_only && units_.size() > 1 && - !options_->output_filename.empty() && options_->output_filename != "-") { - // TODO: Command line structure should change to make this implicit - // (passing non-compiling inputs differently), and the warning should be - // removed. - CARBON_DIAGNOSTIC( - CompileMultipleInputsWithOutput, Warning, - "only outputting {0} to {1}, skipping output of {2} input " - "file{2:s}; pass `--output-last-input-only` to silence this warning", - std::string, std::string, Diagnostics::IntAsSelect); - driver_env.emitter.Emit(CompileMultipleInputsWithOutput, - units_.back()->input_filename().str(), - options_->output_filename.str(), units_.size() - 1); - output_last_input_only = true; - } - // Codegen. - if (output_last_input_only) { - units_.back()->RunCodeGen(); - } else { - for (const auto& unit : units_) { + for (const auto& unit : units_) { + if (unit->is_lowered()) { unit->RunCodeGen(); } } diff --git a/toolchain/driver/compile_driver.h b/toolchain/driver/compile_driver.h index f421775683db..cdb1d163b5d6 100644 --- a/toolchain/driver/compile_driver.h +++ b/toolchain/driver/compile_driver.h @@ -20,7 +20,10 @@ class MultiUnitCache; // Ties together information for a file being compiled. class CompilationUnit { public: - // `driver_env`, `options`, `consumer`, and `target` must be non-null. + // `driver_env`, `options`, `consumer`, and `target` must be non-null. If + // `output_filename` is empty, no output will be generated for this file. This + // is used for inputs that are only used as dependencies of the current + // compilation. explicit CompilationUnit(SemIR::CheckIRId check_ir_id, int total_ir_count, DriverEnv* driver_env, const CompileOptions* options, Diagnostics::Consumer* consumer, @@ -67,6 +70,7 @@ class CompilationUnit { auto input_filename() -> llvm::StringRef { return input_filename_; } auto output_filename() -> llvm::StringRef { return output_filename_; } + auto is_lowered() -> bool { return !output_filename_.empty(); } auto has_include_in_dumps() -> bool { return tokens_ && tokens_->has_include_in_dumps(); } @@ -236,8 +240,7 @@ class CompileDriver { explicit CompileDriver(CompileOptions* options); // Configure the toolchain to compile all input files and dependencies. - // The `map_input` function maps an input file name to an output static - // object name. + // The `map_input` function maps an input file name to an output file name. // Returns `false` on configuration error. [[nodiscard]] auto Initialize( DriverEnv& driver_env, diff --git a/toolchain/driver/compile_options.cpp b/toolchain/driver/compile_options.cpp index 0507e2e13629..fc57f6e510d7 100644 --- a/toolchain/driver/compile_options.cpp +++ b/toolchain/driver/compile_options.cpp @@ -374,17 +374,6 @@ Excludes files with the given prefix from dumps. )""", }, [&](auto& arg_b) { arg_b.Append(&exclude_dump_file_prefixes); }); - b.AddFlag( - { - .name = "output-last-input-only", - .help = R"""( -Only write output for the last input file, ignoring all others. - -TODO: This is a temporary workaround and should be removed once separate -compilation is better implemented. -)""", - }, - [&](auto& arg_b) { arg_b.Set(&output_last_input_only); }); b.AddStringOption( { .name = "sem-ir-crash-dump", diff --git a/toolchain/driver/compile_options.h b/toolchain/driver/compile_options.h index b874f8fb5b03..a85ce0520404 100644 --- a/toolchain/driver/compile_options.h +++ b/toolchain/driver/compile_options.h @@ -115,7 +115,6 @@ struct CompileOptions { Parse::ParseOptions::DumpFormat parse_dump_format; bool builtin_sem_ir = false; bool prelude_import = true; - bool output_last_input_only = false; bool include_carbon_core = true; llvm::SmallVector exclude_dump_file_prefixes; diff --git a/toolchain/driver/compile_subcommand.cpp b/toolchain/driver/compile_subcommand.cpp index f2c65ebcc166..6a913da62db2 100644 --- a/toolchain/driver/compile_subcommand.cpp +++ b/toolchain/driver/compile_subcommand.cpp @@ -4,6 +4,10 @@ #include "toolchain/driver/compile_subcommand.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Path.h" +#include "toolchain/diagnostics/emitter.h" +#include "toolchain/diagnostics/format_providers.h" #include "toolchain/driver/compile_driver.h" namespace Carbon { @@ -35,12 +39,84 @@ auto CompileSubcommand::Run(DriverEnv& driver_env) -> DriverResult { return {.success = false}; } + // If we're lowering and have an output file name, we can only support a + // single input filename. + // TODO: Produce an error in this case rather than skipping all files but the + // last, and remove the `--output-last-input-only` flag. + if (options_.compile_options.phase >= CompileOptions::Phase::Lower && + options_.compile_options.input_filenames.size() > 1 && + !options_.output_last_input_only && + !options_.compile_options.output_filename.empty() && + options_.compile_options.output_filename != "-") { + CARBON_DIAGNOSTIC( + CompileMultipleInputsWithOutput, Warning, + "only outputting {0} to {1}, skipping output of {2} input " + "file{2:s}; pass `--output-last-input-only` to silence this " + "warning", + std::string, std::string, Diagnostics::IntAsSelect); + driver_env.emitter.Emit( + CompileMultipleInputsWithOutput, + options_.compile_options.input_filenames.back().str(), + options_.compile_options.output_filename.str(), + options_.compile_options.input_filenames.size() - 1); + } + + llvm::StringSet<> input_filenames(llvm::from_range, + options_.compile_options.input_filenames); + auto compile_driver = CompileDriver(&options_.compile_options); - if (!compile_driver.Initialize( - driver_env, [&](llvm::StringRef) -> std::string { - return options_.compile_options.output_filename.str(); - })) { + bool init_success = true; + auto get_output_filename = + [&](llvm::StringRef input_filename) -> std::string { + // We only generate output for inputs specified on the command line, + // not for inputs discovered through imports. + if (!input_filenames.contains(input_filename)) { + return ""; + } + + // If the output filename is "-", that's used for all inputs. + if (options_.compile_options.output_filename == "-") { + return "-"; + } + + // If single output filename was specified, it's used for the final + // input filename only. + if (!options_.compile_options.output_filename.empty()) { + if (input_filename == options_.compile_options.input_filenames.back()) { + return options_.compile_options.output_filename.str(); + } + return ""; + } + + // Otherwise, generate an output filename for each explicitly-specified + // input file. + bool is_regular_file = true; + if (input_filename == "-") { + // TODO: If we would produce textual output, using "-" as the default + // output filename here would be reasonable and useful. + is_regular_file = false; + } else if (auto status = driver_env.fs->status(input_filename); + status && status->isOther()) { + is_regular_file = false; + } + if (!is_regular_file) { + CARBON_DIAGNOSTIC(CompileInputNotRegularFile, Error, + "output file name must be specified for input " + "`{0}` that is not a regular file", + std::string); + driver_env.emitter.Emit(CompileInputNotRegularFile, input_filename.str()); + init_success = false; + return ""; + } + llvm::SmallString<256> output_filename = input_filename; + llvm::sys::path::replace_extension( + output_filename, options_.compile_options.asm_output ? ".s" : ".o"); + return output_filename.str().str(); + }; + + if (!compile_driver.Initialize(driver_env, get_output_filename) || + !init_success) { return {.success = false}; } diff --git a/toolchain/driver/compile_subcommand.h b/toolchain/driver/compile_subcommand.h index 47a64ba13353..8aa57568484d 100644 --- a/toolchain/driver/compile_subcommand.h +++ b/toolchain/driver/compile_subcommand.h @@ -16,10 +16,22 @@ namespace Carbon { struct CompileSubcommandOptions { auto Build(CommandLine::CommandBuilder& b) -> void { compile_options.BuildForCompileSubcommand(b, &codegen_options); + b.AddFlag( + { + .name = "output-last-input-only", + .help = R"""( +Only write output for the last input file, ignoring all others. + +TODO: This is a temporary workaround and should be removed once separate +compilation is better implemented. +)""", + }, + [&](auto& arg_b) { arg_b.Set(&output_last_input_only); }); } CodegenOptions codegen_options; CompileOptions compile_options; + bool output_last_input_only = false; }; // Implements the compile subcommand of the driver. diff --git a/toolchain/driver/testdata/stdin.carbon b/toolchain/driver/testdata/stdin.carbon index 27df3370f956..e53f7f351ab3 100644 --- a/toolchain/driver/testdata/stdin.carbon +++ b/toolchain/driver/testdata/stdin.carbon @@ -6,7 +6,7 @@ // dump flags. // TODO: Align lex/parse with check/lower. // -// ARGS: compile - --phase=lower --no-prelude-import --target=x86_64-linux-gnu --dump-tokens --dump-parse-tree --parse-dump-format=yaml-postorder --dump-sem-ir --dump-raw-sem-ir --dump-llvm-ir +// ARGS: compile - --output=- --phase=lower --no-prelude-import --target=x86_64-linux-gnu --dump-tokens --dump-parse-tree --parse-dump-format=yaml-postorder --dump-sem-ir --dump-raw-sem-ir --dump-llvm-ir // // AUTOUPDATE // TIP: To test this file alone, run: diff --git a/toolchain/lower/testdata/function/generic/call_different_specific.carbon b/toolchain/lower/testdata/function/generic/call_different_specific.carbon index dc454daec477..b96f762c0ad5 100644 --- a/toolchain/lower/testdata/function/generic/call_different_specific.carbon +++ b/toolchain/lower/testdata/function/generic/call_different_specific.carbon @@ -48,7 +48,7 @@ fn M(ptr_i32: i32*, ptr_f64: f64*) { // CHECK:STDOUT: ; ModuleID = 'call_different_specific.carbon' // CHECK:STDOUT: source_filename = "call_different_specific.carbon" // CHECK:STDOUT: -// CHECK:STDOUT: %type.58 = type {} +// CHECK:STDOUT: %type.0 = type {} // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define void @_CM.Main(ptr %ptr_i32, ptr %ptr_f64) #0 !dbg !4 { @@ -73,7 +73,7 @@ fn M(ptr_i32: i32*, ptr_f64: f64*) { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define linkonce_odr void @_CF.Main.58016a73bff04416(ptr %x) #0 !dbg !27 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %A.call = call %type.58 @_CA.Main.ee509b43cf4eb3c5(%type.58 zeroinitializer), !dbg !30 +// CHECK:STDOUT: %A.call = call %type.0 @_CA.Main.ee509b43cf4eb3c5(%type.0 zeroinitializer), !dbg !30 // CHECK:STDOUT: call void @_CB.Main.58016a73bff04416(ptr %x), !dbg !31 // CHECK:STDOUT: ret void, !dbg !32 // CHECK:STDOUT: } @@ -81,15 +81,15 @@ fn M(ptr_i32: i32*, ptr_f64: f64*) { // CHECK:STDOUT: ; Function Attrs: nounwind // CHECK:STDOUT: define linkonce_odr void @_CF.Main.fa1f0912a5bbe922(ptr %x) #0 !dbg !33 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %A.call = call %type.58 @_CA.Main.ee509b43cf4eb3c5(%type.58 zeroinitializer), !dbg !36 +// CHECK:STDOUT: %A.call = call %type.0 @_CA.Main.ee509b43cf4eb3c5(%type.0 zeroinitializer), !dbg !36 // CHECK:STDOUT: call void @_CB.Main.fa1f0912a5bbe922(ptr %x), !dbg !37 // CHECK:STDOUT: ret void, !dbg !38 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind -// CHECK:STDOUT: define linkonce_odr %type.58 @_CA.Main.ee509b43cf4eb3c5(%type.58 %x) #0 !dbg !39 { +// CHECK:STDOUT: define linkonce_odr %type.0 @_CA.Main.ee509b43cf4eb3c5(%type.0 %x) #0 !dbg !39 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: ret %type.58 %x, !dbg !44 +// CHECK:STDOUT: ret %type.0 %x, !dbg !44 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: ; Function Attrs: nounwind diff --git a/toolchain/lower/testdata/interop/cpp/operators.carbon b/toolchain/lower/testdata/interop/cpp/operators.carbon index 610f3dad578a..b199ae8608d4 100644 --- a/toolchain/lower/testdata/interop/cpp/operators.carbon +++ b/toolchain/lower/testdata/interop/cpp/operators.carbon @@ -290,7 +290,7 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" // CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu" // CHECK:STDOUT: -// CHECK:STDOUT: %struct.A.62 = type { i32 } +// CHECK:STDOUT: %struct.A.4 = type { i32 } // CHECK:STDOUT: // CHECK:STDOUT: $_Zlt1AS_ = comdat any // CHECK:STDOUT: @@ -313,8 +313,8 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: %x.addr = alloca ptr, align 8 // CHECK:STDOUT: %y.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 -// CHECK:STDOUT: %agg.tmp = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.62, align 4 +// CHECK:STDOUT: %agg.tmp = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.4, align 4 // CHECK:STDOUT: store ptr %x, ptr %x.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %y, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !24 @@ -323,9 +323,9 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %1, i64 4, i1 false), !tbaa.struct !26 // CHECK:STDOUT: %2 = load ptr, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp1, ptr align 4 %2, i64 4, i1 false), !tbaa.struct !26 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp, i32 0, i32 0 // CHECK:STDOUT: %3 = load i32, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp1, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp1, i32 0, i32 0 // CHECK:STDOUT: %4 = load i32, ptr %coerce.dive2, align 4 // CHECK:STDOUT: %call = call noundef zeroext i1 @_Zlt1AS_(i32 %3, i32 %4) // CHECK:STDOUT: %storedv = zext i1 %call to i8 @@ -339,8 +339,8 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: %x.addr = alloca ptr, align 8 // CHECK:STDOUT: %y.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 -// CHECK:STDOUT: %agg.tmp = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.62, align 4 +// CHECK:STDOUT: %agg.tmp = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.4, align 4 // CHECK:STDOUT: store ptr %x, ptr %x.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %y, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !24 @@ -349,9 +349,9 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %1, i64 4, i1 false), !tbaa.struct !26 // CHECK:STDOUT: %2 = load ptr, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp1, ptr align 4 %2, i64 4, i1 false), !tbaa.struct !26 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp, i32 0, i32 0 // CHECK:STDOUT: %3 = load i32, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp1, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp1, i32 0, i32 0 // CHECK:STDOUT: %4 = load i32, ptr %coerce.dive2, align 4 // CHECK:STDOUT: %call = call noundef zeroext i1 @_Zle1AS_(i32 %3, i32 %4) // CHECK:STDOUT: %storedv = zext i1 %call to i8 @@ -365,8 +365,8 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: %x.addr = alloca ptr, align 8 // CHECK:STDOUT: %y.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 -// CHECK:STDOUT: %agg.tmp = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.62, align 4 +// CHECK:STDOUT: %agg.tmp = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.4, align 4 // CHECK:STDOUT: store ptr %x, ptr %x.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %y, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !24 @@ -375,9 +375,9 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %1, i64 4, i1 false), !tbaa.struct !26 // CHECK:STDOUT: %2 = load ptr, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp1, ptr align 4 %2, i64 4, i1 false), !tbaa.struct !26 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp, i32 0, i32 0 // CHECK:STDOUT: %3 = load i32, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp1, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp1, i32 0, i32 0 // CHECK:STDOUT: %4 = load i32, ptr %coerce.dive2, align 4 // CHECK:STDOUT: %call = call noundef zeroext i1 @_Zgt1AS_(i32 %3, i32 %4) // CHECK:STDOUT: %storedv = zext i1 %call to i8 @@ -391,8 +391,8 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: %x.addr = alloca ptr, align 8 // CHECK:STDOUT: %y.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 -// CHECK:STDOUT: %agg.tmp = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.62, align 4 +// CHECK:STDOUT: %agg.tmp = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp1 = alloca %struct.A.4, align 4 // CHECK:STDOUT: store ptr %x, ptr %x.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %y, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !24 @@ -401,9 +401,9 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %1, i64 4, i1 false), !tbaa.struct !26 // CHECK:STDOUT: %2 = load ptr, ptr %y.addr, align 8, !tbaa !21 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp1, ptr align 4 %2, i64 4, i1 false), !tbaa.struct !26 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp, i32 0, i32 0 // CHECK:STDOUT: %3 = load i32, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp1, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive2 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp1, i32 0, i32 0 // CHECK:STDOUT: %4 = load i32, ptr %coerce.dive2, align 4 // CHECK:STDOUT: %call = call noundef zeroext i1 @_Zge1AS_(i32 %3, i32 %4) // CHECK:STDOUT: %storedv = zext i1 %call to i8 @@ -467,15 +467,15 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: ; Function Attrs: mustprogress nounwind uwtable // CHECK:STDOUT: define linkonce_odr dso_local noundef zeroext i1 @_Zlt1AS_(i32 %x.coerce, i32 %y.coerce) #4 comdat { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %x = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %y = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %x, i32 0, i32 0 +// CHECK:STDOUT: %x = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %y = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %x, i32 0, i32 0 // CHECK:STDOUT: store i32 %x.coerce, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.62, ptr %y, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.4, ptr %y, i32 0, i32 0 // CHECK:STDOUT: store i32 %y.coerce, ptr %coerce.dive1, align 4 -// CHECK:STDOUT: %value = getelementptr inbounds nuw %struct.A.62, ptr %x, i32 0, i32 0 +// CHECK:STDOUT: %value = getelementptr inbounds nuw %struct.A.4, ptr %x, i32 0, i32 0 // CHECK:STDOUT: %0 = load i32, ptr %value, align 4, !tbaa !61 -// CHECK:STDOUT: %value2 = getelementptr inbounds nuw %struct.A.62, ptr %y, i32 0, i32 0 +// CHECK:STDOUT: %value2 = getelementptr inbounds nuw %struct.A.4, ptr %y, i32 0, i32 0 // CHECK:STDOUT: %1 = load i32, ptr %value2, align 4, !tbaa !61 // CHECK:STDOUT: %cmp = icmp slt i32 %0, %1 // CHECK:STDOUT: ret i1 %cmp @@ -487,19 +487,19 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: ; Function Attrs: mustprogress nounwind uwtable // CHECK:STDOUT: define linkonce_odr dso_local noundef zeroext i1 @_Zle1AS_(i32 %x.coerce, i32 %y.coerce) #4 comdat { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %x = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %y = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp2 = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %x, i32 0, i32 0 +// CHECK:STDOUT: %x = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %y = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp2 = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %x, i32 0, i32 0 // CHECK:STDOUT: store i32 %x.coerce, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.62, ptr %y, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.4, ptr %y, i32 0, i32 0 // CHECK:STDOUT: store i32 %y.coerce, ptr %coerce.dive1, align 4 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %y, i64 4, i1 false), !tbaa.struct !26 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp2, ptr align 4 %x, i64 4, i1 false), !tbaa.struct !26 -// CHECK:STDOUT: %coerce.dive3 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive3 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp, i32 0, i32 0 // CHECK:STDOUT: %0 = load i32, ptr %coerce.dive3, align 4 -// CHECK:STDOUT: %coerce.dive4 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp2, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive4 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp2, i32 0, i32 0 // CHECK:STDOUT: %1 = load i32, ptr %coerce.dive4, align 4 // CHECK:STDOUT: %call = call noundef zeroext i1 @_Zlt1AS_(i32 %0, i32 %1) // CHECK:STDOUT: %lnot = xor i1 %call, true @@ -509,19 +509,19 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: ; Function Attrs: mustprogress nounwind uwtable // CHECK:STDOUT: define linkonce_odr dso_local noundef zeroext i1 @_Zgt1AS_(i32 %x.coerce, i32 %y.coerce) #4 comdat { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %x = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %y = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp2 = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %x, i32 0, i32 0 +// CHECK:STDOUT: %x = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %y = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp2 = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %x, i32 0, i32 0 // CHECK:STDOUT: store i32 %x.coerce, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.62, ptr %y, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.4, ptr %y, i32 0, i32 0 // CHECK:STDOUT: store i32 %y.coerce, ptr %coerce.dive1, align 4 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %y, i64 4, i1 false), !tbaa.struct !26 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp2, ptr align 4 %x, i64 4, i1 false), !tbaa.struct !26 -// CHECK:STDOUT: %coerce.dive3 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive3 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp, i32 0, i32 0 // CHECK:STDOUT: %0 = load i32, ptr %coerce.dive3, align 4 -// CHECK:STDOUT: %coerce.dive4 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp2, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive4 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp2, i32 0, i32 0 // CHECK:STDOUT: %1 = load i32, ptr %coerce.dive4, align 4 // CHECK:STDOUT: %call = call noundef zeroext i1 @_Zlt1AS_(i32 %0, i32 %1) // CHECK:STDOUT: ret i1 %call @@ -530,19 +530,19 @@ fn Driver(x: Cpp.A, y: Cpp.A) { // CHECK:STDOUT: ; Function Attrs: mustprogress nounwind uwtable // CHECK:STDOUT: define linkonce_odr dso_local noundef zeroext i1 @_Zge1AS_(i32 %x.coerce, i32 %y.coerce) #4 comdat { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %x = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %y = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %agg.tmp2 = alloca %struct.A.62, align 4 -// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.62, ptr %x, i32 0, i32 0 +// CHECK:STDOUT: %x = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %y = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %agg.tmp2 = alloca %struct.A.4, align 4 +// CHECK:STDOUT: %coerce.dive = getelementptr inbounds nuw %struct.A.4, ptr %x, i32 0, i32 0 // CHECK:STDOUT: store i32 %x.coerce, ptr %coerce.dive, align 4 -// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.62, ptr %y, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive1 = getelementptr inbounds nuw %struct.A.4, ptr %y, i32 0, i32 0 // CHECK:STDOUT: store i32 %y.coerce, ptr %coerce.dive1, align 4 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp, ptr align 4 %x, i64 4, i1 false), !tbaa.struct !26 // CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %agg.tmp2, ptr align 4 %y, i64 4, i1 false), !tbaa.struct !26 -// CHECK:STDOUT: %coerce.dive3 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive3 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp, i32 0, i32 0 // CHECK:STDOUT: %0 = load i32, ptr %coerce.dive3, align 4 -// CHECK:STDOUT: %coerce.dive4 = getelementptr inbounds nuw %struct.A.62, ptr %agg.tmp2, i32 0, i32 0 +// CHECK:STDOUT: %coerce.dive4 = getelementptr inbounds nuw %struct.A.4, ptr %agg.tmp2, i32 0, i32 0 // CHECK:STDOUT: %1 = load i32, ptr %coerce.dive4, align 4 // CHECK:STDOUT: %call = call noundef zeroext i1 @_Zlt1AS_(i32 %0, i32 %1) // CHECK:STDOUT: %lnot = xor i1 %call, true diff --git a/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon b/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon index dd0d76773517..009c76fd8b01 100644 --- a/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon +++ b/toolchain/lower/testdata/interop/cpp/std_initializer_list.carbon @@ -368,7 +368,7 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" // CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu" // CHECK:STDOUT: -// CHECK:STDOUT: %"class.std::initializer_list.64" = type { ptr, i64 } +// CHECK:STDOUT: %"class.std::initializer_list.6" = type { ptr, i64 } // CHECK:STDOUT: // CHECK:STDOUT: $_ZN11vector_likeD2Ev = comdat any // CHECK:STDOUT: @@ -442,7 +442,7 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: entry: // CHECK:STDOUT: %list.addr = alloca ptr, align 8 // CHECK:STDOUT: %return.addr = alloca ptr, align 8 -// CHECK:STDOUT: %agg.tmp = alloca %"class.std::initializer_list.64", align 8 +// CHECK:STDOUT: %agg.tmp = alloca %"class.std::initializer_list.6", align 8 // CHECK:STDOUT: store ptr %list, ptr %list.addr, align 8, !tbaa !38 // CHECK:STDOUT: store ptr %return, ptr %return.addr, align 8, !tbaa !41 // CHECK:STDOUT: %0 = load ptr, ptr %return.addr, align 8, !tbaa !41 @@ -521,7 +521,7 @@ fn InitNontrivialDtor() { // CHECK:STDOUT: ; Function Attrs: mustprogress nounwind uwtable // CHECK:STDOUT: define linkonce_odr dso_local void @_ZN11vector_likeC2ESt16initializer_listIiE(ptr noundef nonnull align 1 dereferenceable(1) %this, ptr %list.coerce0, i64 %list.coerce1) unnamed_addr #2 comdat align 2 { // CHECK:STDOUT: entry: -// CHECK:STDOUT: %list = alloca %"class.std::initializer_list.64", align 8 +// CHECK:STDOUT: %list = alloca %"class.std::initializer_list.6", align 8 // CHECK:STDOUT: %this.addr = alloca ptr, align 8 // CHECK:STDOUT: %0 = getelementptr inbounds nuw { ptr, i64 }, ptr %list, i32 0, i32 0 // CHECK:STDOUT: store ptr %list.coerce0, ptr %0, align 8