Patchwork [3/3,RFC] Fixup COND_EXECs before reload

login
register
mail settings
Submitter Alexander Monakov
Date Oct. 26, 2011, 5:58 p.m.
Message ID <alpine.LNX.2.00.1110262149490.6939@monoid.intra.ispras.ru>
Download mbox | patch
Permalink /patch/121957/
State New
Headers show

Comments

Alexander Monakov - Oct. 26, 2011, 5:58 p.m.
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  <mouseentity@ispras.ru>

	* sel-sched.c (convert_cond_execs): New.  Use it...
	(sel_global_finish): ... here.
Andrey Belevantsev - Nov. 15, 2011, 8:39 a.m.
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.  */
>

Patch

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