This RFC patch implements conversion of COND_EXEC instructions to control flow for pre-RA selective scheduler. Something like this is needed to employ predication support before reload.
Each COND_EXEC is converted separately to a new basic block with the unconditional variant of the instruction, and a conditional jump around it. I'm not sure what would be an acceptable approach here. I'm also not sure about the recommended way to emit JUMPs. 2011-10-26 Sergey Grechanik <mouseent...@ispras.ru> * sel-sched.c (convert_cond_execs): New. Use it... (sel_global_finish): ... here. diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c index f5c6f8b..b8f2663 100644 --- a/gcc/sel-sched.c +++ b/gcc/sel-sched.c @@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see #include "rtlhooks-def.h" #include "output.h" #include "emit-rtl.h" +#include "cfghooks.h" #ifdef INSN_SCHEDULING #include "sel-sched-ir.h" @@ -7978,6 +7979,60 @@ sel_global_init (void) init_hard_regs_data (); } +/* Convert cond_execs to jumps before reload. */ +static void +convert_cond_execs (void) +{ + basic_block bb; + rtx insn; + + if (reload_completed) + return; + + FOR_EACH_BB (bb) + /* We don't need the safe variant because we break immediately after + removing the current instruction. */ + FOR_BB_INSNS (bb, insn) + if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == COND_EXEC) + { + rtx jump; + rtx cond = COND_EXEC_TEST (PATTERN (insn)); + rtx rcond = reversed_comparison (cond, GET_MODE (cond)); + rtx unpredicated = copy_rtx (COND_EXEC_CODE (PATTERN (insn))); + + /* Split bb into BB, NEW_BB, NEXT_BB (in that order). */ + edge e1 = split_block (bb, insn); + basic_block next_bb = e1->dest; + edge e2 = split_block (bb, insn); + basic_block new_bb = e2->dest; + + /* Emit conditional jump at the end of bb. */ + rtx label = block_label (next_bb); + + /* FIXME There should be a better way. */ + rtx jump_pat + = gen_rtx_SET (GET_MODE (pc_rtx), pc_rtx, + gen_rtx_IF_THEN_ELSE (GET_MODE (pc_rtx), + rcond, + gen_rtx_LABEL_REF (VOIDmode, + label), + pc_rtx)); + + make_edge (bb, next_bb, 0); + jump = emit_jump_insn_after (jump_pat, BB_END (bb)); + JUMP_LABEL (jump) = label; + LABEL_NUSES (label)++; + + emit_insn_after_noloc (unpredicated, BB_HEAD (new_bb), new_bb); + + delete_insn (insn); + break; + } +#ifdef ENABLE_CHECKING + verify_flow_info (); +#endif +} + /* Free the global data of the scheduler. */ static void sel_global_finish (void) @@ -7998,6 +8053,8 @@ sel_global_finish (void) free_sched_pools (); free_dominance_info (CDI_DOMINATORS); + + convert_cond_execs (); } /* Return true when we need to skip selective scheduling. Used for debugging. */