[LLVMdev] readonly and infinite loops

Sanjoy Das sanjoy at playingwithpointers.com
Thu Jul 9 12:29:22 PDT 2015


Here's a fun spin on this same topic (I can't file a bug at this
moment since llvm.org is down).

Consider:

define i32 @x(i32* %x, i1* %y) {
 entry:
  br label %loop

 loop:
  %v = phi i32 [ 0 , %entry ], [ %v.inc, %exit.inner ], [ %v, %loop ]
  %c = load volatile i1, i1* %y
  br i1 %c, label %exit.inner, label %loop

 exit.inner:
  %c1 = load volatile i1, i1* %y
  %x.val = load i32, i32* %x
  %v.inc = add i32 %v, %x.val
  br i1 %c1, label %exit.real, label %loop

 exit.real:
  ret i32 %v
}

Now if %c is false every time, %x is never dereferenced.  Since this
is an infinitely looping program that does a volatile load in every
iteration, it is well defined (going by what Hal said).

However, opt -licm transforms this to

; ModuleID = '/Users/sanjoy/tmp/inf.ll'

define i32 @x(i32* %x, i1* %y) {
entry:
  %x.val = load i32, i32* %x
  br label %loop.outer

loop.outer:                                       ; preds = %exit.inner, %entry
  %v.ph = phi i32 [ %v.inc, %exit.inner ], [ 0, %entry ]
  br label %loop

loop:                                             ; preds = %loop.outer, %loop
  %c = load volatile i1, i1* %y
  br i1 %c, label %exit.inner, label %loop

exit.inner:                                       ; preds = %loop
  %c1 = load volatile i1, i1* %y
  %v.inc = add i32 %v.ph, %x.val
  br i1 %c1, label %exit.real, label %loop.outer

exit.real:                                        ; preds = %exit.inner
  %v.ph.lcssa = phi i32 [ %v.ph, %exit.inner ]
  ret i32 %v.ph.lcssa
}

where it unconditionally dereferences %x, effectively introducing UB
if %x is not dereferenceable.


The bug is in isGuaranteedToExecute.  It assumes that if an
instruction dominates all the loop exits then it will always be
executed by the loop "on its way out".  But there may never be a way
out of the loop.

-- Sanjoy



More information about the llvm-dev mailing list