Here is a small program that illustrates the bug:
define void @f(i32* %loc) {
entry:
br label %loop
loop:
%idx = phi i32 [ 6, %entry ], [ %idx.dec, %loop ]
store i32 %idx, i32* %loc
%idx.dec = sub nuw i32 %idx, 1
%cond = icmp uge i32 %idx.dec, 5
br i1 %cond, label %loop, label %exit
exit:
ret void
}
The store is supposed to happen exactly twice. But opt -indvars turns
it into an infinite loop:
define void @f(i32* %loc) {
entry:
br label %loop
loop: ; preds = %loop, %entry
%idx = phi i32 [ 6, %entry ], [ %idx.dec, %loop ]
store i32 %idx, i32* %loc
%idx.dec = sub nuw nsw i32 %idx, 1
br i1 true, label %loop, label %exit
exit: ; preds = %loop
ret void
}
because %idx.dec, which is {5,+,-1}<nuw><%loop> can never be ult 5.
On Wed, Jan 14, 2015 at 10:28 PM, David Majnemer
<david.majnemer at gmail.com> wrote:> On Wed, Jan 14, 2015 at 10:14 PM, Sanjoy Das
> <sanjoy at playingwithpointers.com> wrote:
>>
>> > We are permitted to turn 'sub nsw i32 %x, 1' into 'add
nsw i32 %x, -1'
>>
>> nsw also has the same problem:
>>
>> sub nsw int_min, int_min is 0 but
>> add nsw int_min, (-int_min) is poison
>
>
> Right, it doesn't work with all values. I was specifically referring
to the
> %x and -1 case.
>
>>
>>
>> -- Sanjoy
>
>