I can't seem to figure out how to tell the PassManager that one Pass requires the results of two other Passes, in such a way that it will not crash itself. Attached file is the simplest possible example of Passes A, B, and C, such that C's getAnalysisUsage(AU) method calls AU.addRequired<A>() and AU.addRequired<B>(). When I try to run opt -load ... -opt-c, it tells me: opt: PassManagerT.h:348: void PassManagerT<UnitType>::markPassUsed (const PassInfo *, Pass *) [with UnitType = Module]: Assertion `Parent != 0 && "Pass available but not found!"' failed. I don't grok this error message. Of course, -opt-a and -opt-b both work fine in isolation. -- Casey Carter Casey at Carter.net ccarter at uiuc.edu AIM: cartec69 -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: duh.cpp URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20021018/5f76155b/attachment.ksh>
Sorry in advance for taking so long to respond to this issue...> I can't seem to figure out how to tell the PassManager that one Pass > requires the results of two other Passes, in such a way that it will not > crash itself. Attached file is the simplest possible example of Passes> I don't grok this error message. Of course, -opt-a and -opt-b both work > fine in isolation.You're right, this error message is terrible. As it turns out, all of your passes invalidate all of the other passes, so C doesn't get A (which is invalidated by B). The problem turns out to be a really trivial bug: virtual void getAnalysisUsage(AnalysisUsage& AU) const { AU.preservesAll(); // This is the accessor, not the setter } which should call: AU.setPreservesAll(); On a different subject, I noticed that you tried to optimize out the string overhead for the name() methods: virtual const string& name() const { static string a("B"); return a; } instead of a simple: virtual const string& name() const { return "B"; } Because you're trying to be as efficient as possible, here are a few pointers: 1. Static variables defined in a function or method impose quite a bit of overhead. These static variables are initialized the first time the function is executed... which implies that every time the function is executed, the check must be performed. 2. Don't optimize things that don't have to be optimized. In general these methods aren't called enough, or only during debugging, so it is better to be clear than it is to save a few cycles. As a general rule, optimize for clarity, not performance. Often performance comes for free with clarity. 3. If you REALLY want to be efficient, think about other short-cuts. In this case, a constant string is always returned. You could change the virtual method to always return a const char*, therefore avoiding a copy constructor call that may be unneccesary: virtual const char *name() const { return "B"; } ... but this obviously only works if all of the implementations ONLY return static strings. Anyway, good luck with LLVM. It's good to know that you're digging into the pass infrastructure stuff. I'll look into renaming the preservesAll interface to something more obvious in the future. :) -Chris http://llvm.cs.uiuc.edu/ http://www.nondot.org/~sabre/Projects/
Chris Lattner wrote:>>I don't grok this error message. Of course, -opt-a and -opt-b both work >>fine in isolation. >> >> > >You're right, this error message is terrible. As it turns out, all of >your passes invalidate all of the other passes, so C doesn't get A (which >is invalidated by B). The problem turns out to be a really trivial bug: > > virtual void getAnalysisUsage(AnalysisUsage& AU) const { > AU.preservesAll(); // This is the accessor, not the setter > } > >which should call: > AU.setPreservesAll(); > >Ouch. mea culpa. It would be a good idea for preservesAll and preservesCFG to have the same interface (since I, at least, thought that they did ;)>On a different subject, I noticed that you tried to optimize out the >string overhead for the name() methods: > > virtual const string& name() const > { static string a("B"); return a; } > >instead of a simple: > virtual const string& name() const { return "B"; } >Do you think it's a good idea to return a reference to a temporary?> >Because you're trying to be as efficient as possible, here are a few >pointers: > 1. Static variables defined in a function or method impose quite a bit > of overhead. These static variables are initialized the first time > the function is executed... which implies that every time the > function is executed, the check must be performed. > >Are you claiming that most compilers are so grossly inefficient that checking on every call is more expensive than creating the object on every call? If you're going to be passing around objects, they have to be created somewhere. By declaring things static (and preferably const as well), the compiler has the opportunity to optimize away the constructor call.> 2. Don't optimize things that don't have to be optimized. In general > these methods aren't called enough, or only during debugging, so it > is better to be clear than it is to save a few cycles. As a general > rule, optimize for clarity, not performance. Often performance comes > for free with clarity. > >What could be more clear than "static X x; return x;"?> 3. If you REALLY want to be efficient, think about other short-cuts. In > this case, a constant string is always returned. You could change > the virtual method to always return a const char*, therefore avoiding > a copy constructor call that may be unneccesary: > >A good reference-counted string implementation should efficiently handle returning a const& as in this case. Of course, this is example code that I hacked out in about ten minutes just to illustrate the problem, so I would say that the goal is to optimize for speed of coding: I wrote it as it came to me. -- Casey Carter Casey at Carter.net ccarter at uiuc.edu AIM: cartec69