OSDN Git Service

PR optimization/6713
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 17 Jul 2002 18:00:35 +0000 (18:00 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 17 Jul 2002 18:00:35 +0000 (18:00 +0000)
 * loop.c (loop_givs_rescan): Explicitly delete the insn that
 sets a non-replaceable giv after issuing the new one.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@55539 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/loop.c
gcc/testsuite/g++.dg/opt/pr6713.C [new file with mode: 0644]

index c51a6ff..da5ebc2 100644 (file)
@@ -1,3 +1,10 @@
+2002-06-17  Eric Botcazou <ebotcazou@multimania.com>
+            Glen Nakamura <glen@imodulo.com>
+
+       PR optimization/6713
+       * loop.c (loop_givs_rescan): Explicitly delete the insn that
+       sets a non-replaceable giv after issuing the new one.
+
 2002-07-17  Neil Booth  <neil@daikokuya.co.uk>
 
        * cppexp.c (cpp_interpret_integer, append_digit, parse_defined,
index dc64b5c..5966324 100644 (file)
@@ -4874,10 +4874,20 @@ loop_givs_rescan (loop, bl, reg_map)
        }
       else
        {
+         rtx original_insn = v->insn;
+
          /* Not replaceable; emit an insn to set the original giv reg from
             the reduced giv, same as above.  */
-         loop_insn_emit_after (loop, 0, v->insn,
-                               gen_move_insn (v->dest_reg, v->new_reg));
+         v->insn = loop_insn_emit_after (loop, 0, original_insn,
+                                         gen_move_insn (v->dest_reg,
+                                                        v->new_reg));
+
+         /* The original insn may have a REG_EQUAL note.  This note is
+            now incorrect and may result in invalid substitutions later.
+            We could just delete the note, but we know that the entire
+            insn is dead, so we might as well save ourselves the bother
+            and remove the whole thing.  */
+         delete_insn (original_insn);
        }
 
       /* When a loop is reversed, givs which depend on the reversed
diff --git a/gcc/testsuite/g++.dg/opt/pr6713.C b/gcc/testsuite/g++.dg/opt/pr6713.C
new file mode 100644 (file)
index 0000000..c844ddb
--- /dev/null
@@ -0,0 +1,116 @@
+// PR optimization/6713
+// This testcase segfaulted on x86 because a dangling REG_EQUAL note
+// resulted in incorrect substitutions later.
+// { dg-do run }
+// { dg-options "-O2" }
+
+template<typename _CharT> class basic_iterator
+{
+  public:
+    basic_iterator(_CharT* _p) : _M_current(_p) {}
+    basic_iterator& operator++() { ++_M_current; return *this; }
+    _CharT& operator*() const { return *_M_current; }
+    bool operator!=(basic_iterator &_rhs) { return _M_current != _rhs._M_current; }
+
+  private:
+    _CharT* _M_current;
+};
+
+template<typename _CharT> class basic_string
+{
+  public:
+    typedef unsigned int size_type;
+    typedef basic_iterator<_CharT> iterator;
+
+  private:
+    struct _Rep
+    {
+      size_type _M_length;
+      size_type _M_capacity;
+      int _M_references;
+
+      bool _M_is_leaked() const { return _M_references < 0; }
+      bool _M_is_shared() const { return _M_references > 0; }
+      void _M_set_leaked() { _M_references = -1; }
+      void _M_set_sharable() { _M_references = 0; }
+    };
+
+    struct _Rep _M_rep;
+
+    struct _Alloc_hider
+    {
+      _CharT _raw[16];
+      _CharT* _M_p;
+    };
+
+    mutable _Alloc_hider _M_dataplus;
+
+    _CharT* _M_data() const { return _M_dataplus._M_p; }
+
+    void _M_leak() { if (!_M_rep._M_is_leaked()) _M_leak_hard(); }
+
+    static int count;
+
+    static void _M_leak_hard();
+
+  public:
+    explicit basic_string(const _CharT* __s);
+
+    iterator begin() { _M_leak(); return iterator(_M_data()); }
+
+    iterator end() { _M_leak(); return iterator(_M_data() + this->size()); }
+
+    size_type size() const { return _M_rep._M_length; }
+};
+
+template<typename _CharT> basic_string<_CharT>::
+basic_string(const _CharT* __s)
+{
+  int i;
+
+  for (i=0; i<15; i++) {
+    if (!__s[i])
+      break;
+
+    _M_dataplus._raw[i] = __s[i];
+  }
+
+  _M_dataplus._raw[i] = 0;
+  _M_dataplus._M_p = _M_dataplus._raw;
+
+  _M_rep._M_length = i;
+  _M_rep._M_capacity = i;
+  _M_rep._M_references = 1;
+}     
+
+template<typename _CharT> int basic_string<_CharT>::count = 0;
+
+template<typename _CharT> void basic_string<_CharT>::
+_M_leak_hard()
+{
+  count++;
+}
+
+typedef basic_string<char> string;
+
+
+int isspa(int ch)
+{
+  return 0;
+}
+
+void foo(string& str)
+{
+  string::iterator it = str.begin();
+  string::iterator stop = str.end();
+
+  for (; it != stop; ++it)
+    if (isspa(*it))
+      break;
+}
+
+int main()
+{
+  string str("test");
+  foo(str);
+}