[cfe-dev] [LLVMdev] Clang devirtualization proposal

Sanjoy Das sanjoy at playingwithpointers.com
Mon Aug 3 00:24:41 PDT 2015


On Sat, Aug 1, 2015 at 2:05 PM, Sanjoy Das
<sanjoy at playingwithpointers.com> wrote:
>> The trouble is that we want to express ideas like "at this call site, but
>> not others, I know that this call will not mutate state through this
>> pointer". We can't express that with the llvm type system we have today.
>
> Yes; to do that we'll effectively have to introduce some form of
> quantification.
>
> IOW: we'd have to have 4x the number of pointer types we have today --
> each pointer type should be quantifiable with `noaccess`, `read`,
> `write` and `readwrite` (the second one may not be very useful if we
> do not want to support memory with only `PROT_WRITE`).
>
> Functions and other consumers types would then have to be modified to
> allow universal (and other forms of?) quantification.  I should be able to
> write a function `@calc` of the type:

I'm not going to derail this thread further, except this one last mail
** (we can talk off list or on another thread if this looks
interesting to you): what I said about quantification won't work
directly -- we'll have problems with pointer comparison for starters.
For instance, if we have a function of type

forall $domain in { noaccess, read, write, readwrite }, forall
$domain2 in { noaccess, read, write, readwrite }: (i8* $domain, i8*
$domain2) -> i32

that wants to compare its first two arguments, then such a comparison
will be well typed only if both $domain and $domain2 are same.  In
other words, only 4 out of the sixteen possible instantiations will be
well typed, so the quantification is not really forall but something
else.

But I don't see any direct, incremental way to make the current
function argument "readonly" consistent.  Semantically, we'd like to
say that programs that store through readonly *SSA values* are
undefined, but unless we track some extra information at runtime,
there is no way to tell if a store to a location happened through
readonly SSA value, or through a normal, read-write SSA value that
happened to evaluate to something that a readonly SSA value also
evaluates to.

For instance, here is another example that's problematic:

define void @f(i8* readonly %ro) {
 i8* %rw = some_computation()
 %ptr = select condition, %ro, %rw;

  ;; work

  *(%ptr) = 42
}

There is no way to know if the store has UB or not without keeping
track of condition till the store.  If the select was instead was
br-phi then we'd have to manufacture a value to keep track what %ptr
is.  Note that %rw can be == %ro, so you cannot just inspecting the
value of %ptr is not enough.

In fact, with readonly, I think mem2reg is also problematic:

define void @f(i8* readonly %ro) {
 %t = alloca
 store %ro to %t

 %ptr = load %t
  store 24 to %ptr
}

The store does not happen through the pointer argument, so the above
program is well defined.  But it becomes undefined after mem2reg
(unless it has special handling for this situation).

** it always is "one last mail" :)

-- Sanjoy



More information about the cfe-dev mailing list