[PATCH] D93039: Introduce llvm.noalias.decl intrinsic

Nikita Popov via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 10 12:09:03 PST 2020


nikic added a comment.

While the concept of the intrinsic is intuitive, I think we're missing something here in terms of how it is formalized. I have a bit of a hard time formulating the rules.

Let's consider this code:

  call @llvm.noalias.decl(!metadata !2)
  load i8, i8* %a, !alias.scope !2
  call @llvm.noalias.decl(!metadata !2)
  store i8 0, i8* %a, !noalias !2

Something along the lines you could get from a naive unrolling. Now, clean semantics would be to say that noalias.decl acts as a barrier, and !2 before noalias.decl and !2 after it refer to separate scopes. But we can't do that from a technical perspective.

So I guess instead, we say that the above code invoked undefined behavior.

However, is this undefined behavior as well?

    br i1 %c, label %if, label %else
  
  if:
    call @llvm.noalias.decl(!metadata !2)
    load i8, i8* %a, !alias.scope !2
    br label %end
  
  else:
    call @llvm.noalias.decl(!metadata !2)
    store i8 0, i8* %a, !noalias !2
    br label %end
  
  end:
    ret void
  }

I would say "no", this code is fine. So the rule would be:

> If an `@llvm.noalias.decl` intrinsic for a certain scope is dominated by another `@llvm.noalias.decl` intrinsic for the same scope, the behavior is undefined.

Loop unrolling etc then need to perform the renaming to avoid that UB.

Next, what about this code?

  load i8, i8* %a, !alias.scope !2 ; before noalias.decl
  call @llvm.noalias.decl(!metadata !2)
  store i8 0, i8* %a, !noalias !2
  
  // and this
  if:
    call @llvm.noalias.decl(!metadata !2)
    br label %end
  
  else:
    br label %end
  
  end:
    store i8 0, i8* %a, !noalias !2 ; after noalias.decl, but not dominated
    ret void

I would assume this is also UB:

> Any usage of a certain scope must be dominated by a `@llvm.noalias.decl` intrinsic for that scope, otherwise the behavior is undefined. As an exception, if there is no `@llvm.noalias.decl` call for a certain scope contained in the function, the behavior is as if such a call were located at the start of the function.

The exception here is a bit ugly. Without it existing IR would have to be auto-upgraded by inserting `@llvm.noalias.decl` for any scopes that are used.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D93039/new/

https://reviews.llvm.org/D93039



More information about the llvm-commits mailing list