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]
Other format: [Raw text]

[PATCH] Rename/export combine_insn_cost as insn_rtx_cost


The following patch moves and renames combine.c's combine_insn_cost
to rtlanal.c and exports it as insn_rtx_cost.  The functionality to
determine the cost of an instruction (a recognized pattern) is useful
throughout the RTL optimizers, and isn't specific to combine.  By
consolidating and reusing this API entry, improvements in backend
parameterization can be localized to a single function.

This patch also updates ifcvt.c's total_bb_rtx_cost to call this
function, rather than pass a raw pattern to rtx_cost.  This avoids
poorly parameterized backends being confused by parallels, uses,
clobbers, etc...  The API of total_bb_rtx_cost is also extended
such that it will now return -1 if the cost of any instruction in
the basic block can't be determined.  The existing callers in
find_if_case_1 and find_if_case_2 are updated to abort their
transformations, if total_bb_rtx_cost returns a negative value.

Finally, I noticed that we were calling rtx_cost with CALL and
branch instructions.  Asking the backend for the cost of a
subroutine call doesn't make much sense (yet :>), so this patch
tightens up the existing INSN_P checks to become NONJUMP_INSN_P
checks before calling insn_rtx_cost.  Hence, we disable if-conversion
if a basic block to be unconditionalized contains a subroutine
call, and we reallow combine to always recombine/merge sequences
containing call or branch instructions.


The following patch has been tested on i686-pc-linux-gnu with a
full "make bootstrap", all default languages, and regression tested
with a top-level "make -k check" with no new failures.

Ok for mainline?



2004-07-10  Roger Sayle  <roger@eyesopen.com>

	* rtlanal.c (insn_rtx_cost): New function, moved and renamed from
	combine.c's combine_insn_cost.
	* rtl.h (insn_rtx_cost): Prototype here.
	* combine.c (combine_insn_cost): Delete function.
	(combine_validate_cost): Update callers of combine_insn_cost to
	call insn_rtx_cost instead.
	(combine_instructions): Likewise.  Use NONJUMP_INSN_P to avoid
	requesting the rtx_cost of call and/or jump instructions.

	* ifcvt.c (total_bb_rtx_cost): Use insn_rtx_cost instead of calling
	rtx_cost directly.  Don't use request the cost of call or jump
	instructions.  Return -1 if the cost of any instruction can't be
	determined (or the BB contains a function call).
	(find_if_case_1): Abort transformation if total_bb_rtx_cost returns
	-1 (i.e. can't determine the cost of any instruction or the basic
	block contains a subroutine call).
	(find_if_case_2): Likewise.


Index: rtlanal.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtlanal.c,v
retrieving revision 1.194
diff -c -3 -p -r1.194 rtlanal.c
*** rtlanal.c	9 Jul 2004 03:29:35 -0000	1.194
--- rtlanal.c	10 Jul 2004 23:54:21 -0000
*************** num_sign_bit_copies1 (rtx x, enum machin
*** 4785,4787 ****
--- 4785,4823 ----
    return nonzero & ((HOST_WIDE_INT) 1 << (bitwidth - 1))
  	 ? 1 : bitwidth - floor_log2 (nonzero) - 1;
  }
+
+ /* Calculate the rtx_cost of a single instruction.  A return value of
+    zero indicates an instruction pattern without a known cost.  */
+
+ int
+ insn_rtx_cost (rtx pat)
+ {
+   int i, cost;
+   rtx set;
+
+   /* Extract the single set rtx from the instruction pattern.
+      We can't use single_set since we only have the pattern.  */
+   if (GET_CODE (pat) == SET)
+     set = pat;
+   else if (GET_CODE (pat) == PARALLEL)
+     {
+       set = NULL_RTX;
+       for (i = 0; i < XVECLEN (pat, 0); i++)
+ 	{
+ 	  rtx x = XVECEXP (pat, 0, i);
+ 	  if (GET_CODE (x) == SET)
+ 	    {
+ 	      if (set)
+ 		return 0;
+ 	      set = x;
+ 	    }
+ 	}
+       if (!set)
+ 	return 0;
+     }
+   else
+     return 0;
+
+   cost = rtx_cost (SET_SRC (set), SET);
+   return cost > 0 ? cost : COSTS_N_INSNS (1);
+ }
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.489
diff -c -3 -p -r1.489 rtl.h
*** rtl.h	9 Jul 2004 03:29:34 -0000	1.489
--- rtl.h	10 Jul 2004 23:54:21 -0000
*************** extern int loc_mentioned_in_p (rtx *, rt
*** 1879,1884 ****
--- 1879,1885 ----
  extern rtx find_first_parameter_load (rtx, rtx);
  extern bool keep_with_call_p (rtx);
  extern bool label_is_jump_target_p (rtx, rtx);
+ extern int insn_rtx_cost (rtx);

  /* flow.c */

Index: combine.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/combine.c,v
retrieving revision 1.442
diff -c -3 -p -r1.442 combine.c
*** combine.c	9 Jul 2004 03:29:26 -0000	1.442
--- combine.c	10 Jul 2004 23:54:23 -0000
*************** static basic_block this_basic_block;
*** 284,290 ****
     those blocks as starting points.  */
  static sbitmap refresh_blocks;

! /* The following array records the combine_insn_cost for every insn
     in the instruction stream.  */

  static int *uid_insn_cost;
--- 284,290 ----
     those blocks as starting points.  */
  static sbitmap refresh_blocks;

! /* The following array records the insn_rtx_cost for every insn
     in the instruction stream.  */

  static int *uid_insn_cost;
*************** do_SUBST_INT (int *into, int newval)
*** 515,558 ****

  #define SUBST_INT(INTO, NEWVAL)  do_SUBST_INT(&(INTO), (NEWVAL))

- /* Calculate the rtx_cost of a single instruction.  A return value of zero
-    indicates an instruction without a known cost.  */
-
- static int
- combine_insn_cost (rtx pat)
- {
-   int i, cost;
-   rtx set;
-
-   /* Extract the single set rtx from the instruction pattern.
-      We can't use single_set since we only have the pattern.  */
-   if (GET_CODE (pat) == SET)
-     set = pat;
-   else if (GET_CODE (pat) == PARALLEL)
-     {
-       set = NULL_RTX;
-       for (i = 0; i < XVECLEN (pat, 0); i++)
- 	{
- 	  rtx x = XVECEXP (pat, 0, i);
- 	  if (GET_CODE (x) == SET)
- 	    {
- 	      if (set)
- 		return 0;
- 	      set = x;
- 	    }
- 	}
-       if (!set)
- 	return 0;
-     }
-   else
-     return 0;
-
-   cost = rtx_cost (SET_SRC (set), SET);
-   return cost > 0 ? cost : COSTS_N_INSNS (1);
- }
-
  /* Subroutine of try_combine.  Determine whether the combine replacement
!    patterns NEWPAT and NEWI2PAT are cheaper according to combine_insn_cost
     that the original instruction sequence I1, I2 and I3.  Note that I1
     and/or NEWI2PAT may be NULL_RTX.  This function returns false, if the
     costs of all instructions can be estimated, and the replacements are
--- 515,522 ----

  #define SUBST_INT(INTO, NEWVAL)  do_SUBST_INT(&(INTO), (NEWVAL))

  /* Subroutine of try_combine.  Determine whether the combine replacement
!    patterns NEWPAT and NEWI2PAT are cheaper according to insn_rtx_cost
     that the original instruction sequence I1, I2 and I3.  Note that I1
     and/or NEWI2PAT may be NULL_RTX.  This function returns false, if the
     costs of all instructions can be estimated, and the replacements are
*************** combine_validate_cost (rtx i1, rtx i2, r
*** 565,571 ****
    int new_i2_cost, new_i3_cost;
    int old_cost, new_cost;

!   /* Lookup the original combine_insn_costs.  */
    i2_cost = INSN_UID (i2) <= last_insn_cost
  	    ? uid_insn_cost[INSN_UID (i2)] : 0;
    i3_cost = INSN_UID (i3) <= last_insn_cost
--- 529,535 ----
    int new_i2_cost, new_i3_cost;
    int old_cost, new_cost;

!   /* Lookup the original insn_rtx_costs.  */
    i2_cost = INSN_UID (i2) <= last_insn_cost
  	    ? uid_insn_cost[INSN_UID (i2)] : 0;
    i3_cost = INSN_UID (i3) <= last_insn_cost
*************** combine_validate_cost (rtx i1, rtx i2, r
*** 584,594 ****
        i1_cost = 0;
      }

!   /* Calculate the replacement combine_insn_costs.  */
!   new_i3_cost = combine_insn_cost (newpat);
    if (newi2pat)
      {
!       new_i2_cost = combine_insn_cost (newi2pat);
        new_cost = (new_i2_cost > 0 && new_i3_cost > 0)
  		 ? new_i2_cost + new_i3_cost : 0;
      }
--- 548,558 ----
        i1_cost = 0;
      }

!   /* Calculate the replacement insn_rtx_costs.  */
!   new_i3_cost = insn_rtx_cost (newpat);
    if (newi2pat)
      {
!       new_i2_cost = insn_rtx_cost (newi2pat);
        new_cost = (new_i2_cost > 0 && new_i3_cost > 0)
  		 ? new_i2_cost + new_i3_cost : 0;
      }
*************** combine_instructions (rtx f, unsigned in
*** 708,714 ****
    refresh_blocks = sbitmap_alloc (last_basic_block);
    sbitmap_zero (refresh_blocks);

!   /* Allocate array of current combine_insn_costs.  */
    uid_insn_cost = xcalloc (max_uid_cuid + 1, sizeof (int));
    last_insn_cost = max_uid_cuid;

--- 672,678 ----
    refresh_blocks = sbitmap_alloc (last_basic_block);
    sbitmap_zero (refresh_blocks);

!   /* Allocate array of current insn_rtx_costs.  */
    uid_insn_cost = xcalloc (max_uid_cuid + 1, sizeof (int));
    last_insn_cost = max_uid_cuid;

*************** combine_instructions (rtx f, unsigned in
*** 731,738 ****
  						NULL);
  #endif

! 	  /* Record the current combine_insn_cost of this instruction.  */
! 	  uid_insn_cost[INSN_UID (insn)] = combine_insn_cost (PATTERN (insn));
  	  if (dump_file)
  	    fprintf(dump_file, "insn_cost %d: %d\n",
  		    INSN_UID (insn), uid_insn_cost[INSN_UID (insn)]);
--- 695,703 ----
  						NULL);
  #endif

! 	  /* Record the current insn_rtx_cost of this instruction.  */
! 	  if (NONJUMP_INSN_P (insn))
! 	    uid_insn_cost[INSN_UID (insn)] = insn_rtx_cost (PATTERN (insn));
  	  if (dump_file)
  	    fprintf(dump_file, "insn_cost %d: %d\n",
  		    INSN_UID (insn), uid_insn_cost[INSN_UID (insn)]);
*************** try_combine (rtx i3, rtx i2, rtx i1, int
*** 2655,2661 ****
    }
  #endif

!   /* Only allow this combination if combine_insn_costs reports that the
       replacement instructions are cheaper than the originals.  */
    if (!combine_validate_cost (i1, i2, i3, newpat, newi2pat))
      {
--- 2620,2626 ----
    }
  #endif

!   /* Only allow this combination if insn_rtx_costs reports that the
       replacement instructions are cheaper than the originals.  */
    if (!combine_validate_cost (i1, i2, i3, newpat, newi2pat))
      {
Index: ifcvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ifcvt.c,v
retrieving revision 1.157
diff -c -3 -p -r1.157 ifcvt.c
*** ifcvt.c	10 Jul 2004 08:04:57 -0000	1.157
--- ifcvt.c	10 Jul 2004 23:54:25 -0000
*************** count_bb_insns (basic_block bb)
*** 161,167 ****
    return count;
  }

! /* Count the total rtx_cost of non-jump active insns in BB.  */

  static int
  total_bb_rtx_cost (basic_block bb)
--- 161,169 ----
    return count;
  }

! /* Count the total insn_rtx_cost of non-jump active insns in BB.
!    This function returns -1, if the cost of any instruction could
!    not be estimated.  */

  static int
  total_bb_rtx_cost (basic_block bb)
*************** total_bb_rtx_cost (basic_block bb)
*** 171,179 ****

    while (1)
      {
!       if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == INSN)
! 	count += rtx_cost (PATTERN (insn), 0);
!
        if (insn == BB_END (bb))
  	break;
        insn = NEXT_INSN (insn);
--- 173,188 ----

    while (1)
      {
!       if (NONJUMP_INSN_P (insn))
! 	{
! 	  int cost = insn_rtx_cost (PATTERN (insn));
! 	  if (cost == 0)
! 	    return -1;
! 	  count += cost;
! 	}
!       else if (CALL_P (insn))
! 	return -1;
!
        if (insn == BB_END (bb))
  	break;
        insn = NEXT_INSN (insn);
*************** find_if_case_1 (basic_block test_bb, edg
*** 2867,2873 ****
    basic_block then_bb = then_edge->dest;
    basic_block else_bb = else_edge->dest, new_bb;
    edge then_succ = then_bb->succ;
!   int then_bb_index;

    /* If we are partitioning hot/cold basic blocks, we don't want to
       mess up unconditional or indirect jumps that cross between hot
--- 2876,2882 ----
    basic_block then_bb = then_edge->dest;
    basic_block else_bb = else_edge->dest, new_bb;
    edge then_succ = then_bb->succ;
!   int then_bb_index, bb_cost;

    /* If we are partitioning hot/cold basic blocks, we don't want to
       mess up unconditional or indirect jumps that cross between hot
*************** find_if_case_1 (basic_block test_bb, edg
*** 2904,2910 ****
  	     test_bb->index, then_bb->index);

    /* THEN is small.  */
!   if (total_bb_rtx_cost (then_bb) >= COSTS_N_INSNS (BRANCH_COST))
      return FALSE;

    /* Registers set are dead, or are predicable.  */
--- 2913,2920 ----
  	     test_bb->index, then_bb->index);

    /* THEN is small.  */
!   bb_cost = total_bb_rtx_cost (then_bb);
!   if (bb_cost < 0 || bb_cost >= COSTS_N_INSNS (BRANCH_COST))
      return FALSE;

    /* Registers set are dead, or are predicable.  */
*************** find_if_case_2 (basic_block test_bb, edg
*** 2947,2952 ****
--- 2957,2963 ----
    basic_block then_bb = then_edge->dest;
    basic_block else_bb = else_edge->dest;
    edge else_succ = else_bb->succ;
+   int bb_cost;
    rtx note;

    /* If we are partitioning hot/cold basic blocks, we don't want to
*************** find_if_case_2 (basic_block test_bb, edg
*** 2995,3001 ****
  	     test_bb->index, else_bb->index);

    /* ELSE is small.  */
!   if (total_bb_rtx_cost (else_bb) >= COSTS_N_INSNS (BRANCH_COST))
      return FALSE;

    /* Registers set are dead, or are predicable.  */
--- 3006,3013 ----
  	     test_bb->index, else_bb->index);

    /* ELSE is small.  */
!   bb_cost = total_bb_rtx_cost (else_bb);
!   if (bb_cost < 0 || bb_cost >= COSTS_N_INSNS (BRANCH_COST))
      return FALSE;

    /* Registers set are dead, or are predicable.  */


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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