How to force MemoryDependenceAnalysis to run on original module

Hi,

I do have a FunctionPass that does change the code. This FunctionPass requires another FunctionPass which performs all the necessary analyses. This AnalysisPass again requires MemoryDependenceAnalysis.

The problem is, that I would like MemoryDependenceAnalysis to run on the unaltered module. I do not want to have dependencies to changed code. What is the cleanest way to do this?
Sounds easy, but I do not get it right :smiley:

Thanks
Marc

Hi Marc,

This isn't really possible. The issue is that MemDep doesn't just "analyze your function". It is designed to be as lazy as possible, which means that it only does analysis when a query is performed. This means that if you have MemDep->Pass1->Pass2 and Pass2 uses MemDep info that you need to make Pass1 preserve that memdep info.

-Chris

Chris Lattner schrieb:

Hi,

I do have a FunctionPass that does change the code. This FunctionPass
requires another FunctionPass which performs all the necessary analyses.
This AnalysisPass again requires MemoryDependenceAnalysis.

The problem is, that I would like MemoryDependenceAnalysis to run on the
unaltered module. I do not want to have dependencies to changed code.
What is the cleanest way to do this?
Sounds easy, but I do not get it right :smiley:

Hi Marc,

This isn't really possible. The issue is that MemDep doesn't just "analyze your function". It is designed to be as lazy as possible, which means that it only does analysis when a query is performed. This means that if you have MemDep->Pass1->Pass2 and Pass2 uses MemDep info that you need to make Pass1 preserve that memdep info.

Hi,

actually my problem is easier. So I still have hope that it is possible:

MemDep->Pass1->Pass2

Pass1 uses MemDep. Pass2 only uses Pass1. Eventually, Pass2 changes the code. Unfortunately, non-local dependencies of MemDep might point to code changed by Pass2. Therefore, Pass1 might see changes applied by Pass2. This breaks encapsulation.

So I want to make sure the PassManager runs Pass1 on the whole module, before Pass2's runOnFunction is called the first time.

Still impossible?

Thanks
Marc

Not impossible at all. I assume that Pass1 is your pass, just make the "Pass1::runOnFunction" method do everything you need.

If Pass2 ends up calling pass1 in various ways that require it to do things after its runonfunciton is complete, just make pass1 "transitively depend on" memdep, and give pass1 an update interface that is a superset of what memdep needs.

-Chris

Chris Lattner schrieb:

This isn't really possible. The issue is that MemDep doesn't just
"analyze your function". It is designed to be as lazy as possible,
which means that it only does analysis when a query is performed. This
means that if you have MemDep->Pass1->Pass2 and Pass2 uses MemDep info
that you need to make Pass1 preserve that memdep info.

Hi,

actually my problem is easier. So I still have hope that it is possible:

MemDep->Pass1->Pass2

Pass1 uses MemDep. Pass2 only uses Pass1. Eventually, Pass2 changes the
code. Unfortunately, non-local dependencies of MemDep might point to
code changed by Pass2. Therefore, Pass1 might see changes applied by
Pass2. This breaks encapsulation.

So I want to make sure the PassManager runs Pass1 on the whole module,
before Pass2's runOnFunction is called the first time.

Not impossible at all. I assume that Pass1 is your pass, just make the "Pass1::runOnFunction" method do everything you need.

Hi Chris,

I'm not sure whether I got you right.

Now I run the whole analysis (Pass1) on the first call to Pass1::runOnFunction. That is, I get the module of the passed function and iterate over _all_ functions of the module.
On subsequent calls to runOnFunction I just do not do anything.

I cache the analysis result for later queries. While it works, it also means that I keep state across invocations of runOnFunction which isn't allowed[1].

All in all it looks awkward, doesn't feel right, but works.
Did you mean something like that or did I misunderstand you completely?

Many thanks!
Marc

[1] http://llvm.org/docs/WritingAnLLVMPass.html#FunctionPass

Pass1 and Pass2 are function passes. Pass1 will first operate on
function F1 before Pass2 gets a chance on F1. However, after Pass2
operates on F1, the Pass1 will not operate on F1, so it won't see any
changes applied by Pass2.

?

Devang Patel schrieb:

actually my problem is easier. So I still have hope that it is possible:

MemDep->Pass1->Pass2

Pass1 uses MemDep. Pass2 only uses Pass1. Eventually, Pass2 changes the
code. Unfortunately, non-local dependencies of MemDep might point to
code changed by Pass2. Therefore, Pass1 might see changes applied by
Pass2. This breaks encapsulation.

Pass1 and Pass2 are function passes. Pass1 will first operate on
function F1 before Pass2 gets a chance on F1. However, after Pass2
operates on F1, the Pass1 will not operate on F1, so it won't see any
changes applied by Pass2.

Hi,

that's not the end of the story; it's just the beginning:
Pass2 changes F1. Next, Pass1 is run on F2. Pass1 asks MemDep for non-local dependencies. Unfortunately the non-local dependency is an instruction in F1. So Pass1 might see changes done by Pass2.

Ciao
Marc