re PR rtl-optimization/23478 (Miscompilation due to reloading of a var that is also...
authorJakub Jelinek <jakub@redhat.com>
Mon, 22 Aug 2005 16:58:50 +0000 (18:58 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Mon, 22 Aug 2005 16:58:50 +0000 (18:58 +0200)
PR rtl-optimization/23478
* regs.h (reg_info): Add throw_calls_crossed.
(REG_N_THROWING_CALLS_CROSSED): Define.
* flow.c (allocate_reg_life_data): Initialize
REG_N_THROWING_CALLS_CROSSED.
(propagate_one_insn, attempt_auto_inc): Update
REG_N_THROWING_CALLS_CROSSED.
* global.c (global_alloc): Don't allocate pseudos across
calls that may throw.

* g++.dg/opt/pr23478.C: New test.

From-SVN: r103348

gcc/ChangeLog
gcc/flow.c
gcc/global.c
gcc/regs.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/pr23478.C [new file with mode: 0644]

index 8a5e2f00c21ebe2dda56b8407b03fa2f34796447..3663104e59c78df9a80470f647e85b6b04c536cd 100644 (file)
@@ -1,3 +1,15 @@
+2005-08-22  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/23478
+       * regs.h (reg_info): Add throw_calls_crossed.
+       (REG_N_THROWING_CALLS_CROSSED): Define.
+       * flow.c (allocate_reg_life_data): Initialize
+       REG_N_THROWING_CALLS_CROSSED.
+       (propagate_one_insn, attempt_auto_inc): Update
+       REG_N_THROWING_CALLS_CROSSED.
+       * global.c (global_alloc): Don't allocate pseudos across
+       calls that may throw.
+
 2005-08-22  Andrew Pinski  <pinskia@physics.uc.edu>
 
        PR c/18715
index 79b26d698f05271166887dce472d2f47d63bda43..aa45def3e7c2f41118ee0da84036afbc314667f7 100644 (file)
@@ -104,7 +104,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 
    life_analysis fills in certain vectors containing information about
    register usage: REG_N_REFS, REG_N_DEATHS, REG_N_SETS, REG_LIVE_LENGTH,
-   REG_N_CALLS_CROSSED and REG_BASIC_BLOCK.
+   REG_N_CALLS_CROSSED, REG_N_THROWING_CALLS_CROSSED and REG_BASIC_BLOCK.
 
    life_analysis sets current_function_sp_is_unchanging if the function
    doesn't modify the stack pointer.  */
@@ -1589,6 +1589,7 @@ allocate_reg_life_data (void)
       REG_N_REFS (i) = 0;
       REG_N_DEATHS (i) = 0;
       REG_N_CALLS_CROSSED (i) = 0;
+      REG_N_THROWING_CALLS_CROSSED (i) = 0;
       REG_LIVE_LENGTH (i) = 0;
       REG_FREQ (i) = 0;
       REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN;
@@ -1820,6 +1821,9 @@ propagate_one_insn (struct propagate_block_info *pbi, rtx insn)
          reg_set_iterator rsi;
          EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i, rsi)
            REG_N_CALLS_CROSSED (i)++;
+          if (can_throw_internal (insn))
+           EXECUTE_IF_SET_IN_REG_SET (pbi->reg_live, 0, i, rsi)
+             REG_N_THROWING_CALLS_CROSSED (i)++;
        }
 
       /* Record sets.  Do this even for dead instructions, since they
@@ -3512,7 +3516,11 @@ attempt_auto_inc (struct propagate_block_info *pbi, rtx inc, rtx insn,
         that REGNO now crosses them.  */
       for (temp = insn; temp != incr; temp = NEXT_INSN (temp))
        if (CALL_P (temp))
-         REG_N_CALLS_CROSSED (regno)++;
+         {
+           REG_N_CALLS_CROSSED (regno)++;
+           if (can_throw_internal (temp))
+             REG_N_THROWING_CALLS_CROSSED (regno)++;
+         }
 
       /* Invalidate alias info for Q since we just changed its value.  */
       clear_reg_alias_info (q);
index 13b81736859a137ecc17b193a370199e6e0fdd0c..f82cd08017a15b8465778ef34133a5f75318400b 100644 (file)
@@ -465,7 +465,9 @@ global_alloc (FILE *file)
        /* Don't allocate pseudos that cross calls,
           if this function receives a nonlocal goto.  */
        && (! current_function_has_nonlocal_label
-           || REG_N_CALLS_CROSSED (i) == 0))
+           || REG_N_CALLS_CROSSED (i) == 0)
+       /* Don't allocate pseudos that cross calls that may throw.  */
+       && REG_N_THROWING_CALLS_CROSSED (i) == 0)
       {
        if (reg_renumber[i] < 0
            && reg_may_share[i] && reg_allocno[reg_may_share[i]] >= 0)
index 3caa89b081b7b2ac2d6cfa7c5e21ac0d8e9bc1b2..d29e0e1aace3093686cb6907593984cd08e30e25 100644 (file)
@@ -61,6 +61,7 @@ typedef struct reg_info_def
   int deaths;                  /* # of times (REG n) dies */
   int live_length;             /* # of instructions (REG n) is live */
   int calls_crossed;           /* # of calls (REG n) is live across */
+  int throw_calls_crossed;     /* # of calls that may throw (REG n) is live across */
   int basic_block;             /* # of basic blocks (REG n) is used in */
 } reg_info;
 
@@ -125,6 +126,12 @@ extern varray_type reg_n_info;
 
 #define REG_N_CALLS_CROSSED(N) (VARRAY_REG (reg_n_info, N)->calls_crossed)
 
+/* Indexed by N, gives number of CALL_INSNS that may throw, across which
+   (REG n) is live.  */
+
+#define REG_N_THROWING_CALLS_CROSSED(N) \
+  (VARRAY_REG (reg_n_info, N)->throw_calls_crossed)
+
 /* Total number of instructions at which (REG n) is live.
    The larger this is, the less priority (REG n) gets for
    allocation in a hard register (in global-alloc).
index bd6b162405ff07c4c6b37f6d23284a0cc5c2f5b3..bb30ee1c0b330fa0dd33e8dd10e40e7c7cdc4cb4 100644 (file)
@@ -1,3 +1,8 @@
+2005-08-22  Jakub Jelinek  <jakub@redhat.com>
+
+       PR rtl-optimization/23478
+       * g++.dg/opt/pr23478.C: New test.
+
 2005-08-22  Andrew Pinski  <pinskia@physics.uc.edu>
 
        PR c/18715
diff --git a/gcc/testsuite/g++.dg/opt/pr23478.C b/gcc/testsuite/g++.dg/opt/pr23478.C
new file mode 100644 (file)
index 0000000..da1371d
--- /dev/null
@@ -0,0 +1,211 @@
+// PR rtl-optimization/23478
+// { dg-do run }
+// { dg-options "-O2" }
+
+extern "C" void abort ();
+bool tthrow;
+struct C3 { int i; };
+class C14 {};
+struct C7
+{
+  virtual ~C7 ();
+};
+
+C7::~C7 ()
+{
+  asm volatile ("" : : : "memory");
+}
+class C2 : public C7 {};
+
+template <class X> class C13
+{
+  bool ma;
+  X *mb;
+public:
+  explicit C13 (X *p = 0) throw () : ma (p != 0), mb (p) {}
+  ~C13 ();
+};
+
+template <class X>
+C13<X>::~C13 ()
+{
+  asm volatile ("" : : "r" (ma), "r" (mb) : "memory");
+}
+
+struct C1
+{
+  C1 (const C3 &, const C3 &, const C3 &, const C3 *&);
+};
+
+C1::C1 (const C3 &, const C3 &, const C3 &, const C3 *&)
+{
+  if (!tthrow)
+    throw 24;
+}
+
+struct C8
+{
+  struct C15 {};
+  typedef C15 *C9;
+  virtual void f1 (C2 &, long *, void *, C3 &, void *, bool) = 0;
+  virtual C13<C14> f3 () const = 0;
+  virtual ~C8 () {}
+};
+
+bool
+xx14 ()
+{
+  bool b = false;
+  if (tthrow)
+    throw 6;
+  asm volatile ("" : : "r" (&b) : "memory");
+  return b;
+}
+
+bool
+xx2 ()
+{
+  bool b = false;
+  if (tthrow)
+    throw 6;
+  asm volatile ("" : : "r" (&b) : "memory");
+  return b;
+}
+
+C13<C7>
+xx9 ()
+{
+  return C13<C7>();
+}
+
+C2 &
+xx10 ()
+{
+  static C2 c2;
+  return c2;
+}
+
+C3 &
+xx12 ()
+{
+  static C3 c3 = { 1 };
+  return c3;
+}
+
+const C3 &
+xx5 ()
+{
+  static const C3 c3 = { 2 };
+  return c3;
+}
+
+const C3 *&
+xx4 ()
+{
+  static const C3 *p;
+  if (tthrow)
+    throw 6;
+  return p;
+}
+
+long ll13;
+
+long
+xx13 ()
+{
+  long ret;
+  asm volatile ("" : "=r" (ret) : "r" (ll13));
+  return ret;
+}
+
+void
+xx15 (C3 &x, C13<C1> &y)
+{
+  asm volatile ("" : : "r" (&x), "r" (&y) : "memory");
+}
+
+long
+xx16 (const void *x)
+{
+  long ret;
+  asm volatile ("" : "=r" (ret) : "0" (1), "r" (x) : "memory");
+  return ret;
+}
+
+void
+xx1 (C13<C14> x)
+{
+  asm volatile ("" : : "r" (&x) : "memory");
+  if (tthrow)
+    throw 6;
+}
+
+void
+xx3 (const C7 *x)
+{
+  if (x)
+    abort ();
+}
+
+void
+xx7 ()
+{
+  asm volatile ("" : : : "memory");
+}
+
+struct C5
+{
+  C13<C7> f2 (C3 &v1, const void *v2, C8 *v6);
+  C7 *m2[2];
+  long m1[2];
+};
+
+C13<C7>
+C5::f2 (C3 &v1, const void *v2, C8 *v6)
+{
+  C13<C7> v13 = xx9 ();
+  C2 &v9 = xx10 ();
+  for (long i = 1; i < 2; i++)
+    xx3 (m2[i]);
+  const C3 &ld = xx5 ();
+  xx7 ();
+  if (xx2 ())
+    throw "";
+  xx4 ();
+  C3 &si = xx12 ();
+  for (long i = 0; i < xx16 (v2); ++i)
+    {
+      C13<C1> sk (new C1 (xx5 (), ld, xx5 (), xx4 ()));
+      xx15 (si, sk);
+    }
+  long v4 = xx13 ();
+  for (long i = v4 - 1; i >= 0; --i)
+    m1[i] = i;
+  bool v8 = xx2 ();
+  for (long i = 0; i < 2 && !xx14 (); i++)
+    {
+      v6[i].f1 (v9, 0, __null, v1, __null, v8);
+      if (v8)
+       xx1 (v6[i].f3 ());
+    }
+  return v13;
+}
+
+int
+main (void)
+{
+  C5 c5 = { { __null, __null }, { 0, 0 } };
+  bool seen = false;
+  try
+    {
+      c5.f2 (xx12 (), __null, __null);
+    }
+  catch (int n)
+    {
+      if (n != 24)
+       abort ();
+      seen = true;
+    }
+  if (!seen)
+    abort ();
+}