mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-13 09:22:22 -07: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;
|
||||
}
|
||||
|
||||
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 *new_type = original_type;
|
||||
|
||||
+17
-17
@@ -11296,30 +11296,30 @@ void ir_begin_procedure_body(irProcedure *proc) {
|
||||
if (proc->type->Proc.has_named_results) {
|
||||
GB_ASSERT(proc->type->Proc.result_count > 0);
|
||||
TypeTuple *results = &proc->type->Proc.results->Tuple;
|
||||
|
||||
for_array(i, results->variables) {
|
||||
Entity *e = results->variables[i];
|
||||
if (e->kind != Entity_Variable) {
|
||||
continue;
|
||||
}
|
||||
GB_ASSERT(e->kind == Entity_Variable);
|
||||
|
||||
if (e->token.string != "") {
|
||||
GB_ASSERT(!is_blank_ident(e->token));
|
||||
irValue *res = ir_add_local(proc, e, e->identifier, true);
|
||||
|
||||
irValue *c = nullptr;
|
||||
switch (e->Variable.param_value.kind) {
|
||||
case ParameterValue_Constant:
|
||||
c = ir_value_constant(e->type, e->Variable.param_value.value);
|
||||
break;
|
||||
case ParameterValue_Nil:
|
||||
c = ir_value_nil(e->type);
|
||||
break;
|
||||
case ParameterValue_Location:
|
||||
GB_PANIC("ParameterValue_Location");
|
||||
break;
|
||||
irAddr res = {};
|
||||
if (proc->type->Proc.return_by_pointer) {
|
||||
irValue *ptr = proc->return_ptr;
|
||||
if (results->variables.count != 1) {
|
||||
ptr = ir_emit_struct_ep(proc, ptr, cast(i32)i);
|
||||
}
|
||||
|
||||
res = ir_addr(ptr);
|
||||
ir_module_add_value(proc->module, e, ptr);
|
||||
} else {
|
||||
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;
|
||||
|
||||
|
||||
lbValue return_ptr_value = {};
|
||||
if (p->type->Proc.return_by_pointer) {
|
||||
// NOTE(bill): this must be parameter 0
|
||||
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);
|
||||
e->flags |= EntityFlag_Sret | EntityFlag_NoAlias;
|
||||
|
||||
lbValue return_ptr_value = {};
|
||||
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);
|
||||
|
||||
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);
|
||||
TypeTuple *results = &p->type->Proc.results->Tuple;
|
||||
|
||||
isize result_index = 0;
|
||||
|
||||
for_array(i, results->variables) {
|
||||
Entity *e = results->variables[i];
|
||||
if (e->kind != Entity_Variable) {
|
||||
continue;
|
||||
}
|
||||
GB_ASSERT(e->kind == Entity_Variable);
|
||||
|
||||
if (e->token.string != "") {
|
||||
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 = {};
|
||||
switch (e->Variable.param_value.kind) {
|
||||
case ParameterValue_Constant:
|
||||
c = lb_const_value(p->module, e->type, e->Variable.param_value.value);
|
||||
break;
|
||||
case ParameterValue_Nil:
|
||||
c = lb_const_nil(p->module, e->type);
|
||||
break;
|
||||
case ParameterValue_Location:
|
||||
GB_PANIC("ParameterValue_Location");
|
||||
break;
|
||||
res = lb_addr(ptr);
|
||||
lb_add_entity(p->module, e, ptr);
|
||||
} else {
|
||||
res = lb_add_local(p, e->type, e);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
result_index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12188,7 +12183,7 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
|
||||
LLVMPassManagerRef default_function_pass_manager = LLVMCreateFunctionPassManagerForModule(mod);
|
||||
defer (LLVMDisposePassManager(default_function_pass_manager));
|
||||
{
|
||||
/*{
|
||||
LLVMAddMemCpyOptPass(default_function_pass_manager);
|
||||
LLVMAddPromoteMemoryToRegisterPass(default_function_pass_manager);
|
||||
LLVMAddMergedLoadStoreMotionPass(default_function_pass_manager);
|
||||
@@ -12219,8 +12214,58 @@ void lb_generate_code(lbGenerator *gen) {
|
||||
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);
|
||||
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) {
|
||||
if (type == nullptr) {
|
||||
return gb_string_appendc(str, "<no type>");
|
||||
|
||||
Reference in New Issue
Block a user