summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>2005-09-20 21:48:36 +0000
committeramylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4>2005-09-20 21:48:36 +0000
commit16afa8ae1933c570085475a7ea0fbdf9b8880b47 (patch)
treeb5aed08c2aba5538d50f0915cdd9050b95ec600d
parentd65b8df84253ce7cbef6fea4afb9af5b870e1751 (diff)
downloadgcc-16afa8ae1933c570085475a7ea0fbdf9b8880b47.tar.gz
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
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/bb-reorder.c6
-rw-r--r--gcc/final.c33
-rw-r--r--gcc/genattr.c1
-rw-r--r--gcc/genattrtab.c57
-rw-r--r--gcc/output.h4
6 files changed, 101 insertions, 13 deletions
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 <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.
+
2005-09-20 Steve Ellcey <sje@cup.hp.com>
* 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);