Improve multiple return value copy-elision

This commit is contained in:
gingerBill
2020-10-20 17:08:55 +01:00
parent c4dbc88a12
commit feeb342c00
4 changed files with 96 additions and 49 deletions
-9
View File
@@ -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
View File
@@ -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
View File
@@ -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));
{
+11
View File
@@ -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>");