Skip to content

Commit 26f4401

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents 25c9084 + 0442c7c commit 26f4401

File tree

10 files changed

+231
-31
lines changed

10 files changed

+231
-31
lines changed

include/swift/AST/SILOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,10 @@ class SILOptions {
316316
/// records.
317317
std::string OptRecordFile;
318318

319+
/// The names of the auxiliar files to which the backend should save optimization
320+
/// records for the remaining (other than the main one) LLVMModules.
321+
std::vector<std::string> AuxOptRecordFiles;
322+
319323
/// The regex that filters the passes that should be saved to the optimization
320324
/// records.
321325
std::string OptRecordPasses;

include/swift/Frontend/FrontendInputsAndOutputs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,9 @@ class FrontendInputsAndOutputs {
253253
const PrimarySpecificPaths &
254254
getPrimarySpecificPathsForAtMostOnePrimary() const;
255255

256+
const PrimarySpecificPaths &
257+
getPrimarySpecificPathsForRemaining(unsigned i) const;
258+
256259
const PrimarySpecificPaths &
257260
getPrimarySpecificPathsForPrimary(StringRef) const;
258261

lib/Frontend/ArgsToFrontendOutputsConverter.cpp

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,44 @@ SupplementaryOutputPathsComputer::computeOutputPaths() const {
298298
});
299299
if (hadError)
300300
return std::nullopt;
301+
302+
// In WMO mode compute supplementary output paths for optimization record
303+
// data (opt-remarks). We need one path per LLVMModule that will be created as
304+
// part of wmo.
305+
if (!InputsAndOutputs.hasPrimaryInputs() && OutputFiles.size() > 1) {
306+
unsigned i = 0;
307+
InputsAndOutputs.forEachInput([&](const InputFile &input) -> bool {
308+
// First input is already computed.
309+
if (InputsAndOutputs.firstInput().getFileName() == input.getFileName()) {
310+
++i;
311+
return false;
312+
}
313+
SupplementaryOutputPaths outputs;
314+
315+
// Compute auxiliar opt record paths.
316+
StringRef defaultSupplementaryOutputPathExcludingExtension =
317+
deriveDefaultSupplementaryOutputPathExcludingExtension(OutputFiles[i], input);
318+
319+
auto YAMLOptRecordPath = determineSupplementaryOutputFilename(
320+
options::OPT_save_optimization_record_path,
321+
"",
322+
file_types::TY_YAMLOptRecord, "",
323+
defaultSupplementaryOutputPathExcludingExtension, true);
324+
outputs.YAMLOptRecordPath = YAMLOptRecordPath;
325+
326+
auto bitstreamOptRecordPath = determineSupplementaryOutputFilename(
327+
options::OPT_save_optimization_record_path,
328+
"",
329+
file_types::TY_BitstreamOptRecord, "",
330+
defaultSupplementaryOutputPathExcludingExtension, true);
331+
332+
outputs.BitstreamOptRecordPath = bitstreamOptRecordPath;
333+
334+
outputPaths.emplace_back(std::move(outputs));
335+
++i;
336+
return false;
337+
});
338+
}
301339
return outputPaths;
302340
}
303341

@@ -615,7 +653,21 @@ std::string
615653
SupplementaryOutputPathsComputer::determineSupplementaryOutputFilename(
616654
options::ID emitOpt, std::string pathFromArguments, file_types::ID type,
617655
StringRef mainOutputIfUsable,
618-
StringRef defaultSupplementaryOutputPathExcludingExtension) const {
656+
StringRef defaultSupplementaryOutputPathExcludingExtension,
657+
bool forceDefaultSupplementaryOutputPathExcludingExtension) const {
658+
659+
auto computeDefaultSupplementaryOutputPathExcludingExtension =
660+
[&] () -> std::string {
661+
llvm::SmallString<128> path(
662+
defaultSupplementaryOutputPathExcludingExtension);
663+
664+
llvm::sys::path::replace_extension(path, file_types::getExtension(type));
665+
return path.str().str();
666+
};
667+
668+
if (forceDefaultSupplementaryOutputPathExcludingExtension) {
669+
return computeDefaultSupplementaryOutputPathExcludingExtension();
670+
}
619671

620672
if (!pathFromArguments.empty())
621673
return pathFromArguments;
@@ -627,9 +679,7 @@ SupplementaryOutputPathsComputer::determineSupplementaryOutputFilename(
627679
return mainOutputIfUsable.str();
628680
}
629681

630-
llvm::SmallString<128> path(defaultSupplementaryOutputPathExcludingExtension);
631-
llvm::sys::path::replace_extension(path, file_types::getExtension(type));
632-
return path.str().str();
682+
return computeDefaultSupplementaryOutputPathExcludingExtension();
633683
}
634684

635685
void SupplementaryOutputPathsComputer::deriveModulePathParameters(

lib/Frontend/ArgsToFrontendOutputsConverter.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,8 @@ class SupplementaryOutputPathsComputer {
180180
std::string determineSupplementaryOutputFilename(
181181
options::ID emitOpt, std::string pathFromArgumentsOrFilelists,
182182
file_types::ID type, StringRef mainOutputIfUsable,
183-
StringRef defaultSupplementaryOutputPathExcludingExtension) const;
183+
StringRef defaultSupplementaryOutputPathExcludingExtension,
184+
bool forceDefaultSupplementaryOutputPathExcludingExtension = false) const;
184185

185186
void deriveModulePathParameters(StringRef mainOutputFile,
186187
options::ID &emitOption,

lib/Frontend/FrontendInputsAndOutputs.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -380,21 +380,32 @@ void FrontendInputsAndOutputs::setMainAndSupplementaryOutputs(
380380
}
381381
return;
382382
}
383-
assert(supplementaryOutputs.size() == 1 &&
384-
"WMO only ever produces one set of supplementary outputs");
383+
384+
assert(supplementaryOutputs.size() == 1 ||
385+
supplementaryOutputs.size() == AllInputs.size() &&
386+
"WMO produces wrong number of sets of supplementary outputs");
385387
if (outputFiles.size() == 1) {
386-
AllInputs.front().setPrimarySpecificPaths(PrimarySpecificPaths(
387-
outputFiles.front(), outputFilesForIndexUnits.front(),
388-
firstInputProducingOutput().getFileName(),
389-
supplementaryOutputs.front()));
388+
for (auto i : indices(AllInputs)) {
389+
if (i == 0)
390+
AllInputs[i].setPrimarySpecificPaths(PrimarySpecificPaths(
391+
outputFiles.front(), outputFilesForIndexUnits.front(),
392+
firstInputProducingOutput().getFileName(),
393+
supplementaryOutputs.front()));
394+
else
395+
AllInputs[i].setPrimarySpecificPaths(PrimarySpecificPaths(
396+
"", "", "",
397+
supplementaryOutputs.size() == 1 ? SupplementaryOutputPaths()
398+
: supplementaryOutputs[i]));
399+
}
390400
return;
391401
}
392402
assert(outputFiles.size() == AllInputs.size() &&
393403
"Multi-threaded WMO requires one main output per input");
394404
for (auto i : indices(AllInputs))
395405
AllInputs[i].setPrimarySpecificPaths(PrimarySpecificPaths(
396406
outputFiles[i], outputFilesForIndexUnits[i], outputFiles[i],
397-
i == 0 ? supplementaryOutputs.front() : SupplementaryOutputPaths()));
407+
supplementaryOutputs.size() == 1 && i != 0 ? SupplementaryOutputPaths()
408+
: supplementaryOutputs[i]));
398409
}
399410

400411
std::vector<std::string> FrontendInputsAndOutputs::copyOutputFilenames() const {
@@ -488,6 +499,14 @@ FrontendInputsAndOutputs::getPrimarySpecificPathsForAtMostOnePrimary() const {
488499
: emptyPaths;
489500
}
490501

502+
const PrimarySpecificPaths &
503+
FrontendInputsAndOutputs::getPrimarySpecificPathsForRemaining(unsigned i) const {
504+
static auto emptyPaths = PrimarySpecificPaths();
505+
unsigned firstProducingIdx = getIndexOfFirstOutputProducingInput();
506+
return (hasInputs() && i > 0) ?
507+
AllInputs[firstProducingIdx+i].getPrimarySpecificPaths() : emptyPaths;
508+
}
509+
491510
const PrimarySpecificPaths &
492511
FrontendInputsAndOutputs::getPrimarySpecificPathsForPrimary(
493512
StringRef filename) const {

lib/FrontendTool/FrontendTool.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -740,7 +740,8 @@ bool swift::performCompileStepsPostSema(CompilerInstance &Instance,
740740
const auto &Invocation = Instance.getInvocation();
741741
const FrontendOptions &opts = Invocation.getFrontendOptions();
742742

743-
auto getSILOptions = [&](const PrimarySpecificPaths &PSPs) -> SILOptions {
743+
auto getSILOptions = [&](const PrimarySpecificPaths &PSPs,
744+
const std::vector<PrimarySpecificPaths> &auxPSPs) -> SILOptions {
744745
SILOptions SILOpts = Invocation.getSILOptions();
745746
if (SILOpts.OptRecordFile.empty()) {
746747
// Check if the record file path was passed via supplemental outputs.
@@ -749,6 +750,15 @@ bool swift::performCompileStepsPostSema(CompilerInstance &Instance,
749750
PSPs.SupplementaryOutputs.YAMLOptRecordPath :
750751
PSPs.SupplementaryOutputs.BitstreamOptRecordPath;
751752
}
753+
if (!auxPSPs.empty()) {
754+
assert(SILOpts.AuxOptRecordFiles.empty());
755+
for (const auto &auxFile: auxPSPs) {
756+
SILOpts.AuxOptRecordFiles.push_back(
757+
SILOpts.OptRecordFormat == llvm::remarks::Format::YAML ?
758+
auxFile.SupplementaryOutputs.YAMLOptRecordPath :
759+
auxFile.SupplementaryOutputs.BitstreamOptRecordPath);
760+
}
761+
}
752762
return SILOpts;
753763
};
754764

@@ -758,13 +768,24 @@ bool swift::performCompileStepsPostSema(CompilerInstance &Instance,
758768
// SILModule for the entire module.
759769
const PrimarySpecificPaths PSPs =
760770
Instance.getPrimarySpecificPathsForWholeModuleOptimizationMode();
761-
SILOptions SILOpts = getSILOptions(PSPs);
771+
772+
std::vector<PrimarySpecificPaths> auxPSPs;
773+
for (unsigned i = 1; i < opts.InputsAndOutputs.inputCount(); ++i) {
774+
auto &auxPSP =
775+
opts.InputsAndOutputs.getPrimarySpecificPathsForRemaining(i);
776+
auxPSPs.push_back(auxPSP);
777+
}
778+
779+
SILOptions SILOpts = getSILOptions(PSPs, auxPSPs);
762780
IRGenOptions irgenOpts = Invocation.getIRGenOptions();
763781
auto SM = performASTLowering(mod, Instance.getSILTypes(), SILOpts,
764782
&irgenOpts);
765783
return performCompileStepsPostSILGen(Instance, std::move(SM), mod, PSPs,
766784
ReturnValue, observer);
767785
}
786+
787+
788+
std::vector<PrimarySpecificPaths> emptyAuxPSPs;
768789
// If there are primary source files, build a separate SILModule for
769790
// each source file, and run the remaining SILOpt-Serialize-IRGen-LLVM
770791
// once for each such input.
@@ -773,7 +794,7 @@ bool swift::performCompileStepsPostSema(CompilerInstance &Instance,
773794
for (auto *PrimaryFile : Instance.getPrimarySourceFiles()) {
774795
const PrimarySpecificPaths PSPs =
775796
Instance.getPrimarySpecificPathsForSourceFile(*PrimaryFile);
776-
SILOptions SILOpts = getSILOptions(PSPs);
797+
SILOptions SILOpts = getSILOptions(PSPs, emptyAuxPSPs);
777798
IRGenOptions irgenOpts = Invocation.getIRGenOptions();
778799
auto SM = performASTLowering(*PrimaryFile, Instance.getSILTypes(),
779800
SILOpts, &irgenOpts);
@@ -793,7 +814,7 @@ bool swift::performCompileStepsPostSema(CompilerInstance &Instance,
793814
if (opts.InputsAndOutputs.isInputPrimary(SASTF->getFilename())) {
794815
const PrimarySpecificPaths &PSPs =
795816
Instance.getPrimarySpecificPathsForPrimary(SASTF->getFilename());
796-
SILOptions SILOpts = getSILOptions(PSPs);
817+
SILOptions SILOpts = getSILOptions(PSPs, emptyAuxPSPs);
797818
auto SM = performASTLowering(*SASTF, Instance.getSILTypes(), SILOpts);
798819
result |= performCompileStepsPostSILGen(Instance, std::move(SM), mod,
799820
PSPs, ReturnValue, observer);

lib/IRGen/IRGen.cpp

Lines changed: 68 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/ABI/MetadataValues.h"
2121
#include "swift/ABI/ObjectFile.h"
2222
#include "swift/AST/DiagnosticsIRGen.h"
23+
#include "swift/AST/DiagnosticsFrontend.h"
2324
#include "swift/AST/IRGenOptions.h"
2425
#include "swift/AST/IRGenRequests.h"
2526
#include "swift/AST/LinkLibrary.h"
@@ -71,6 +72,8 @@
7172
#include "llvm/Passes/PassBuilder.h"
7273
#include "llvm/Passes/PassPlugin.h"
7374
#include "llvm/Passes/StandardInstrumentations.h"
75+
#include "llvm/Remarks/Remark.h"
76+
#include "llvm/Remarks/RemarkStreamer.h"
7477
#include "llvm/Support/CommandLine.h"
7578
#include "llvm/Support/Debug.h"
7679
#include "llvm/Support/ErrorHandling.h"
@@ -1157,7 +1160,7 @@ static void embedBitcode(llvm::Module *M, const IRGenOptions &Opts)
11571160
NewUsed->setSection("llvm.metadata");
11581161
}
11591162

1160-
static void initLLVMModule(IRGenModule &IGM, SILModule &SIL) {
1163+
static void initLLVMModule(IRGenModule &IGM, SILModule &SIL, std::optional<unsigned> idx = {}) {
11611164
auto *Module = IGM.getModule();
11621165
assert(Module && "Expected llvm:Module for IR generation!");
11631166

@@ -1200,17 +1203,67 @@ static void initLLVMModule(IRGenModule &IGM, SILModule &SIL) {
12001203
llvm::ConstantAsMetadata::get(Value)}));
12011204

12021205
if (auto *SILstreamer = SIL.getSILRemarkStreamer()) {
1203-
// Install RemarkStreamer into LLVM and keep the remarks file alive. This is
1204-
// required even if no LLVM remarks are enabled, because the AsmPrinter
1205-
// serializes meta information about the remarks into the object file.
1206-
IGM.RemarkStream = SILstreamer->releaseStream();
1207-
SILstreamer->intoLLVMContext(Context);
1208-
auto &RS = *IGM.getLLVMContext().getMainRemarkStreamer();
1209-
if (IGM.getOptions().AnnotateCondFailMessage) {
1206+
auto remarkStream = SILstreamer->releaseStream();
1207+
if (remarkStream) {
1208+
// Install RemarkStreamer into LLVM and keep the remarks file alive. This is
1209+
// required even if no LLVM remarks are enabled, because the AsmPrinter
1210+
// serializes meta information about the remarks into the object file.
1211+
IGM.RemarkStream = std::move(remarkStream);
1212+
SILstreamer->intoLLVMContext(Context);
1213+
auto &RS = *IGM.getLLVMContext().getMainRemarkStreamer();
1214+
if (IGM.getOptions().AnnotateCondFailMessage) {
1215+
Context.setLLVMRemarkStreamer(
1216+
std::make_unique<llvm::LLVMRemarkStreamer>(RS));
1217+
} else {
1218+
// Don't filter for now.
1219+
Context.setLLVMRemarkStreamer(
1220+
std::make_unique<llvm::LLVMRemarkStreamer>(RS));
1221+
}
1222+
} else {
1223+
assert(idx && "Not generating multiple output files?");
1224+
1225+
// Construct llvmremarkstreamer objects for LLVM remarks originating in
1226+
// the LLVM backend and install it in the remaining LLVMModule(s).
1227+
auto &SILOpts = SIL.getOptions();
1228+
assert(SILOpts.AuxOptRecordFiles.size() > (*idx - 1));
1229+
1230+
const auto &filename = SILOpts.AuxOptRecordFiles[*idx - 1];
1231+
auto &diagEngine = SIL.getASTContext().Diags;
1232+
std::error_code errorCode;
1233+
auto file = std::make_unique<llvm::raw_fd_ostream>(filename, errorCode,
1234+
llvm::sys::fs::OF_None);
1235+
if (errorCode) {
1236+
diagEngine.diagnose(SourceLoc(), diag::cannot_open_file, filename,
1237+
errorCode.message());
1238+
return;
1239+
}
1240+
1241+
const auto format = SILOpts.OptRecordFormat;
1242+
llvm::Expected<std::unique_ptr<llvm::remarks::RemarkSerializer>>
1243+
remarkSerializerOrErr = llvm::remarks::createRemarkSerializer(
1244+
format, llvm::remarks::SerializerMode::Separate, *file);
1245+
if (llvm::Error err = remarkSerializerOrErr.takeError()) {
1246+
diagEngine.diagnose(SourceLoc(), diag::error_creating_remark_serializer,
1247+
toString(std::move(err)));
1248+
return;
1249+
}
1250+
1251+
auto auxRS = std::make_unique<llvm::remarks::RemarkStreamer>(
1252+
std::move(*remarkSerializerOrErr), filename);
1253+
const auto passes = SILOpts.OptRecordPasses;
1254+
if (!passes.empty()) {
1255+
if (llvm::Error err = auxRS->setFilter(passes)) {
1256+
diagEngine.diagnose(SourceLoc(), diag::error_creating_remark_serializer,
1257+
toString(std::move(err)));
1258+
return ;
1259+
}
1260+
}
1261+
1262+
Context.setMainRemarkStreamer(std::move(auxRS));
12101263
Context.setLLVMRemarkStreamer(
1211-
std::make_unique<llvm::LLVMRemarkStreamer>(RS));
1212-
// FIXME: add a frontend flag to enable all LLVM remarks
1213-
cantFail(RS.setFilter("annotation-remarks"));
1264+
std::make_unique<llvm::LLVMRemarkStreamer>(
1265+
*Context.getMainRemarkStreamer()));
1266+
IGM.RemarkStream = std::move(file);
12141267
}
12151268
}
12161269
}
@@ -1559,6 +1612,7 @@ static void performParallelIRGeneration(IRGenDescriptor desc) {
15591612
auto &Ctx = M->getASTContext();
15601613
// Create an IRGenModule for each source file.
15611614
bool DidRunSILCodeGenPreparePasses = false;
1615+
unsigned idx = 0;
15621616
for (auto *File : M->getFiles()) {
15631617
auto nextSF = dyn_cast<SourceFile>(File);
15641618
if (!nextSF)
@@ -1575,11 +1629,12 @@ static void performParallelIRGeneration(IRGenDescriptor desc) {
15751629
if (!targetMachine) continue;
15761630

15771631
// Create the IR emitter.
1632+
auto outputName = *OutputIter++;
15781633
IRGenModule *IGM = new IRGenModule(
1579-
irgen, std::move(targetMachine), nextSF, desc.ModuleName, *OutputIter++,
1634+
irgen, std::move(targetMachine), nextSF, desc.ModuleName, outputName,
15801635
nextSF->getFilename(), nextSF->getPrivateDiscriminator().str());
15811636

1582-
initLLVMModule(*IGM, *SILMod);
1637+
initLLVMModule(*IGM, *SILMod, idx++);
15831638
if (!DidRunSILCodeGenPreparePasses) {
15841639
// Run SIL level IRGen preparation passes on the module the first time
15851640
// around.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
open class C {
2+
var x = 1
3+
var y = 2
4+
5+
public init() {
6+
}
7+
8+
public func method() {
9+
print("x: \(x)")
10+
}
11+
12+
public func method2() {
13+
print("x2: \(y)")
14+
}
15+
}
16+
17+
@_assemblyVision
18+
@inline(never)
19+
public func runSomeTest(_ c: C) {
20+
for i in 0..<100 {
21+
c.method()
22+
c.method2()
23+
}
24+
}

0 commit comments

Comments
 (0)