https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69241
--- Comment #20 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Ah, as for whether versioning supports changing return type to void, clearly it supports it and even fnsplit uses it for the !split_part_return_p. So perhaps: --- ipa-split.c.jj1 2016-01-04 14:55:52.000000000 +0100 +++ ipa-split.c 2016-02-03 13:01:45.905136051 +0100 @@ -1254,7 +1254,7 @@ split_function (basic_block return_bb, s else main_part_return_p = true; } - /* The main part also returns if we we split on a fallthru edge + /* The main part also returns if we split on a fallthru edge and the split part returns. */ if (split_part_return_p) FOR_EACH_EDGE (e, ei, split_point->entry_bb->preds) @@ -1364,8 +1364,9 @@ split_function (basic_block return_bb, s /* Now create the actual clone. */ cgraph_edge::rebuild_edges (); node = cur_node->create_version_clone_with_body - (vNULL, NULL, args_to_skip, !split_part_return_p, split_point->split_bbs, - split_point->entry_bb, "part"); + (vNULL, NULL, args_to_skip, + !split_part_return_p || !split_point->split_part_set_retval, + split_point->split_bbs, split_point->entry_bb, "part"); node->split_part = true; (completely untested, but fixes the testcase). And as incremental step there could be what I spoke above, handle SSA uses of DECL_BY_REFERENCE RESULT_DECL as artificial "parameter".