mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Improve multiple return value copy-elision
This commit is contained in:
@@ -2318,15 +2318,6 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type, ProcCall
|
|||||||
return new_type;
|
return new_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *reduce_tuple_to_single_type(Type *original_type) {
|
|
||||||
if (original_type != nullptr) {
|
|
||||||
Type *t = core_type(original_type);
|
|
||||||
if (t->kind == Type_Tuple && t->Tuple.variables.count == 1) {
|
|
||||||
return t->Tuple.variables[0]->type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return original_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type, ProcCallingConvention cc) {
|
Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type, ProcCallingConvention cc) {
|
||||||
Type *new_type = original_type;
|
Type *new_type = original_type;
|
||||||
|
|||||||
+17
-17
@@ -11296,30 +11296,30 @@ void ir_begin_procedure_body(irProcedure *proc) {
|
|||||||
if (proc->type->Proc.has_named_results) {
|
if (proc->type->Proc.has_named_results) {
|
||||||
GB_ASSERT(proc->type->Proc.result_count > 0);
|
GB_ASSERT(proc->type->Proc.result_count > 0);
|
||||||
TypeTuple *results = &proc->type->Proc.results->Tuple;
|
TypeTuple *results = &proc->type->Proc.results->Tuple;
|
||||||
|
|
||||||
for_array(i, results->variables) {
|
for_array(i, results->variables) {
|
||||||
Entity *e = results->variables[i];
|
Entity *e = results->variables[i];
|
||||||
if (e->kind != Entity_Variable) {
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e->token.string != "") {
|
if (e->token.string != "") {
|
||||||
GB_ASSERT(!is_blank_ident(e->token));
|
GB_ASSERT(!is_blank_ident(e->token));
|
||||||
irValue *res = ir_add_local(proc, e, e->identifier, true);
|
|
||||||
|
|
||||||
irValue *c = nullptr;
|
irAddr res = {};
|
||||||
switch (e->Variable.param_value.kind) {
|
if (proc->type->Proc.return_by_pointer) {
|
||||||
case ParameterValue_Constant:
|
irValue *ptr = proc->return_ptr;
|
||||||
c = ir_value_constant(e->type, e->Variable.param_value.value);
|
if (results->variables.count != 1) {
|
||||||
break;
|
ptr = ir_emit_struct_ep(proc, ptr, cast(i32)i);
|
||||||
case ParameterValue_Nil:
|
}
|
||||||
c = ir_value_nil(e->type);
|
|
||||||
break;
|
res = ir_addr(ptr);
|
||||||
case ParameterValue_Location:
|
ir_module_add_value(proc->module, e, ptr);
|
||||||
GB_PANIC("ParameterValue_Location");
|
} else {
|
||||||
break;
|
res = ir_addr(ir_add_local(proc, e, e->identifier, true));
|
||||||
}
|
}
|
||||||
if (c != nullptr) {
|
|
||||||
ir_emit_store(proc, res, c);
|
if (e->Variable.param_value.kind != ParameterValue_Invalid) {
|
||||||
|
irValue *c = ir_handle_param_value(proc, e->type, e->Variable.param_value, e->token.pos);
|
||||||
|
ir_addr_store(proc, res, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+68
-23
@@ -2430,15 +2430,16 @@ void lb_begin_procedure_body(lbProcedure *p) {
|
|||||||
|
|
||||||
i32 parameter_index = 0;
|
i32 parameter_index = 0;
|
||||||
|
|
||||||
|
|
||||||
|
lbValue return_ptr_value = {};
|
||||||
if (p->type->Proc.return_by_pointer) {
|
if (p->type->Proc.return_by_pointer) {
|
||||||
// NOTE(bill): this must be parameter 0
|
// NOTE(bill): this must be parameter 0
|
||||||
Type *ptr_type = alloc_type_pointer(reduce_tuple_to_single_type(p->type->Proc.results));
|
Type *ptr_type = alloc_type_pointer(reduce_tuple_to_single_type(p->type->Proc.results));
|
||||||
Entity *e = alloc_entity_param(nullptr, make_token_ident(str_lit("agg.result")), ptr_type, false, false);
|
Entity *e = alloc_entity_param(nullptr, make_token_ident(str_lit("agg.result")), ptr_type, false, false);
|
||||||
e->flags |= EntityFlag_Sret | EntityFlag_NoAlias;
|
e->flags |= EntityFlag_Sret | EntityFlag_NoAlias;
|
||||||
|
|
||||||
lbValue return_ptr_value = {};
|
|
||||||
return_ptr_value.value = LLVMGetParam(p->value, 0);
|
return_ptr_value.value = LLVMGetParam(p->value, 0);
|
||||||
return_ptr_value.type = alloc_type_pointer(p->type->Proc.abi_compat_result_type);
|
return_ptr_value.type = ptr_type;
|
||||||
p->return_ptr = lb_addr(return_ptr_value);
|
p->return_ptr = lb_addr(return_ptr_value);
|
||||||
|
|
||||||
lb_add_entity(p->module, e, return_ptr_value);
|
lb_add_entity(p->module, e, return_ptr_value);
|
||||||
@@ -2475,37 +2476,31 @@ void lb_begin_procedure_body(lbProcedure *p) {
|
|||||||
GB_ASSERT(p->type->Proc.result_count > 0);
|
GB_ASSERT(p->type->Proc.result_count > 0);
|
||||||
TypeTuple *results = &p->type->Proc.results->Tuple;
|
TypeTuple *results = &p->type->Proc.results->Tuple;
|
||||||
|
|
||||||
isize result_index = 0;
|
|
||||||
|
|
||||||
for_array(i, results->variables) {
|
for_array(i, results->variables) {
|
||||||
Entity *e = results->variables[i];
|
Entity *e = results->variables[i];
|
||||||
if (e->kind != Entity_Variable) {
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e->token.string != "") {
|
if (e->token.string != "") {
|
||||||
GB_ASSERT(!is_blank_ident(e->token));
|
GB_ASSERT(!is_blank_ident(e->token));
|
||||||
|
|
||||||
lbAddr res = lb_add_local(p, e->type, e);
|
lbAddr res = {};
|
||||||
|
if (p->type->Proc.return_by_pointer) {
|
||||||
|
lbValue ptr = return_ptr_value;
|
||||||
|
if (results->variables.count != 1) {
|
||||||
|
ptr = lb_emit_struct_ep(p, ptr, cast(i32)i);
|
||||||
|
}
|
||||||
|
|
||||||
lbValue c = {};
|
res = lb_addr(ptr);
|
||||||
switch (e->Variable.param_value.kind) {
|
lb_add_entity(p->module, e, ptr);
|
||||||
case ParameterValue_Constant:
|
} else {
|
||||||
c = lb_const_value(p->module, e->type, e->Variable.param_value.value);
|
res = lb_add_local(p, e->type, e);
|
||||||
break;
|
|
||||||
case ParameterValue_Nil:
|
|
||||||
c = lb_const_nil(p->module, e->type);
|
|
||||||
break;
|
|
||||||
case ParameterValue_Location:
|
|
||||||
GB_PANIC("ParameterValue_Location");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (c.value != nullptr) {
|
|
||||||
|
if (e->Variable.param_value.kind != ParameterValue_Invalid) {
|
||||||
|
lbValue c = lb_handle_param_value(p, e->type, e->Variable.param_value, e->token.pos);
|
||||||
lb_addr_store(p, res, c);
|
lb_addr_store(p, res, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result_index += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12188,7 +12183,7 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
|
|
||||||
LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(mod);
|
LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(mod);
|
||||||
defer (LLVMDisposePassManager(default_function_pass_manager));
|
defer (LLVMDisposePassManager(default_function_pass_manager));
|
||||||
{
|
/*{
|
||||||
LLVMAddMemCpyOptPass(default_function_pass_manager);
|
LLVMAddMemCpyOptPass(default_function_pass_manager);
|
||||||
LLVMAddPromoteMemoryToRegisterPass(default_function_pass_manager);
|
LLVMAddPromoteMemoryToRegisterPass(default_function_pass_manager);
|
||||||
LLVMAddMergedLoadStoreMotionPass(default_function_pass_manager);
|
LLVMAddMergedLoadStoreMotionPass(default_function_pass_manager);
|
||||||
@@ -12219,8 +12214,58 @@ void lb_generate_code(lbGenerator *gen) {
|
|||||||
LLVMAddLoopVectorizePass(default_function_pass_manager);
|
LLVMAddLoopVectorizePass(default_function_pass_manager);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
|
if (build_context.optimization_level == 0 && false) {
|
||||||
|
auto dfpm = default_function_pass_manager;
|
||||||
|
|
||||||
|
LLVMAddMemCpyOptPass(dfpm);
|
||||||
|
LLVMAddPromoteMemoryToRegisterPass(dfpm);
|
||||||
|
LLVMAddMergedLoadStoreMotionPass(dfpm);
|
||||||
|
LLVMAddAggressiveInstCombinerPass(dfpm);
|
||||||
|
LLVMAddConstantPropagationPass(dfpm);
|
||||||
|
LLVMAddAggressiveDCEPass(dfpm);
|
||||||
|
LLVMAddMergedLoadStoreMotionPass(dfpm);
|
||||||
|
LLVMAddPromoteMemoryToRegisterPass(dfpm);
|
||||||
|
LLVMAddCFGSimplificationPass(dfpm);
|
||||||
|
LLVMAddScalarizerPass(dfpm);
|
||||||
|
} else {
|
||||||
|
auto dfpm = default_function_pass_manager;
|
||||||
|
|
||||||
|
LLVMAddMemCpyOptPass(dfpm);
|
||||||
|
LLVMAddPromoteMemoryToRegisterPass(dfpm);
|
||||||
|
LLVMAddMergedLoadStoreMotionPass(dfpm);
|
||||||
|
LLVMAddAggressiveInstCombinerPass(dfpm);
|
||||||
|
LLVMAddConstantPropagationPass(dfpm);
|
||||||
|
LLVMAddAggressiveDCEPass(dfpm);
|
||||||
|
LLVMAddMergedLoadStoreMotionPass(dfpm);
|
||||||
|
LLVMAddPromoteMemoryToRegisterPass(dfpm);
|
||||||
|
LLVMAddCFGSimplificationPass(dfpm);
|
||||||
|
|
||||||
|
|
||||||
|
// LLVMAddInstructionCombiningPass(dfpm);
|
||||||
|
LLVMAddSLPVectorizePass(dfpm);
|
||||||
|
LLVMAddLoopVectorizePass(dfpm);
|
||||||
|
LLVMAddEarlyCSEPass(dfpm);
|
||||||
|
LLVMAddEarlyCSEMemSSAPass(dfpm);
|
||||||
|
|
||||||
|
LLVMAddScalarizerPass(dfpm);
|
||||||
|
LLVMAddLoopIdiomPass(dfpm);
|
||||||
|
|
||||||
|
// LLVMAddAggressiveInstCombinerPass(dfpm);
|
||||||
|
// LLVMAddLowerExpectIntrinsicPass(dfpm);
|
||||||
|
|
||||||
|
// LLVMAddPartiallyInlineLibCallsPass(dfpm);
|
||||||
|
|
||||||
|
// LLVMAddAlignmentFromAssumptionsPass(dfpm);
|
||||||
|
// LLVMAddDeadStoreEliminationPass(dfpm);
|
||||||
|
// LLVMAddReassociatePass(dfpm);
|
||||||
|
// LLVMAddAddDiscriminatorsPass(dfpm);
|
||||||
|
// LLVMAddPromoteMemoryToRegisterPass(dfpm);
|
||||||
|
// LLVMAddCorrelatedValuePropagationPass(dfpm);
|
||||||
|
// LLVMAddMemCpyOptPass(dfpm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LLVMPassManagerRef default_function_pass_manager_without_memcpy = LLVMCreateFunctionPassManagerForModule(mod);
|
LLVMPassManagerRef default_function_pass_manager_without_memcpy = LLVMCreateFunctionPassManagerForModule(mod);
|
||||||
defer (LLVMDisposePassManager(default_function_pass_manager_without_memcpy));
|
defer (LLVMDisposePassManager(default_function_pass_manager_without_memcpy));
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3338,6 +3338,17 @@ Type *get_struct_field_type(Type *t, isize index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Type *reduce_tuple_to_single_type(Type *original_type) {
|
||||||
|
if (original_type != nullptr) {
|
||||||
|
Type *t = core_type(original_type);
|
||||||
|
if (t->kind == Type_Tuple && t->Tuple.variables.count == 1) {
|
||||||
|
return t->Tuple.variables[0]->type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return original_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
gbString write_type_to_string(gbString str, Type *type) {
|
gbString write_type_to_string(gbString str, Type *type) {
|
||||||
if (type == nullptr) {
|
if (type == nullptr) {
|
||||||
return gb_string_appendc(str, "<no type>");
|
return gb_string_appendc(str, "<no type>");
|
||||||
|
|||||||
Reference in New Issue
Block a user