Clang devirtualization proposal

From: "Chandler Carruth" <chandlerc@google.com>
To: "Hal Finkel" <hfinkel@anl.gov>, "Sanjoy Das" <sanjoy@playingwithpointers.com>
Cc: "cfe-dev@cs.uiuc.edu Developers" <cfe-dev@cs.uiuc.edu>, "LLVM Developers Mailing List" <llvmdev@cs.uiuc.edu>
Sent: Friday, August 7, 2015 5:52:04 PM
Subject: Re: [cfe-dev] [LLVMdev] Clang devirtualization proposal

> From: "Sanjoy Das" < sanjoy@playingwithpointers.com >
> To: "Reid Kleckner" < rnk@google.com >
> Cc: "Piotr Padlewski" < prazek@google.com >, " cfe-dev@cs.uiuc.edu
> Developers" < cfe-dev@cs.uiuc.edu >, "LLVM Developers
> Mailing List" < llvmdev@cs.uiuc.edu >
> Sent: Saturday, August 1, 2015 1:22:50 AM
> Subject: Re: [LLVMdev] [cfe-dev] Clang devirtualization proposal
>
> > Consider this pseudo-IR and some possible transforms that I would
> > expect to
> > be semantics preserving:
> >
> > void f(i32* readonly %a, i32* %b) {
> > llvm.assume(%a == %b)
> > store i32 42, i32* %b
> > }
> > ...
> > %p = alloca i32
> > store i32 13, i32* %p
> > call f(i32* readonly %p, i32* %p)
> > %r = load i32, i32* %p
> >
> > ; Propagate llvm.assume info
> > void f(i32* readonly %a, i32* %b) {
> > store i32 42, i32* %a
> > }
> > ...
> > %p = alloca i32
> > store i32 13, i32* %p
> > call f(i32* readonly %p, i32* %p)
> > %r = load i32, i32* %p
>
> I'd say this first transformation is incorrect. `readonly` is
> effectively part of `%a`'s "type" as it constrains and affects the
> operations you can do on `%a`. Even if `%b` is bitwise equivalent
> to
> `%a` at runtime, it is "type incompatible" to replace `%a` with
> `%b`.
>
> This is similar to how you cannot replace `store i32 42, i32
> addrspace(1)* %a` with `store i32 42, i32 addrspace(2)* %b`, even
> if
> you can prove `ptrtoint %a` == `ptrtoint %b` -- the nature of
> `store`
> is dependent on the type of the pointer you store through.
>
> The glitch in LLVM IR right now is that the `readonly`ness of `%a`
> is
> not modeled in the type system, when I think it should be. An `i32
> readonly*` should be a different type from `i32*`. In practice this
> may be non-trivial to get right (for instance `phi`s and `selects`
> will either have to do a type merge, or we'd have to have explicit
> type operators at the IR level).

We could do this, but then we'd need to promote these things to
first-class parts of the type system (and I'd need to put further
thought about how this interacts with dynamically-true properties at
callsites and inlining).

The alternative way of looking at it, which is true today, is that
@llvm.assume is not removed even when its information is 'used'. It
appears, given this example, that this is actually required for
correctness, and that dead-argument elimination needs to
specifically not ignore effectively-ephemeral values/arguments.

What follows is an off-the-cuff response. I'm still thinking through
it, but wanted to let others do so as well.

There is yet another interpretation that we might use: the final
transformation Reid proposed is actually correct and allowed
according to the IR.

Specifically, we could make 'readonly' a property of the memory much
like aliasing is. That would mean that the function promises not to
modify the memory pointed to by %a in this example. The optimizer
gets to ignore any such modifications while remaining correct.

We could certainly do this, but it will obviously make inference harder. That might not be a good thing.

As I said earlier, the original problem highlighted by Reid's example cannot currently occur: that could only happen if you remove the @llvm.assume call (thus making the other argument unused). We already don't do this (because the assumes could be useful if later inlined), and now we have a second reason. Regardless, because we don't actively remove @llvm.assume, I'm not convinced the current state of things is currently broken.

-Hal

> From: "Chandler Carruth" <chandlerc@google.com>
> To: "Hal Finkel" <hfinkel@anl.gov>, "Sanjoy Das" <
sanjoy@playingwithpointers.com>
> Cc: "cfe-dev@cs.uiuc.edu Developers" <cfe-dev@cs.uiuc.edu>, "LLVM
Developers Mailing List" <llvmdev@cs.uiuc.edu>
> Sent: Friday, August 7, 2015 5:52:04 PM
> Subject: Re: [cfe-dev] [LLVMdev] Clang devirtualization proposal
>
>
> > From: "Sanjoy Das" < sanjoy@playingwithpointers.com >
> > To: "Reid Kleckner" < rnk@google.com >
> > Cc: "Piotr Padlewski" < prazek@google.com >, " cfe-dev@cs.uiuc.edu
> > Developers" < cfe-dev@cs.uiuc.edu >, "LLVM Developers
> > Mailing List" < llvmdev@cs.uiuc.edu >
> > Sent: Saturday, August 1, 2015 1:22:50 AM
> > Subject: Re: [LLVMdev] [cfe-dev] Clang devirtualization proposal
> >
> > > Consider this pseudo-IR and some possible transforms that I would
> > > expect to
> > > be semantics preserving:
> > >
> > > void f(i32* readonly %a, i32* %b) {
> > > llvm.assume(%a == %b)
> > > store i32 42, i32* %b
> > > }
> > > ...
> > > %p = alloca i32
> > > store i32 13, i32* %p
> > > call f(i32* readonly %p, i32* %p)
> > > %r = load i32, i32* %p
> > >
> > > ; Propagate llvm.assume info
> > > void f(i32* readonly %a, i32* %b) {
> > > store i32 42, i32* %a
> > > }
> > > ...
> > > %p = alloca i32
> > > store i32 13, i32* %p
> > > call f(i32* readonly %p, i32* %p)
> > > %r = load i32, i32* %p
> >
> > I'd say this first transformation is incorrect. `readonly` is
> > effectively part of `%a`'s "type" as it constrains and affects the
> > operations you can do on `%a`. Even if `%b` is bitwise equivalent
> > to
> > `%a` at runtime, it is "type incompatible" to replace `%a` with
> > `%b`.
> >
> > This is similar to how you cannot replace `store i32 42, i32
> > addrspace(1)* %a` with `store i32 42, i32 addrspace(2)* %b`, even
> > if
> > you can prove `ptrtoint %a` == `ptrtoint %b` -- the nature of
> > `store`
> > is dependent on the type of the pointer you store through.
> >
> > The glitch in LLVM IR right now is that the `readonly`ness of `%a`
> > is
> > not modeled in the type system, when I think it should be. An `i32
> > readonly*` should be a different type from `i32*`. In practice this
> > may be non-trivial to get right (for instance `phi`s and `selects`
> > will either have to do a type merge, or we'd have to have explicit
> > type operators at the IR level).
>
> We could do this, but then we'd need to promote these things to
> first-class parts of the type system (and I'd need to put further
> thought about how this interacts with dynamically-true properties at
> callsites and inlining).
>
> The alternative way of looking at it, which is true today, is that
> @llvm.assume is not removed even when its information is 'used'. It
> appears, given this example, that this is actually required for
> correctness, and that dead-argument elimination needs to
> specifically not ignore effectively-ephemeral values/arguments.
>
> What follows is an off-the-cuff response. I'm still thinking through
> it, but wanted to let others do so as well.
>
>
> There is yet another interpretation that we might use: the final
> transformation Reid proposed is actually correct and allowed
> according to the IR.
>
>
> Specifically, we could make 'readonly' a property of the memory much
> like aliasing is. That would mean that the function promises not to
> modify the memory pointed to by %a in this example. The optimizer
> gets to ignore any such modifications while remaining correct.

We could certainly do this, but it will obviously make inference harder.
That might not be a good thing.

As I said earlier, the original problem highlighted by Reid's example
cannot currently occur: that could only happen if you remove the
@llvm.assume call (thus making the other argument unused). We already don't
do this (because the assumes could be useful if later inlined), and now we
have a second reason. Regardless, because we don't actively remove
@llvm.assume, I'm not convinced the current state of things is currently
broken.

Aren't analogs of his problem still possible? I'm picturing something along
the lines of an icmp-br pair which allows a transform to RAUW in the
BranchInst's 'true' successor.

From: “Chandler Carruth” <chandlerc@google.com>
To: “Hal Finkel” <hfinkel@anl.gov>, “Sanjoy Das” <sanjoy@playingwithpointers.com>
Cc: “cfe-dev@cs.uiuc.edu Developers” <cfe-dev@cs.uiuc.edu>, “LLVM Developers Mailing List” <llvmdev@cs.uiuc.edu>
Sent: Friday, August 7, 2015 5:52:04 PM
Subject: Re: [cfe-dev] [LLVMdev] Clang devirtualization proposal

From: “Sanjoy Das” < sanjoy@playingwithpointers.com >
To: “Reid Kleckner” < rnk@google.com >
Cc: “Piotr Padlewski” < prazek@google.com >, " cfe-dev@cs.uiuc.edu
Developers" < cfe-dev@cs.uiuc.edu >, “LLVM Developers
Mailing List” < llvmdev@cs.uiuc.edu >
Sent: Saturday, August 1, 2015 1:22:50 AM
Subject: Re: [LLVMdev] [cfe-dev] Clang devirtualization proposal

Consider this pseudo-IR and some possible transforms that I would
expect to
be semantics preserving:

void f(i32* readonly %a, i32* %b) {
llvm.assume(%a == %b)
store i32 42, i32* %b
}

%p = alloca i32
store i32 13, i32* %p
call f(i32* readonly %p, i32* %p)
%r = load i32, i32* %p

; Propagate llvm.assume info
void f(i32* readonly %a, i32* %b) {
store i32 42, i32* %a
}

%p = alloca i32
store i32 13, i32* %p
call f(i32* readonly %p, i32* %p)
%r = load i32, i32* %p

I’d say this first transformation is incorrect. readonly is
effectively part of %a’s “type” as it constrains and affects the
operations you can do on %a. Even if %b is bitwise equivalent
to
%a at runtime, it is “type incompatible” to replace %a with
%b.

This is similar to how you cannot replace store i32 42, i32 addrspace(1)* %a with store i32 42, i32 addrspace(2)* %b, even
if
you can prove ptrtoint %a == ptrtoint %b – the nature of
store
is dependent on the type of the pointer you store through.

The glitch in LLVM IR right now is that the readonlyness of %a
is
not modeled in the type system, when I think it should be. An i32 readonly* should be a different type from i32*. In practice this
may be non-trivial to get right (for instance phis and selects
will either have to do a type merge, or we’d have to have explicit
type operators at the IR level).

We could do this, but then we’d need to promote these things to
first-class parts of the type system (and I’d need to put further
thought about how this interacts with dynamically-true properties at
callsites and inlining).

The alternative way of looking at it, which is true today, is that
@llvm.assume is not removed even when its information is ‘used’. It
appears, given this example, that this is actually required for
correctness, and that dead-argument elimination needs to
specifically not ignore effectively-ephemeral values/arguments.

What follows is an off-the-cuff response. I’m still thinking through
it, but wanted to let others do so as well.

There is yet another interpretation that we might use: the final
transformation Reid proposed is actually correct and allowed
according to the IR.

Specifically, we could make ‘readonly’ a property of the memory much
like aliasing is. That would mean that the function promises not to
modify the memory pointed to by %a in this example. The optimizer
gets to ignore any such modifications while remaining correct.

We could certainly do this, but it will obviously make inference harder. That might not be a good thing.

The other approach that seems reasonable is to push this to the caller to make inference in the callee easier. In that scenario, you would say that the readonly tells the caller that the memory location represented by the argument is not written through that argument but might be written through some other argument. Since the caller passes two pointers which alias, it cannot forward the store.

The problem I see is that if the transformation in the body of the callee does CSE of any form, it allows dead argument elimination to remove this non-readonly potentially-aliasing argument.

So if we want to go this route, I think we need to at least block dead argument elimination from removing a potentially writable aliasing argument even if it is unused in the function body, because it might be modeling a writable way for a particular memory location to enter the function.

All in all, I would prefer the stronger guarantee of the readonly attribute (that the memory location is unchanged, regardless of through which pointer it is accessed).

As I said earlier, the original problem highlighted by Reid’s example cannot currently occur: that could only happen if you remove the @llvm.assume call (thus making the other argument unused). We already don’t do this (because the assumes could be useful if later inlined), and now we have a second reason. Regardless, because we don’t actively remove @llvm.assume, I’m not convinced the current state of things is currently broken.

As others have said, anything which triggers CSE seems problematic here.

From: "David Majnemer" <david.majnemer@gmail.com>
To: "Hal Finkel" <hfinkel@anl.gov>
Cc: "Chandler Carruth" <chandlerc@google.com>, "llvm-dev" <llvm-dev@lists.llvm.org>, "Sanjoy Das"
<sanjoy@playingwithpointers.com>, cfe-dev@lists.llvm.org
Sent: Friday, August 7, 2015 7:32:16 PM
Subject: Re: [cfe-dev] [LLVMdev] Clang devirtualization proposal

> From: "Chandler Carruth" < chandlerc@google.com >
> To: "Hal Finkel" < hfinkel@anl.gov >, "Sanjoy Das" <
> sanjoy@playingwithpointers.com >
> Cc: " cfe-dev@cs.uiuc.edu Developers" < cfe-dev@cs.uiuc.edu >,
> "LLVM Developers Mailing List" < llvmdev@cs.uiuc.edu >
> Sent: Friday, August 7, 2015 5:52:04 PM
> Subject: Re: [cfe-dev] [LLVMdev] Clang devirtualization proposal
>

>
> > From: "Sanjoy Das" < sanjoy@playingwithpointers.com >
> > To: "Reid Kleckner" < rnk@google.com >
> > Cc: "Piotr Padlewski" < prazek@google.com >, "
> > cfe-dev@cs.uiuc.edu
> > Developers" < cfe-dev@cs.uiuc.edu >, "LLVM Developers
> > Mailing List" < llvmdev@cs.uiuc.edu >
> > Sent: Saturday, August 1, 2015 1:22:50 AM
> > Subject: Re: [LLVMdev] [cfe-dev] Clang devirtualization proposal
> >
> > > Consider this pseudo-IR and some possible transforms that I
> > > would
> > > expect to
> > > be semantics preserving:
> > >
> > > void f(i32* readonly %a, i32* %b) {
> > > llvm.assume(%a == %b)
> > > store i32 42, i32* %b
> > > }
> > > ...
> > > %p = alloca i32
> > > store i32 13, i32* %p
> > > call f(i32* readonly %p, i32* %p)
> > > %r = load i32, i32* %p
> > >
> > > ; Propagate llvm.assume info
> > > void f(i32* readonly %a, i32* %b) {
> > > store i32 42, i32* %a
> > > }
> > > ...
> > > %p = alloca i32
> > > store i32 13, i32* %p
> > > call f(i32* readonly %p, i32* %p)
> > > %r = load i32, i32* %p
> >
> > I'd say this first transformation is incorrect. `readonly` is
> > effectively part of `%a`'s "type" as it constrains and affects
> > the
> > operations you can do on `%a`. Even if `%b` is bitwise equivalent
> > to
> > `%a` at runtime, it is "type incompatible" to replace `%a` with
> > `%b`.
> >
> > This is similar to how you cannot replace `store i32 42, i32
> > addrspace(1)* %a` with `store i32 42, i32 addrspace(2)* %b`, even
> > if
> > you can prove `ptrtoint %a` == `ptrtoint %b` -- the nature of
> > `store`
> > is dependent on the type of the pointer you store through.
> >
> > The glitch in LLVM IR right now is that the `readonly`ness of
> > `%a`
> > is
> > not modeled in the type system, when I think it should be. An
> > `i32
> > readonly*` should be a different type from `i32*`. In practice
> > this
> > may be non-trivial to get right (for instance `phi`s and
> > `selects`
> > will either have to do a type merge, or we'd have to have
> > explicit
> > type operators at the IR level).
>
> We could do this, but then we'd need to promote these things to
> first-class parts of the type system (and I'd need to put further
> thought about how this interacts with dynamically-true properties
> at
> callsites and inlining).
>
> The alternative way of looking at it, which is true today, is that
> @llvm.assume is not removed even when its information is 'used'. It
> appears, given this example, that this is actually required for
> correctness, and that dead-argument elimination needs to
> specifically not ignore effectively-ephemeral values/arguments.
>
> What follows is an off-the-cuff response. I'm still thinking
> through
> it, but wanted to let others do so as well.
>
>
> There is yet another interpretation that we might use: the final
> transformation Reid proposed is actually correct and allowed
> according to the IR.
>
>
> Specifically, we could make 'readonly' a property of the memory
> much
> like aliasing is. That would mean that the function promises not to
> modify the memory pointed to by %a in this example. The optimizer
> gets to ignore any such modifications while remaining correct.

We could certainly do this, but it will obviously make inference
harder. That might not be a good thing.

As I said earlier, the original problem highlighted by Reid's example
cannot currently occur: that could only happen if you remove the
@llvm.assume call (thus making the other argument unused). We
already don't do this (because the assumes could be useful if later
inlined), and now we have a second reason. Regardless, because we
don't actively remove @llvm.assume, I'm not convinced the current
state of things is currently broken.

Aren't analogs of his problem still possible? I'm picturing something
along the lines of an icmp-br pair which allows a transform to RAUW
in the BranchInst's 'true' successor.

You can certainly have this:

if (a == b) {
  *b = 5;
}

and transform this into:

if (a == b) {
  *a = 5;
}

but that does not completely remove b, and so the dead-argument removal could not kick in.

-Hal

From: "Chandler Carruth" <chandlerc@google.com>
To: "Hal Finkel" <hfinkel@anl.gov>
Cc: "Sanjoy Das" <sanjoy@playingwithpointers.com>, "llvm-dev"
<llvm-dev@lists.llvm.org>, cfe-dev@lists.llvm.org
Sent: Friday, August 7, 2015 7:35:57 PM
Subject: Re: [cfe-dev] [LLVMdev] Clang devirtualization proposal

> > From: "Chandler Carruth" < chandlerc@google.com >

> > To: "Hal Finkel" < hfinkel@anl.gov >, "Sanjoy Das" <
> > sanjoy@playingwithpointers.com >

> > Cc: " cfe-dev@cs.uiuc.edu Developers" < cfe-dev@cs.uiuc.edu >,
> > "LLVM Developers Mailing List" < llvmdev@cs.uiuc.edu >

> > Sent: Friday, August 7, 2015 5:52:04 PM

> > Subject: Re: [cfe-dev] [LLVMdev] Clang devirtualization proposal

> >

> >

> > > From: "Sanjoy Das" < sanjoy@playingwithpointers.com >

> > > To: "Reid Kleckner" < rnk@google.com >

> > > Cc: "Piotr Padlewski" < prazek@google.com >, "
> > > cfe-dev@cs.uiuc.edu

> > > Developers" < cfe-dev@cs.uiuc.edu >, "LLVM Developers

> > > Mailing List" < llvmdev@cs.uiuc.edu >

> > > Sent: Saturday, August 1, 2015 1:22:50 AM

> > > Subject: Re: [LLVMdev] [cfe-dev] Clang devirtualization
> > > proposal

> > >

> > > > Consider this pseudo-IR and some possible transforms that I
> > > > would

> > > > expect to

> > > > be semantics preserving:

> > > >

> > > > void f(i32* readonly %a, i32* %b) {

> > > > llvm.assume(%a == %b)

> > > > store i32 42, i32* %b

> > > > }

> > > > ...

> > > > %p = alloca i32

> > > > store i32 13, i32* %p

> > > > call f(i32* readonly %p, i32* %p)

> > > > %r = load i32, i32* %p

> > > >

> > > > ; Propagate llvm.assume info

> > > > void f(i32* readonly %a, i32* %b) {

> > > > store i32 42, i32* %a

> > > > }

> > > > ...

> > > > %p = alloca i32

> > > > store i32 13, i32* %p

> > > > call f(i32* readonly %p, i32* %p)

> > > > %r = load i32, i32* %p

> > >

> > > I'd say this first transformation is incorrect. `readonly` is

> > > effectively part of `%a`'s "type" as it constrains and affects
> > > the

> > > operations you can do on `%a`. Even if `%b` is bitwise
> > > equivalent

> > > to

> > > `%a` at runtime, it is "type incompatible" to replace `%a` with

> > > `%b`.

> > >

> > > This is similar to how you cannot replace `store i32 42, i32

> > > addrspace(1)* %a` with `store i32 42, i32 addrspace(2)* %b`,
> > > even

> > > if

> > > you can prove `ptrtoint %a` == `ptrtoint %b` -- the nature of

> > > `store`

> > > is dependent on the type of the pointer you store through.

> > >

> > > The glitch in LLVM IR right now is that the `readonly`ness of
> > > `%a`

> > > is

> > > not modeled in the type system, when I think it should be. An
> > > `i32

> > > readonly*` should be a different type from `i32*`. In practice
> > > this

> > > may be non-trivial to get right (for instance `phi`s and
> > > `selects`

> > > will either have to do a type merge, or we'd have to have
> > > explicit

> > > type operators at the IR level).

> >

> > We could do this, but then we'd need to promote these things to

> > first-class parts of the type system (and I'd need to put further

> > thought about how this interacts with dynamically-true properties
> > at

> > callsites and inlining).

> >

> > The alternative way of looking at it, which is true today, is
> > that

> > @llvm.assume is not removed even when its information is 'used'.
> > It

> > appears, given this example, that this is actually required for

> > correctness, and that dead-argument elimination needs to

> > specifically not ignore effectively-ephemeral values/arguments.

> >

> > What follows is an off-the-cuff response. I'm still thinking
> > through

> > it, but wanted to let others do so as well.

> >

> >

> > There is yet another interpretation that we might use: the final

> > transformation Reid proposed is actually correct and allowed

> > according to the IR.

> >

> >

> > Specifically, we could make 'readonly' a property of the memory
> > much

> > like aliasing is. That would mean that the function promises not
> > to

> > modify the memory pointed to by %a in this example. The optimizer

> > gets to ignore any such modifications while remaining correct.

> We could certainly do this, but it will obviously make inference
> harder. That might not be a good thing.

The other approach that seems reasonable is to push this to the
caller to make inference in the callee easier. In that scenario, you
would say that the readonly tells the caller that the memory
location represented by the argument is not written *through that
argument* but might be written through some other argument. Since
the caller passes two pointers which alias, it cannot forward the
store.

Isn't that what happens today?

The problem I see is that if the transformation in the body of the
callee does CSE of any form, it allows dead argument elimination to
remove this non-readonly potentially-aliasing argument.

Right, that seems to be the problem.

So if we want to go this route, I think we need to at least block
dead argument elimination from removing a potentially writable
aliasing argument even if it is unused in the function body, because
it might be modeling a writable way for a particular memory location
to enter the function.

All in all, I would prefer the stronger guarantee of the readonly
attribute (that the memory location is unchanged, regardless of
through which pointer it is accessed).

Perhaps this is indeed the only strategy that is completely self-consistent. I don't object to pursuring this.

> As I said earlier, the original problem highlighted by Reid's
> example
> cannot currently occur: that could only happen if you remove the
> @llvm.assume call (thus making the other argument unused). We
> already don't do this (because the assumes could be useful if later
> inlined), and now we have a second reason. Regardless, because we
> don't actively remove @llvm.assume, I'm not convinced the current
> state of things is currently broken.

As others have said, *anything* which triggers CSE seems problematic
here.

Fair enough. To record the example you provided to me on IRC here:

chandlerc: we start with 'if (a == b) { *b = 42; } else { x(); }'
chandlerc: then CSE to 'if (a == b) { *a = 42; } else { x(); }'
chandlerc: then inline to 'if (a == b) { *a = 42; } else { unreachable; }'
chandlerc: then fold to 'if (true) { *a = 42; }'
chandlerc: b is now dead
chandlerc: x was marked as 'readnone'
chandlerc: and contained unreachable

-Hal

Summing up, it seems there are three choices here that are all reasonably defensible:

  1. We can change how CSE works such that equality is not sufficient for substitutability.
  2. We can change the requirements of ‘readonly’ (and related) parameter attribute to be that the memory location is not modified by the function.
  3. We can change argument elimination to not eliminate dead arguments which might change the set of memory locations which can be read or written by the function.

The only one of these I see as completely infeasible is #1.

For #3, this is at odds with how I understand dereferencable works, and it seems like these should work the same way and dereferencable had particularly good reasons to need to work the way it does.

For #2, it really does make inference significantly more tricky. Here is an example of the new challenges: if the caller has already escaped a pointer to the memory location (which we must assume it has) then any function which might write to memory must be assumed to write to the memory aliased by the passed in pointer.

Also for #2, we should probably finish converging with dereferencable and have a size attached. This will become especially important with type-less pointers.

I suspect #2 is the right design, mostly because I suspect most of the interesting and important inference cases are going to be cases where we can easily infer the stronger guarantee, and once inferred we will have much more freedom to optimize based on this stronger guarantee… But I can’t say I’m completely confident in this model yet.

-Chandler

I suspect #2 is the right design, mostly because I suspect most of the interesting and important inference cases are going to be cases where we can easily infer the stronger guarantee, and once inferred we will have much more freedom to optimize based on this stronger guarantee...

Can't the stronger guarantee be represented in the existing system by either:

* Adding 'readonly' to all the aliasing pointer arguments.
* Adding 'noalias' to the pointer argument (if there aren't any
aliasing pointer arguments).

The proposal sounds interesting but it seems like it would prevent
languages with strong versions of 'const' (or similar) from marking
pointers as 'readonly', which might be a useful parameter attribute
for APIs (i.e. function declarations where inference isn't possible).

I may not have followed the discussion completely, but would it be
possible to simply strip the 'readonly' attributes when dead arguments
are eliminated?

I think this actually works. Think of it this way: the result of
functionattrs is actually an analysis that we cache and maintain in the IR.
DAE invalidates that analysis, so it must flush the cache or repopulate it.

Hi all,
I am finishing my internship today and I want to make small report:

  1. available_externally vtables are now generated for classes without inline / hidden virtual functions
  2. Assumption loads are generated for the same case as above (temporary works only with -fstrict-vtable-pointers because of some performance lose in InstCombine)
  3. Using invariant.group metadata, vtable loads and vfunction loads are now squashed to one load across one BB.

If someone would like to contact me, piotr.padlewski@gmail.com is my personal email (I won’t have access to prazek@google.com)

Piotr Padlewski

Thanks for sharing your progress and all the work along the way.

Is there a bug filed for this?