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]

RFA: fix PR rtl-optimization/23898


Regression tested on i686-pc-linux-gnu native, X sh-elf and X sh64-elf.
2005-09-19  J"orn Rennecke <joern.rennecke@st.com>

	PR rtl-optimization/23898
	* output.h (get_attr_min_length): Declare.
	* final.c (get_attr_length_1): New function, broken out of:
	(get_attr_length).
	(get_attr_min_length): New function.
	* bb-reorder.c (copy_bb_p, get_uncond_jump_length): Use it.
	(duplicate_computed_gotos): Likewise.
	* genattr.c (insn_min_length): Generate declaration.
	* genattrtab.c (min_fn, min_attr_value): New functions.
	(make_length_attrs): Generate insn_min_length.

Index: bb-reorder.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/bb-reorder.c,v
retrieving revision 1.112
diff -p -r1.112 bb-reorder.c
*** bb-reorder.c	24 Aug 2005 07:56:51 -0000	1.112
--- bb-reorder.c	19 Sep 2005 20:17:19 -0000
*************** copy_bb_p (basic_block bb, int code_may_
*** 1178,1184 ****
    FOR_BB_INSNS (bb, insn)
      {
        if (INSN_P (insn))
! 	size += get_attr_length (insn);
      }
  
    if (size <= max_size)
--- 1178,1184 ----
    FOR_BB_INSNS (bb, insn)
      {
        if (INSN_P (insn))
! 	size += get_attr_min_length (insn);
      }
  
    if (size <= max_size)
*************** get_uncond_jump_length (void)
*** 1205,1211 ****
    label = emit_label_before (gen_label_rtx (), get_insns ());
    jump = emit_jump_insn (gen_jump (label));
  
!   length = get_attr_length (jump);
  
    delete_insn (jump);
    delete_insn (label);
--- 1205,1211 ----
    label = emit_label_before (gen_label_rtx (), get_insns ());
    jump = emit_jump_insn (gen_jump (label));
  
!   length = get_attr_min_length (jump);
  
    delete_insn (jump);
    delete_insn (label);
*************** duplicate_computed_gotos (void)
*** 2030,2036 ****
        FOR_BB_INSNS (bb, insn)
  	if (INSN_P (insn))
  	  {
! 	    size += get_attr_length (insn);
  	    if (size > max_size)
  	       break;
  	  }
--- 2030,2036 ----
        FOR_BB_INSNS (bb, insn)
  	if (INSN_P (insn))
  	  {
! 	    size += get_attr_min_length (insn);
  	    if (size > max_size)
  	       break;
  	  }
Index: final.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/final.c,v
retrieving revision 1.360
diff -p -r1.360 final.c
*** final.c	10 Aug 2005 09:02:42 -0000	1.360
--- final.c	19 Sep 2005 20:17:20 -0000
*************** init_insn_lengths (void)
*** 383,392 ****
  }
  
  /* Obtain the current length of an insn.  If branch shortening has been done,
!    get its actual length.  Otherwise, get its maximum length.  */
! 
! int
! get_attr_length (rtx insn ATTRIBUTE_UNUSED)
  {
  #ifdef HAVE_ATTR_length
    rtx body;
--- 383,392 ----
  }
  
  /* Obtain the current length of an insn.  If branch shortening has been done,
!    get its actual length.  Otherwise, use FALLBACK_FN to calcualte the
!    length.  */
! static inline int
! get_attr_length_1 (rtx insn ATTRIBUTE_UNUSED, int (*fallback_fn) (rtx))
  {
  #ifdef HAVE_ATTR_length
    rtx body;
*************** get_attr_length (rtx insn ATTRIBUTE_UNUS
*** 404,410 ****
  	return 0;
  
        case CALL_INSN:
! 	length = insn_default_length (insn);
  	break;
  
        case JUMP_INSN:
--- 404,410 ----
  	return 0;
  
        case CALL_INSN:
! 	length = fallback_fn (insn);
  	break;
  
        case JUMP_INSN:
*************** get_attr_length (rtx insn ATTRIBUTE_UNUS
*** 415,421 ****
  	       ADDR_VEC_ALIGN.  */
  	  }
  	else
! 	  length = insn_default_length (insn);
  	break;
  
        case INSN:
--- 415,421 ----
  	       ADDR_VEC_ALIGN.  */
  	  }
  	else
! 	  length = fallback_fn (insn);
  	break;
  
        case INSN:
*************** get_attr_length (rtx insn ATTRIBUTE_UNUS
*** 424,435 ****
  	  return 0;
  
  	else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
! 	  length = asm_insn_count (body) * insn_default_length (insn);
  	else if (GET_CODE (body) == SEQUENCE)
  	  for (i = 0; i < XVECLEN (body, 0); i++)
  	    length += get_attr_length (XVECEXP (body, 0, i));
  	else
! 	  length = insn_default_length (insn);
  	break;
  
        default:
--- 424,435 ----
  	  return 0;
  
  	else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
! 	  length = asm_insn_count (body) * fallback_fn (insn);
  	else if (GET_CODE (body) == SEQUENCE)
  	  for (i = 0; i < XVECLEN (body, 0); i++)
  	    length += get_attr_length (XVECEXP (body, 0, i));
  	else
! 	  length = fallback_fn (insn);
  	break;
  
        default:
*************** get_attr_length (rtx insn ATTRIBUTE_UNUS
*** 444,449 ****
--- 444,465 ----
    return 0;
  #endif /* not HAVE_ATTR_length */
  }
+ 
+ /* Obtain the current length of an insn.  If branch shortening has been done,
+    get its actual length.  Otherwise, get its maximum length.  */
+ int
+ get_attr_length (rtx insn)
+ {
+   return get_attr_length_1 (insn, insn_default_length);
+ }
+ 
+ /* Obtain the current length of an insn.  If branch shortening has been done,
+    get its actual length.  Otherwise, get its minimum length.  */
+ int
+ get_attr_min_length (rtx insn)
+ {
+   return get_attr_length_1 (insn, insn_min_length);
+ }
  
  /* Code to handle alignment inside shorten_branches.  */
  
Index: genattr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/genattr.c,v
retrieving revision 1.65
diff -p -r1.65 genattr.c
*** genattr.c	25 Jun 2005 02:00:11 -0000	1.65
--- genattr.c	19 Sep 2005 20:17:20 -0000
*************** gen_attr (rtx attr)
*** 79,84 ****
--- 79,85 ----
        puts ("\
  extern void shorten_branches (rtx);\n\
  extern int insn_default_length (rtx);\n\
+ extern int insn_min_length (rtx);\n\
  extern int insn_variable_length_p (rtx);\n\
  extern int insn_current_length (rtx);\n\n\
  #include \"insn-addr.h\"\n");
Index: genattrtab.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/genattrtab.c,v
retrieving revision 1.162
diff -p -r1.162 genattrtab.c
*** genattrtab.c	6 Aug 2005 21:11:52 -0000	1.162
--- genattrtab.c	19 Sep 2005 20:17:20 -0000
*************** static rtx identity_fn		(rtx);
*** 285,290 ****
--- 285,291 ----
  static rtx zero_fn		(rtx);
  static rtx one_fn		(rtx);
  static rtx max_fn		(rtx);
+ static rtx min_fn		(rtx);
  static void write_length_unit_log (void);
  static rtx simplify_cond	(rtx, int, int);
  static void clear_struct_flag (rtx);
*************** static void gen_insn		(rtx, int);
*** 307,312 ****
--- 308,314 ----
  static void gen_delay		(rtx, int);
  static void write_test_expr	(rtx, int);
  static int max_attr_value	(rtx, int*);
+ static int min_attr_value	(rtx, int*);
  static int or_attr_value	(rtx, int*);
  static void walk_attr_value	(rtx);
  static void write_attr_get	(struct attr_desc *);
*************** make_length_attrs (void)
*** 1583,1593 ****
    static const char *new_names[] =
      {
        "*insn_default_length",
        "*insn_variable_length_p",
        "*insn_current_length"
      };
!   static rtx (*const no_address_fn[]) (rtx) = {identity_fn, zero_fn, zero_fn};
!   static rtx (*const address_fn[]) (rtx) = {max_fn, one_fn, identity_fn};
    size_t i;
    struct attr_desc *length_attr, *new_attr;
    struct attr_value *av, *new_av;
--- 1585,1598 ----
    static const char *new_names[] =
      {
        "*insn_default_length",
+       "*insn_min_length",
        "*insn_variable_length_p",
        "*insn_current_length"
      };
!   static rtx (*const no_address_fn[]) (rtx)
!     = {identity_fn,identity_fn, zero_fn, zero_fn};
!   static rtx (*const address_fn[]) (rtx)
!     = {max_fn, min_fn, one_fn, identity_fn};
    size_t i;
    struct attr_desc *length_attr, *new_attr;
    struct attr_value *av, *new_av;
*************** max_fn (rtx exp)
*** 1654,1659 ****
--- 1659,1671 ----
    return make_numeric_value (max_attr_value (exp, &unknown));
  }
  
+ static rtx
+ min_fn (rtx exp)
+ {
+   int unknown;
+   return make_numeric_value (min_attr_value (exp, &unknown));
+ }
+ 
  static void
  write_length_unit_log (void)
  {
*************** max_attr_value (rtx exp, int *unknownp)
*** 3531,3536 ****
--- 3543,3589 ----
    return current_max;
  }
  
+ /* Given an attribute value, return the minimum CONST_STRING argument
+    encountered.  Set *UNKNOWNP and return 0 if the value is unknown.  */
+ 
+ static int
+ min_attr_value (rtx exp, int *unknownp)
+ {
+   int current_min;
+   int i, n;
+ 
+   switch (GET_CODE (exp))
+     {
+     case CONST_STRING:
+       current_min = atoi (XSTR (exp, 0));
+       break;
+ 
+     case COND:
+       current_min = min_attr_value (XEXP (exp, 1), unknownp);
+       for (i = 0; i < XVECLEN (exp, 0); i += 2)
+ 	{
+ 	  n = min_attr_value (XVECEXP (exp, 0, i + 1), unknownp);
+ 	  if (n < current_min)
+ 	    current_min = n;
+ 	}
+       break;
+ 
+     case IF_THEN_ELSE:
+       current_min = min_attr_value (XEXP (exp, 1), unknownp);
+       n = min_attr_value (XEXP (exp, 2), unknownp);
+       if (n < current_min)
+ 	current_min = n;
+       break;
+ 
+     default:
+       *unknownp = 1;
+       current_min = INT_MAX;
+       break;
+     }
+ 
+   return current_min;
+ }
+ 
  /* Given an attribute value, return the result of ORing together all
     CONST_STRING arguments encountered.  Set *UNKNOWNP and return -1
     if the numeric value is not known.  */
Index: output.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/output.h,v
retrieving revision 1.160
diff -p -r1.160 output.h
*** output.h	31 Jul 2005 09:12:24 -0000	1.160
--- output.h	19 Sep 2005 20:17:20 -0000
*************** extern void init_insn_lengths (void);
*** 49,54 ****
--- 49,58 ----
     get its actual length.  Otherwise, get its maximum length.  */
  extern int get_attr_length (rtx);
  
+ /* Obtain the current length of an insn.  If branch shortening has been done,
+    get its actual length.  Otherwise, get its minimum length.  */
+ extern int get_attr_min_length (rtx);
+ 
  /* Make a pass over all insns and compute their actual lengths by shortening
     any branches of variable length if possible.  */
  extern void shorten_branches (rtx);

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