Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Also change lowering of getproperty #37289

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Conversation

Keno
Copy link
Member

@Keno Keno commented Aug 30, 2020

So after thinking about #37268, I was wondering what would happen
if one applied the same trick to the lowering of getproperty
as well. This PR starts at that, but is mostly a placeholder for
discussion of whether this is something we want to do. In particular,
this PR lowers a.b to:

getproperty(a)(a, :b)

with a default implementation of

getproperty(a) = getfield

The inference benefit is as expected. Timing end-to-end inference&optimize
time of:

struct Foo; end
f(a::Foo) = a.x

shows that time to infer f drops by about a third (because it doesn't need to
infer getproperty twice). Overall build time of the system image drops
by 6% for me.

If we do decide to go this way, things that would still need to be fixed:

  • Do the same for setproperty!
  • ccall doesn't like this lowering. Didn't look into it too closely
  • Needs a fallback to backwards compatibility. I'm thinking something
    along the lines of
getproperty(x) = hasmethod(getproperty, Tuple{typeof(x), Symbol}) ? getproperty : getfield

but obviously it would need inference integration to be fast.

Keno added 2 commits August 30, 2020 15:59
In expressions like `Foo.Bar.f() = 1`, we would lower this as

`Expr(:method, Expr(:call, :getproperty, Expr(:call, :getproperty, :Foo, :Bar), :f) ...)`

where args[1] is supposed to be the name of the method. However, if
this is not a symbol, the name is actually ignored and the method
is required to exist already (i.e. `function foo(); end` is allowed
to introduce a new method if `foo` doesn't exist, but `function Main.foo(); end`
is not). It doesn't do much harm currently other than being a bit ugly.
However, I was trying to do some experiments with getproperty lowering
that made the lowering a bit more complicated, which made the frontend
unhappy, because there were now more complicated expressions in there
(the fact that it works for call is a bit of an accident). Since there
is no good reason to keep it and I did the work to drop it anyway,
for my experimenting, let's just drop this unused expr arg entirely
and replace it by nothing if it's not supposed to be used.
So after thinking about #37268, I was wondering what would happen
if one applied the same trick to the lowering of `getproperty`
as well. This PR starts at that, but is mostly a placeholder for
discussion of whether this is something we want to do. In particular,
this PR lowers `a.b` to:

```
getproperty(a)(a, :b)
```

with a default implementation of

```
getproperty(a) = getfield
```

The inference benefit is as expected. Timing end-to-end inference&optimize
time of:

```
struct Foo; end
f(a::Foo) = a.x
```

shows that time to infer `f` drops by about a third (because it doesn't need to
infer getproperty twice). Overall build time of the system image drops
by 6% for me.

If we do decide to go this way, things that would still need to be fixed:

- [] Do the same for `setproperty!`
- [] `ccall` doesn't like this lowering. Didn't look into it too closely
- [] Needs a fallback to backwards compatibility. I'm thinking something
along the lines of

```
getproperty(x) = hasmethod(getproperty, Tuple{typeof(x), Symbol}) ? getproperty : getfield
```

but obviously it would need inference integration to be fast.
@Keno
Copy link
Member Author

Keno commented Sep 2, 2020

In discussion with @JeffBezanson and @vtjnash we decided this was at least a worthwhile direction to explore, so we'll get this PR in shape. @JeffBezanson wanted to look at the ccall lowering issue and then I can finish this up.

@vtjnash
Copy link
Member

vtjnash commented Apr 21, 2021

We had a similar discussion for dotgetfield, and felt this might not be useful. Do we still want to pursue this? That performance improvement is substantial (and I could see this might affect current work to add atomics).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants