Pass Incompatibility

I have a transformation where I'd like to use both DominatorTree (for ExtractCodeRegion), and DemoteRegisterToMemory (i.e., reg2mem). The transformation is phased, so all occurrences of getAnalysis<DominatorTree>(Function) happen before any occurrence of getAnalysisID<FunctionPass>(&DemoteRegisterToMemoryID, Function).

If I register these two passes with DominatorTree first, I get the following assert.

PassAnalysisSupport.h:239: AnalysisType& llvm::Pass::getAnalysisID(const void*, llvm::Function&) [with AnalysisType = llvm::DominatorTree]: Assertion `ResultPass && "Unable to find requested analysis info"' failed.

If I register DemoteRegisterToMemoryID first then I get this assert during code extraction.

CodeExtractor.cpp:681: llvm::Function*<unnamed>::CodeExtractor::ExtractCodeRegion(const std::vector<llvm::BasicBlock*, std::allocator<llvm::BasicBlock*> >&): Assertion `BlocksToExtract.count(*PI) && "No blocks in this region may have entries from outside the region" " except for the first block!"' failed.

If I split my pass in half, then the transformation works as expected, with region extraction and DemoteRegisterToMemory going on their merry way. The split pass is harder to understand though, and injects a pass into -help that doesn't actually work on its own.

Is it simply the case the, in order to use these two passes, I must split my transformation into two passes, or is there another/a better way?

Thanks,
Luke

I have a transformation where I'd like to use both DominatorTree (for ExtractCodeRegion), and DemoteRegisterToMemory (i.e., reg2mem). The transformation is phased, so all occurrences of getAnalysis<DominatorTree>(Function) happen before any occurrence of getAnalysisID<FunctionPass>(&DemoteRegisterToMemoryID, Function).

I believe that reg2mem is a transform pass, correct? If so, then you should not be making it a prerequisite for your pass. Instead, whatever is scheduling the set of transform passes (e.g, the user on the opt command line or the source code that schedules your pass to be run with a PassManager) should run reg2mem right before your pass is run. Your pass should assert that the LLVM bitcode has the property that reg2mem creates.

In general, passes cannot depend upon transform passes. There are certain situations in which PassManager cannot resolve dependencies when a transform pass is part of a dependency chain (e.g., Transform Pass A requires Transform Pass B and Analysis Pass C, but B invalidates C), and so you get cryptic error messages. That is probably what you are seeing here.

-- John T.

If I register DemoteRegisterToMemoryID first

I'd expect this to work.

then I get this assert during code extraction.

CodeExtractor.cpp:681: llvm::Function*<unnamed>::CodeExtractor::ExtractCodeRegion(const std::vector<llvm::BasicBlock*, std::allocator<llvm::BasicBlock*> >&): Assertion `BlocksToExtract.count(*PI) && "No blocks in this region may have entries from outside the region" " except for the first block!"' failed.

AFAIU, this assertion is not related to ordering of analysis passes. Analyzing incoming bb vector for ExtractCodeRegion() may help you understand why you're triggering this assertion. May the vector is stale ?

This is a good point.

I have a transformation where I'd like to use both DominatorTree (for ExtractCodeRegion), and DemoteRegisterToMemory (i.e., reg2mem). The transformation is phased, so all occurrences of getAnalysis<DominatorTree>(Function) happen before any occurrence of getAnalysisID<FunctionPass>(&DemoteRegisterToMemoryID, Function).

I believe that reg2mem is a transform pass, correct?

Absolutely.

If so, then you should not be making it a prerequisite for your pass. Instead, whatever is scheduling the set of transform passes (e.g, the user on the opt command line or the source code that schedules your pass to be run with a PassManager) should run reg2mem right before your pass is run. Your pass should assert that the LLVM bitcode has the property that reg2mem creates.

Hmm... so it sounds like the only thing that makes sense in my situation is to split my transformation into two passes, since it's important to me that the incoming code to the pass be post-mem2reg.

In general, passes cannot depend upon transform passes. There are certain situations in which PassManager cannot resolve dependencies when a transform pass is part of a dependency chain (e.g., Transform Pass A requires Transform Pass B and Analysis Pass C, but B invalidates C), and so you get cryptic error messages. That is probably what you are seeing here.

OK. The asymmetry in failures between

  void getAnalysisUsage(AnalysisUsage& au) const {
    au.addRequired<DominatorTree>();
    au.addRequiredID(DemoteRegisterToMemoryID);
  }

and

  void getAnalysisUsage(AnalysisUsage& au) const {
    au.addRequiredID(DemoteRegisterToMemoryID);
    au.addRequired<DominatorTree>();
  }

had me confused.

Luke

If I register DemoteRegisterToMemoryID first

I'd expect this to work.

then I get this assert during code extraction.

CodeExtractor.cpp:681: llvm::Function*<unnamed>::CodeExtractor::ExtractCodeRegion(const std::vector<llvm::BasicBlock*, std::allocator<llvm::BasicBlock*> >&): Assertion `BlocksToExtract.count(*PI) && "No blocks in this region may have entries from outside the region" " except for the first block!"' failed.

AFAIU, this assertion is not related to ordering of analysis passes. Analyzing incoming bb vector for ExtractCodeRegion() may help you understand why you're triggering this assertion. May the vector is stale ?

Hmm... the code for extraction doesn't change, it's literally the order of registration that matters. The extraction point looks like:

  vector<BasicBlock*> blocks;
  fill(blocks);
  ExtractCodeRegion(getAnalysis<DominatorTree>(*f), blocks)

Maybe, when DemoteRegisterToMemory is added before DominatorTree, this getAnalysis call triggers a DemoteRegisterToMemory on the function where blocks come from before running the DominatorTree analysis...

It sound like I'm just going to need multiple transformation passes to do what I want.

Thanks,
Luke