aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPaolo Bonzini <bonzini@gnu.org>2005-01-24 08:55:47 +0000
committerPaolo Bonzini <bonzini@gcc.gnu.org>2005-01-24 08:55:47 +0000
commitcf94b0fccc0d17e630f33ed3eff7619e71645f1c (patch)
tree41828e58bb4f1c77ba97241564241cbc154e5432 /gcc
parentb77302be88147ea826ab87d7d31e810fa68f4279 (diff)
downloadgcc-cf94b0fccc0d17e630f33ed3eff7619e71645f1c.zip
gcc-cf94b0fccc0d17e630f33ed3eff7619e71645f1c.tar.gz
gcc-cf94b0fccc0d17e630f33ed3eff7619e71645f1c.tar.bz2
rtlanal.c (non_rtx_starting_operands, [...]): New.
2005-01-24 Paolo Bonzini <bonzini@gnu.org> * rtlanal.c (non_rtx_starting_operands, for_each_rtx_1, init_rtlanal): New. (for_each_rtx): Call for_each_rtx_1. * rtl.h (init_rtlanal): Declare. * toplev.c (backend_init): Call init_rtlanal. From-SVN: r94146
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/rtlanal.c135
-rw-r--r--gcc/toplev.c1
4 files changed, 109 insertions, 36 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 815f01f..874eccd 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2005-01-24 Paolo Bonzini <bonzini@gnu.org>
+
+ * rtlanal.c (non_rtx_starting_operands, for_each_rtx_1,
+ init_rtlanal): New.
+ (for_each_rtx): Call for_each_rtx_1.
+ * rtl.h (init_rtlanal): Declare.
+ * toplev.c (backend_init): Call init_rtlanal.
+
2005-01-24 Jakub Jelinek <jakub@redhat.com>
* flow.c (propagate_one_insn): Formatting.
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 9579232..7e01029 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -966,6 +966,7 @@ enum label_kind
not to use an rtx with this cost under any circumstances. */
#define MAX_COST INT_MAX
+extern void init_rtlanal (void);
extern int rtx_cost (rtx, enum rtx_code);
extern int address_cost (rtx, enum machine_mode);
extern unsigned int subreg_lsb (rtx);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 607f74c..94e8d4c 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -58,6 +58,10 @@ static unsigned int cached_num_sign_bit_copies (rtx, enum machine_mode, rtx,
static unsigned int num_sign_bit_copies1 (rtx, enum machine_mode, rtx,
enum machine_mode, unsigned int);
+/* Offset of the first 'e', 'E' or 'V' operand for each rtx code, or
+ -1 if a code has no such operand. */
+static int non_rtx_starting_operands[NUM_RTX_CODE];
+
/* Bit flags that specify the machine subtype we are compiling for.
Bits are tested using macros TARGET_... defined in the tm.h file
and set by `-m...' switches. Must be defined in rtlanal.c. */
@@ -2624,6 +2628,82 @@ computed_jump_p (rtx insn)
return 0;
}
+/* Optimized loop of for_each_rtx, trying to avoid useless recursive
+ calls. Processes the subexpressions of EXP and passes them to F. */
+static int
+for_each_rtx_1 (rtx exp, int n, rtx_function f, void *data)
+{
+ int result, i, j;
+ const char *format = GET_RTX_FORMAT (GET_CODE (exp));
+ rtx *x;
+
+ for (; format[n] != '\0'; n++)
+ {
+ switch (format[n])
+ {
+ case 'e':
+ /* Call F on X. */
+ x = &XEXP (exp, n);
+ result = (*f) (x, data);
+ if (result == -1)
+ /* Do not traverse sub-expressions. */
+ continue;
+ else if (result != 0)
+ /* Stop the traversal. */
+ return result;
+
+ if (*x == NULL_RTX)
+ /* There are no sub-expressions. */
+ continue;
+
+ i = non_rtx_starting_operands[GET_CODE (*x)];
+ if (i >= 0)
+ {
+ result = for_each_rtx_1 (*x, i, f, data);
+ if (result != 0)
+ return result;
+ }
+ break;
+
+ case 'V':
+ case 'E':
+ if (XVEC (exp, n) == 0)
+ continue;
+ for (j = 0; j < XVECLEN (exp, n); ++j)
+ {
+ /* Call F on X. */
+ x = &XVECEXP (exp, n, j);
+ result = (*f) (x, data);
+ if (result == -1)
+ /* Do not traverse sub-expressions. */
+ continue;
+ else if (result != 0)
+ /* Stop the traversal. */
+ return result;
+
+ if (*x == NULL_RTX)
+ /* There are no sub-expressions. */
+ continue;
+
+ i = non_rtx_starting_operands[GET_CODE (*x)];
+ if (i >= 0)
+ {
+ result = for_each_rtx_1 (*x, i, f, data);
+ if (result != 0)
+ return result;
+ }
+ }
+ break;
+
+ default:
+ /* Nothing to do. */
+ break;
+ }
+ }
+
+ return 0;
+}
+
/* Traverse X via depth-first search, calling F for each
sub-expression (including X itself). F is also passed the DATA.
If F returns -1, do not traverse sub-expressions, but continue
@@ -2641,8 +2721,6 @@ int
for_each_rtx (rtx *x, rtx_function f, void *data)
{
int result;
- int length;
- const char *format;
int i;
/* Call F on X. */
@@ -2658,43 +2736,14 @@ for_each_rtx (rtx *x, rtx_function f, void *data)
/* There are no sub-expressions. */
return 0;
- length = GET_RTX_LENGTH (GET_CODE (*x));
- format = GET_RTX_FORMAT (GET_CODE (*x));
-
- for (i = 0; i < length; ++i)
- {
- switch (format[i])
- {
- case 'e':
- result = for_each_rtx (&XEXP (*x, i), f, data);
- if (result != 0)
- return result;
- break;
-
- case 'V':
- case 'E':
- if (XVEC (*x, i) != 0)
- {
- int j;
- for (j = 0; j < XVECLEN (*x, i); ++j)
- {
- result = for_each_rtx (&XVECEXP (*x, i, j), f, data);
- if (result != 0)
- return result;
- }
- }
- break;
-
- default:
- /* Nothing to do. */
- break;
- }
-
- }
+ i = non_rtx_starting_operands[GET_CODE (*x)];
+ if (i < 0)
+ return 0;
- return 0;
+ return for_each_rtx_1 (*x, i, f, data);
}
+
/* Searches X for any reference to REGNO, returning the rtx of the
reference found if any. Otherwise, returns NULL_RTX. */
@@ -4612,3 +4661,17 @@ get_condition (rtx jump, rtx *earliest, int allow_cc_mode, int valid_at_insn_p)
allow_cc_mode, valid_at_insn_p);
}
+
+/* Initialize non_rtx_starting_operands, which is used to speed up
+ for_each_rtx. */
+void
+init_rtlanal (void)
+{
+ int i;
+ for (i = 0; i < NUM_RTX_CODE; i++)
+ {
+ const char *format = GET_RTX_FORMAT (i);
+ const char *first = strpbrk (format, "eEV");
+ non_rtx_starting_operands[i] = first ? first - format : -1;
+ }
+}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index e79090f..af57e57 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1951,6 +1951,7 @@ backend_init (void)
#endif
|| flag_test_coverage);
+ init_rtlanal ();
init_regs ();
init_fake_stack_mems ();
init_alias_once ();