This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Loop insn hoisting patch



This patch introduces a new function loop_insn_hoist that should be
used exclusively to hoist insns out of a loop.  This is required
as part of my work to make the loop optimiser CFG aware.

This patch survives a bootstrap and introduces no new regressions.

2001-01-07  Michael Hayes  <mhayes@redhat.com>

	* loop.h (loop_insn_hoist): New prototype.
	* loop.c (loop_insn_hoist, loop_insn_emit_before): New.
	(move_movables, loop_givs_rescan): Use loop_insn_hoist.
	(check_dbra_loop, load_mems): Likewise.
	* unroll.c (unroll_loop, find_splittable_regs): Likewise.
	(find_splittable_givs): Likewise.

Index: loop.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/loop.c,v
retrieving revision 1.316
diff -c -3 -p -r1.316 loop.c
*** loop.c	2001/01/07 03:59:47	1.316
--- loop.c	2001/01/07 04:16:48
*************** static rtx check_insn_for_givs PARAMS((s
*** 246,251 ****
--- 246,254 ----
  static rtx check_insn_for_bivs PARAMS((struct loop *, rtx, int, int));
  static int iv_add_mult_cost PARAMS ((rtx, rtx, rtx, rtx));
  
+ static rtx loop_insn_emit_before PARAMS((const struct loop *, basic_block, 
+ 					 rtx, rtx));
+ 
  static void loop_dump_aux PARAMS ((const struct loop *, FILE *, int));
  void debug_biv PARAMS ((const struct induction *));
  void debug_giv PARAMS ((const struct induction *));
*************** move_movables (loop, movables, threshold
*** 1711,1717 ****
  		  for (m1 = m; m1->match; m1 = m1->match);
  		  newpat = gen_move_insn (SET_DEST (PATTERN (m->insn)),
  					  SET_DEST (PATTERN (m1->insn)));
! 		  i1 = emit_insn_before (newpat, loop_start);
  
  		  /* Mark the moved, invariant reg as being allowed to
  		     share a hard reg with the other matching invariant.  */
--- 1711,1717 ----
  		  for (m1 = m; m1->match; m1 = m1->match);
  		  newpat = gen_move_insn (SET_DEST (PATTERN (m->insn)),
  					  SET_DEST (PATTERN (m1->insn)));
! 		  i1 = loop_insn_hoist (loop, newpat);
  
  		  /* Mark the moved, invariant reg as being allowed to
  		     share a hard reg with the other matching invariant.  */
*************** move_movables (loop, movables, threshold
*** 1735,1741 ****
  		 the move insn before the loop.  */
  	      else if (m->move_insn)
  		{
! 		  rtx i1, temp;
  
  		  for (count = m->consec; count >= 0; count--)
  		    {
--- 1735,1741 ----
  		 the move insn before the loop.  */
  	      else if (m->move_insn)
  		{
! 		  rtx i1, temp, seq;
  
  		  for (count = m->consec; count >= 0; count--)
  		    {
*************** move_movables (loop, movables, threshold
*** 1772,1782 ****
  		  start_sequence ();
  		  emit_move_insn (m->set_dest, m->set_src);
  		  temp = get_insns ();
  		  end_sequence ();
  
  		  add_label_notes (m->set_src, temp);
  
! 		  i1 = emit_insns_before (temp, loop_start);
  		  if (! find_reg_note (i1, REG_EQUAL, NULL_RTX))
  		    REG_NOTES (i1)
  		      = gen_rtx_EXPR_LIST (m->is_equiv ? REG_EQUIV : REG_EQUAL,
--- 1772,1783 ----
  		  start_sequence ();
  		  emit_move_insn (m->set_dest, m->set_src);
  		  temp = get_insns ();
+ 		  seq = gen_sequence ();
  		  end_sequence ();
  
  		  add_label_notes (m->set_src, temp);
  
! 		  i1 = loop_insn_hoist (loop, seq);
  		  if (! find_reg_note (i1, REG_EQUAL, NULL_RTX))
  		    REG_NOTES (i1)
  		      = gen_rtx_EXPR_LIST (m->is_equiv ? REG_EQUIV : REG_EQUAL,
*************** move_movables (loop, movables, threshold
*** 1877,1883 ****
  				      = copy_rtx (CALL_INSN_FUNCTION_USAGE (temp));
  				}
  			      else
! 				i1 = emit_insn_before (body, loop_start);
  			      if (first == 0)
  				first = i1;
  			      if (temp == fn_address_insn)
--- 1878,1884 ----
  				      = copy_rtx (CALL_INSN_FUNCTION_USAGE (temp));
  				}
  			      else
! 				i1 = loop_insn_hoist (loop, body);
  			      if (first == 0)
  				first = i1;
  			      if (temp == fn_address_insn)
*************** move_movables (loop, movables, threshold
*** 1910,1916 ****
  			    emit_move_insn (reg, tem);
  			  sequence = gen_sequence ();
  			  end_sequence ();
! 			  i1 = emit_insn_before (sequence, loop_start);
  			}
  		      else if (GET_CODE (p) == CALL_INSN)
  			{
--- 1911,1917 ----
  			    emit_move_insn (reg, tem);
  			  sequence = gen_sequence ();
  			  end_sequence ();
! 			  i1 = loop_insn_hoist (loop, sequence);
  			}
  		      else if (GET_CODE (p) == CALL_INSN)
  			{
*************** move_movables (loop, movables, threshold
*** 1924,1939 ****
  			}
  		      else if (count == m->consec && m->move_insn_first)
  			{
  			  /* The SET_SRC might not be invariant, so we must
  			     use the REG_EQUAL note.  */
  			  start_sequence ();
  			  emit_move_insn (m->set_dest, m->set_src);
  			  temp = get_insns ();
  			  end_sequence ();
  
  			  add_label_notes (m->set_src, temp);
  
! 			  i1 = emit_insns_before (temp, loop_start);
  			  if (! find_reg_note (i1, REG_EQUAL, NULL_RTX))
  			    REG_NOTES (i1)
  			      = gen_rtx_EXPR_LIST ((m->is_equiv ? REG_EQUIV
--- 1925,1942 ----
  			}
  		      else if (count == m->consec && m->move_insn_first)
  			{
+ 			  rtx seq;
  			  /* The SET_SRC might not be invariant, so we must
  			     use the REG_EQUAL note.  */
  			  start_sequence ();
  			  emit_move_insn (m->set_dest, m->set_src);
  			  temp = get_insns ();
+ 			  seq = gen_sequence ();
  			  end_sequence ();
  
  			  add_label_notes (m->set_src, temp);
  
! 			  i1 = loop_insn_hoist (loop, seq);
  			  if (! find_reg_note (i1, REG_EQUAL, NULL_RTX))
  			    REG_NOTES (i1)
  			      = gen_rtx_EXPR_LIST ((m->is_equiv ? REG_EQUIV
*************** move_movables (loop, movables, threshold
*** 1941,1947 ****
  						   m->set_src, REG_NOTES (i1));
  			}
  		      else
! 			i1 = emit_insn_before (PATTERN (p), loop_start);
  
  		      if (REG_NOTES (i1) == 0)
  			{
--- 1944,1950 ----
  						   m->set_src, REG_NOTES (i1));
  			}
  		      else
! 			i1 = loop_insn_hoist (loop, PATTERN (p));
  
  		      if (REG_NOTES (i1) == 0)
  			{
*************** loop_givs_rescan (loop, bl, reg_map, end
*** 4041,4058 ****
  			  end_insert_before);
        else if (v->final_value)
  	{
- 	  rtx insert_before;
- 	  
  	  /* If the loop has multiple exits, emit the insn before the
  	     loop to ensure that it will always be executed no matter
  	     how the loop exits.  Otherwise, emit the insn after the loop,
  	     since this is slightly more efficient.  */
  	  if (loop->exit_count)
! 	    insert_before = loop->start;
  	  else
! 	    insert_before = end_insert_before;
! 	  emit_insn_before (gen_move_insn (v->dest_reg, v->final_value),
! 			    insert_before);
  	}
        
        if (loop_dump_stream)
--- 4044,4059 ----
  			  end_insert_before);
        else if (v->final_value)
  	{
  	  /* If the loop has multiple exits, emit the insn before the
  	     loop to ensure that it will always be executed no matter
  	     how the loop exits.  Otherwise, emit the insn after the loop,
  	     since this is slightly more efficient.  */
  	  if (loop->exit_count)
! 	    loop_insn_hoist (loop, 
! 			     gen_move_insn (v->dest_reg, v->final_value));
  	  else
! 	    emit_insn_before (gen_move_insn (v->dest_reg, v->final_value),
! 			      end_insert_before);
  	}
        
        if (loop_dump_stream)
*************** check_dbra_loop (loop, insn_count)
*** 7432,7439 ****
  		  && GET_CODE (comparison_value) == CONST_INT)
  		{
  		  start_value = GEN_INT (comparison_val - add_adjust);
! 		  emit_insn_before (gen_move_insn (reg, start_value),
! 				    loop_start);
  		}
  	      else if (GET_CODE (initial_value) == CONST_INT)
  		{
--- 7433,7439 ----
  		  && GET_CODE (comparison_value) == CONST_INT)
  		{
  		  start_value = GEN_INT (comparison_val - add_adjust);
! 		  loop_insn_hoist (loop, gen_move_insn (reg, start_value));
  		}
  	      else if (GET_CODE (initial_value) == CONST_INT)
  		{
*************** check_dbra_loop (loop, insn_count)
*** 7450,7458 ****
  		    return 0;
  		  start_value
  		    = gen_rtx_PLUS (mode, comparison_value, offset);
! 		  emit_insn_before ((GEN_FCN (icode)
! 				     (reg, comparison_value, offset)),
! 				    loop_start);
  		  if (GET_CODE (comparison) == LE)
  		    final_value = gen_rtx_PLUS (mode, comparison_value,
  						GEN_INT (add_val));
--- 7450,7457 ----
  		    return 0;
  		  start_value
  		    = gen_rtx_PLUS (mode, comparison_value, offset);
! 		  loop_insn_hoist (loop, (GEN_FCN (icode)
! 					     (reg, comparison_value, offset)));
  		  if (GET_CODE (comparison) == LE)
  		    final_value = gen_rtx_PLUS (mode, comparison_value,
  						GEN_INT (add_val));
*************** check_dbra_loop (loop, insn_count)
*** 7470,7478 ****
  		    return 0;
  		  start_value
  		    = gen_rtx_MINUS (mode, comparison_value, initial_value);
! 		  emit_insn_before ((GEN_FCN (icode)
! 				     (reg, comparison_value, initial_value)),
! 				    loop_start);
  		}
  	      else
  		/* We could handle the other cases too, but it'll be
--- 7469,7477 ----
  		    return 0;
  		  start_value
  		    = gen_rtx_MINUS (mode, comparison_value, initial_value);
! 		  loop_insn_hoist (loop, (GEN_FCN (icode)
! 					     (reg, comparison_value,
! 					      initial_value)));
  		}
  	      else
  		/* We could handle the other cases too, but it'll be
*************** load_mems (loop)
*** 8972,8978 ****
  		best = copy_rtx (best_equiv->loc);
  	    }
  	  set = gen_move_insn (reg, best);
! 	  set = emit_insn_before (set, loop->start);
  	  if (const_equiv)
  	    REG_NOTES (set) = gen_rtx_EXPR_LIST (REG_EQUAL,
  						 copy_rtx (const_equiv->loc),
--- 8971,8977 ----
  		best = copy_rtx (best_equiv->loc);
  	    }
  	  set = gen_move_insn (reg, best);
! 	  set = loop_insn_hoist (loop, set);
  	  if (const_equiv)
  	    REG_NOTES (set) = gen_rtx_EXPR_LIST (REG_EQUAL,
  						 copy_rtx (const_equiv->loc),
*************** replace_label (x, data)
*** 9353,9358 ****
--- 9352,9384 ----
    --LABEL_NUSES (old_label);
  
    return 0;
+ }
+ 
+ /* If WHERE_INSN is non-zero emit insn for PATTERN before WHERE_INSN
+    in basic block WHERE_BB (ignored in the interim) within the loop
+    otherwise hoist PATTERN into the loop pre-header.  */
+ 
+ static rtx
+ loop_insn_emit_before (loop, where_bb, where_insn, pattern)
+      const struct loop *loop;
+      basic_block where_bb ATTRIBUTE_UNUSED;
+      rtx where_insn;
+      rtx pattern;
+ {
+   if (! where_insn)
+     return loop_insn_hoist (loop, pattern);
+   return emit_insn_before (pattern, where_insn);
+ }
+ 
+ 
+ /* Hoist insn for PATTERN into the loop pre-header.  */
+ 
+ rtx
+ loop_insn_hoist (loop, pattern)
+      const struct loop *loop;
+      rtx pattern;
+ {
+   return loop_insn_emit_before (loop, 0, loop->start, pattern);
  }
  
  static void
*** ../../fsf/gcc/loop.h	Sat Jan  6 12:34:57 2001
--- loop.h	Sat Jan  6 17:17:41 2001
*************** int back_branch_in_range_p PARAMS ((cons
*** 404,409 ****
--- 404,410 ----
  int loop_insn_first_p PARAMS ((rtx, rtx));
  typedef rtx (*loop_insn_callback) PARAMS ((struct loop *, rtx, int, int));
  void for_each_insn_in_loop PARAMS ((struct loop *, loop_insn_callback));
+ rtx loop_insn_hoist PARAMS((const struct loop *, rtx));
  
  /* Forward declarations for non-static functions declared in doloop.c.  */
  int doloop_optimize PARAMS ((const struct loop *));
*** ../../fsf/gcc/unroll.c	Sat Jan  6 16:36:30 2001
--- unroll.c	Sat Jan  6 17:17:49 2001
*************** unroll_loop (loop, insn_count, end_inser
*** 1045,1051 ****
  
  	  sequence = gen_sequence ();
  	  end_sequence ();
! 	  emit_insn_before (sequence, loop_start);
  
  	  /* Only the last copy of the loop body here needs the exit
  	     test, so set copy_end to exclude the compare/branch here,
--- 1045,1051 ----
  
  	  sequence = gen_sequence ();
  	  end_sequence ();
! 	  loop_insn_hoist (loop, sequence);
  
  	  /* Only the last copy of the loop body here needs the exit
  	     test, so set copy_end to exclude the compare/branch here,
*************** find_splittable_regs (loop, unroll_type,
*** 2512,2519 ****
  		  rtx tem = gen_reg_rtx (bl->biv->mode);
  
  		  record_base_value (REGNO (tem), bl->biv->add_val, 0);
! 		  emit_insn_before (gen_move_insn (tem, bl->biv->src_reg),
! 				    loop_start);
  
  		  if (loop_dump_stream)
  		    fprintf (loop_dump_stream,
--- 2512,2519 ----
  		  rtx tem = gen_reg_rtx (bl->biv->mode);
  
  		  record_base_value (REGNO (tem), bl->biv->add_val, 0);
! 		  loop_insn_hoist (loop, 
! 				   gen_move_insn (tem, bl->biv->src_reg));
  
  		  if (loop_dump_stream)
  		    fprintf (loop_dump_stream,
*************** find_splittable_regs (loop, unroll_type,
*** 2571,2581 ****
  	      rtx tem = gen_reg_rtx (bl->biv->mode);
  	      record_base_value (REGNO (tem), bl->biv->add_val, 0);
  
! 	      emit_insn_before (gen_move_insn (tem, bl->biv->src_reg),
! 				loop_start);
! 	      emit_insn_before (gen_move_insn (bl->biv->src_reg,
! 					       biv_final_value),
! 				loop_start);
  
  	      if (loop_dump_stream)
  		fprintf (loop_dump_stream, "Biv %d mapped to %d for split.\n",
--- 2571,2579 ----
  	      rtx tem = gen_reg_rtx (bl->biv->mode);
  	      record_base_value (REGNO (tem), bl->biv->add_val, 0);
  
! 	      loop_insn_hoist (loop, gen_move_insn (tem, bl->biv->src_reg));
! 	      loop_insn_hoist (loop, gen_move_insn (bl->biv->src_reg,
! 						    biv_final_value));
  
  	      if (loop_dump_stream)
  		fprintf (loop_dump_stream, "Biv %d mapped to %d for split.\n",
*************** find_splittable_givs (loop, bl, unroll_t
*** 2717,2725 ****
  	     to its final value before loop start to ensure that this insn
  	     will always be executed, no matter how we exit.  */
  	  tem = gen_reg_rtx (v->mode);
! 	  emit_insn_before (gen_move_insn (tem, v->dest_reg), loop_start);
! 	  emit_insn_before (gen_move_insn (v->dest_reg, final_value),
! 			    loop_start);
  
  	  if (loop_dump_stream)
  	    fprintf (loop_dump_stream, "Giv %d mapped to %d for split.\n",
--- 2715,2722 ----
  	     to its final value before loop start to ensure that this insn
  	     will always be executed, no matter how we exit.  */
  	  tem = gen_reg_rtx (v->mode);
! 	  loop_insn_hoist (loop, gen_move_insn (tem, v->dest_reg));
! 	  loop_insn_hoist (loop, gen_move_insn (v->dest_reg, final_value));
  
  	  if (loop_dump_stream)
  	    fprintf (loop_dump_stream, "Giv %d mapped to %d for split.\n",
*************** find_splittable_givs (loop, bl, unroll_t
*** 2752,2759 ****
  	      rtx tem = gen_reg_rtx (bl->biv->mode);
  
  	      record_base_value (REGNO (tem), bl->biv->add_val, 0);
! 	      emit_insn_before (gen_move_insn (tem, bl->biv->src_reg),
! 				loop->start);
  	      biv_initial_value = tem;
  	    }
  	  biv_initial_value = extend_value_for_giv (v, biv_initial_value);
--- 2749,2755 ----
  	      rtx tem = gen_reg_rtx (bl->biv->mode);
  
  	      record_base_value (REGNO (tem), bl->biv->add_val, 0);
! 	      loop_insn_hoist (loop, gen_move_insn (tem, bl->biv->src_reg));
  	      biv_initial_value = tem;
  	    }
  	  biv_initial_value = extend_value_for_giv (v, biv_initial_value);
*************** find_splittable_givs (loop, bl, unroll_t
*** 2923,2931 ****
  		     instruction on machines with complex addressing modes.
  		     If we can't recognize it, then delete it and emit insns
  		     to calculate the value from scratch.  */
! 		  emit_insn_before (gen_rtx_SET (VOIDmode, tem,
! 						 copy_rtx (v->new_reg)),
! 				    loop->start);
  		  if (recog_memoized (PREV_INSN (loop->start)) < 0)
  		    {
  		      rtx sequence, ret;
--- 2919,2926 ----
  		     instruction on machines with complex addressing modes.
  		     If we can't recognize it, then delete it and emit insns
  		     to calculate the value from scratch.  */
! 		  loop_insn_hoist (loop, gen_rtx_SET (VOIDmode, tem,
! 						      copy_rtx (v->new_reg)));
  		  if (recog_memoized (PREV_INSN (loop->start)) < 0)
  		    {
  		      rtx sequence, ret;
*************** find_splittable_givs (loop, bl, unroll_t
*** 2942,2948 ****
  			emit_move_insn (tem, ret);
  		      sequence = gen_sequence ();
  		      end_sequence ();
! 		      emit_insn_before (sequence, loop->start);
  
  		      if (loop_dump_stream)
  			fprintf (loop_dump_stream,
--- 2937,2943 ----
  			emit_move_insn (tem, ret);
  		      sequence = gen_sequence ();
  		      end_sequence ();
! 		      loop_insn_hoist (loop, sequence);
  
  		      if (loop_dump_stream)
  			fprintf (loop_dump_stream,

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]