]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
configure.in (--enable-checking): Add fold category.
authorJakub Jelinek <jakub@redhat.com>
Mon, 28 Jul 2003 15:42:24 +0000 (17:42 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 28 Jul 2003 15:42:24 +0000 (17:42 +0200)
* 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

gcc/ChangeLog
gcc/config.in
gcc/configure
gcc/configure.in
gcc/convert.c
gcc/doc/install.texi
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/20030725-1.c [new file with mode: 0644]

index cc7e60ae904d9f1f27f426b1a0b6516044e89495..1bdd3fc1e94032d122689e43d7809f5b74a25077 100644 (file)
@@ -1,3 +1,19 @@
+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>
 
        * fixinc/fixinc.svr4: Remove dead code.  Remove now-unnecessary 
index cdb7c563831138534cce340468deb10593527051..e1feb70cb30a89709245be7ea01893fd39cc9c02 100644 (file)
@@ -1,4 +1,4 @@
-/* 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'.
    Usually this is either `int' or `gid_t'.  */
    every opportunity.  This is extremely expensive. */
 #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
    through valgrind (a memory checker).  This is extremely expensive. */
 #undef ENABLE_VALGRIND_CHECKING
index cbb57e7bf356934458555be46c49f40095564aa1..c102e87ba1ac20d468f2b20f76e493f0ec371665 100755 (executable)
@@ -34,7 +34,7 @@ ac_help="$ac_help
   --enable-checking[=LIST]
                          enable expensive run-time checks.  With LIST,
                          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"
 ac_help="$ac_help
   --enable-coverage[=LEVEL]
@@ -1933,6 +1933,7 @@ ac_rtl_checking=
 ac_rtlflag_checking=
 ac_gc_checking=
 ac_gc_always_collect=
+ac_fold_checking=
 case "${enableval}" in
 yes)   ac_checking=1 ; ac_tree_checking=1 ; ac_gc_checking=1 ;
        ac_rtlflag_checking=1 ;;
@@ -1949,6 +1950,7 @@ no)       ;;
                rtl)    ac_rtl_checking=1 ;;
                gc)     ac_gc_checking=1 ;;
                gcac)   ac_gc_always_collect=1 ;;
+               fold)   ac_fold_checking=1 ;;
                valgrind)       ac_checking_valgrind=1 ;;
                *)      { echo "configure: error: unknown check category $check" 1>&2; exit 1; } ;;
                esac
@@ -1999,6 +2001,12 @@ if test x$ac_gc_always_collect != x ; then
 #define ENABLE_GC_ALWAYS_COLLECT 1
 EOF
 
+fi
+if test x$ac_fold_checking != x ; then
+  cat >> confdefs.h <<\EOF
+#define ENABLE_FOLD_CHECKING 1
+EOF
+
 fi
 valgrind_path_defines=
 valgrind_command=
index abf2576a4fb82bea619859631aff8f5857b8c44a..5f031236a30c4f648d297dacfeeda89d2e49d59f 100644 (file)
@@ -318,7 +318,7 @@ AC_ARG_ENABLE(checking,
 [  --enable-checking[=LIST]
                          enable expensive run-time checks.  With LIST,
                          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],
 [ac_checking=
 ac_tree_checking=
@@ -326,6 +326,7 @@ ac_rtl_checking=
 ac_rtlflag_checking=
 ac_gc_checking=
 ac_gc_always_collect=
+ac_fold_checking=
 case "${enableval}" in
 yes)   ac_checking=1 ; ac_tree_checking=1 ; ac_gc_checking=1 ;
        ac_rtlflag_checking=1 ;;
@@ -342,6 +343,7 @@ no) ;;
                rtl)    ac_rtl_checking=1 ;;
                gc)     ac_gc_checking=1 ;;
                gcac)   ac_gc_always_collect=1 ;;
+               fold)   ac_fold_checking=1 ;;
                valgrind)       ac_checking_valgrind=1 ;;
                *)      AC_MSG_ERROR(unknown check category $check) ;;
                esac
@@ -388,6 +390,11 @@ if test x$ac_gc_always_collect != x ; then
    paranoid mode, validating the entire heap and collecting garbage at
    every opportunity.  This is extremely expensive.])
 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_command=
 if test x$ac_checking_valgrind != x ; then
index fc001b6e74e040b9bbb93a9c4d7f672ac4067284..5bab1c19d3561b0224bfcf46a51946bd205cd660 100644 (file)
@@ -320,6 +320,7 @@ convert_to_integer (tree type, tree expr)
 
       if (TREE_CODE_CLASS (ex_form) == '<')
        {
+         expr = copy_node (expr);
          TREE_TYPE (expr) = type;
          return 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_XOR_EXPR)
        {
+         expr = copy_node (expr);
          TREE_OPERAND (expr, 0) = convert (type, TREE_OPERAND (expr, 0));
          TREE_OPERAND (expr, 1) = convert (type, TREE_OPERAND (expr, 1));
          TREE_TYPE (expr) = type;
@@ -336,6 +338,7 @@ convert_to_integer (tree type, tree expr)
 
       else if (ex_form == TRUTH_NOT_EXPR)
        {
+         expr = copy_node (expr);
          TREE_OPERAND (expr, 0) = convert (type, TREE_OPERAND (expr, 0));
          TREE_TYPE (expr) = type;
          return expr;
index 1aeb50fcf791c9ae41e2e6edf6699b3042696f6e..6f3fbf1dbcb9ee83e88eea6c80ea42d2c07f211f 100644 (file)
@@ -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
 specifying @var{list}; the categories of checks available are
 @samp{misc}, @samp{tree}, @samp{gc}, @samp{rtl}, @samp{rtlflag},
-@samp{gcac} and @samp{valgrind}.  The check @samp{valgrind} requires the
-external @command{valgrind} simulator, available from
+@samp{fold}, @samp{gcac} and @samp{valgrind}.  The check @samp{valgrind}
+requires the external @command{valgrind} simulator, available from
 @uref{http://developer.kde.org/~sewardj/}.  The default when @var{list} is
 not specified is @samp{misc,tree,gc,rtlflag}; the checks @samp{rtl},
 @samp{gcac} and @samp{valgrind} are very expensive.
index 114aaae44c8a1992b2ef954e3e3c395c5724f918..58cec23773b90b304ace3587340ba202cb516200 100644 (file)
@@ -56,6 +56,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "ggc.h"
 #include "hashtab.h"
 #include "langhooks.h"
+#include "md5.h"
 
 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 *);
@@ -4921,7 +4922,7 @@ fold_single_bit_test (enum tree_code code, tree arg0, tree arg1,
     }
   return NULL_TREE;
 }
+
 /* Perform constant folding and related simplification of EXPR.
    The related simplifications include x*1 => x, x*0 => 0, etc.,
    and application of the associative law.
@@ -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,
    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
 fold (tree expr)
 {
-  tree t = expr;
+  tree t = expr, orig_t;
   tree t1 = NULL_TREE;
   tree tem;
   tree type = TREE_TYPE (expr);
@@ -4957,6 +4963,7 @@ fold (tree expr)
 #ifdef MAX_INTEGER_COMPUTATION_MODE
   check_max_integer_computation_mode (expr);
 #endif
+  orig_t = t;
 
   if (code == NOP_EXPR || code == FLOAT_EXPR || code == CONVERT_EXPR)
     {
@@ -5028,12 +5035,15 @@ fold (tree expr)
   if ((code == PLUS_EXPR || code == MULT_EXPR || code == MIN_EXPR
        || code == MAX_EXPR || code == BIT_IOR_EXPR || code == BIT_XOR_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 = TREE_OPERAND (t, 0); TREE_OPERAND (t, 0) = TREE_OPERAND (t, 1);
-      TREE_OPERAND (t, 1) = tem;
+      if (t == orig_t)
+       t = copy_node (t);
+      TREE_OPERAND (t, 0) = arg0;
+      TREE_OPERAND (t, 1) = arg1;
     }
 
   /* Now WINS is set as described above,
@@ -5282,6 +5292,8 @@ fold (tree expr)
          /* Don't leave an assignment inside a conversion
             unless assigning a bitfield.  */
          tree prev = TREE_OPERAND (t, 0);
+         if (t == orig_t)
+           t = copy_node (t);
          TREE_OPERAND (t, 0) = TREE_OPERAND (prev, 1);
          /* First do the assignment, then return converted constant.  */
          t = build (COMPOUND_EXPR, TREE_TYPE (t), prev, fold (t));
@@ -5334,7 +5346,12 @@ fold (tree expr)
 
       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 fold_convert (t, arg0);
@@ -5356,7 +5373,12 @@ fold (tree expr)
       return t;
 
     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;
 
     case NEGATE_EXPR:
@@ -6379,6 +6401,8 @@ fold (tree expr)
         RROTATE_EXPR by a new constant.  */
       if (code == LROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST)
        {
+         if (t == orig_t)
+           t = copy_node (t);
          TREE_SET_CODE (t, RROTATE_EXPR);
          code = RROTATE_EXPR;
          TREE_OPERAND (t, 1) = arg1
@@ -6591,6 +6615,8 @@ fold (tree expr)
          || (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, 1) = arg0;
          arg0 = TREE_OPERAND (t, 0);
@@ -6907,6 +6933,8 @@ fold (tree expr)
                                           arg0);
                case GE_EXPR:
                  code = EQ_EXPR;
+                 if (t == orig_t)
+                   t = copy_node (t);
                  TREE_SET_CODE (t, EQ_EXPR);
                  break;
                case LE_EXPR:
@@ -6915,6 +6943,8 @@ fold (tree expr)
                                           arg0);
                case LT_EXPR:
                  code = NE_EXPR;
+                 if (t == orig_t)
+                   t = copy_node (t);
                  TREE_SET_CODE (t, NE_EXPR);
                  break;
 
@@ -6951,6 +6981,8 @@ fold (tree expr)
                                           arg0);
                case LE_EXPR:
                  code = EQ_EXPR;
+                 if (t == orig_t)
+                   t = copy_node (t);
                  TREE_SET_CODE (t, EQ_EXPR);
                  break;
 
@@ -6960,6 +6992,8 @@ fold (tree expr)
                                           arg0);
                case GT_EXPR:
                  code = NE_EXPR;
+                 if (t == orig_t)
+                   t = copy_node (t);
                  TREE_SET_CODE (t, NE_EXPR);
                  break;
 
@@ -7185,6 +7219,8 @@ fold (tree expr)
                  || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
                return constant_boolean_node (1, type);
              code = EQ_EXPR;
+             if (t == orig_t)
+               t = copy_node (t);
              TREE_SET_CODE (t, code);
              break;
 
@@ -7902,6 +7938,199 @@ fold (tree expr)
     } /* 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
    expression EXPR.  This behaves identically to "fold" but ignores
    potential run-time traps and exceptions that fold must preserve.  */
index ee4a57f5ecc4792ec5e25928fa8b85905bb17756..cd4eb7dc0e2eb15b45b7a441ed752af71f66bb3e 100644 (file)
@@ -1,3 +1,7 @@
+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>
 
        * gcc.dg/20030505.c: Only run for SPE.
diff --git a/gcc/testsuite/gcc.c-torture/compile/20030725-1.c b/gcc/testsuite/gcc.c-torture/compile/20030725-1.c
new file mode 100644 (file)
index 0000000..26f2714
--- /dev/null
@@ -0,0 +1,9 @@
+/* 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);
+}