[llvm-dev] ScalarEvolution in a ModulePass

TB Schardl via llvm-dev llvm-dev at lists.llvm.org
Sat Aug 11 07:16:17 PDT 2018


Hey LLVMDev,

I'm working on a ModulePass that uses ScalarEvolution along with several
other analyses.  After some debugging, it looks to me like
ScalarEvolutionWrapperPass does not handle memory correctly for this case.
Here's my current understanding of the problem.

ScalarEvolutionWrapperPass maintains a unique_ptr to a ScalarEvolution.
Calling getSE() dereferences this pointer.  Meanwhile runOnFunction()
resets the pointer to point to a new ScalarEvolution.  As a result,
runOnFunction destructs and frees any ScalarEvolution the unique_ptr
pointed to before.

The ModulePass I'm working on uses ScalarEvolution and several other
analysis FunctionPasses, including DominatorTree, LoopInfo,
OptimizationRemarkEmitter, and a custom analysis pass I'm working on, which
resembles LoopInfo.  To run ScalarEvolution and these other analysis
FunctionPasses in a ModulePass, the ModulePass creates lambdas to get the
analysis for a particular function, e.g.,

auto GetSE = [this](Function &F) -> ScalarEvolution & {
  return this->getAnalysis<ScalarEvolutionWrapperPass>(F).getSE();
};


Later, when the ModulePass examines a particular Function, it calls the
appropriate lambda to get the analysis for that Function.

The problem seems to arise when lambdas for other analysis FunctionPasses
run after calling the GetSE lambda, e.g., when evaluating a statement like
this:

for (Function &F : M)
  Changed |= MyPassImpl(F, GetSE(F), GetDT(F), GetLI(F), GetORE(F),
...).run();


It appears that these other analysis FunctionPasses can cause
ScalarEvolutionWrapperPass::runOnFunction() to rerun after GetSE() returns
a pointer to a ScalarEvolution, which changes the underlying
ScalarEvolution object that the wrapper pass points to.  As a result, the
pointer originally obtained from GetSE() points to invalid memory, and
chaos ensues.  Running valgrind on the "opt -mypass" indicates that the
ScalarEvolution object used by MyPassImpl points to freed memory.

I've been able to work around this problem, but I figured I should raise
the issue and see if you might have more insights into this problem.  For
example, I'm not totally sure why the other analysis FunctionPasses cause
ScalarEvolutionWrapperPass::runOnFunction() to rerun.  I'm also concerned
about other analysis FunctionPasses, that might suffer from the same
problem.  MemorySSAWrapperPass, for example, uses a unique_ptr similarly to
ScalarEvolution.

Cheers,
TB
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20180811/8d58a7bb/attachment.html>


More information about the llvm-dev mailing list