I have written several passes that have no pre-requisites for any
previous LLVM native passes prior to my own. For those passes, I have verified that at
least the following two approaches are equivalent in terms of executing
those self-written passes and getting the correct results:
Then, only method 1 can work; The following error msg was what
I got from using method 2:
LLVM/llvm-3.3.src/include/llvm/PassAnalysisSupport.h:200: AnalysisType& llvm::Pass::getAnalysis() const [with AnalysisType = llvm::DominatorTree]: Assertion `Resolver && "Pass has not been inserted into a PassManager object!"' failed.
Note: I have added "initializeDominatorTreePass(*PassRegistry::getPassRegistry());"
to the constructor of my own pass;
I don't know if you *must* run all passes via a PassManager, but I think you should. That's how passes are designed to work, and running them through a PassManager provides some future-proofing benefits (e.g., if you add a prerequisite analysis pass to one of your passes, it will "just work").
Thanks John. Out of curiosity, I wonder if it's possible to summarize the LLVMpass-specific design patterns. I.e., the software engineering techniques that were used to design/implement the LLVM Pass Infrastructure. Equivalently, this may also answer the question "Why is the code this way". This visibility can improve understanding and that is likely to improve quality as more developers are better informed.
Thanks John. Out of curiosity, I wonder if it's possible to summarize the LLVMpass-specific design patterns. I.e., the software engineering techniques that were used to design/implement the LLVM Pass Infrastructure. Equivalently, this may also answer the question "Why is the code this way". This visibility can improve understanding and that is likely to improve quality as more developers are better informed.
Thanks John. Out of curiosity, I wonder if it's possible to summarize the LLVMpass-specific design patterns. I.e., the software engineering techniques that were used to design/implement the LLVM Pass Infrastructure. Equivalently, this may also answer the question "Why is the code this way". This visibility can improve understanding and that is likely to improve quality as more developers are better informed.
I'm probably not the best person to answer this, but at a high level, the Pass Infrastructure does two things:
1) It helps people follow the "Separation of Concerns" principle of compiler writing by making it easy to plug in new transforms into the LLVM copiler.
2) It helps optimize the running of analysis passes.
Separation of Concerns means that instead of writing one big piece of code to optimize a program, we write small transforms, run one after another, that perform simple transforms. For example, we have one pass that does constant propagation and another pass that removes dead code. Adding a new optimization simply requires that one write a new pass and plug it into the chain of optimizations passes being run by a PassManager.
The LLVM PassManager is designed to avoid re-running analysis passes that simply gather information about the program for other passes. For example, multiple optimizations use dominance information which can be expensive to compute. Some passes transform the code in a way that requires that any existing dominance analysis be redone; other passes transform the code in a way that allows existing dominance analysis to be reused by later optimization passes. By knowing which passes use dominance information and which passes do not modify dominance information, the PassManager can avoid running the dominance analysis pass more times than necessary.