mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Add code to create llvm::RemarkStreamer objects for all the LLVMModules in WMO mode
rdar://154403078
This commit is contained in:
@@ -316,6 +316,10 @@ public:
|
|||||||
/// records.
|
/// records.
|
||||||
std::string OptRecordFile;
|
std::string OptRecordFile;
|
||||||
|
|
||||||
|
/// The names of the auxiliar files to which the backend should save optimization
|
||||||
|
/// records for the remaining (other than the main one) LLVMModules.
|
||||||
|
std::vector<std::string> AuxOptRecordFiles;
|
||||||
|
|
||||||
/// The regex that filters the passes that should be saved to the optimization
|
/// The regex that filters the passes that should be saved to the optimization
|
||||||
/// records.
|
/// records.
|
||||||
std::string OptRecordPasses;
|
std::string OptRecordPasses;
|
||||||
|
|||||||
@@ -253,6 +253,9 @@ public:
|
|||||||
const PrimarySpecificPaths &
|
const PrimarySpecificPaths &
|
||||||
getPrimarySpecificPathsForAtMostOnePrimary() const;
|
getPrimarySpecificPathsForAtMostOnePrimary() const;
|
||||||
|
|
||||||
|
const PrimarySpecificPaths &
|
||||||
|
getPrimarySpecificPathsForRemaining(unsigned i) const;
|
||||||
|
|
||||||
const PrimarySpecificPaths &
|
const PrimarySpecificPaths &
|
||||||
getPrimarySpecificPathsForPrimary(StringRef) const;
|
getPrimarySpecificPathsForPrimary(StringRef) const;
|
||||||
|
|
||||||
|
|||||||
@@ -298,6 +298,44 @@ SupplementaryOutputPathsComputer::computeOutputPaths() const {
|
|||||||
});
|
});
|
||||||
if (hadError)
|
if (hadError)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|
||||||
|
// In WMO mode compute supplementary output paths for optimization record
|
||||||
|
// data (opt-remarks). We need one path per LLVMModule that will be created as
|
||||||
|
// part of wmo.
|
||||||
|
if (!InputsAndOutputs.hasPrimaryInputs() && OutputFiles.size() > 1) {
|
||||||
|
unsigned i = 0;
|
||||||
|
InputsAndOutputs.forEachInput([&](const InputFile &input) -> bool {
|
||||||
|
// First input is already computed.
|
||||||
|
if (InputsAndOutputs.firstInput().getFileName() == input.getFileName()) {
|
||||||
|
++i;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SupplementaryOutputPaths outputs;
|
||||||
|
|
||||||
|
// Compute auxiliar opt record paths.
|
||||||
|
StringRef defaultSupplementaryOutputPathExcludingExtension =
|
||||||
|
deriveDefaultSupplementaryOutputPathExcludingExtension(OutputFiles[i], input);
|
||||||
|
|
||||||
|
auto YAMLOptRecordPath = determineSupplementaryOutputFilename(
|
||||||
|
options::OPT_save_optimization_record_path,
|
||||||
|
"",
|
||||||
|
file_types::TY_YAMLOptRecord, "",
|
||||||
|
defaultSupplementaryOutputPathExcludingExtension, true);
|
||||||
|
outputs.YAMLOptRecordPath = YAMLOptRecordPath;
|
||||||
|
|
||||||
|
auto bitstreamOptRecordPath = determineSupplementaryOutputFilename(
|
||||||
|
options::OPT_save_optimization_record_path,
|
||||||
|
"",
|
||||||
|
file_types::TY_BitstreamOptRecord, "",
|
||||||
|
defaultSupplementaryOutputPathExcludingExtension, true);
|
||||||
|
|
||||||
|
outputs.BitstreamOptRecordPath = bitstreamOptRecordPath;
|
||||||
|
|
||||||
|
outputPaths.emplace_back(std::move(outputs));
|
||||||
|
++i;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
return outputPaths;
|
return outputPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,7 +653,21 @@ std::string
|
|||||||
SupplementaryOutputPathsComputer::determineSupplementaryOutputFilename(
|
SupplementaryOutputPathsComputer::determineSupplementaryOutputFilename(
|
||||||
options::ID emitOpt, std::string pathFromArguments, file_types::ID type,
|
options::ID emitOpt, std::string pathFromArguments, file_types::ID type,
|
||||||
StringRef mainOutputIfUsable,
|
StringRef mainOutputIfUsable,
|
||||||
StringRef defaultSupplementaryOutputPathExcludingExtension) const {
|
StringRef defaultSupplementaryOutputPathExcludingExtension,
|
||||||
|
bool forceDefaultSupplementaryOutputPathExcludingExtension) const {
|
||||||
|
|
||||||
|
auto computeDefaultSupplementaryOutputPathExcludingExtension =
|
||||||
|
[&] () -> std::string {
|
||||||
|
llvm::SmallString<128> path(
|
||||||
|
defaultSupplementaryOutputPathExcludingExtension);
|
||||||
|
|
||||||
|
llvm::sys::path::replace_extension(path, file_types::getExtension(type));
|
||||||
|
return path.str().str();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (forceDefaultSupplementaryOutputPathExcludingExtension) {
|
||||||
|
return computeDefaultSupplementaryOutputPathExcludingExtension();
|
||||||
|
}
|
||||||
|
|
||||||
if (!pathFromArguments.empty())
|
if (!pathFromArguments.empty())
|
||||||
return pathFromArguments;
|
return pathFromArguments;
|
||||||
@@ -627,9 +679,7 @@ SupplementaryOutputPathsComputer::determineSupplementaryOutputFilename(
|
|||||||
return mainOutputIfUsable.str();
|
return mainOutputIfUsable.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::SmallString<128> path(defaultSupplementaryOutputPathExcludingExtension);
|
return computeDefaultSupplementaryOutputPathExcludingExtension();
|
||||||
llvm::sys::path::replace_extension(path, file_types::getExtension(type));
|
|
||||||
return path.str().str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SupplementaryOutputPathsComputer::deriveModulePathParameters(
|
void SupplementaryOutputPathsComputer::deriveModulePathParameters(
|
||||||
|
|||||||
@@ -180,7 +180,8 @@ private:
|
|||||||
std::string determineSupplementaryOutputFilename(
|
std::string determineSupplementaryOutputFilename(
|
||||||
options::ID emitOpt, std::string pathFromArgumentsOrFilelists,
|
options::ID emitOpt, std::string pathFromArgumentsOrFilelists,
|
||||||
file_types::ID type, StringRef mainOutputIfUsable,
|
file_types::ID type, StringRef mainOutputIfUsable,
|
||||||
StringRef defaultSupplementaryOutputPathExcludingExtension) const;
|
StringRef defaultSupplementaryOutputPathExcludingExtension,
|
||||||
|
bool forceDefaultSupplementaryOutputPathExcludingExtension = false) const;
|
||||||
|
|
||||||
void deriveModulePathParameters(StringRef mainOutputFile,
|
void deriveModulePathParameters(StringRef mainOutputFile,
|
||||||
options::ID &emitOption,
|
options::ID &emitOption,
|
||||||
|
|||||||
@@ -380,13 +380,23 @@ void FrontendInputsAndOutputs::setMainAndSupplementaryOutputs(
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(supplementaryOutputs.size() == 1 &&
|
|
||||||
"WMO only ever produces one set of supplementary outputs");
|
assert(supplementaryOutputs.size() == 1 ||
|
||||||
|
supplementaryOutputs.size() == AllInputs.size() &&
|
||||||
|
"WMO produces wrong number of sets of supplementary outputs");
|
||||||
if (outputFiles.size() == 1) {
|
if (outputFiles.size() == 1) {
|
||||||
AllInputs.front().setPrimarySpecificPaths(PrimarySpecificPaths(
|
for (auto i : indices(AllInputs)) {
|
||||||
outputFiles.front(), outputFilesForIndexUnits.front(),
|
if (i == 0)
|
||||||
firstInputProducingOutput().getFileName(),
|
AllInputs[i].setPrimarySpecificPaths(PrimarySpecificPaths(
|
||||||
supplementaryOutputs.front()));
|
outputFiles.front(), outputFilesForIndexUnits.front(),
|
||||||
|
firstInputProducingOutput().getFileName(),
|
||||||
|
supplementaryOutputs.front()));
|
||||||
|
else
|
||||||
|
AllInputs[i].setPrimarySpecificPaths(PrimarySpecificPaths(
|
||||||
|
"", "", "",
|
||||||
|
supplementaryOutputs.size() == 1 ? SupplementaryOutputPaths()
|
||||||
|
: supplementaryOutputs[i]));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(outputFiles.size() == AllInputs.size() &&
|
assert(outputFiles.size() == AllInputs.size() &&
|
||||||
@@ -394,7 +404,8 @@ void FrontendInputsAndOutputs::setMainAndSupplementaryOutputs(
|
|||||||
for (auto i : indices(AllInputs))
|
for (auto i : indices(AllInputs))
|
||||||
AllInputs[i].setPrimarySpecificPaths(PrimarySpecificPaths(
|
AllInputs[i].setPrimarySpecificPaths(PrimarySpecificPaths(
|
||||||
outputFiles[i], outputFilesForIndexUnits[i], outputFiles[i],
|
outputFiles[i], outputFilesForIndexUnits[i], outputFiles[i],
|
||||||
i == 0 ? supplementaryOutputs.front() : SupplementaryOutputPaths()));
|
supplementaryOutputs.size() == 1 && i != 0 ? SupplementaryOutputPaths()
|
||||||
|
: supplementaryOutputs[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> FrontendInputsAndOutputs::copyOutputFilenames() const {
|
std::vector<std::string> FrontendInputsAndOutputs::copyOutputFilenames() const {
|
||||||
@@ -488,6 +499,14 @@ FrontendInputsAndOutputs::getPrimarySpecificPathsForAtMostOnePrimary() const {
|
|||||||
: emptyPaths;
|
: emptyPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PrimarySpecificPaths &
|
||||||
|
FrontendInputsAndOutputs::getPrimarySpecificPathsForRemaining(unsigned i) const {
|
||||||
|
static auto emptyPaths = PrimarySpecificPaths();
|
||||||
|
unsigned firstProducingIdx = getIndexOfFirstOutputProducingInput();
|
||||||
|
return (hasInputs() && i > 0) ?
|
||||||
|
AllInputs[firstProducingIdx+i].getPrimarySpecificPaths() : emptyPaths;
|
||||||
|
}
|
||||||
|
|
||||||
const PrimarySpecificPaths &
|
const PrimarySpecificPaths &
|
||||||
FrontendInputsAndOutputs::getPrimarySpecificPathsForPrimary(
|
FrontendInputsAndOutputs::getPrimarySpecificPathsForPrimary(
|
||||||
StringRef filename) const {
|
StringRef filename) const {
|
||||||
|
|||||||
@@ -740,7 +740,8 @@ bool swift::performCompileStepsPostSema(CompilerInstance &Instance,
|
|||||||
const auto &Invocation = Instance.getInvocation();
|
const auto &Invocation = Instance.getInvocation();
|
||||||
const FrontendOptions &opts = Invocation.getFrontendOptions();
|
const FrontendOptions &opts = Invocation.getFrontendOptions();
|
||||||
|
|
||||||
auto getSILOptions = [&](const PrimarySpecificPaths &PSPs) -> SILOptions {
|
auto getSILOptions = [&](const PrimarySpecificPaths &PSPs,
|
||||||
|
const std::vector<PrimarySpecificPaths> &auxPSPs) -> SILOptions {
|
||||||
SILOptions SILOpts = Invocation.getSILOptions();
|
SILOptions SILOpts = Invocation.getSILOptions();
|
||||||
if (SILOpts.OptRecordFile.empty()) {
|
if (SILOpts.OptRecordFile.empty()) {
|
||||||
// Check if the record file path was passed via supplemental outputs.
|
// Check if the record file path was passed via supplemental outputs.
|
||||||
@@ -749,6 +750,15 @@ bool swift::performCompileStepsPostSema(CompilerInstance &Instance,
|
|||||||
PSPs.SupplementaryOutputs.YAMLOptRecordPath :
|
PSPs.SupplementaryOutputs.YAMLOptRecordPath :
|
||||||
PSPs.SupplementaryOutputs.BitstreamOptRecordPath;
|
PSPs.SupplementaryOutputs.BitstreamOptRecordPath;
|
||||||
}
|
}
|
||||||
|
if (!auxPSPs.empty()) {
|
||||||
|
assert(SILOpts.AuxOptRecordFiles.empty());
|
||||||
|
for (const auto &auxFile: auxPSPs) {
|
||||||
|
SILOpts.AuxOptRecordFiles.push_back(
|
||||||
|
SILOpts.OptRecordFormat == llvm::remarks::Format::YAML ?
|
||||||
|
auxFile.SupplementaryOutputs.YAMLOptRecordPath :
|
||||||
|
auxFile.SupplementaryOutputs.BitstreamOptRecordPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
return SILOpts;
|
return SILOpts;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -758,13 +768,24 @@ bool swift::performCompileStepsPostSema(CompilerInstance &Instance,
|
|||||||
// SILModule for the entire module.
|
// SILModule for the entire module.
|
||||||
const PrimarySpecificPaths PSPs =
|
const PrimarySpecificPaths PSPs =
|
||||||
Instance.getPrimarySpecificPathsForWholeModuleOptimizationMode();
|
Instance.getPrimarySpecificPathsForWholeModuleOptimizationMode();
|
||||||
SILOptions SILOpts = getSILOptions(PSPs);
|
|
||||||
|
std::vector<PrimarySpecificPaths> auxPSPs;
|
||||||
|
for (unsigned i = 1; i < opts.InputsAndOutputs.inputCount(); ++i) {
|
||||||
|
auto &auxPSP =
|
||||||
|
opts.InputsAndOutputs.getPrimarySpecificPathsForRemaining(i);
|
||||||
|
auxPSPs.push_back(auxPSP);
|
||||||
|
}
|
||||||
|
|
||||||
|
SILOptions SILOpts = getSILOptions(PSPs, auxPSPs);
|
||||||
IRGenOptions irgenOpts = Invocation.getIRGenOptions();
|
IRGenOptions irgenOpts = Invocation.getIRGenOptions();
|
||||||
auto SM = performASTLowering(mod, Instance.getSILTypes(), SILOpts,
|
auto SM = performASTLowering(mod, Instance.getSILTypes(), SILOpts,
|
||||||
&irgenOpts);
|
&irgenOpts);
|
||||||
return performCompileStepsPostSILGen(Instance, std::move(SM), mod, PSPs,
|
return performCompileStepsPostSILGen(Instance, std::move(SM), mod, PSPs,
|
||||||
ReturnValue, observer);
|
ReturnValue, observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<PrimarySpecificPaths> emptyAuxPSPs;
|
||||||
// If there are primary source files, build a separate SILModule for
|
// If there are primary source files, build a separate SILModule for
|
||||||
// each source file, and run the remaining SILOpt-Serialize-IRGen-LLVM
|
// each source file, and run the remaining SILOpt-Serialize-IRGen-LLVM
|
||||||
// once for each such input.
|
// once for each such input.
|
||||||
@@ -773,7 +794,7 @@ bool swift::performCompileStepsPostSema(CompilerInstance &Instance,
|
|||||||
for (auto *PrimaryFile : Instance.getPrimarySourceFiles()) {
|
for (auto *PrimaryFile : Instance.getPrimarySourceFiles()) {
|
||||||
const PrimarySpecificPaths PSPs =
|
const PrimarySpecificPaths PSPs =
|
||||||
Instance.getPrimarySpecificPathsForSourceFile(*PrimaryFile);
|
Instance.getPrimarySpecificPathsForSourceFile(*PrimaryFile);
|
||||||
SILOptions SILOpts = getSILOptions(PSPs);
|
SILOptions SILOpts = getSILOptions(PSPs, emptyAuxPSPs);
|
||||||
IRGenOptions irgenOpts = Invocation.getIRGenOptions();
|
IRGenOptions irgenOpts = Invocation.getIRGenOptions();
|
||||||
auto SM = performASTLowering(*PrimaryFile, Instance.getSILTypes(),
|
auto SM = performASTLowering(*PrimaryFile, Instance.getSILTypes(),
|
||||||
SILOpts, &irgenOpts);
|
SILOpts, &irgenOpts);
|
||||||
@@ -793,7 +814,7 @@ bool swift::performCompileStepsPostSema(CompilerInstance &Instance,
|
|||||||
if (opts.InputsAndOutputs.isInputPrimary(SASTF->getFilename())) {
|
if (opts.InputsAndOutputs.isInputPrimary(SASTF->getFilename())) {
|
||||||
const PrimarySpecificPaths &PSPs =
|
const PrimarySpecificPaths &PSPs =
|
||||||
Instance.getPrimarySpecificPathsForPrimary(SASTF->getFilename());
|
Instance.getPrimarySpecificPathsForPrimary(SASTF->getFilename());
|
||||||
SILOptions SILOpts = getSILOptions(PSPs);
|
SILOptions SILOpts = getSILOptions(PSPs, emptyAuxPSPs);
|
||||||
auto SM = performASTLowering(*SASTF, Instance.getSILTypes(), SILOpts);
|
auto SM = performASTLowering(*SASTF, Instance.getSILTypes(), SILOpts);
|
||||||
result |= performCompileStepsPostSILGen(Instance, std::move(SM), mod,
|
result |= performCompileStepsPostSILGen(Instance, std::move(SM), mod,
|
||||||
PSPs, ReturnValue, observer);
|
PSPs, ReturnValue, observer);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "swift/ABI/MetadataValues.h"
|
#include "swift/ABI/MetadataValues.h"
|
||||||
#include "swift/ABI/ObjectFile.h"
|
#include "swift/ABI/ObjectFile.h"
|
||||||
#include "swift/AST/DiagnosticsIRGen.h"
|
#include "swift/AST/DiagnosticsIRGen.h"
|
||||||
|
#include "swift/AST/DiagnosticsFrontend.h"
|
||||||
#include "swift/AST/IRGenOptions.h"
|
#include "swift/AST/IRGenOptions.h"
|
||||||
#include "swift/AST/IRGenRequests.h"
|
#include "swift/AST/IRGenRequests.h"
|
||||||
#include "swift/AST/LinkLibrary.h"
|
#include "swift/AST/LinkLibrary.h"
|
||||||
@@ -71,6 +72,8 @@
|
|||||||
#include "llvm/Passes/PassBuilder.h"
|
#include "llvm/Passes/PassBuilder.h"
|
||||||
#include "llvm/Passes/PassPlugin.h"
|
#include "llvm/Passes/PassPlugin.h"
|
||||||
#include "llvm/Passes/StandardInstrumentations.h"
|
#include "llvm/Passes/StandardInstrumentations.h"
|
||||||
|
#include "llvm/Remarks/Remark.h"
|
||||||
|
#include "llvm/Remarks/RemarkStreamer.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
@@ -1143,7 +1146,7 @@ static void embedBitcode(llvm::Module *M, const IRGenOptions &Opts)
|
|||||||
NewUsed->setSection("llvm.metadata");
|
NewUsed->setSection("llvm.metadata");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void initLLVMModule(IRGenModule &IGM, SILModule &SIL) {
|
static void initLLVMModule(IRGenModule &IGM, SILModule &SIL, std::optional<unsigned> idx = {}) {
|
||||||
auto *Module = IGM.getModule();
|
auto *Module = IGM.getModule();
|
||||||
assert(Module && "Expected llvm:Module for IR generation!");
|
assert(Module && "Expected llvm:Module for IR generation!");
|
||||||
|
|
||||||
@@ -1186,17 +1189,67 @@ static void initLLVMModule(IRGenModule &IGM, SILModule &SIL) {
|
|||||||
llvm::ConstantAsMetadata::get(Value)}));
|
llvm::ConstantAsMetadata::get(Value)}));
|
||||||
|
|
||||||
if (auto *SILstreamer = SIL.getSILRemarkStreamer()) {
|
if (auto *SILstreamer = SIL.getSILRemarkStreamer()) {
|
||||||
// Install RemarkStreamer into LLVM and keep the remarks file alive. This is
|
auto remarkStream = SILstreamer->releaseStream();
|
||||||
// required even if no LLVM remarks are enabled, because the AsmPrinter
|
if (remarkStream) {
|
||||||
// serializes meta information about the remarks into the object file.
|
// Install RemarkStreamer into LLVM and keep the remarks file alive. This is
|
||||||
IGM.RemarkStream = SILstreamer->releaseStream();
|
// required even if no LLVM remarks are enabled, because the AsmPrinter
|
||||||
SILstreamer->intoLLVMContext(Context);
|
// serializes meta information about the remarks into the object file.
|
||||||
auto &RS = *IGM.getLLVMContext().getMainRemarkStreamer();
|
IGM.RemarkStream = std::move(remarkStream);
|
||||||
if (IGM.getOptions().AnnotateCondFailMessage) {
|
SILstreamer->intoLLVMContext(Context);
|
||||||
|
auto &RS = *IGM.getLLVMContext().getMainRemarkStreamer();
|
||||||
|
if (IGM.getOptions().AnnotateCondFailMessage) {
|
||||||
|
Context.setLLVMRemarkStreamer(
|
||||||
|
std::make_unique<llvm::LLVMRemarkStreamer>(RS));
|
||||||
|
} else {
|
||||||
|
// Don't filter for now.
|
||||||
|
Context.setLLVMRemarkStreamer(
|
||||||
|
std::make_unique<llvm::LLVMRemarkStreamer>(RS));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(idx && "Not generating multiple output files?");
|
||||||
|
|
||||||
|
// Construct llvmremarkstreamer objects for LLVM remarks originating in
|
||||||
|
// the LLVM backend and install it in the remaining LLVMModule(s).
|
||||||
|
auto &SILOpts = SIL.getOptions();
|
||||||
|
assert(SILOpts.AuxOptRecordFiles.size() > (*idx - 1));
|
||||||
|
|
||||||
|
const auto &filename = SILOpts.AuxOptRecordFiles[*idx - 1];
|
||||||
|
auto &diagEngine = SIL.getASTContext().Diags;
|
||||||
|
std::error_code errorCode;
|
||||||
|
auto file = std::make_unique<llvm::raw_fd_ostream>(filename, errorCode,
|
||||||
|
llvm::sys::fs::OF_None);
|
||||||
|
if (errorCode) {
|
||||||
|
diagEngine.diagnose(SourceLoc(), diag::cannot_open_file, filename,
|
||||||
|
errorCode.message());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto format = SILOpts.OptRecordFormat;
|
||||||
|
llvm::Expected<std::unique_ptr<llvm::remarks::RemarkSerializer>>
|
||||||
|
remarkSerializerOrErr = llvm::remarks::createRemarkSerializer(
|
||||||
|
format, llvm::remarks::SerializerMode::Separate, *file);
|
||||||
|
if (llvm::Error err = remarkSerializerOrErr.takeError()) {
|
||||||
|
diagEngine.diagnose(SourceLoc(), diag::error_creating_remark_serializer,
|
||||||
|
toString(std::move(err)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto auxRS = std::make_unique<llvm::remarks::RemarkStreamer>(
|
||||||
|
std::move(*remarkSerializerOrErr), filename);
|
||||||
|
const auto passes = SILOpts.OptRecordPasses;
|
||||||
|
if (!passes.empty()) {
|
||||||
|
if (llvm::Error err = auxRS->setFilter(passes)) {
|
||||||
|
diagEngine.diagnose(SourceLoc(), diag::error_creating_remark_serializer,
|
||||||
|
toString(std::move(err)));
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.setMainRemarkStreamer(std::move(auxRS));
|
||||||
Context.setLLVMRemarkStreamer(
|
Context.setLLVMRemarkStreamer(
|
||||||
std::make_unique<llvm::LLVMRemarkStreamer>(RS));
|
std::make_unique<llvm::LLVMRemarkStreamer>(
|
||||||
// FIXME: add a frontend flag to enable all LLVM remarks
|
*Context.getMainRemarkStreamer()));
|
||||||
cantFail(RS.setFilter("annotation-remarks"));
|
IGM.RemarkStream = std::move(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1545,6 +1598,7 @@ static void performParallelIRGeneration(IRGenDescriptor desc) {
|
|||||||
auto &Ctx = M->getASTContext();
|
auto &Ctx = M->getASTContext();
|
||||||
// Create an IRGenModule for each source file.
|
// Create an IRGenModule for each source file.
|
||||||
bool DidRunSILCodeGenPreparePasses = false;
|
bool DidRunSILCodeGenPreparePasses = false;
|
||||||
|
unsigned idx = 0;
|
||||||
for (auto *File : M->getFiles()) {
|
for (auto *File : M->getFiles()) {
|
||||||
auto nextSF = dyn_cast<SourceFile>(File);
|
auto nextSF = dyn_cast<SourceFile>(File);
|
||||||
if (!nextSF)
|
if (!nextSF)
|
||||||
@@ -1561,11 +1615,12 @@ static void performParallelIRGeneration(IRGenDescriptor desc) {
|
|||||||
if (!targetMachine) continue;
|
if (!targetMachine) continue;
|
||||||
|
|
||||||
// Create the IR emitter.
|
// Create the IR emitter.
|
||||||
|
auto outputName = *OutputIter++;
|
||||||
IRGenModule *IGM = new IRGenModule(
|
IRGenModule *IGM = new IRGenModule(
|
||||||
irgen, std::move(targetMachine), nextSF, desc.ModuleName, *OutputIter++,
|
irgen, std::move(targetMachine), nextSF, desc.ModuleName, outputName,
|
||||||
nextSF->getFilename(), nextSF->getPrivateDiscriminator().str());
|
nextSF->getFilename(), nextSF->getPrivateDiscriminator().str());
|
||||||
|
|
||||||
initLLVMModule(*IGM, *SILMod);
|
initLLVMModule(*IGM, *SILMod, idx++);
|
||||||
if (!DidRunSILCodeGenPreparePasses) {
|
if (!DidRunSILCodeGenPreparePasses) {
|
||||||
// Run SIL level IRGen preparation passes on the module the first time
|
// Run SIL level IRGen preparation passes on the module the first time
|
||||||
// around.
|
// around.
|
||||||
|
|||||||
24
test/Frontend/Inputs/opt-record-2.swift
Normal file
24
test/Frontend/Inputs/opt-record-2.swift
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
open class C {
|
||||||
|
var x = 1
|
||||||
|
var y = 2
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public func method() {
|
||||||
|
print("x: \(x)")
|
||||||
|
}
|
||||||
|
|
||||||
|
public func method2() {
|
||||||
|
print("x2: \(y)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@_assemblyVision
|
||||||
|
@inline(never)
|
||||||
|
public func runSomeTest(_ c: C) {
|
||||||
|
for i in 0..<100 {
|
||||||
|
c.method()
|
||||||
|
c.method2()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,11 +2,17 @@
|
|||||||
// RUN: echo '"%s": { yaml-opt-record: "%t/foo.opt.yaml" }' > %t/filemap.yaml.yaml
|
// RUN: echo '"%s": { yaml-opt-record: "%t/foo.opt.yaml" }' > %t/filemap.yaml.yaml
|
||||||
// RUN: echo '"%s": { bitstream-opt-record: "%t/foo.opt.bitstream" }' > %t/filemap.bitstream.yaml
|
// RUN: echo '"%s": { bitstream-opt-record: "%t/foo.opt.bitstream" }' > %t/filemap.bitstream.yaml
|
||||||
|
|
||||||
// RUN: %target-swift-frontend -c -O -wmo -save-optimization-record=bitstream %s -module-name foo -o %t/foo.o -supplementary-output-file-map %t/filemap.bitstream.yaml
|
// RUN: %target-swift-frontend -c -O -num-threads 2 -save-optimization-record=bitstream %s %S/Inputs/opt-record-2.swift -module-name foo -o %t/foo.o -o %t/opt-record-2.o -supplementary-output-file-map %t/filemap.bitstream.yaml
|
||||||
// RUN: llvm-bcanalyzer -dump "%t/foo.opt.bitstream" | %FileCheck -check-prefix=BITSTREAM %s
|
// RUN: llvm-bcanalyzer -dump "%t/foo.opt.bitstream" | %FileCheck -check-prefix=BITSTREAM %s
|
||||||
|
// RUN: llvm-bcanalyzer -dump "%t/opt-record-2.opt.bitstream" | %FileCheck -check-prefix=BITSTREAM2 %s
|
||||||
|
|
||||||
// RUN: %target-swift-frontend -c -O -wmo -save-optimization-record=yaml %s -module-name foo -o %t/foo.o -supplementary-output-file-map %t/filemap.yaml.yaml
|
// RUN: %empty-directory(%t)
|
||||||
|
// RUN: echo '"%s": { yaml-opt-record: "%t/foo.opt.yaml" }' > %t/filemap.yaml.yaml
|
||||||
|
// RUN: echo '"%s": { bitstream-opt-record: "%t/foo.opt.bitstream" }' > %t/filemap.bitstream.yaml
|
||||||
|
|
||||||
|
// RUN: %target-swift-frontend -c -O -num-threads 2 -save-optimization-record=yaml %s %S/Inputs/opt-record-2.swift -module-name foo -o %t/foo.o -o %t/opt-record-2.o -supplementary-output-file-map %t/filemap.yaml.yaml
|
||||||
// RUN: %FileCheck %s -check-prefix=YAML --input-file=%t/foo.opt.yaml
|
// RUN: %FileCheck %s -check-prefix=YAML --input-file=%t/foo.opt.yaml
|
||||||
|
// RUN: %FileCheck %s -check-prefix=YAML2 --input-file=%t/opt-record-2.opt.yaml
|
||||||
|
|
||||||
// REQUIRES: VENDOR=apple
|
// REQUIRES: VENDOR=apple
|
||||||
|
|
||||||
@@ -18,10 +24,19 @@ func foo() {
|
|||||||
}
|
}
|
||||||
#sourceLocation() // reset
|
#sourceLocation() // reset
|
||||||
|
|
||||||
|
@_assemblyVision
|
||||||
public func bar() {
|
public func bar() {
|
||||||
foo()
|
foo()
|
||||||
|
|
||||||
|
runSomeTest(C())
|
||||||
// BITSTREAM: <Remark NumWords=13 BlockCodeSize=4>
|
// BITSTREAM: <Remark NumWords=13 BlockCodeSize=4>
|
||||||
// BITSTREAM: </Remark>
|
// BITSTREAM: </Remark>
|
||||||
|
|
||||||
|
// BITSTREAM2: <Remark NumWords={{[0-9]+}} BlockCodeSize={{[0-9]*}}>
|
||||||
|
// BITSTREAM2: </Remark>
|
||||||
|
|
||||||
// YAML: sil-assembly-vision-remark-gen
|
// YAML: sil-assembly-vision-remark-gen
|
||||||
|
|
||||||
|
// YAML2: Pass: asm-printer
|
||||||
|
// YAML2: Name: InstructionCount
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,14 @@
|
|||||||
// CHECK-NEXT: {
|
// CHECK-NEXT: {
|
||||||
// CHECK-NEXT: "type": "abi-baseline-json",
|
// CHECK-NEXT: "type": "abi-baseline-json",
|
||||||
// CHECK-NEXT: "path": "{{.*[\\/]}}parseable_output_emit_module.swift.tmp.abi.json"
|
// CHECK-NEXT: "path": "{{.*[\\/]}}parseable_output_emit_module.swift.tmp.abi.json"
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: {
|
||||||
|
// CHECK-NEXT: "type": "yaml-opt-record",
|
||||||
|
// CHECK-NEXT: "path": "parseable_output_emit_module.opt.yaml"
|
||||||
|
// CHECK-NEXT: },
|
||||||
|
// CHECK-NEXT: {
|
||||||
|
// CHECK-NEXT: "type": "bitstream-opt-record",
|
||||||
|
// CHECK-NEXT: "path": "parseable_output_emit_module.opt.bitstream"
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
// CHECK-NEXT: ],
|
// CHECK-NEXT: ],
|
||||||
// CHECK-NEXT: "pid": [[PID:[0-9]*]]
|
// CHECK-NEXT: "pid": [[PID:[0-9]*]]
|
||||||
|
|||||||
Reference in New Issue
Block a user