It turns out the SSA var defs/uses generated by the gimplifier can break apart in a way no longer satisfying the dominance requirement of SSA uses vs. their defs by means of CFG construction adding abnormal edges for stuff like setjmp (but also non-local gotos I guess).
This would be quite costly to overcome in gimplification - one needs to check whether a (part?) of an expression to be gimplified may produce such edges and disable SSA name generation for them. With the recursive nature of the gimplifier plus the general complexity of GENERIC I can't see how to do this. Thus the following patch "recovers" from the extra abnormal edges by effectively treating SSA vars pre into-SSA as "non-SSA" and thus doing PHI insertion for them when rewriting the function into SSA. Implementation-wise the easiest thing was to re-write the affected SSA vars out-of-SSA (replace them by a decl). The out-of-SSA rewriting is placed in insert_phi_nodes because thats the first point in time we have immediate uses present (otherwise it could be done at any point after CFG construction). I'm not 100% happy with this but after trying for a day I can't come up with a better solution - it has the chance of papering over bogus gimplifications but OTOH that we only do this for functions calling setjmp or having non-local labels would make those trigger SSA verification in the other cases. Bootstrap and regtest running on x86_64-unknown-linux-gnu. Any comments / ideas? Anyone with good arguments that this is even conceptually the correct thing to do? I'm bootstrapping this with the calls_setjmp/has_nonlocal_label short-cutted with a 1 || as well as without (to increase testing coverage). Thanks, Richard. 2017-02-10 Richard Biener <rguent...@suse.de> PR middle-end/79432 * tree-into-ssa.c (insert_phi_nodes): When the function can have abnormal edges rewrite SSA names with broken use-def dominance out of SSA and register them for PHI insertion. * gcc.dg/torture/pr79432.c: New testcase. Index: gcc/tree-into-ssa.c =================================================================== --- gcc/tree-into-ssa.c (revision 245323) +++ gcc/tree-into-ssa.c (working copy) @@ -1066,6 +1066,59 @@ insert_phi_nodes (bitmap_head *dfs) timevar_push (TV_TREE_INSERT_PHI_NODES); + /* When the gimplifier introduces SSA names it cannot easily avoid + situations where abnormal edges added by CFG construction break + the use-def dominance requirement. For this case rewrite SSA + names with broken use-def dominance out-of-SSA and register them + for PHI insertion. We only need to do this if abnormal edges + can appear in the function. */ + tree name; + if (cfun->calls_setjmp + || cfun->has_nonlocal_label) + FOR_EACH_SSA_NAME (i, name, cfun) + { + gimple *def_stmt = SSA_NAME_DEF_STMT (name); + if (SSA_NAME_IS_DEFAULT_DEF (name)) + continue; + + basic_block def_bb = gimple_bb (def_stmt); + imm_use_iterator it; + gimple *use_stmt; + bool need_phis = false; + FOR_EACH_IMM_USE_STMT (use_stmt, it, name) + { + basic_block use_bb = gimple_bb (use_stmt); + if (use_bb != def_bb + && ! dominated_by_p (CDI_DOMINATORS, use_bb, def_bb)) + need_phis = true; + } + if (need_phis) + { + tree var = create_tmp_reg (TREE_TYPE (name)); + use_operand_p use_p; + FOR_EACH_IMM_USE_STMT (use_stmt, it, name) + { + basic_block use_bb = gimple_bb (use_stmt); + FOR_EACH_IMM_USE_ON_STMT (use_p, it) + SET_USE (use_p, var); + update_stmt (use_stmt); + set_livein_block (var, use_bb); + set_rewrite_uses (use_stmt, true); + bitmap_set_bit (interesting_blocks, use_bb->index); + } + def_operand_p def_p; + ssa_op_iter dit; + FOR_EACH_SSA_DEF_OPERAND (def_p, def_stmt, dit, SSA_OP_DEF) + if (DEF_FROM_PTR (def_p) == name) + SET_DEF (def_p, var); + update_stmt (def_stmt); + set_def_block (var, def_bb, false); + set_register_defs (def_stmt, true); + bitmap_set_bit (interesting_blocks, def_bb->index); + release_ssa_name (name); + } + } + auto_vec<var_info *> vars (var_infos->elements ()); FOR_EACH_HASH_TABLE_ELEMENT (*var_infos, info, var_info_p, hi) if (info->info.need_phi_state != NEED_PHI_STATE_NO) Index: gcc/testsuite/gcc.dg/torture/pr79432.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr79432.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/pr79432.c (working copy) @@ -0,0 +1,20 @@ +/* { dg-do compile } */ + +int fn1 (void); +int __attribute__((returns_twice)) vfork (void); + +void fn2 () +{ + int a; + a = fn1() + 2 + (vfork() + 1 + vfork()); +} +void fn3 () +{ + int a; + a = fn1() + 1 + vfork(); +} +void fn4 () +{ + int a; + a = fn1() + vfork(); +}