[LLVMdev] RFC: Exception Handling Proposal II

John McCall rjmccall at apple.com
Sun Nov 28 16:41:28 PST 2010


On Nov 28, 2010, at 4:27 PM, Bill Wendling wrote:

> On Nov 28, 2010, at 3:47 PM, John McCall wrote:
> 
>> This is well-formed SSA;  the alloca instruction %x is in the entry block and thus dominates both the store in %try and the load in %catch.  mem2reg wants to eliminate %x and replace the load in %catch with a fixed value.  This involves looking at the value stored in %x at all predecessor points, which is a challenge because one of those predecessors is an arbitrary point within the block %try, and %x actually has two values over that extent.  So mem2reg would have to split %try and make a phi in %lp, like so:
>> 
>> try1: unwinds to %lp
>> %count = load i32* @count
>> br label %try2
>> try2: unwinds to %lp
>> call void foo()
>> br label %return
>> lp:
>> %t = phi i32 [ i32 0, label %try1 ], [ i32 %count, label %try2 ]
>> #etc.
>> 
>> That's a lot of added complexity for mem2reg (and other transformations that use it as a subroutine), but it's pretty much inherent in any design where edges don't always come from terminators.
>> 
>> Now, in this specific case, mem2reg could say "hey, %count can't throw, I don't need the phi at all".  But it would still need to split %lp to make the IR well-formed;  it's just that %lp1 wouldn't have an "unwinds" clause.  And in the general case, it needs a phi.
> 
> Thanks. Your initial statement was confusing. :-) Yes, this is one scenario (and possibly the only one??) for how things would work with adorning BBs with "unwinds to" attributes.


Yeah, I think there are two reasonable possibilities here.  The first is that nothing in an adorned block dominates the edge;  the second is that the phi nodes do.  Consider code like this:

extern void print(int);
extern void bar();
void foo(int *var) {
  int x = 0;
  if (var) x = *var;
  try {
    bar();
  } catch (...) {
    print(x);
  }
}

Is the following well-formed, or do we need the phi in its own, unadorned block?

entry:
  %cond = icmp ne i32* %var, null
  br i1 %cond, label %yes, label %cont
yes:
  %ld = load i32* %var
  br label %cont
cont: unwinds to %lp
  %x = phi i32 [i32 0, label %entry], [i32 %ld, label %yes]
  call void @bar()
  ret void
lp:
  dispatch [catchall, label %catch]
catch:
  #simplified
  call void @print(i32 %x)
  ret void

My intuition is that passes which insert phis will be significantly simplified if phis dominate the EH edge, but it's a slightly more complicated rule, and it might be obnoxious to work with in the end.

John.



More information about the llvm-dev mailing list