Commit 31ae0165 authored by Gabor Horvath's avatar Gabor Horvath
Browse files

[LTO] Add optimization remarks for removed functions

This only works with regular LTO for now.

Differential Revision: https://reviews.llvm.org/D73597
parent a10cec02
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -45,6 +45,9 @@ Error thinBackend(const Config &C, unsigned Task, AddStreamFn AddStream,
                  const FunctionImporter::ImportMapTy &ImportList,
                  const GVSummaryMapTy &DefinedGlobals,
                  MapVector<StringRef, BitcodeModule> &ModuleMap);

Error finalizeOptimizationRemarks(
    std::unique_ptr<ToolOutputFile> DiagOutputFile);
}
}

+3 −6
Original line number Diff line number Diff line
@@ -244,11 +244,8 @@ OptimizationRemark::OptimizationRemark(const char *PassName,
                                   RemarkName, *Inst->getParent()->getParent(),
                                   Inst->getDebugLoc(), Inst->getParent()) {}

// Helper to allow for an assert before attempting to return an invalid
// reference.
static const BasicBlock &getFirstFunctionBlock(const Function *Func) {
  assert(!Func->empty() && "Function does not have a body");
  return Func->front();
static const BasicBlock *getFirstFunctionBlock(const Function *Func) {
  return Func->empty() ? nullptr : &Func->front();
}

OptimizationRemark::OptimizationRemark(const char *PassName,
@@ -256,7 +253,7 @@ OptimizationRemark::OptimizationRemark(const char *PassName,
                                       const Function *Func)
    : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
                                   RemarkName, *Func, Func->getSubprogram(),
                                   &getFirstFunctionBlock(Func)) {}
                                   getFirstFunctionBlock(Func)) {}

bool OptimizationRemark::isEnabled() const {
  const Function &Fn = getFunction();
+36 −14
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@

#include "llvm/LTO/LTO.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Bitcode/BitcodeReader.h"
@@ -781,8 +782,15 @@ Error LTO::linkRegularLTO(RegularLTOState::AddedModule Mod,
                          bool LivenessFromIndex) {
  std::vector<GlobalValue *> Keep;
  for (GlobalValue *GV : Mod.Keep) {
    if (LivenessFromIndex && !ThinLTO.CombinedIndex.isGUIDLive(GV->getGUID()))
    if (LivenessFromIndex && !ThinLTO.CombinedIndex.isGUIDLive(GV->getGUID())) {
      if (Function *F = dyn_cast<Function>(GV)) {
        OptimizationRemarkEmitter ORE(F);
        ORE.emit(OptimizationRemark(DEBUG_TYPE, "deadfunction", F)
                 << ore::NV("Function", F)
                 << " not added to the combined module ");
      }
      continue;
    }

    if (!GV->hasAvailableExternallyLinkage()) {
      Keep.push_back(GV);
@@ -931,17 +939,6 @@ Error LTO::run(AddStreamFn AddStream, NativeObjectCache Cache) {
    return StatsFileOrErr.takeError();
  std::unique_ptr<ToolOutputFile> StatsFile = std::move(StatsFileOrErr.get());

  // Finalize linking of regular LTO modules containing summaries now that
  // we have computed liveness information.
  for (auto &M : RegularLTO.ModsWithSummaries)
    if (Error Err = linkRegularLTO(std::move(M),
                                   /*LivenessFromIndex=*/true))
      return Err;

  // Ensure we don't have inconsistently split LTO units with type tests.
  if (Error Err = checkPartiallySplit())
    return Err;

  Error Result = runRegularLTO(AddStream);
  if (!Result)
    Result = runThinLTO(AddStream, Cache, GUIDPreservedSymbols);
@@ -953,6 +950,27 @@ Error LTO::run(AddStreamFn AddStream, NativeObjectCache Cache) {
}

Error LTO::runRegularLTO(AddStreamFn AddStream) {
  // Setup optimization remarks.
  auto DiagFileOrErr = lto::setupOptimizationRemarks(
      RegularLTO.CombinedModule->getContext(), Conf.RemarksFilename,
      Conf.RemarksPasses, Conf.RemarksFormat, Conf.RemarksWithHotness);
  if (!DiagFileOrErr)
    return DiagFileOrErr.takeError();

  // Finalize linking of regular LTO modules containing summaries now that
  // we have computed liveness information.
  for (auto &M : RegularLTO.ModsWithSummaries)
    if (Error Err = linkRegularLTO(std::move(M),
                                   /*LivenessFromIndex=*/true))
      return Err;

  // Ensure we don't have inconsistently split LTO units with type tests.
  // FIXME: this checks both LTO and ThinLTO. It happens to work as we take
  // this path both cases but eventually this should be split into two and
  // do the ThinLTO checks in `runThinLTO`.
  if (Error Err = checkPartiallySplit())
    return Err;

  // Make sure commons have the right size/alignment: we kept the largest from
  // all the prevailing when adding the inputs, and we apply it here.
  const DataLayout &DL = RegularLTO.CombinedModule->getDataLayout();
@@ -1017,8 +1035,12 @@ Error LTO::runRegularLTO(AddStreamFn AddStream) {
        !Conf.PostInternalizeModuleHook(0, *RegularLTO.CombinedModule))
      return Error::success();
  }
  return backend(Conf, AddStream, RegularLTO.ParallelCodeGenParallelismLevel,
                 std::move(RegularLTO.CombinedModule), ThinLTO.CombinedIndex);
  if (Error Err =
          backend(Conf, AddStream, RegularLTO.ParallelCodeGenParallelismLevel,
                  std::move(RegularLTO.CombinedModule), ThinLTO.CombinedIndex))
    return Err;

  return finalizeOptimizationRemarks(std::move(*DiagFileOrErr));
}

static const char *libcallRoutineNames[] = {
+4 −12
Original line number Diff line number Diff line
@@ -434,8 +434,8 @@ Expected<const Target *> initAndLookupTarget(const Config &C, Module &Mod) {
}
}

static Error
finalizeOptimizationRemarks(std::unique_ptr<ToolOutputFile> DiagOutputFile) {
Error lto::finalizeOptimizationRemarks(
    std::unique_ptr<ToolOutputFile> DiagOutputFile) {
  // Make sure we flush the diagnostic remarks file in case the linker doesn't
  // call the global destructors before exiting.
  if (!DiagOutputFile)
@@ -455,18 +455,10 @@ Error lto::backend(const Config &C, AddStreamFn AddStream,

  std::unique_ptr<TargetMachine> TM = createTargetMachine(C, *TOrErr, *Mod);

  // Setup optimization remarks.
  auto DiagFileOrErr = lto::setupOptimizationRemarks(
      Mod->getContext(), C.RemarksFilename, C.RemarksPasses, C.RemarksFormat,
      C.RemarksWithHotness);
  if (!DiagFileOrErr)
    return DiagFileOrErr.takeError();
  auto DiagnosticOutputFile = std::move(*DiagFileOrErr);

  if (!C.CodeGenOnly) {
    if (!opt(C, TM.get(), 0, *Mod, /*IsThinLTO=*/false,
             /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr))
      return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
      return Error::success();
  }

  if (ParallelCodeGenParallelismLevel == 1) {
@@ -475,7 +467,7 @@ Error lto::backend(const Config &C, AddStreamFn AddStream,
    splitCodeGen(C, TM.get(), AddStream, ParallelCodeGenParallelismLevel,
                 std::move(Mod));
  }
  return finalizeOptimizationRemarks(std::move(DiagnosticOutputFile));
  return Error::success();
}

static void dropDeadSymbols(Module &Mod, const GVSummaryMapTy &DefinedGlobals,
+13 −3
Original line number Diff line number Diff line
; RUN: opt -module-summary -o %t %s
; RUN: opt -module-summary -o %t2 %S/Inputs/dead-strip-fulllto.ll

; RUN: llvm-lto2 run %t -r %t,main,px -r %t,live1, -r %t,live2,p -r %t,dead2,p \
; RUN: llvm-lto2 run --pass-remarks-output=%t4.yaml --pass-remarks-filter=. \
; RUN:               %t -r %t,main,px -r %t,live1, -r %t,live2,p -r %t,dead2,p \
; RUN:               %t2 -r %t2,live1,p -r %t2,live2, -r %t2,dead1,p -r %t2,dead2, -r %t2,odr, \
; RUN:               -save-temps -o %t3

; RUN: cat %t4.yaml | FileCheck %s -check-prefix=REMARK
; RUN: llvm-nm %t3.0 | FileCheck --check-prefix=FULL %s
; RUN: llvm-nm %t3.1 | FileCheck --check-prefix=THIN %s

@@ -13,6 +16,13 @@
; RUN: llvm-nm %t3.0 | FileCheck --check-prefix=FULL %s
; RUN: llvm-nm %t3.1 | FileCheck --check-prefix=THIN %s

; REMARK:      Pass:            lto
; REMARK-NEXT: Name:            deadfunction
; REMARK-NEXT: Function:        dead2
; REMARK-NEXT: Args:
; REMARK-NEXT:   - Function:        dead2
; REMARK-NEXT:   - String:          ' not added to the combined module '

; FULL-NOT: dead
; FULL: U live1
; FULL: T live2