This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RFA: fix PR rtl-optimization/23898
- From: Joern RENNECKE <joern dot rennecke at st dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 20 Sep 2005 19:54:23 +0100
- Subject: 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);