Message ID | alpine.LNX.2.00.1110262149490.6939@monoid.intra.ispras.ru |
---|---|
State | New |
Headers | show |
Hello, On 26.10.2011 21:58, Alexander Monakov wrote: > > 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. This code looks good, but before checking it in we need to understand whether this functionality is needed by other passes (SMS?). If yes, then we need to move this to cfgrtl.c or similar. If no, then at least we need to conditionalize this code on flag_sel_sched_predication as it is yet another pass over all insns. Can it be unified with other initialization passes of sel-sched? Andrey > > > 2011-10-26 Sergey Grechanik<mouseentity@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. */ >
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. */