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


Reply via email to