[LLVMdev] How to handle divide-by-zero exception?
nicholas at mxc.ca
Thu May 15 01:53:40 CDT 2008
Dan Gohman wrote:
> On May 9, 2008, at 10:04 PM, Nick Lewycky wrote:
>> Dan Gohman wrote:
>>> Having a dom tree with multiple roots, where blocks may
>>> not be dominated by the entry block is pretty scary.
>> The dom tree code already supports it, because it already happens to
>> postdominator trees. There are some clients that will need to be
>> changed, but I think it's pretty minimal.
> Please reconsider prohibiting the entry block from having an
> "unwinds to". Beyond dom tree clients, there's also the widely
> useful idiom of allocas in the entry block that this would
*shrug* I'm not married to the idea. It just hasn't hit me that it's
Put another way, if I actually encounter passes doing things like
inserting alloca's in the first block and this is harder to fix than
disallowing 'unwinds to' on the entry BB would be, I'll disallow
'unwinds to' on the entry BB.
> I just hunted through the archives and confirmed my memory
> of seeing this concern raised but never addressed. If I
> missed a reason why entry needs to have "unwinds to", please
> point it out again.
> Also, in that case, please also explain what will happen here:
> entry: unwinds to %handler
> call void @foo()
> br label %exit
> br label %exit
> ret void
> Where does %exit stand in dom tree land?
Yup, it's exactly where you think:
| | |
entry handler exit
>>> "predecessor" mean different things in the context of the CFG
>>> versus the context of the dom tree is very scary.
>>> Say we have this CFG:
>>> B X
>>> and B "unwinds to" X. Instead of having X be a successor to B,
>>> how about making X a successor to A (and A a predecessor of X)?
>>> A would need a special new kind of terminator instruction which
>>> looks something like a conditional branch with B and X as
>>> destinations, though it would always branch to B when executed.
>> Sure. We could even call it "invoke".
>> The problem is that you end up with a CFG that looks like this:
>> / \
>> B X
>> which doesn't represent what could happen at all. Any pass should be
>> able to reasonably look at that CFG and say that instructions from B
>> X are exclusive. The reality is that instructions in X will occur
>> some of the instructions in B are executed.
> I maintain that it does represent what happens, with a little
> abstraction :-). Control will flow to B in the case that B doesn't
> end up interrupted by an exception, and to X in the case that
> it does. It's not a coincidence that this is the CFG that results
> from reverse-engineering a CFG from the dom tree that you're
> proposing to use.
That drops the fact that some instructions from B may execute before X.
In practise, what users want out of the domtree is to know the nearest
block they can put an instruction that is guaranteed to be executed
before entering this/these other blocks. That's how I justify my change
to the domtree -- it doesn't really apply to the CFG though.
> Unfortunately, after thinking this through a little more I
> found a problem with the magic side-effects intrinsic. As a
> call it can easily appear to have lots of side-effects, but it
> won't easily be able to appear to access alloca or malloc
> memory in the function that doesn't escape.
> There were some other minor issues with my proposal which I
> believe can be reasonably fixed, but this issue with the
> side-effects intrinsic is a fundamental problem :-/.
Right. Calling an intrinsic that might have arbitrary side-effects
(modify arbitrary memory) would also break mem2reg in all cases.
The simpler method of avoiding an intrinsic and just having a "br label
%foo, onunwind %unwind" instruction is still up for grabs, but I still
think it's bad for reasons up 2 frames in this thread.
More information about the LLVMdev