Index: gcc/gcc/rtl.c |
diff --git a/gcc/gcc/rtl.c b/gcc/gcc/rtl.c |
index c275091ad775df86f00209fa8f9ae78f442409b1..fe9c9514f1cd40624b9af8ab00ad8ebbc861b4bb 100644 |
--- a/gcc/gcc/rtl.c |
+++ b/gcc/gcc/rtl.c |
@@ -1,6 +1,6 @@ |
/* RTL utility routines. |
Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002, |
- 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. |
+ 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. |
This file is part of GCC. |
@@ -164,6 +164,20 @@ rtvec_alloc (int n) |
return rt; |
} |
+/* Create a bitwise copy of VEC. */ |
+ |
+rtvec |
+shallow_copy_rtvec (rtvec vec) |
+{ |
+ rtvec newvec; |
+ int n; |
+ |
+ n = GET_NUM_ELEM (vec); |
+ newvec = rtvec_alloc (n); |
+ memcpy (&newvec->elem[0], &vec->elem[0], sizeof (rtx) * n); |
+ return newvec; |
+} |
+ |
/* Return the number of bytes occupied by rtx value X. */ |
unsigned int |
@@ -206,12 +220,12 @@ bool |
shared_const_p (const_rtx orig) |
{ |
gcc_assert (GET_CODE (orig) == CONST); |
- |
+ |
/* CONST can be shared if it contains a SYMBOL_REF. If it contains |
a LABEL_REF, it isn't sharable. */ |
return (GET_CODE (XEXP (orig, 0)) == PLUS |
&& GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF |
- && GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT); |
+ && CONST_INT_P(XEXP (XEXP (orig, 0), 1))); |
} |
@@ -232,6 +246,8 @@ copy_rtx (rtx orig) |
switch (code) |
{ |
case REG: |
+ case DEBUG_EXPR: |
+ case VALUE: |
case CONST_INT: |
case CONST_DOUBLE: |
case CONST_FIXED: |
@@ -334,8 +350,10 @@ int currently_expanding_to_rtl; |
-/* Same as rtx_equal_p, but call CB on each pair of rtx if CB is not NULL. |
- When the callback returns true, we continue with the new pair. */ |
+/* Same as rtx_equal_p, but call CB on each pair of rtx if CB is not NULL. |
+ When the callback returns true, we continue with the new pair. |
+ Whenever changing this function check if rtx_equal_p below doesn't need |
+ changing as well. */ |
int |
rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb) |
@@ -367,6 +385,10 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb) |
if (GET_MODE (x) != GET_MODE (y)) |
return 0; |
+ /* MEMs refering to different address space are not equivalent. */ |
+ if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y)) |
+ return 0; |
+ |
/* Some RTL can be compared nonrecursively. */ |
switch (code) |
{ |
@@ -379,6 +401,8 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb) |
case SYMBOL_REF: |
return XSTR (x, 0) == XSTR (y, 0); |
+ case DEBUG_EXPR: |
+ case VALUE: |
case SCRATCH: |
case CONST_DOUBLE: |
case CONST_INT: |
@@ -416,7 +440,7 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb) |
/* And the corresponding elements must match. */ |
for (j = 0; j < XVECLEN (x, i); j++) |
- if (rtx_equal_p_cb (XVECEXP (x, i, j), |
+ if (rtx_equal_p_cb (XVECEXP (x, i, j), |
XVECEXP (y, i, j), cb) == 0) |
return 0; |
break; |
@@ -453,12 +477,122 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb) |
} |
/* Return 1 if X and Y are identical-looking rtx's. |
- This is the Lisp function EQUAL for rtx arguments. */ |
+ This is the Lisp function EQUAL for rtx arguments. |
+ Whenever changing this function check if rtx_equal_p_cb above doesn't need |
+ changing as well. */ |
int |
rtx_equal_p (const_rtx x, const_rtx y) |
{ |
- return rtx_equal_p_cb (x, y, NULL); |
+ int i; |
+ int j; |
+ enum rtx_code code; |
+ const char *fmt; |
+ |
+ if (x == y) |
+ return 1; |
+ if (x == 0 || y == 0) |
+ return 0; |
+ |
+ code = GET_CODE (x); |
+ /* Rtx's of different codes cannot be equal. */ |
+ if (code != GET_CODE (y)) |
+ return 0; |
+ |
+ /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. |
+ (REG:SI x) and (REG:HI x) are NOT equivalent. */ |
+ |
+ if (GET_MODE (x) != GET_MODE (y)) |
+ return 0; |
+ |
+ /* MEMs refering to different address space are not equivalent. */ |
+ if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y)) |
+ return 0; |
+ |
+ /* Some RTL can be compared nonrecursively. */ |
+ switch (code) |
+ { |
+ case REG: |
+ return (REGNO (x) == REGNO (y)); |
+ |
+ case LABEL_REF: |
+ return XEXP (x, 0) == XEXP (y, 0); |
+ |
+ case SYMBOL_REF: |
+ return XSTR (x, 0) == XSTR (y, 0); |
+ |
+ case DEBUG_EXPR: |
+ case VALUE: |
+ case SCRATCH: |
+ case CONST_DOUBLE: |
+ case CONST_INT: |
+ case CONST_FIXED: |
+ return 0; |
+ |
+ default: |
+ break; |
+ } |
+ |
+ /* Compare the elements. If any pair of corresponding elements |
+ fail to match, return 0 for the whole thing. */ |
+ |
+ fmt = GET_RTX_FORMAT (code); |
+ for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) |
+ { |
+ switch (fmt[i]) |
+ { |
+ case 'w': |
+ if (XWINT (x, i) != XWINT (y, i)) |
+ return 0; |
+ break; |
+ |
+ case 'n': |
+ case 'i': |
+ if (XINT (x, i) != XINT (y, i)) |
+ return 0; |
+ break; |
+ |
+ case 'V': |
+ case 'E': |
+ /* Two vectors must have the same length. */ |
+ if (XVECLEN (x, i) != XVECLEN (y, i)) |
+ return 0; |
+ |
+ /* And the corresponding elements must match. */ |
+ for (j = 0; j < XVECLEN (x, i); j++) |
+ if (rtx_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0) |
+ return 0; |
+ break; |
+ |
+ case 'e': |
+ if (rtx_equal_p (XEXP (x, i), XEXP (y, i)) == 0) |
+ return 0; |
+ break; |
+ |
+ case 'S': |
+ case 's': |
+ if ((XSTR (x, i) || XSTR (y, i)) |
+ && (! XSTR (x, i) || ! XSTR (y, i) |
+ || strcmp (XSTR (x, i), XSTR (y, i)))) |
+ return 0; |
+ break; |
+ |
+ case 'u': |
+ /* These are just backpointers, so they don't matter. */ |
+ break; |
+ |
+ case '0': |
+ case 't': |
+ break; |
+ |
+ /* It is believed that rtx's at this level will never |
+ contain anything but integers and other rtx's, |
+ except for within LABEL_REFs and SYMBOL_REFs. */ |
+ default: |
+ gcc_unreachable (); |
+ } |
+ } |
+ return 1; |
} |
void |
@@ -489,7 +623,7 @@ dump_rtx_statistics (void) |
fprintf (stderr, "%-20s %7d %10d\n", |
"Total", total_counts, total_sizes); |
fprintf (stderr, "---------------------------------------\n"); |
-#endif |
+#endif |
} |
#if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) |