[llvm-dev] Preservation of CallGraph (by BasicBlockPass, FunctionPass)

Björn Pettersson A via llvm-dev llvm-dev at lists.llvm.org
Mon May 7 07:32:15 PDT 2018


If I run:
  opt -globals-aa -die -inline -debug-pass=Details foo.ll -S

then I will get this pass structure:

Target Library Information
Target Transform Information
Target Pass Configuration
Assumption Cache Tracker
Profile summary info
  ModulePass Manager
    CallGraph Construction
    Globals Alias Analysis
    FunctionPass Manager
      BasicBlockPass Manager
        Dead Instruction Elimination
    Call Graph SCC Pass Manager
      Function Integration/Inlining
      FunctionPass Manager
        Module Verifier
    Print Module IR


FPPassManager:: getAnalysisUsage is doing setPreservesAll(),
but is it correct that the FunctionPass Manager always preserves the CallGraph?


My real problem is that when I use a foo.ll input that looks like this:

;----------------------------------------------------------------
target triple = "x86_64-unknown-linux-gnu"

@b = external global i16, align 1

; Function Attrs: nounwind readnone
define i16 @f1() #0 {
entry:
  ret i16 undef
}

define void @f2() {
entry:
  %call = call i16 @f1()
  store i16 %call, i16* @b, align 1
  %call1 = call i16 @f1()
  ret void
}

attributes #0 = { nounwind readnone }
;----------------------------------------------------------------

then %call1 will be removed by the Dead Instruction Elimination pass. I.e. that pass is not preserving the CallGraph!

Dead Instruction Elimination is a BasicBlockPass, and DeadInstElimination::getAnalysisUsage is doing setPreservesCFG() (even though that should be implicit for a BasicBlockPass afaik).
When reading the description of BasicBlockPass it seems to be legal to remove calls, and that should not impact the CFG, right? But it will impact the CallGraph.

I believe that when the FunctionPass Manager is used from within the Call Graph SCC Pass Manager, then the CGPassManager will check the modification status from the FPManager and call RefreshCallGraph() (or set CallGraphUpToDate=false;) in case modification had been done. Thus, it seems to be legit for a FunctionPass (and thereby also the FunctionPassManager) to not always preserve the CallGraph. And I think this is handled within the CGPassManager, but not when FPManager is executed directly from the MPManager

Currently the test case above will end up in an assert, since there is a missing use of @f1 in the CallGraph when doing the inlining.
That will go away if I remove the setPreservesAll from the FPPassManager:: getAnalysisUsage (which I assume is too aggressive).

Would it be correct to change the FPPassManager:: getAnalysisUsage to exclude "CallGraph Construction" from the set of preserved analyses, or am I missing something here?

I assume that DeadInstElimination isn't preserving the CallGraph. Shouldn't that (automatically/dynamically) impact which analyses that are preserved from the BBPassManager and the FPPassManager for this pass structure?

Regards,
Björn
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180507/d60b5721/attachment.html>


More information about the llvm-dev mailing list