[InstrProfiling] Lightweight Instrumentation Problems

I read ellishg’s post about Lightweight Instrumentation.

But I find in some situations, it can’t filter the __llvm_prf_names section. I read the source codes implement it.

bool InstrProfiling::run(
    Module &M, std::function<const TargetLibraryInfo &(Function &F)> GetTLI) {
  ......
  emitVNodes();
  emitNameData();

  // Emit runtime hook for the cases where the target does not unconditionally
  // require pulling in profile runtime, and coverage is enabled on code that is
  // not eliminated by the front-end, e.g. unused functions with internal
  // linkage.
  if (!NeedsRuntimeHook && ContainsProfiling)
    emitRuntimeHook();

  emitRegistration();
  emitUses();
  emitInitialization();
  return true;
}

The __llvm_prf_nm which not be filtered comes from emitNameData(). It is possible for us to add flag on it?

Like this.

if(!DebugInfoCorrelate)
    emitNameData();

CC @ellishg

When using debug info correlation, we do nothing in createDataVariable() which is responsible for populating ReferencedNames.

Then if ReferencedNames is empty, emitNameData() does nothing.

cc @ZequanWu

I have read the code segments. But I find in some situations ReferencedNames is not empty.

bool InstrProfiling::run(
    Module &M, std::function<const TargetLibraryInfo &(Function &F)> GetTLI) {
  ......
  bool ContainsProfiling = containsProfilingIntrinsics(M);
  GlobalVariable *CoverageNamesVar =
      M.getNamedGlobal(getCoverageUnusedNamesVarName());
  .....
  if (CoverageNamesVar) {
    lowerCoverageData(CoverageNamesVar);
    MadeChange = true;
  }

  .....
  emitNameData();
  ....
}

When it can get data from CoverageNamesVar, it will run lowerCoverageData function, where it will push some names in ReferencedNames. It makes ReferencedNames not empry.

void InstrProfiling::lowerCoverageData(GlobalVariable *CoverageNamesVar) {
  ConstantArray *Names =
      cast<ConstantArray>(CoverageNamesVar->getInitializer());
  for (unsigned I = 0, E = Names->getNumOperands(); I < E; ++I) {
    Constant *NC = Names->getOperand(I);
    Value *V = NC->stripPointerCasts();
    assert(isa<GlobalVariable>(V) && "Missing reference to function name");
    GlobalVariable *Name = cast<GlobalVariable>(V);

    Name->setLinkage(GlobalValue::PrivateLinkage);
    ReferencedNames.push_back(Name);
    if (isa<ConstantExpr>(NC))
      NC->dropAllReferences();
  }
  CoverageNamesVar->eraseFromParent();
}

I’m comfused whether it is reasonable or not?

:melting_face: :melting_face: :melting_face: I know what happens. Because I use -fprofile-instr-generate -fcoverage-mapping flags and they are not supported this method in the latest llvm if I recall correctly.

:pray:I’m excepted to find a lightweight Source-based Code Coverage implement.

By the way, @ellishg I also want to know why it is not supported when using -fprofile-instr-generate?

-fprofile-instr-generate -fcoverage-mapping is used for clang frontend instrumentation while I’ve only implemented lightweight instrumentation for LLVM’s IRPGO using -fprofile-generate.
If I remember correctly, the llvm-cov tool might look up the names in the __llvm_prf_nm section in the binary. So implementing lightweight instrumentation for Clang frontend instrumentation might take a lot of work. I don’t have any current plans to support this right now.

1 Like

I have attempted to add support for source code coverage with debug info correlation: [Coverage] Allow Clang coverage to be used with debug info correlation. · llvm/llvm-project@32db121 · GitHub (reverted because of performance regression) and [llvm-cov] Add --debug-info flag to llvm-cov to lookup debug info file. by ZequanWu · Pull Request #66798 · llvm/llvm-project · GitHub (abandoned). I decided not to continue with that because I think binary correlation is a better option for code coverage.

To enable it, you can use the flag -mllvm -profile-correlate=binary at instrumentation stage. Then at merging stage, llvm-profdata merge -binary-file=[unstripped-binary] ... to get indexed profile file.

There’s also an open PR to support merging lightweight raw profiles with multiple binaries at one time.

1 Like

:smiley:Thank you very much for your answer! You mentioned PR just what I need. :pray:

In some situation, when the program is so big, the section __llvm_prf_nm will take up quite a bit of space. It will raise a link problem “relocation out of range”. :innocent: That’s why I want to find a lightweight implement of coverage. :melting_face: