Index: clang/lib/CodeGen/CodeGenAction.cpp =================================================================== --- clang/lib/CodeGen/CodeGenAction.cpp +++ clang/lib/CodeGen/CodeGenAction.cpp @@ -82,6 +82,40 @@ BackendConsumer *BackendCon; }; + // setOptRecordFile returns true if there is a record file. The record file can + // be an empty file. If it returns false, then there is an error. + bool setOptRecordFile(const CodeGenOptions CGOpts, DiagnosticsEngine &Diags, + LLVMContext &Ctx, + std::unique_ptr &OptRecordFile) + { + Expected> OptRecordFileOrErr = + llvm::setupOptimizationRemarks(Ctx, CGOpts.OptRecordFile, + CGOpts.OptRecordPasses, + CGOpts.OptRecordFormat, + CGOpts.DiagnosticsWithHotness, + CGOpts.DiagnosticsHotnessThreshold); + if (Error E = OptRecordFileOrErr.takeError()) { + handleAllErrors( + std::move(E), + [&](const RemarkSetupFileError &E) { + Diags.Report(diag::err_cannot_open_file) + << CGOpts.OptRecordFile << E.message(); + }, + [&](const RemarkSetupPatternError &E) { + Diags.Report(diag::err_drv_optimization_remark_pattern) + << E.message() << CGOpts.OptRecordPasses; + }, + [&](const RemarkSetupFormatError &E) { + Diags.Report(diag::err_drv_optimization_remark_format) + << CGOpts.OptRecordFormat; + }); + return false; + } + OptRecordFile = std::move(*OptRecordFileOrErr); + + return true; + } + class BackendConsumer : public ASTConsumer { using LinkModule = CodeGenAction::LinkModule; @@ -267,33 +301,14 @@ Ctx.setDiagnosticHandler(std::make_unique( CodeGenOpts, this)); - Expected> OptRecordFileOrErr = - setupOptimizationRemarks(Ctx, CodeGenOpts.OptRecordFile, - CodeGenOpts.OptRecordPasses, - CodeGenOpts.OptRecordFormat, - CodeGenOpts.DiagnosticsWithHotness, - CodeGenOpts.DiagnosticsHotnessThreshold); - - if (Error E = OptRecordFileOrErr.takeError()) { - handleAllErrors( - std::move(E), - [&](const RemarkSetupFileError &E) { - Diags.Report(diag::err_cannot_open_file) - << CodeGenOpts.OptRecordFile << E.message(); - }, - [&](const RemarkSetupPatternError &E) { - Diags.Report(diag::err_drv_optimization_remark_pattern) - << E.message() << CodeGenOpts.OptRecordPasses; - }, - [&](const RemarkSetupFormatError &E) { - Diags.Report(diag::err_drv_optimization_remark_format) - << CodeGenOpts.OptRecordFormat; - }); + std::unique_ptr OptRecordFile; + bool isSet = setOptRecordFile(CodeGenOpts, Diags, Ctx, OptRecordFile); + + // Error: the record file is erroneous. + if (!isSet) return; - } - std::unique_ptr OptRecordFile = - std::move(*OptRecordFileOrErr); + // There is a record file and it is not empty. if (OptRecordFile && CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone) Ctx.setDiagnosticsHotnessRequested(true); @@ -1077,10 +1092,52 @@ Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler, &CI.getDiagnostics()); + std::unique_ptr OptRecordFile; + if (BA == Backend_EmitObj) { + if (!isModelParsingAction()) + CI.createPreprocessor(getTranslationUnitKind()); + CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), + &CI.getPreprocessor()); + if (!CI.InitializeSourceManager(getCurrentInput())) + return; + + // Parsing a model file should reuse the existing ASTContext. + if (!isModelParsingAction()) + CI.createASTContext(); + + bool isSet = setOptRecordFile(CI.getCodeGenOpts(), CI.getDiagnostics(), + Ctx, OptRecordFile); + // There is a record file and it is not empty. + if (isSet && OptRecordFile) { + // Create a consumer + std::unique_ptr Consumer = + CreateASTConsumer(CI, getCurrentFileOrBufferName()); + if (!Consumer) + return; + + CI.setASTConsumer(std::move(Consumer)); + if (!CI.hasASTConsumer()) + return; + + Ctx.setBiteCodeDiagnosticHandler( + std::make_unique(CI.getCodeGenOpts(), + BEConsumer), + false); + + if (OptRecordFile && + CI.getCodeGenOpts().getProfileUse() != CodeGenOptions::ProfileNone) + Ctx.setDiagnosticsHotnessRequested(true); + } + } + EmitBackendOutput(CI.getDiagnostics(), CI.getHeaderSearchOpts(), CI.getCodeGenOpts(), TargetOpts, CI.getLangOpts(), CI.getTarget().getDataLayout(), TheModule.get(), BA, std::move(OS)); + + if (OptRecordFile) + OptRecordFile->keep(); + return; } Index: clang/test/CodeGen/opt-record-1.c =================================================================== --- /dev/null +++ clang/test/CodeGen/opt-record-1.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 %s -opt-record-file=t1.opt -fopenmp -emit-llvm-bc -o %t.bc +// RUN: %clang_cc1 -x ir %t.bc -opt-record-file %t.opt -fopenmp -emit-obj +// RUN: cat %t.opt | FileCheck -check-prefix=CHECK -check-prefix=CHECK-PASSES %s + + +void foo(int *a, int *b, int *c) { +#pragma omp parallel for + for (int i = 0; i < 100; i++) { + a[i] = b[i] + c[i]; + } +} + +// CHECK: --- !Missed +// CHECK: Pass: inline +// CHECK: Name: NoDefinition +// CHECK: Function: foo +// CHECK-PASSES: Pass: inline + Index: llvm/include/llvm/IR/LLVMContext.h =================================================================== --- llvm/include/llvm/IR/LLVMContext.h +++ llvm/include/llvm/IR/LLVMContext.h @@ -148,6 +148,9 @@ /// \see LLVMContext::setYieldCallback. using YieldCallbackTy = void (*)(LLVMContext *Context, void *OpaqueHandle); + void setBitCodeDiagnosticHandler(std::unique_ptr&&DH, + bool RespectFilters = false); + /// setInlineAsmDiagnosticHandler - This method sets a handler that is invoked /// when problems with inline asm are detected by the backend. The first /// argument is a function pointer and the second is a context pointer that Index: llvm/lib/IR/LLVMContext.cpp =================================================================== --- llvm/lib/IR/LLVMContext.cpp +++ llvm/lib/IR/LLVMContext.cpp @@ -114,6 +114,13 @@ return pImpl->InlineAsmDiagContext; } +void LLVMContext:: +setBitCodeDiagnosticHandler(std::unique_ptr&&DH, bool RespectFilters) +{ + pImpl->DiagHandler = std::move(DH); + pImpl->RespectDiagnosticFilters = RespectFilters; +} + void LLVMContext::setDiagnosticHandlerCallBack( DiagnosticHandler::DiagnosticHandlerTy DiagnosticHandler, void *DiagnosticContext, bool RespectFilters) {