[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Chris Lattner clattner at apple.com
Thu Jun 28 10:02:34 PDT 2007


On Jun 27, 2007, at 1:50 PM, Dan Gohman wrote:

>>>> I think that undef udiv intmax -> 0, no?  If not, plz update
>>>> instcombine as well.
>>>
>>> intmax udiv intmax -> 1.
>>> It seems like folding undef/X to undef isn't safe either though,  
>>> with
>>> the way it sounds like undef is intended to work. This code:
>>>
>>>   %x = udiv i32 undef, %intmax
>>>   %y = udiv i32 %x, 2
>>>
>>> will always set %y to 0. Maybe instcombine can fold the second
>>> udiv by looking through its operands, but it can't safely fold the
>>> first. The best it could do is try to fold away all of %x's uses so
>>> that %x isn't needed anymore.

Duncan pointed out that I confused myself.  If something is undef, we  
can choose to pick any specific value for the undef to pick the  
cancellation.

>> Ug, excellent point.  At this point, I'm inclined to just give up
>> folding of udiv undefs.  What do you think?
>
> udiv isn't the only one, the way this is going...
>
>   %x = mul i32 undef, 2
>   %y = srem i32 %x, 2

This is fine, we fold the mul to 0 (because the undef could be zero).

>   %x = and i32 undef, 0xffff0000
>   %y = and i32 %x,    0x0000ffff
>
> and so on for a lot of others.

For and, we fold undef to 0 (because the undef could be 0)
For or undef, X, we fold to -1, because the undef could be -1.

>>> Even simple things like undef+X don't seem to be safe to fold.
>>>
>>>   %x = undef;
>>>   if (%x >= 0)
>>>     %z = %y / (%x + 1);         // don't divide by undef!
>>
>> Fortunately, this isn't a problem.  LLVM has no copy instruction, so
>> the code is really this:
>>
>>>   if (undef >= 0)
>>>     %z = %y / (undef + 1);         // don't divide by undef!
>>
>> There is nothing that specifies the two undefs are the same value.
>> Also, in C, if you have an undefined variable, you aren't guaranteed
>> to get the same undef value each time you read the variable, so
>> transforming C into LLVM is ok :)
>
> In C, an uninitialized variable has an "indeterminate value", which is
> potentially a trap representation, which can't even be multiplied by
> zero without incurring undefined behavior. I don't know where it
> suggests that a variable with indeterminate value might be different
> on each read though.

There have been discussions about this issue on the GCC list.  I  
remember the resolution (they take the same basic approach we do),  
but I don't remember why.  I think a DR may be submitted to the C  
committee on the issue.

IIRC, the basic reason this (allowing an undefined value to have  
multiple values) bites GCC is due to regalloc.  For example, if you  
have:

   int x;
   int y;

   y = 1;
   print(x, y);
   ...

   y = 2;
   print(x, y);

Because there is no live range for x (just uses) x and y can be  
allocated to the same register.  Doing so causes the value of x to  
follow the value of y.

> LLVM does so have copy instructions. The syntax is a little odd  
> though,
> and the keyword is spelled 'bitcast' ;-).

Point taken. :)

-Chris





More information about the llvm-commits mailing list