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
Rebase of julia effects to LLVM #50188
base: master
Are you sure you want to change the base?
Conversation
We might be able to add readnone if we see we have no pointer arguments |
That might conflict with the pgcstack being passed as an argument. |
src/codegen.cpp
Outdated
attr.addAttribute("consistent"); | ||
} | ||
if (effect_free == 0) { | ||
attr.addAttribute("effect_free"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this not desirable to make readnone/only/write only where applicable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think we can add more things to the functions for sure.
src/codegen.cpp
Outdated
attr.addAttribute("noinbounds"); | ||
} | ||
if (is_decl && consistent == 0 && effect_free == 0 && nothrow == 1 && terminates == 1){ | ||
attr.addAttribute(Attribute::Speculatable); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You probably want to change these to be added at functionindex
It may be worthwhile considering if any attributes on params are also useful
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think they might be, but I'm not sure what information we can infer from here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also when creating the AttrList we pass the builder to the FnAttr
builder
src/codegen.cpp
Outdated
@@ -4204,7 +4256,13 @@ static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, bool is_opaque_clos | |||
TheCallee = ai.decorateInst(ctx.builder.CreateAlignedLoad(TheCallee->getType(), GV, Align(sizeof(void*)))); | |||
} | |||
CallInst *call = ctx.builder.CreateCall(cft, TheCallee, argvals); | |||
call->setAttributes(returninfo.attrs); | |||
|
|||
if (isa<Function>(TheCallee)){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make this a F=dyn_cast for ease?
I guess readnone is always wrong with or without the pgcstack arg, at least it's not a global anymore |
One thing that should be possible is that if we determine a function has the terminates effect we should just not insert a safepoint at entry. |
The issue with that is that if you have a for loop that calls the function a bunch of times you aren't ever hitting a safepoint. |
That's true, but if we've proven a function to terminate, its runtime is probably really small and the safepoint will probably take up a good fraction of its runtime, so it's likely that even a loop on a terminates function will itself exit quickly. |
But I think that's kind of the point, because we don't know termination for loops, only for the function itself, and it is what's guaranteeing that a GC may run. |
@nanosoldier |
Your package evaluation job has completed - possible new issues were detected. |
So digging into the the failure, it is reproducible. julia> CHUNK_TYPE = Dict(1=>"FileHeader")
Dict{Int64, String} with 1 entry:
1 => "FileHeader"
julia> foo(v) = [length(x) for x in values(v)]
foo (generic function with 1 method)
julia> foo(CHUNK_TYPE) is enough to reproduce. Interestingly, while debugging with Cthulhu, I trigger
|
So that might have been a red herring but doing @code_llvm raw=true dump_module=true foo(CHUNK_TYPE) shows that we codegen %32 = call swiftcc i64 @j_length_234({}*** nonnull swiftself %0, {} addrspace(10)* null), !dbg !134 which doesn't seem very correct. |
@nanosoldier |
@nanosoldier |
Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. |
Your package evaluation job has completed - possible new issues were detected. |
src/codegen.cpp
Outdated
@@ -4327,7 +4379,12 @@ static jl_cgval_t emit_call_specfun_other(jl_codectx_t &ctx, bool is_opaque_clos | |||
setName(ctx.emission_context, TheCallee, namep); | |||
} | |||
CallInst *call = ctx.builder.CreateCall(cft, TheCallee, argvals); | |||
call->setAttributes(returninfo.attrs); | |||
if (auto fun = dyn_cast<Function>(TheCallee)){ | |||
fun->setAttributes(AttributeList::get(ctx.builder.getContext(), {get_attrs_ipoeffects(ctx.builder.getContext(), effects, true, has_ptr_arg), returninfo.attrs, attrs})); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is generally pretty sketchy to mutate the callee to assume information that was only valid for this particular caller call site. I would delete this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The slightly annoying thing is that speculatable can't be passed to call sites, only on declarations. Also aren't the ipo effects the ones that are valid on call sites of the specific MI?
param.addDereferenceableAttr(props.union_bytes); | ||
param.addAlignmentAttr(props.union_align); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we actually ensure this when making this sret alloca? Normally this is the upper bounds that are permitted to be assumed, not the actual values at runtime, but this might be a special case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This what we do when we build the function in
Line 7806 in 8b8da91
param.addDereferenceableAttr(returninfo.union_bytes); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, fair. That is the only place it matters too. Elsewhere it just adds a little bit of extra overhead to the function declaration to track some extraneous attributes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't it potenially give more information with how much memory an sret a function has ,i t's likely that the information is there on the pointer now but with opaque pointers it might not be?
src/codegen.cpp
Outdated
if (is_decl && consistent == 0 && effect_free == 0 && nothrow == 1 && terminates == 1 && has_ptr_arg == false){ | ||
attr.addAttribute(Attribute::Speculatable); // This might not be legal because it assumes pointers can be null | ||
} | ||
attr.addAttribute(std::to_string(effects)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like it should be ifndef NDEBUG?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can add it as a comment to the module instead.
src/llvm-late-gc-lowering.cpp
Outdated
} else if (SRet_gc == Alloca) { | ||
continue; | ||
//check if isSret is passed directly | ||
if (!(&F.arg_begin()[0] == CI->arg_begin()[0].get())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if the sret gets copied directly from somewhere else, it still needs to determine where the associated GC roots are, and make sure they are rooted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I added this as an attempt to figure an error out. What was happening here was that LLVM eliding everything about the sret and then complaining that it couldn't find it.
b8993d9
to
1e8224e
Compare
} else if (inaccessiblememonly == 2){ | ||
attr.addAttribute(Attribute::InaccessibleMemOrArgMemOnly); | ||
} | ||
if (notaskstate == 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that read only task state or task state at all?
I.e. should we verify this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, from the docs
## `:notaskstate`
The `:notaskstate` setting asserts that the method does not use or modify the
local task state (task local storage, RNG state, etc.) and may thus be safely
moved between tasks without observable results.
What other effects can we do, i.e readnone etc.