re PR tree-optimization/16341 (BOOT_CFLAGS='-O2 -fno-inline' causes a comparision...
authorRichard Henderson <rth@redhat.com>
Sun, 4 Jul 2004 02:52:36 +0000 (19:52 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Sun, 4 Jul 2004 02:52:36 +0000 (19:52 -0700)
        PR tree-optimization/16341
        * tree-sra.c (sra_walk_function): Increment to next stmt before
        processing the current stmt.
        (sra_insert_after): Always use BSI_SAME_STMT.

From-SVN: r84070

gcc/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20040703-1.c [new file with mode: 0644]
gcc/tree-sra.c

index 5ab89e1acaae4b0211da73321bea22491ebdcbdb..4bf082f1a700e86e207ff68b2933c8b26a7bcda8 100644 (file)
@@ -1,3 +1,10 @@
+2004-07-03  Richard Henderson  <rth@redhat.com>
+
+       PR tree-optimization/16341
+       * tree-sra.c (sra_walk_function): Increment to next stmt before
+       processing the current stmt.
+       (sra_insert_after): Always use BSI_SAME_STMT.
+
 2004-07-03  Richard Henderson  <rth@redhat.com>
 
        * tree-ssa-dom.c (simplify_rhs_and_lookup_avail_expr): Don't fold
diff --git a/gcc/testsuite/gcc.c-torture/execute/20040703-1.c b/gcc/testsuite/gcc.c-torture/execute/20040703-1.c
new file mode 100644 (file)
index 0000000..eba358d
--- /dev/null
@@ -0,0 +1,147 @@
+/* PR 16341 */
+
+#define PART_PRECISION (sizeof (cpp_num_part) * 8)
+
+typedef unsigned int cpp_num_part;
+typedef struct cpp_num cpp_num;
+struct cpp_num
+{
+   cpp_num_part high;
+   cpp_num_part low;
+   int unsignedp;  /* True if value should be treated as unsigned.  */
+   int overflow;   /* True if the most recent calculation overflowed.  */
+};
+
+static  int
+num_positive (cpp_num num, unsigned int precision)
+{
+   if (precision > PART_PRECISION)
+     {
+       precision -= PART_PRECISION;
+       return (num.high & (cpp_num_part) 1 << (precision - 1)) == 0;
+     }
+
+   return (num.low & (cpp_num_part) 1 << (precision - 1)) == 0;
+}
+
+static cpp_num
+num_trim (cpp_num num, unsigned int precision)
+{
+   if (precision > PART_PRECISION)
+     {
+       precision -= PART_PRECISION;
+       if (precision < PART_PRECISION)
+         num.high &= ((cpp_num_part) 1 << precision) - 1;
+     }
+   else
+     {
+       if (precision < PART_PRECISION)
+         num.low &= ((cpp_num_part) 1 << precision) - 1;
+       num.high = 0;
+     }
+
+   return num;
+}
+
+/* Shift NUM, of width PRECISION, right by N bits.  */
+static cpp_num
+num_rshift (cpp_num num, unsigned int precision, unsigned int n)
+{
+   cpp_num_part sign_mask;
+   int x = num_positive (num, precision);
+
+   if (num.unsignedp || x)
+     sign_mask = 0;
+   else
+     sign_mask = ~(cpp_num_part) 0;
+
+   if (n >= precision)
+     num.high = num.low = sign_mask;
+   else
+     {
+       /* Sign-extend.  */
+       if (precision < PART_PRECISION)
+         num.high = sign_mask, num.low |= sign_mask << precision;
+       else if (precision < 2 * PART_PRECISION)
+         num.high |= sign_mask << (precision - PART_PRECISION);
+
+       if (n >= PART_PRECISION)
+         {
+           n -= PART_PRECISION;
+           num.low = num.high;
+           num.high = sign_mask;
+         }
+
+       if (n)
+         {
+           num.low = (num.low >> n) | (num.high << (PART_PRECISION - n));
+           num.high = (num.high >> n) | (sign_mask << (PART_PRECISION - n));
+         }
+     }
+
+   num = num_trim (num, precision);
+   num.overflow = 0;
+   return num;
+}
+                              #define num_zerop(num) ((num.low | num.high) == 0)
+#define num_eq(num1, num2) (num1.low == num2.low && num1.high == num2.high)
+
+cpp_num
+num_lshift (cpp_num num, unsigned int precision, unsigned int n)
+{
+   if (n >= precision)
+     {
+       num.overflow = !num.unsignedp && !num_zerop (num);
+       num.high = num.low = 0;
+     }
+   else
+     {
+       cpp_num orig;
+       unsigned int m = n;
+
+       orig = num;
+       if (m >= PART_PRECISION)
+         {
+           m -= PART_PRECISION;
+           num.high = num.low;
+           num.low = 0;
+         }
+       if (m)
+         {
+           num.high = (num.high << m) | (num.low >> (PART_PRECISION - m));
+           num.low <<= m;
+         }
+       num = num_trim (num, precision);
+
+       if (num.unsignedp)
+         num.overflow = 0;
+       else
+         {
+           cpp_num maybe_orig = num_rshift (num, precision, n);
+           num.overflow = !num_eq (orig, maybe_orig);
+         }
+     }
+
+   return num;
+}
+
+unsigned int precision = 64;
+unsigned int n = 16;
+
+cpp_num num = { 0, 3, 0, 0 };
+
+int main()
+{
+   cpp_num res = num_lshift (num, 64, n);
+
+   if (res.low != 0x30000)
+     abort ();
+
+   if (res.high != 0)
+     abort ();
+
+   if (res.overflow != 0)
+     abort ();
+
+   exit (0);
+}
index 0f04fcb2a2ec67001cc6144ac200565913a94bc7..f315ad90b11ac8057bea0a86e59ce830b8989e28 100644 (file)
@@ -828,13 +828,13 @@ static void
 sra_walk_function (const struct sra_walk_fns *fns)
 {
   basic_block bb;
-  block_stmt_iterator si;
+  block_stmt_iterator si, ni;
 
   /* ??? Phase 4 could derive some benefit to walking the function in
      dominator tree order.  */
 
   FOR_EACH_BB (bb)
-    for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+    for (si = bsi_start (bb); !bsi_end_p (si); si = ni)
       {
        tree stmt, t;
        stmt_ann_t ann;
@@ -842,6 +842,9 @@ sra_walk_function (const struct sra_walk_fns *fns)
        stmt = bsi_stmt (si);
        ann = stmt_ann (stmt);
 
+       ni = si;
+       bsi_next (&ni);
+
        /* If the statement has no virtual operands, then it doesn't
           make any structure references that we care about.  */
        if (NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)) == 0
@@ -1616,7 +1619,7 @@ sra_insert_after (block_stmt_iterator *bsi, tree list)
   if (stmt_ends_bb_p (stmt))
     insert_edge_copies (list, bsi->bb);
   else
-    bsi_insert_after (bsi, list, BSI_CONTINUE_LINKING);
+    bsi_insert_after (bsi, list, BSI_SAME_STMT);
 }
 
 /* Similarly, but replace the statement at BSI.  */