Commit 5dfa45d0 by Jakub Jelinek Committed by Jakub Jelinek

configure.in (--enable-checking): Add fold category.

	* configure.in (--enable-checking): Add fold category.
	(ENABLE_FOLD_CHECKING): Define if requested.
	* configure: Rebuilt.
	* config.in: Rebuilt.
	* doc/install.texi: Document it.
	* fold-const.c: Include md5.h.
	[ENABLE_FOLD_CHECKING] (fold): Define to fold_1.
	[ENABLE_FOLD_CHECKING] (fold, fold_checksum_tree, fold_check_failed,
	print_fold_checksum): New functions.

	* fold-const.c (fold): Never modify argument passed to fold, instead
	change a copy and return it.
	* convert.c (convert_to_integer): Likewise.
testsuite/
	* gcc.c-torture/compile/20030725-1.c: New test.

From-SVN: r69886
parent 66584e64
2003-07-28 Jakub Jelinek <jakub@redhat.com>
* configure.in (--enable-checking): Add fold category.
(ENABLE_FOLD_CHECKING): Define if requested.
* configure: Rebuilt.
* config.in: Rebuilt.
* doc/install.texi: Document it.
* fold-const.c: Include md5.h.
[ENABLE_FOLD_CHECKING] (fold): Define to fold_1.
[ENABLE_FOLD_CHECKING] (fold, fold_checksum_tree, fold_check_failed,
print_fold_checksum): New functions.
* fold-const.c (fold): Never modify argument passed to fold, instead
change a copy and return it.
* convert.c (convert_to_integer): Likewise.
2003-07-27 Nathanael Nerode <neroden@gcc.gnu.org> 2003-07-27 Nathanael Nerode <neroden@gcc.gnu.org>
* fixinc/fixinc.svr4: Remove dead code. Remove now-unnecessary * fixinc/fixinc.svr4: Remove dead code. Remove now-unnecessary
......
/* config.in. Generated automatically from configure.in by autoheader 2.13. */ /* config.in. Generated automatically from configure.in by autoheader. */
/* Define to the type of elements in the array set by `getgroups'. /* Define to the type of elements in the array set by `getgroups'.
Usually this is either `int' or `gid_t'. */ Usually this is either `int' or `gid_t'. */
...@@ -236,6 +236,10 @@ ...@@ -236,6 +236,10 @@
every opportunity. This is extremely expensive. */ every opportunity. This is extremely expensive. */
#undef ENABLE_GC_ALWAYS_COLLECT #undef ENABLE_GC_ALWAYS_COLLECT
/* Define if you want fold checked that it never destructs its argument.
This is quite expensive. */
#undef ENABLE_FOLD_CHECKING
/* Define if you want to run subprograms and generated programs /* Define if you want to run subprograms and generated programs
through valgrind (a memory checker). This is extremely expensive. */ through valgrind (a memory checker). This is extremely expensive. */
#undef ENABLE_VALGRIND_CHECKING #undef ENABLE_VALGRIND_CHECKING
......
...@@ -34,7 +34,7 @@ ac_help="$ac_help ...@@ -34,7 +34,7 @@ ac_help="$ac_help
--enable-checking[=LIST] --enable-checking[=LIST]
enable expensive run-time checks. With LIST, enable expensive run-time checks. With LIST,
enable only specific categories of checks. enable only specific categories of checks.
Categories are: misc,tree,rtl,rtlflag,gc,gcac; Categories are: misc,tree,rtl,rtlflag,gc,gcac,fold;
default is misc,tree,gc,rtlflag" default is misc,tree,gc,rtlflag"
ac_help="$ac_help ac_help="$ac_help
--enable-coverage[=LEVEL] --enable-coverage[=LEVEL]
...@@ -1933,6 +1933,7 @@ ac_rtl_checking= ...@@ -1933,6 +1933,7 @@ ac_rtl_checking=
ac_rtlflag_checking= ac_rtlflag_checking=
ac_gc_checking= ac_gc_checking=
ac_gc_always_collect= ac_gc_always_collect=
ac_fold_checking=
case "${enableval}" in case "${enableval}" in
yes) ac_checking=1 ; ac_tree_checking=1 ; ac_gc_checking=1 ; yes) ac_checking=1 ; ac_tree_checking=1 ; ac_gc_checking=1 ;
ac_rtlflag_checking=1 ;; ac_rtlflag_checking=1 ;;
...@@ -1949,6 +1950,7 @@ no) ;; ...@@ -1949,6 +1950,7 @@ no) ;;
rtl) ac_rtl_checking=1 ;; rtl) ac_rtl_checking=1 ;;
gc) ac_gc_checking=1 ;; gc) ac_gc_checking=1 ;;
gcac) ac_gc_always_collect=1 ;; gcac) ac_gc_always_collect=1 ;;
fold) ac_fold_checking=1 ;;
valgrind) ac_checking_valgrind=1 ;; valgrind) ac_checking_valgrind=1 ;;
*) { echo "configure: error: unknown check category $check" 1>&2; exit 1; } ;; *) { echo "configure: error: unknown check category $check" 1>&2; exit 1; } ;;
esac esac
...@@ -2000,6 +2002,12 @@ if test x$ac_gc_always_collect != x ; then ...@@ -2000,6 +2002,12 @@ if test x$ac_gc_always_collect != x ; then
EOF EOF
fi fi
if test x$ac_fold_checking != x ; then
cat >> confdefs.h <<\EOF
#define ENABLE_FOLD_CHECKING 1
EOF
fi
valgrind_path_defines= valgrind_path_defines=
valgrind_command= valgrind_command=
if test x$ac_checking_valgrind != x ; then if test x$ac_checking_valgrind != x ; then
......
...@@ -318,7 +318,7 @@ AC_ARG_ENABLE(checking, ...@@ -318,7 +318,7 @@ AC_ARG_ENABLE(checking,
[ --enable-checking[=LIST] [ --enable-checking[=LIST]
enable expensive run-time checks. With LIST, enable expensive run-time checks. With LIST,
enable only specific categories of checks. enable only specific categories of checks.
Categories are: misc,tree,rtl,rtlflag,gc,gcac; Categories are: misc,tree,rtl,rtlflag,gc,gcac,fold;
default is misc,tree,gc,rtlflag], default is misc,tree,gc,rtlflag],
[ac_checking= [ac_checking=
ac_tree_checking= ac_tree_checking=
...@@ -326,6 +326,7 @@ ac_rtl_checking= ...@@ -326,6 +326,7 @@ ac_rtl_checking=
ac_rtlflag_checking= ac_rtlflag_checking=
ac_gc_checking= ac_gc_checking=
ac_gc_always_collect= ac_gc_always_collect=
ac_fold_checking=
case "${enableval}" in case "${enableval}" in
yes) ac_checking=1 ; ac_tree_checking=1 ; ac_gc_checking=1 ; yes) ac_checking=1 ; ac_tree_checking=1 ; ac_gc_checking=1 ;
ac_rtlflag_checking=1 ;; ac_rtlflag_checking=1 ;;
...@@ -342,6 +343,7 @@ no) ;; ...@@ -342,6 +343,7 @@ no) ;;
rtl) ac_rtl_checking=1 ;; rtl) ac_rtl_checking=1 ;;
gc) ac_gc_checking=1 ;; gc) ac_gc_checking=1 ;;
gcac) ac_gc_always_collect=1 ;; gcac) ac_gc_always_collect=1 ;;
fold) ac_fold_checking=1 ;;
valgrind) ac_checking_valgrind=1 ;; valgrind) ac_checking_valgrind=1 ;;
*) AC_MSG_ERROR(unknown check category $check) ;; *) AC_MSG_ERROR(unknown check category $check) ;;
esac esac
...@@ -388,6 +390,11 @@ if test x$ac_gc_always_collect != x ; then ...@@ -388,6 +390,11 @@ if test x$ac_gc_always_collect != x ; then
paranoid mode, validating the entire heap and collecting garbage at paranoid mode, validating the entire heap and collecting garbage at
every opportunity. This is extremely expensive.]) every opportunity. This is extremely expensive.])
fi fi
if test x$ac_fold_checking != x ; then
AC_DEFINE(ENABLE_FOLD_CHECKING, 1,
[Define if you want fold checked that it never destructs its argument.
This is quite expensive.])
fi
valgrind_path_defines= valgrind_path_defines=
valgrind_command= valgrind_command=
if test x$ac_checking_valgrind != x ; then if test x$ac_checking_valgrind != x ; then
......
...@@ -320,6 +320,7 @@ convert_to_integer (tree type, tree expr) ...@@ -320,6 +320,7 @@ convert_to_integer (tree type, tree expr)
if (TREE_CODE_CLASS (ex_form) == '<') if (TREE_CODE_CLASS (ex_form) == '<')
{ {
expr = copy_node (expr);
TREE_TYPE (expr) = type; TREE_TYPE (expr) = type;
return expr; return expr;
} }
...@@ -328,6 +329,7 @@ convert_to_integer (tree type, tree expr) ...@@ -328,6 +329,7 @@ convert_to_integer (tree type, tree expr)
|| ex_form == TRUTH_OR_EXPR || ex_form == TRUTH_ORIF_EXPR || ex_form == TRUTH_OR_EXPR || ex_form == TRUTH_ORIF_EXPR
|| ex_form == TRUTH_XOR_EXPR) || ex_form == TRUTH_XOR_EXPR)
{ {
expr = copy_node (expr);
TREE_OPERAND (expr, 0) = convert (type, TREE_OPERAND (expr, 0)); TREE_OPERAND (expr, 0) = convert (type, TREE_OPERAND (expr, 0));
TREE_OPERAND (expr, 1) = convert (type, TREE_OPERAND (expr, 1)); TREE_OPERAND (expr, 1) = convert (type, TREE_OPERAND (expr, 1));
TREE_TYPE (expr) = type; TREE_TYPE (expr) = type;
...@@ -336,6 +338,7 @@ convert_to_integer (tree type, tree expr) ...@@ -336,6 +338,7 @@ convert_to_integer (tree type, tree expr)
else if (ex_form == TRUTH_NOT_EXPR) else if (ex_form == TRUTH_NOT_EXPR)
{ {
expr = copy_node (expr);
TREE_OPERAND (expr, 0) = convert (type, TREE_OPERAND (expr, 0)); TREE_OPERAND (expr, 0) = convert (type, TREE_OPERAND (expr, 0));
TREE_TYPE (expr) = type; TREE_TYPE (expr) = type;
return expr; return expr;
......
...@@ -1038,8 +1038,8 @@ with GCC@. This is on by default when building from CVS or snapshots, ...@@ -1038,8 +1038,8 @@ with GCC@. This is on by default when building from CVS or snapshots,
but off for releases. More control over the checks may be had by but off for releases. More control over the checks may be had by
specifying @var{list}; the categories of checks available are specifying @var{list}; the categories of checks available are
@samp{misc}, @samp{tree}, @samp{gc}, @samp{rtl}, @samp{rtlflag}, @samp{misc}, @samp{tree}, @samp{gc}, @samp{rtl}, @samp{rtlflag},
@samp{gcac} and @samp{valgrind}. The check @samp{valgrind} requires the @samp{fold}, @samp{gcac} and @samp{valgrind}. The check @samp{valgrind}
external @command{valgrind} simulator, available from requires the external @command{valgrind} simulator, available from
@uref{http://developer.kde.org/~sewardj/}. The default when @var{list} is @uref{http://developer.kde.org/~sewardj/}. The default when @var{list} is
not specified is @samp{misc,tree,gc,rtlflag}; the checks @samp{rtl}, not specified is @samp{misc,tree,gc,rtlflag}; the checks @samp{rtl},
@samp{gcac} and @samp{valgrind} are very expensive. @samp{gcac} and @samp{valgrind} are very expensive.
......
...@@ -56,6 +56,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -56,6 +56,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "ggc.h" #include "ggc.h"
#include "hashtab.h" #include "hashtab.h"
#include "langhooks.h" #include "langhooks.h"
#include "md5.h"
static void encode (HOST_WIDE_INT *, unsigned HOST_WIDE_INT, HOST_WIDE_INT); static void encode (HOST_WIDE_INT *, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
static void decode (HOST_WIDE_INT *, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *); static void decode (HOST_WIDE_INT *, unsigned HOST_WIDE_INT *, HOST_WIDE_INT *);
...@@ -4921,7 +4922,7 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1, ...@@ -4921,7 +4922,7 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
} }
return NULL_TREE; return NULL_TREE;
} }
/* Perform constant folding and related simplification of EXPR. /* Perform constant folding and related simplification of EXPR.
The related simplifications include x*1 => x, x*0 => 0, etc., The related simplifications include x*1 => x, x*0 => 0, etc.,
and application of the associative law. and application of the associative law.
...@@ -4930,10 +4931,15 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1, ...@@ -4930,10 +4931,15 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
We cannot simplify through a CONVERT_EXPR, FIX_EXPR or FLOAT_EXPR, We cannot simplify through a CONVERT_EXPR, FIX_EXPR or FLOAT_EXPR,
but we can constant-fold them if they have constant operands. */ but we can constant-fold them if they have constant operands. */
#ifdef ENABLE_FOLD_CHECKING
# define fold(x) fold_1 (x)
static tree fold_1 (tree);
static
#endif
tree tree
fold (tree expr) fold (tree expr)
{ {
tree t = expr; tree t = expr, orig_t;
tree t1 = NULL_TREE; tree t1 = NULL_TREE;
tree tem; tree tem;
tree type = TREE_TYPE (expr); tree type = TREE_TYPE (expr);
...@@ -4957,6 +4963,7 @@ fold (tree expr) ...@@ -4957,6 +4963,7 @@ fold (tree expr)
#ifdef MAX_INTEGER_COMPUTATION_MODE #ifdef MAX_INTEGER_COMPUTATION_MODE
check_max_integer_computation_mode (expr); check_max_integer_computation_mode (expr);
#endif #endif
orig_t = t;
if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR) if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
{ {
...@@ -5028,12 +5035,15 @@ fold (tree expr) ...@@ -5028,12 +5035,15 @@ fold (tree expr)
if ((code == PLUS_EXPR || code == MULT_EXPR || code == MIN_EXPR if ((code == PLUS_EXPR || code == MULT_EXPR || code == MIN_EXPR
|| code == MAX_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR || code == MAX_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_EXPR
|| code == BIT_AND_EXPR) || code == BIT_AND_EXPR)
&& (TREE_CODE (arg0) == INTEGER_CST || TREE_CODE (arg0) == REAL_CST)) && ((TREE_CODE (arg0) == INTEGER_CST && TREE_CODE (arg1) != INTEGER_CST)
|| (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) != REAL_CST)))
{ {
tem = arg0; arg0 = arg1; arg1 = tem; tem = arg0; arg0 = arg1; arg1 = tem;
tem = TREE_OPERAND (t, 0); TREE_OPERAND (t, 0) = TREE_OPERAND (t, 1); if (t == orig_t)
TREE_OPERAND (t, 1) = tem; t = copy_node (t);
TREE_OPERAND (t, 0) = arg0;
TREE_OPERAND (t, 1) = arg1;
} }
/* Now WINS is set as described above, /* Now WINS is set as described above,
...@@ -5282,6 +5292,8 @@ fold (tree expr) ...@@ -5282,6 +5292,8 @@ fold (tree expr)
/* Don't leave an assignment inside a conversion /* Don't leave an assignment inside a conversion
unless assigning a bitfield. */ unless assigning a bitfield. */
tree prev = TREE_OPERAND (t, 0); tree prev = TREE_OPERAND (t, 0);
if (t == orig_t)
t = copy_node (t);
TREE_OPERAND (t, 0) = TREE_OPERAND (prev, 1); TREE_OPERAND (t, 0) = TREE_OPERAND (prev, 1);
/* First do the assignment, then return converted constant. */ /* First do the assignment, then return converted constant. */
t = build (COMPOUND_EXPR, TREE_TYPE (t), prev, fold (t)); t = build (COMPOUND_EXPR, TREE_TYPE (t), prev, fold (t));
...@@ -5334,7 +5346,12 @@ fold (tree expr) ...@@ -5334,7 +5346,12 @@ fold (tree expr)
if (!wins) if (!wins)
{ {
TREE_CONSTANT (t) = TREE_CONSTANT (arg0); if (TREE_CONSTANT (t) != TREE_CONSTANT (arg0))
{
if (t == orig_t)
t = copy_node (t);
TREE_CONSTANT (t) = TREE_CONSTANT (arg0);
}
return t; return t;
} }
return fold_convert (t, arg0); return fold_convert (t, arg0);
...@@ -5356,7 +5373,12 @@ fold (tree expr) ...@@ -5356,7 +5373,12 @@ fold (tree expr)
return t; return t;
case RANGE_EXPR: case RANGE_EXPR:
TREE_CONSTANT (t) = wins; if (TREE_CONSTANT (t) != wins)
{
if (t == orig_t)
t = copy_node (t);
TREE_CONSTANT (t) = wins;
}
return t; return t;
case NEGATE_EXPR: case NEGATE_EXPR:
...@@ -6379,6 +6401,8 @@ fold (tree expr) ...@@ -6379,6 +6401,8 @@ fold (tree expr)
RROTATE_EXPR by a new constant. */ RROTATE_EXPR by a new constant. */
if (code == LROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST) if (code == LROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST)
{ {
if (t == orig_t)
t = copy_node (t);
TREE_SET_CODE (t, RROTATE_EXPR); TREE_SET_CODE (t, RROTATE_EXPR);
code = RROTATE_EXPR; code = RROTATE_EXPR;
TREE_OPERAND (t, 1) = arg1 TREE_OPERAND (t, 1) = arg1
...@@ -6591,6 +6615,8 @@ fold (tree expr) ...@@ -6591,6 +6615,8 @@ fold (tree expr)
|| (TREE_CODE (arg0) == REAL_CST || (TREE_CODE (arg0) == REAL_CST
&& TREE_CODE (arg0) != REAL_CST)) && TREE_CODE (arg0) != REAL_CST))
{ {
if (t == orig_t)
t = copy_node (t);
TREE_OPERAND (t, 0) = arg1; TREE_OPERAND (t, 0) = arg1;
TREE_OPERAND (t, 1) = arg0; TREE_OPERAND (t, 1) = arg0;
arg0 = TREE_OPERAND (t, 0); arg0 = TREE_OPERAND (t, 0);
...@@ -6907,6 +6933,8 @@ fold (tree expr) ...@@ -6907,6 +6933,8 @@ fold (tree expr)
arg0); arg0);
case GE_EXPR: case GE_EXPR:
code = EQ_EXPR; code = EQ_EXPR;
if (t == orig_t)
t = copy_node (t);
TREE_SET_CODE (t, EQ_EXPR); TREE_SET_CODE (t, EQ_EXPR);
break; break;
case LE_EXPR: case LE_EXPR:
...@@ -6915,6 +6943,8 @@ fold (tree expr) ...@@ -6915,6 +6943,8 @@ fold (tree expr)
arg0); arg0);
case LT_EXPR: case LT_EXPR:
code = NE_EXPR; code = NE_EXPR;
if (t == orig_t)
t = copy_node (t);
TREE_SET_CODE (t, NE_EXPR); TREE_SET_CODE (t, NE_EXPR);
break; break;
...@@ -6951,6 +6981,8 @@ fold (tree expr) ...@@ -6951,6 +6981,8 @@ fold (tree expr)
arg0); arg0);
case LE_EXPR: case LE_EXPR:
code = EQ_EXPR; code = EQ_EXPR;
if (t == orig_t)
t = copy_node (t);
TREE_SET_CODE (t, EQ_EXPR); TREE_SET_CODE (t, EQ_EXPR);
break; break;
...@@ -6960,6 +6992,8 @@ fold (tree expr) ...@@ -6960,6 +6992,8 @@ fold (tree expr)
arg0); arg0);
case GT_EXPR: case GT_EXPR:
code = NE_EXPR; code = NE_EXPR;
if (t == orig_t)
t = copy_node (t);
TREE_SET_CODE (t, NE_EXPR); TREE_SET_CODE (t, NE_EXPR);
break; break;
...@@ -7185,6 +7219,8 @@ fold (tree expr) ...@@ -7185,6 +7219,8 @@ fold (tree expr)
|| ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0)))) || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
return constant_boolean_node (1, type); return constant_boolean_node (1, type);
code = EQ_EXPR; code = EQ_EXPR;
if (t == orig_t)
t = copy_node (t);
TREE_SET_CODE (t, code); TREE_SET_CODE (t, code);
break; break;
...@@ -7902,6 +7938,199 @@ fold (tree expr) ...@@ -7902,6 +7938,199 @@ fold (tree expr)
} /* switch (code) */ } /* switch (code) */
} }
#ifdef ENABLE_FOLD_CHECKING
#undef fold
static void fold_checksum_tree (tree, struct md5_ctx *, htab_t);
static void fold_check_failed (tree, tree);
void print_fold_checksum (tree);
/* When --enable-checking=fold, compute a digest of expr before
and after actual fold call to see if fold did not accidentally
change original expr. */
tree
fold (tree expr)
{
tree ret;
struct md5_ctx ctx;
unsigned char checksum_before[16], checksum_after[16];
htab_t ht;
ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL);
md5_init_ctx (&ctx);
fold_checksum_tree (expr, &ctx, ht);
md5_finish_ctx (&ctx, checksum_before);
htab_empty (ht);
ret = fold_1 (expr);
md5_init_ctx (&ctx);
fold_checksum_tree (expr, &ctx, ht);
md5_finish_ctx (&ctx, checksum_after);
htab_delete (ht);
if (memcmp (checksum_before, checksum_after, 16))
fold_check_failed (expr, ret);
return ret;
}
void
print_fold_checksum (tree expr)
{
struct md5_ctx ctx;
unsigned char checksum[16], cnt;
htab_t ht;
ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL);
md5_init_ctx (&ctx);
fold_checksum_tree (expr, &ctx, ht);
md5_finish_ctx (&ctx, checksum);
htab_delete (ht);
for (cnt = 0; cnt < 16; ++cnt)
fprintf (stderr, "%02x", checksum[cnt]);
putc ('\n', stderr);
}
static void
fold_check_failed (tree expr ATTRIBUTE_UNUSED, tree ret ATTRIBUTE_UNUSED)
{
internal_error ("fold check: original tree changed by fold");
}
static void
fold_checksum_tree (tree expr, struct md5_ctx *ctx, htab_t ht)
{
void **slot;
enum tree_code code;
char buf[sizeof (struct tree_decl)];
int i, len;
if (sizeof (struct tree_exp) + 5 * sizeof (tree)
> sizeof (struct tree_decl)
|| sizeof (struct tree_type) > sizeof (struct tree_decl))
abort ();
if (expr == NULL)
return;
slot = htab_find_slot (ht, expr, INSERT);
if (*slot != NULL)
return;
*slot = expr;
code = TREE_CODE (expr);
if (code == SAVE_EXPR && SAVE_EXPR_NOPLACEHOLDER (expr))
{
/* Allow SAVE_EXPR_NOPLACEHOLDER flag to be modified. */
memcpy (buf, expr, tree_size (expr));
expr = (tree) buf;
SAVE_EXPR_NOPLACEHOLDER (expr) = 0;
}
else if (TREE_CODE_CLASS (code) == 'd' && DECL_ASSEMBLER_NAME_SET_P (expr))
{
/* Allow DECL_ASSEMBLER_NAME to be modified. */
memcpy (buf, expr, tree_size (expr));
expr = (tree) buf;
SET_DECL_ASSEMBLER_NAME (expr, NULL);
}
else if (TREE_CODE_CLASS (code) == 't'
&& (TYPE_POINTER_TO (expr) || TYPE_REFERENCE_TO (expr)))
{
/* Allow TYPE_POINTER_TO and TYPE_REFERENCE_TO to be modified. */
memcpy (buf, expr, tree_size (expr));
expr = (tree) buf;
TYPE_POINTER_TO (expr) = NULL;
TYPE_REFERENCE_TO (expr) = NULL;
}
md5_process_bytes (expr, tree_size (expr), ctx);
fold_checksum_tree (TREE_TYPE (expr), ctx, ht);
if (TREE_CODE_CLASS (code) != 't' && TREE_CODE_CLASS (code) != 'd')
fold_checksum_tree (TREE_CHAIN (expr), ctx, ht);
len = TREE_CODE_LENGTH (code);
switch (TREE_CODE_CLASS (code))
{
case 'c':
switch (code)
{
case STRING_CST:
md5_process_bytes (TREE_STRING_POINTER (expr),
TREE_STRING_LENGTH (expr), ctx);
break;
case COMPLEX_CST:
fold_checksum_tree (TREE_REALPART (expr), ctx, ht);
fold_checksum_tree (TREE_IMAGPART (expr), ctx, ht);
break;
case VECTOR_CST:
fold_checksum_tree (TREE_VECTOR_CST_ELTS (expr), ctx, ht);
break;
default:
break;
}
break;
case 'x':
switch (code)
{
case TREE_LIST:
fold_checksum_tree (TREE_PURPOSE (expr), ctx, ht);
fold_checksum_tree (TREE_VALUE (expr), ctx, ht);
break;
case TREE_VEC:
for (i = 0; i < TREE_VEC_LENGTH (expr); ++i)
fold_checksum_tree (TREE_VEC_ELT (expr, i), ctx, ht);
break;
default:
break;
}
break;
case 'e':
switch (code)
{
case SAVE_EXPR: len = 2; break;
case GOTO_SUBROUTINE_EXPR: len = 0; break;
case RTL_EXPR: len = 0; break;
case WITH_CLEANUP_EXPR: len = 2; break;
default: break;
}
/* FALLTHROUGH */
case 'r':
case '<':
case '1':
case '2':
case 's':
for (i = 0; i < len; ++i)
fold_checksum_tree (TREE_OPERAND (expr, i), ctx, ht);
break;
case 'd':
fold_checksum_tree (DECL_SIZE (expr), ctx, ht);
fold_checksum_tree (DECL_SIZE_UNIT (expr), ctx, ht);
fold_checksum_tree (DECL_NAME (expr), ctx, ht);
fold_checksum_tree (DECL_CONTEXT (expr), ctx, ht);
fold_checksum_tree (DECL_ARGUMENTS (expr), ctx, ht);
fold_checksum_tree (DECL_RESULT_FLD (expr), ctx, ht);
fold_checksum_tree (DECL_INITIAL (expr), ctx, ht);
fold_checksum_tree (DECL_ABSTRACT_ORIGIN (expr), ctx, ht);
fold_checksum_tree (DECL_SECTION_NAME (expr), ctx, ht);
fold_checksum_tree (DECL_ATTRIBUTES (expr), ctx, ht);
fold_checksum_tree (DECL_VINDEX (expr), ctx, ht);
break;
case 't':
fold_checksum_tree (TYPE_VALUES (expr), ctx, ht);
fold_checksum_tree (TYPE_SIZE (expr), ctx, ht);
fold_checksum_tree (TYPE_SIZE_UNIT (expr), ctx, ht);
fold_checksum_tree (TYPE_ATTRIBUTES (expr), ctx, ht);
fold_checksum_tree (TYPE_NAME (expr), ctx, ht);
fold_checksum_tree (TYPE_MIN_VALUE (expr), ctx, ht);
fold_checksum_tree (TYPE_MAX_VALUE (expr), ctx, ht);
fold_checksum_tree (TYPE_MAIN_VARIANT (expr), ctx, ht);
fold_checksum_tree (TYPE_BINFO (expr), ctx, ht);
fold_checksum_tree (TYPE_CONTEXT (expr), ctx, ht);
break;
default:
break;
}
}
#endif
/* Perform constant folding and related simplification of intializer /* Perform constant folding and related simplification of intializer
expression EXPR. This behaves identically to "fold" but ignores expression EXPR. This behaves identically to "fold" but ignores
potential run-time traps and exceptions that fold must preserve. */ potential run-time traps and exceptions that fold must preserve. */
......
2003-07-28 Jakub Jelinek <jakub@redhat.com>
* gcc.c-torture/compile/20030725-1.c: New test.
2003-07-28 Aldy Hernandez <aldyh@redhat.com> 2003-07-28 Aldy Hernandez <aldyh@redhat.com>
* gcc.dg/20030505.c: Only run for SPE. * gcc.dg/20030505.c: Only run for SPE.
......
/* This testcase caused ICE on any 64-bit arch at -O2/-O3 due to
fold/extract_muldiv/convert destroying its argument. */
int x, *y, z, *p;
void
foo (void)
{
p = y + (8 * (x == 1 || x == 3) + z);
}
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