Commit cf94b0fc by Paolo Bonzini Committed by Paolo Bonzini

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
parent b77302be
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> 2005-01-24 Jakub Jelinek <jakub@redhat.com>
* flow.c (propagate_one_insn): Formatting. * flow.c (propagate_one_insn): Formatting.
......
...@@ -966,6 +966,7 @@ enum label_kind ...@@ -966,6 +966,7 @@ enum label_kind
not to use an rtx with this cost under any circumstances. */ not to use an rtx with this cost under any circumstances. */
#define MAX_COST INT_MAX #define MAX_COST INT_MAX
extern void init_rtlanal (void);
extern int rtx_cost (rtx, enum rtx_code); extern int rtx_cost (rtx, enum rtx_code);
extern int address_cost (rtx, enum machine_mode); extern int address_cost (rtx, enum machine_mode);
extern unsigned int subreg_lsb (rtx); extern unsigned int subreg_lsb (rtx);
......
...@@ -58,6 +58,10 @@ static unsigned int cached_num_sign_bit_copies (rtx, enum machine_mode, rtx, ...@@ -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, static unsigned int num_sign_bit_copies1 (rtx, enum machine_mode, rtx,
enum machine_mode, unsigned int); 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. /* Bit flags that specify the machine subtype we are compiling for.
Bits are tested using macros TARGET_... defined in the tm.h file Bits are tested using macros TARGET_... defined in the tm.h file
and set by `-m...' switches. Must be defined in rtlanal.c. */ and set by `-m...' switches. Must be defined in rtlanal.c. */
...@@ -2624,61 +2628,67 @@ computed_jump_p (rtx insn) ...@@ -2624,61 +2628,67 @@ computed_jump_p (rtx insn)
return 0; return 0;
} }
/* Traverse X via depth-first search, calling F for each /* Optimized loop of for_each_rtx, trying to avoid useless recursive
sub-expression (including X itself). F is also passed the DATA. calls. Processes the subexpressions of EXP and passes them to F. */
If F returns -1, do not traverse sub-expressions, but continue static int
traversing the rest of the tree. If F ever returns any other for_each_rtx_1 (rtx exp, int n, rtx_function f, void *data)
nonzero value, stop the traversal, and return the value returned
by F. Otherwise, return 0. This function does not traverse inside
tree structure that contains RTX_EXPRs, or into sub-expressions
whose format code is `0' since it is not known whether or not those
codes are actually RTL.
This routine is very general, and could (should?) be used to
implement many of the other routines in this file. */
int
for_each_rtx (rtx *x, rtx_function f, void *data)
{ {
int result; int result, i, j;
int length; const char *format = GET_RTX_FORMAT (GET_CODE (exp));
const char *format; rtx *x;
int i;
for (; format[n] != '\0'; n++)
{
switch (format[n])
{
case 'e':
/* Call F on X. */ /* Call F on X. */
x = &XEXP (exp, n);
result = (*f) (x, data); result = (*f) (x, data);
if (result == -1) if (result == -1)
/* Do not traverse sub-expressions. */ /* Do not traverse sub-expressions. */
return 0; continue;
else if (result != 0) else if (result != 0)
/* Stop the traversal. */ /* Stop the traversal. */
return result; return result;
if (*x == NULL_RTX) if (*x == NULL_RTX)
/* There are no sub-expressions. */ /* There are no sub-expressions. */
return 0; continue;
length = GET_RTX_LENGTH (GET_CODE (*x));
format = GET_RTX_FORMAT (GET_CODE (*x));
for (i = 0; i < length; ++i) i = non_rtx_starting_operands[GET_CODE (*x)];
{ if (i >= 0)
switch (format[i])
{ {
case 'e': result = for_each_rtx_1 (*x, i, f, data);
result = for_each_rtx (&XEXP (*x, i), f, data);
if (result != 0) if (result != 0)
return result; return result;
}
break; break;
case 'V': case 'V':
case 'E': case 'E':
if (XVEC (*x, i) != 0) if (XVEC (exp, n) == 0)
continue;
for (j = 0; j < XVECLEN (exp, n); ++j)
{ {
int j; /* Call F on X. */
for (j = 0; j < XVECLEN (*x, i); ++j) 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 (&XVECEXP (*x, i, j), f, data); result = for_each_rtx_1 (*x, i, f, data);
if (result != 0) if (result != 0)
return result; return result;
} }
...@@ -2689,12 +2699,51 @@ for_each_rtx (rtx *x, rtx_function f, void *data) ...@@ -2689,12 +2699,51 @@ for_each_rtx (rtx *x, rtx_function f, void *data)
/* Nothing to do. */ /* Nothing to do. */
break; break;
} }
} }
return 0; 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
traversing the rest of the tree. If F ever returns any other
nonzero value, stop the traversal, and return the value returned
by F. Otherwise, return 0. This function does not traverse inside
tree structure that contains RTX_EXPRs, or into sub-expressions
whose format code is `0' since it is not known whether or not those
codes are actually RTL.
This routine is very general, and could (should?) be used to
implement many of the other routines in this file. */
int
for_each_rtx (rtx *x, rtx_function f, void *data)
{
int result;
int i;
/* Call F on X. */
result = (*f) (x, data);
if (result == -1)
/* Do not traverse sub-expressions. */
return 0;
else if (result != 0)
/* Stop the traversal. */
return result;
if (*x == NULL_RTX)
/* There are no sub-expressions. */
return 0;
i = non_rtx_starting_operands[GET_CODE (*x)];
if (i < 0)
return 0;
return for_each_rtx_1 (*x, i, f, data);
}
/* Searches X for any reference to REGNO, returning the rtx of the /* Searches X for any reference to REGNO, returning the rtx of the
reference found if any. Otherwise, returns NULL_RTX. */ 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) ...@@ -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); 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;
}
}
...@@ -1951,6 +1951,7 @@ backend_init (void) ...@@ -1951,6 +1951,7 @@ backend_init (void)
#endif #endif
|| flag_test_coverage); || flag_test_coverage);
init_rtlanal ();
init_regs (); init_regs ();
init_fake_stack_mems (); init_fake_stack_mems ();
init_alias_once (); init_alias_once ();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment