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

improve effect_free to fix regressions from #20726 #20843

Merged
merged 1 commit into from
Mar 7, 2017
Merged

Conversation

JeffBezanson
Copy link
Member

No description provided.

@JeffBezanson
Copy link
Member Author

@nanosoldier runbenchmarks(ALL, vs = ":master")

# fall-through
else
return false
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't you write this as

if !isa(ft, Const) || !contains_is(_pure_builtins, ft.val)
    return false
end

or am I missing something?

@@ -3405,13 +3408,20 @@ function effect_free(e::ANY, src::CodeInfo, mod::Module, allow_volatile::Bool)
# first argument must be immutable to ensure e is affect_free
a = ea[2]
typ = widenconst(exprtype(a, src, mod))
if !isa(typ, DataType) || typ.mutable || typ.abstract
if !isa(typ, DataType) || typ.mutable || (typ.abstract && !isconstType(typ))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some of the fields of DataType aren't affect_free (uid isn't constant)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for code to actually observe that change though? I have trouble believing this is a real issue.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Precompile could. But I have trouble believing we should add that bug. Can you actually observe the benefit of this change for well-written code?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is needed here; the code in question does something like Tuple{...}.types. Would it be sufficient just to exclude anything that might access uid?

elseif is_known_call(e, _apply, src, mod) && length(ea) > 1
ft = exprtype(ea[2], src, mod)
if isa(ft, Const) && contains_is(_pure_builtins, ft.val)
# fall-through
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to duplicate the rest of the logic from :call here (well, DRY it in a helper function probably)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's why I only allowed _pure_builtins; looking into apply's arguments is difficult.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's why I only allowed _pure_builtins

ah, right. So this won't handle return_type either, but is still needed for this PR?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Nothing here was splatting into return_type itself (the code is _return_type(f, eltypestuple(A, Bs...))), but in theory that could need to be added.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's marked @pure though; that should already express that it can be considered effect-free. Couldn't we just ccall arg_type_tuple (or write a proper O(n) Julia function) instead of this crazy O(n^2 * log(n)) implementation though?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are cases of splatting args to a @pure function where we do not end up calling pure_eval_call. That could be fixed as well.

Copy link
Member

@vtjnash vtjnash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 3400 has an isa test. That's from an old bug where we were passing in the wrong sv object. I think that's fixed now that we're passing in the right src object. Is that not true somewhere?
(https://github.com/JuliaLang/julia/pull/20843/files#diff-c0d983631c937ee5acfd0137cd7332deR3400)

@@ -3405,13 +3408,20 @@ function effect_free(e::ANY, src::CodeInfo, mod::Module, allow_volatile::Bool)
# first argument must be immutable to ensure e is affect_free
a = ea[2]
typ = widenconst(exprtype(a, src, mod))
if !isa(typ, DataType) || typ.mutable || typ.abstract
if !isa(typ, DataType) || typ.mutable || (typ.abstract && !isconstType(typ))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Precompile could. But I have trouble believing we should add that bug. Can you actually observe the benefit of this change for well-written code?

elseif is_known_call(e, _apply, src, mod) && length(ea) > 1
ft = exprtype(ea[2], src, mod)
if isa(ft, Const) && contains_is(_pure_builtins, ft.val)
# fall-through
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's why I only allowed _pure_builtins

ah, right. So this won't handle return_type either, but is still needed for this PR?

@JeffBezanson
Copy link
Member Author

Yes, I believe all effect_free calls now pass the right argument.

@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @jrevels

@vchuravy
Copy link
Member

vchuravy commented Mar 1, 2017

Let's do this again for the most recent changes @nanosoldier runbenchmarks(ALL, vs = ":master")

@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @jrevels

@JeffBezanson
Copy link
Member Author

So, what do we make of those results? I'm not sure what to conclude.

@Keno
Copy link
Member

Keno commented Mar 1, 2017

I'd rebase the branch and run it again.

@JeffBezanson
Copy link
Member Author

@nanosoldier runbenchmarks(ALL, vs = ":master")

@nanosoldier
Copy link
Collaborator

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @jrevels

@tkelman
Copy link
Contributor

tkelman commented Mar 2, 2017

where's travis here? attempting to re trigger it

@tkelman tkelman closed this Mar 2, 2017
@tkelman tkelman reopened this Mar 2, 2017
@JeffBezanson
Copy link
Member Author

Should we merge this? It does seem to fix the vector arithmetic issue. The code for Complex{Int64} looks unchanged vs. master.

et = exprtype(e, src, mod)
if !isa(et,Const) && !(isType(et) && isleaftype(et))
# first argument must be immutable to ensure e is affect_free
a = ea[2]
typ = widenconst(exprtype(a, src, mod))
if !isa(typ, DataType) || typ.mutable || typ.abstract
if isconstType(typ)
if Const(:uid) ⊑ exprtype(ea[3], src, mod)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's quite optimistic :P

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as in incorrect? can't tell if this is an objection to the change or not

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it's blacklist of one bad case but doesn't actually handle the general case

although it's possible we should just be more nuanced here. the uid field is probably the only observable value that can change, and it only can change when loading pre-compiled code – so we really only need to be concerned about constant folding it during then. for all other purposes, it's effect-free.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For constant folding, getfield_tfunc uses a whitelist of DataType fields (name, parameters, types, super), so I don't think there's any risk of constant folding the value of type.uid.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so I guess this effect-free test is basically equivalent to tbaa_const, for all current usages? (which all fields of DataType should be)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that sounds right.

@JeffBezanson JeffBezanson merged commit 2e12d10 into master Mar 7, 2017
@ararslan ararslan deleted the jb/fix20726 branch March 7, 2017 03:37
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.

8 participants