[LLVMdev] readonly and infinite loops

Sanjoy Das sanjoy at playingwithpointers.com
Sat Jun 27 23:50:01 PDT 2015


> You dropped some context...

> A daemon program wouldn't be readonly. An infinite loop can be.

Right.

To prevent miscommunication, here is a quick analysis of a problematic
(IMO) example:

We start with

```
define void @infloop(i1 %c) {
 entry:
  br i1 %c,  label %l, label %e

 l:
  br label %l

 e:
  ret void
}

define void @main_func() {
 entry:
  call void @infloop(i1 1)
  ret void
}
```

In this program `@main_func`, when called, will loop infinitely.

If we run this program through `opt -functionattrs -prune-eh
-early-cse`, we get

```
; Function Attrs: nounwind readnone
define void @infloop(i1 %c) #0 {
entry:
  br i1 %c, label %l, label %e

l:                                                ; preds = %l, %entry
  br label %l

e:                                                ; preds = %entry
  ret void
}

; Function Attrs: nounwind
define void @main_func() #1 {
entry:
  ret void
}

attributes #0 = { nounwind readnone }
attributes #1 = { nounwind }
```

LLVM has optimized `@main_func` to return immediately.
`-functionattrs` and `-prune-eh` infer `nounwind readnone` for
`@infloop` and `-early-cse` delets such calls that are dead.

There are three ways to justify what happened:

 1. The optimization was correct.  Infinite loops [1] in LLVM IR are
    UB and since the original program had UB, it can be optimized to
    anything.  This is problematic since if this were true, we would
    have trouble writing frontends for programming languages that
    actually have a well defined `while(1);`.

 2. The bug is in `-early-cse`: a `readnone nounwind` function can
    loop infinitely, so it is not correct to remove a dead call to
    such a function.

 3. The bug is in `-functionattrs`: a function cannot be marked as
    `readonly` if it may loop infinitely.


Needless to say, both (2) and (3) are "easy to fix"; the question is
really about the deeper semantic issue about how LLVM treats
`while(1);`.

There are interesting related questions on the semantics of the
equivalent C/C++ programs, but I personally am interested
only in "pure" LLVM IR semantics.

-- Sanjoy

[1]: We could make the distinction between infinite loops that are
empty vs. infinite loops that are non-empty but that's tricky -- if
only empty infinite loops were UB then e.g. LICM gets harder, since
sinking the store out of loops like `while(1) *addr = 42;` now
introduces UB.



More information about the llvm-dev mailing list