From f1a73cfecf88d38c1c917c93b60cb8b2e4d82960 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Wed, 17 Jul 2002 18:00:35 +0000 Subject: [PATCH] re PR rtl-optimization/6713 (Regression wrt 3.0.4: g++ -O2 leads to seg fault at run time) PR optimization/6713 * loop.c (loop_givs_rescan): Explicitly delete the insn that sets a non-replaceable giv after issuing the new one. Co-Authored-By: Glen Nakamura From-SVN: r55539 --- gcc/ChangeLog | 7 ++ gcc/loop.c | 14 +++- gcc/testsuite/g++.dg/opt/pr6713.C | 116 ++++++++++++++++++++++++++++++ 3 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/pr6713.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c51a6ff2d39..da5ebc2ba2c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2002-06-17 Eric Botcazou + Glen Nakamura + + 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 * cppexp.c (cpp_interpret_integer, append_digit, parse_defined, diff --git a/gcc/loop.c b/gcc/loop.c index dc64b5c889a..5966324dc34 100644 --- a/gcc/loop.c +++ b/gcc/loop.c @@ -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 index 00000000000..c844ddb34d3 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr6713.C @@ -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 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 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 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 int basic_string<_CharT>::count = 0; + +template void basic_string<_CharT>:: +_M_leak_hard() +{ + count++; +} + +typedef basic_string 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); +}