From: amylaar Date: Tue, 20 Sep 2005 21:48:36 +0000 (+0000) Subject: PR rtl-optimization/23898 X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=16afa8ae1933c570085475a7ea0fbdf9b8880b47 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@104468 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 15f7f29204d..a4e0484bc5f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2005-09-20 J"orn Rennecke + + 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. + 2005-09-20 Steve Ellcey * config/pa/pa.c (output_cbranch): Check for zero in operands[2]. diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c index c5de2352fa2..68d2cd88205 100644 --- a/gcc/bb-reorder.c +++ b/gcc/bb-reorder.c @@ -1178,7 +1178,7 @@ copy_bb_p (basic_block bb, int code_may_grow) FOR_BB_INSNS (bb, insn) { if (INSN_P (insn)) - size += get_attr_length (insn); + size += get_attr_min_length (insn); } if (size <= max_size) @@ -1205,7 +1205,7 @@ get_uncond_jump_length (void) label = emit_label_before (gen_label_rtx (), get_insns ()); jump = emit_jump_insn (gen_jump (label)); - length = get_attr_length (jump); + length = get_attr_min_length (jump); delete_insn (jump); delete_insn (label); @@ -2030,7 +2030,7 @@ duplicate_computed_gotos (void) FOR_BB_INSNS (bb, insn) if (INSN_P (insn)) { - size += get_attr_length (insn); + size += get_attr_min_length (insn); if (size > max_size) break; } diff --git a/gcc/final.c b/gcc/final.c index e1a4c189cf6..f8270698ecb 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -383,10 +383,11 @@ init_insn_lengths (void) } /* 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) + 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) ATTRIBUTE_UNUSED) { #ifdef HAVE_ATTR_length rtx body; @@ -404,7 +405,7 @@ get_attr_length (rtx insn ATTRIBUTE_UNUSED) return 0; case CALL_INSN: - length = insn_default_length (insn); + length = fallback_fn (insn); break; case JUMP_INSN: @@ -415,7 +416,7 @@ get_attr_length (rtx insn ATTRIBUTE_UNUSED) ADDR_VEC_ALIGN. */ } else - length = insn_default_length (insn); + length = fallback_fn (insn); break; case INSN: @@ -424,12 +425,12 @@ get_attr_length (rtx insn ATTRIBUTE_UNUSED) return 0; else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0) - length = asm_insn_count (body) * insn_default_length (insn); + 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 = insn_default_length (insn); + length = fallback_fn (insn); break; default: @@ -444,6 +445,22 @@ get_attr_length (rtx insn ATTRIBUTE_UNUSED) 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. */ diff --git a/gcc/genattr.c b/gcc/genattr.c index a103795c750..0e039e7a4b2 100644 --- a/gcc/genattr.c +++ b/gcc/genattr.c @@ -79,6 +79,7 @@ gen_attr (rtx attr) 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"); diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c index 78a61e86981..359ddddae10 100644 --- a/gcc/genattrtab.c +++ b/gcc/genattrtab.c @@ -285,6 +285,7 @@ static rtx identity_fn (rtx); 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); @@ -307,6 +308,7 @@ static void gen_insn (rtx, int); 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 *); @@ -1583,11 +1585,14 @@ make_length_attrs (void) 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, zero_fn, zero_fn}; - static rtx (*const address_fn[]) (rtx) = {max_fn, one_fn, identity_fn}; + 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; @@ -1654,6 +1659,13 @@ max_fn (rtx exp) 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) { @@ -3531,6 +3543,47 @@ max_attr_value (rtx exp, int *unknownp) 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. */ diff --git a/gcc/output.h b/gcc/output.h index c0dfb5fd1c4..cb8d8c04f7d 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -49,6 +49,10 @@ extern void init_insn_lengths (void); 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);