Avoiding removal of a builtin call

Hi Reid, Rafael,

I'm having trouble keeping the call to @llvm.write_register() in the
IR on higher levels of optimization.

At O0:

define void @set_stack_pointer_addr(i64 %addr) #0 {
entry:
  %addr.addr = alloca i64, align 8
  store i64 %addr, i64* %addr.addr, align 8
  %0 = load i64* %addr.addr, align 8
  call void @llvm.write_register.i64(metadata !0, i64 %0)
  ret void
}

At O1:

define void @set_stack_pointer_addr(i64 %addr) #0 {
entry:
  ret void
}

I tried marking the function (or the call) with "builtin" attribute,
but the validation fails:

Attribute 'builtin' only applies to functions!
void (metadata, i64)* @llvm.write_register.i64
Attribute 'builtin' only applies to functions!
call builtin void @llvm.write_register.i64(metadata !0, i64 %0)

Is there a way to avoid that call from being removed without marking
the symbol as extern or other tricks?

cheers,
--renato

The problem I think is that llvm.write_register.i64 is being marked
readnone. We don't have physical registers as first class items in
llvm, so as a small hack we probably need to have doesNotAccessMemory
return false for llvm.write_register (i.e., don't add ReadNone to it).

In particular, the attached patch seems to work.

t.patch (758 Bytes)

Hi Rafael,

Thanks for the reply. Ok, that was me just being conservative, since
it doesn't *really* access memory. But I take your point about not
having registers as first class citizens.

I'll add it to the other issue I found while testing
(http://reviews.llvm.org/D3847).

cheers,
--renato

Hi Rafael,

Thanks for the reply. Ok, that was me just being conservative, since
it doesn't *really* access memory. But I take your point about not
having registers as first class citizens.

Yes, we use memory to mean "global state", which is a bit confusing.

Cheers,
Rafael

More generally, we don't have a way to model non-memory side effects. Having such a mechanism might be useful to avoid polluting alias results for such builtins.

We have a similar case out of tree which we ended up solving by converting a void function to a value returning function and then (volatile) storing the result to a known location. This feels like somewhat of a hack, but does have the advantage of working and not preventing most aliasing based optimizations. :slight_smile:

Philip