mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-29 17:34:34 +00:00
Naïve optimization of named _split_ multiple return valued when defer is never used
This is a naïve optimization but it helps a lot in the general case where callee temporary stack variables are not allocated to represent the named return values by using that specific memory. In the future, try to check if a specific named return value is ever used a `defer` within a procedure or not, or is ever passed to a nested procedure call (e.g. possibly escapes).
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
|
||||
LLVMValueRef lb_call_intrinsic(lbProcedure *p, const char *name, LLVMValueRef* args, unsigned arg_count, LLVMTypeRef* types, unsigned type_count)
|
||||
{
|
||||
unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
|
||||
@@ -596,16 +595,69 @@ void lb_begin_procedure_body(lbProcedure *p) {
|
||||
if (e->token.string != "") {
|
||||
GB_ASSERT(!is_blank_ident(e->token));
|
||||
|
||||
// NOTE(bill): Don't even bother trying to optimize this with the return ptr value
|
||||
// This will violate the defer rules if you do:
|
||||
// foo :: proc() -> (x, y: T) {
|
||||
// defer x = ... // defer is executed after the `defer`
|
||||
// return // the values returned should be zeroed
|
||||
// }
|
||||
// NOTE(bill): REALLY, don't even bother.
|
||||
//
|
||||
// IMPORTANT NOTE(bill): REALLY, don't even bother!!!!!!
|
||||
lbAddr res = lb_add_local(p, e->type, e);
|
||||
lbAddr res = {};
|
||||
if (p->entity && p->entity->decl_info &&
|
||||
p->entity->decl_info->defer_use_checked &&
|
||||
p->entity->decl_info->defer_used == 0) {
|
||||
|
||||
// NOTE(bill): this is a bodge to get around the issue of the problem BELOW
|
||||
// We check to see if we ever use a defer statement ever within a procedure and if it
|
||||
// if it never happens, see if you can possibly do take the return value pointer
|
||||
//
|
||||
// NOTE(bill): this could be buggy in that I have missed a case where `defer` was used
|
||||
//
|
||||
// TODO(bill): This could be optimized to check to see where a `defer` only uses
|
||||
// the variable in question
|
||||
|
||||
bool has_return_ptr = p->return_ptr.addr.value != nullptr;
|
||||
lbValue ptr = {};
|
||||
|
||||
if (ft->multiple_return_original_type != nullptr) {
|
||||
isize the_offset = -1;
|
||||
if (i+1 < results->variables.count) {
|
||||
the_offset = cast(isize)param_offset + ft->original_arg_count + i;
|
||||
} else if (has_return_ptr) {
|
||||
GB_ASSERT(i+1 == results->variables.count);
|
||||
the_offset = 0;
|
||||
}
|
||||
if (the_offset >= 0) {
|
||||
lbValue ptr = {};
|
||||
ptr.value = LLVMGetParam(p->value, cast(unsigned)the_offset);
|
||||
ptr.type = alloc_type_pointer(e->type);
|
||||
|
||||
|
||||
}
|
||||
} else if (has_return_ptr) {
|
||||
lbValue ptr = p->return_ptr.addr;
|
||||
|
||||
if (results->variables.count > 1) {
|
||||
ptr = lb_emit_tuple_ep(p, ptr, cast(i32)i);
|
||||
}
|
||||
GB_ASSERT(is_type_pointer(ptr.type));
|
||||
GB_ASSERT(are_types_identical(type_deref(ptr.type), e->type));
|
||||
}
|
||||
|
||||
if (ptr.value != nullptr) {
|
||||
lb_add_entity(p->module, e, ptr);
|
||||
lb_add_debug_local_variable(p, ptr.value, e->type, e->token);
|
||||
// NOTE(bill): no need to zero on the callee side as it is zeroed on the caller side
|
||||
|
||||
res = lb_addr(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (res.addr.type == nullptr) {
|
||||
// NOTE(bill): Don't even bother trying to optimize this with the return ptr value
|
||||
// This will violate the defer rules if you do:
|
||||
// foo :: proc() -> (x, y: T) {
|
||||
// defer x = ... // defer is executed after the `defer`
|
||||
// return // the values returned should be zeroed
|
||||
// }
|
||||
// NOTE(bill): REALLY, don't even bother.
|
||||
//
|
||||
// IMPORTANT NOTE(bill): REALLY, don't even bother!!!!!!
|
||||
res = lb_add_local(p, e->type, e);
|
||||
}
|
||||
|
||||
if (e->Variable.param_value.kind != ParameterValue_Invalid) {
|
||||
lbValue c = lb_handle_param_value(p, e->type, e->Variable.param_value, e->token.pos);
|
||||
@@ -1006,7 +1058,7 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue> const &args,
|
||||
GB_ASSERT(rt->kind == Type_Tuple);
|
||||
for (isize j = 0; j < rt->Tuple.variables.count-1; j++) {
|
||||
Type *partial_return_type = rt->Tuple.variables[j]->type;
|
||||
lbValue partial_return_ptr = lb_add_local_generated(p, partial_return_type, true).addr;
|
||||
lbValue partial_return_ptr = lb_add_local(p, partial_return_type, nullptr, true, false).addr;
|
||||
array_add(&processed_args, partial_return_ptr);
|
||||
}
|
||||
rt = reduce_tuple_to_single_type(rt->Tuple.variables[rt->Tuple.variables.count-1]->type);
|
||||
|
||||
Reference in New Issue
Block a user