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<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. */