diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/rtl.h | 1 | ||||
-rw-r--r-- | gcc/rtlanal.c | 135 | ||||
-rw-r--r-- | gcc/toplev.c | 1 |
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. @@ -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 (); |