[llvm-dev] Cannot access module pass results from inside loop pass

Sebastian Hain via llvm-dev llvm-dev at lists.llvm.org
Sun Apr 24 09:59:09 PDT 2016


Hello,

I don't know wether this is the right place to ask, but I did not find
any other appropriate place else so just ask:
I'm writing several LLVM passes: the first one is a ModulePass that
performs some analyzations tasks but does not change anything. It
simply looks at some (named) metadata nodes and thats it. It neither
changes them nor does it change anything else. This is the code to
initialize the pass (MyModuleChecker.cpp):

INITIALIZE_PASS_BEGIN(MyModuleChecker, "mmc", "Check module",  false, true)
INITIALIZE_PASS_END(MyModuleChecker, "mmc", "Check module",  false, true)

MyModuleChecker::MyModuleChecker(void) : ModulePass(ID) {
  initializeMyModuleCheckerPass(*PassRegistry::getPassRegistry());
}

void MyModuleChecker::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
}

bool MyModuleChecker::runOnModule(Module &M) {
  // ...
  return false;
}


And then there is a second pass. That pass is a LoopPass and basicly
performs some loop unrolling tasks depending on some other criteria.
For computing the unroll count the pass needs the results of the
MyModuleChecker pass. So I put it in the dependencies like this:

INITIALIZE_PASS_BEGIN(MyLoopUnroll, "myloopunroll", "Unroll loops",
false, false)
INITIALIZE_PASS_DEPENDENCY(LoopInfo)
INITIALIZE_PASS_DEPENDENCY(ScalarEvolution)
INITIALIZE_PASS_DEPENDENCY(MyModuleChecker)
INITIALIZE_PASS_DEPENDENCY(DataLayoutPass)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_END(MyLoopUnroll, "myloopunroll", "Unroll loops",  false, false)

MyLoopUnroll::MyLoopUnroll()
 : LoopPass(ID), MDK(nullptr), LI(nullptr), SE(nullptr), AC(nullptr),
   DL(nullptr) {
  initializeMyLoopUnrollPass(*PassRegistry::getPassRegistry());
}

void HDLLoopUnroll::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.addRequired<LoopInfo>();
  AU.addRequired<ScalarEvolution>();
  AU.addRequired<MyModuleChecker>();
  AU.addPreserved<MyModuleChecker>();
  AU.addRequired<DataLayoutPass>();
  AU.addPreserved<DataLayoutPass>();
  AU.addRequired<AssumptionCacheTracker>();
}

bool MyLoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) {
  LI = &getAnalysis<LoopInfo>();
  SE = &getAnalysis<ScalarEvolution>();
  MDK = &getAnalysis<MyModuleChecker>();
  DL = &getAnalysis<DataLayoutPass>().getDataLayout();
  AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(*L->getHeader()->getParent());

  bool Changed = handleLoop(L, LPM);
  return Changed;
}

The loop unrolling itself is carried out by the functions already
existing in LLVM (and that are used by the LLVM loop unrolling pass).
So my pass "only" computes the loop unroll count.

Currently those passes are part of the Scalar-library so I adopted the
corresponding files (include /llvm/Transforms/Scalar.h,
LinkAllPasses.h, ...) accordingly.

Now I want to run the passes using opt (I'm using LLVM 3.6):
opt -stats -debug -debug-pass=Structure -mem2reg -loop-rotate
-myloopunroll -simplifycfg

And now I get an assertion error:
LoopRotation: rotating Loop at depth 1 containing:
%for.cond<header><exiting>,%for.body,%for.inc<latch>
  Inserted PHI:   %i.01 = phi i32 [ 0, %entry ], [ %i.0, %for.cond ]
  LoopRotation: into Loop at depth 1 containing:
%for.body<header>,%for.inc<latch><exiting>
opt: ~/llvm-clang/source/include/llvm/PassAnalysisSupport.h:214:
AnalysisType& llvm::Pass::getAnalysisID(llvm::AnalysisID) const [with
AnalysisType = MyModuleChecker; llvm::AnalysisID = const void*]:
Assertion `ResultPass && "getAnalysis*() called on an analysis that
was not " "'required' by pass!"' failed.
// ...
#8 0x1685a99 MyModuleChecker&
llvm::Pass::getAnalysisID<MyModuleChecker>(void const*) const
(.../opt+0x1685a99)
#9 0x16857f0 MyModuleChecker&
llvm::Pass::getAnalysis<MyModuleChecker>() const (.../opt+0x16857f0)
#10 0x16853cd MyLoopUnroll::runOnLoop(llvm::Loop*,
llvm::LPPassManager&) (.../opt+0x16853cd)
#11 0xd34aaa llvm::LPPassManager::runOnFunction(llvm::Function&)
(.../opt+0xd34aaa)
#12 0x11c6a34 llvm::FPPassManager::runOnFunction(llvm::Function&)
(.../opt+0x11c6a34)
#13 0x11c6ba4 llvm::FPPassManager::runOnModule(llvm::Module&)
(.../opt+0x11c6ba4)
#14 0x11c6ec2 (anonymous
namespace)::MPPassManager::runOnModule(llvm::Module&)
(.../opt+0x11c6ec2)
#15 0x11c7568 llvm::legacy::PassManagerImpl::run(llvm::Module&)
(.../opt+0x11c7568)
#16 0x11c7787 llvm::legacy::PassManager::run(llvm::Module&) (.../opt+0x11c7787)
// ...

The following passes are run:
Assumption Cache Tracker
  ModulePass Manager
    FunctionPass Manager
      Dominator Tree Construction
      Promote Memory to Register
      Natural Loop Information
      Canonicalize natural loops
      Loop-Closed SSA Form Pass
      Loop Pass Manager
        Rotate Loops
      Scalar Evolution Analysis
    Check module
    FunctionPass Manager
      Dominator Tree Construction
      Natural Loop Information
      Scalar Evolution Analysis
      Loop Pass Manager
        Unroll loops
      Simple constant propagation
      Module Verifier
    Debug Info Verifier
    Bitcode Writer

And then the assertion error occurs and I don't know where that error
comes from and why it occures (and yes, everything compiles without
errors and warnings). It looks like the loop rotation pass is executed
normally and then pass manager gets stuck in the loop unroll pass when
calling the getAnalysis<MyModuleChecker> function in the LoopPass to
get the analysis results.

If I omit the -simplifycfg(when calling opt) and like this do not run
the simplifycfg pass after my own loopunrolling pass, everything works
fine and there is no assertion error. The assertion error also occurs
if I replace the SimplifyCFG pass by - for example - the constprop
pass.
It also seems as if the error does not occur if the ModuleChecker pass
is transformed into a FunctionPass.
Could anyone tell my why this assertion error occures and (perhaps)
how to solve that issue?

Thanks
Sebastian


More information about the llvm-dev mailing list