From: ebotcazou Date: Sun, 7 Dec 2003 13:05:43 +0000 (+0000) Subject: PR optimization/12965 X-Git-Tag: upstream/4.9.2~74848 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7ce63ed26051e10930a0774ce984703929e5717c;p=platform%2Fupstream%2Flinaro-gcc.git PR optimization/12965 * caller-save.c (save_call_clobbered_regs): Do not save/restore registers around no-return calls. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@74389 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3b7ed52..d95d628 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2003-12-07 Eric Botcazou + + PR optimization/12965 + * caller-save.c (save_call_clobbered_regs): Do not save/restore + registers around no-return calls. + 2003-12-07 Nathanael Nerode * configure.in: Make minimum necessary changes for autoconf 2.5x. diff --git a/gcc/caller-save.c b/gcc/caller-save.c index d40c8d9..7467385 100644 --- a/gcc/caller-save.c +++ b/gcc/caller-save.c @@ -408,7 +408,7 @@ save_call_clobbered_regs (void) regno += insert_restore (chain, 1, regno, MOVE_MAX_WORDS, save_mode); } - if (code == CALL_INSN) + if (code == CALL_INSN && ! find_reg_note (insn, REG_NORETURN, NULL)) { int regno; HARD_REG_SET hard_regs_to_save; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b075f0e..558f7a4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2003-12-07 Falk Hueffner + + * g++.dg/opt/noreturn-1.C: New test. + 2003-12-07 Wolfgang Bangerth * gcc.dg/overflow-1.c: New test. diff --git a/gcc/testsuite/g++.dg/opt/noreturn-1.C b/gcc/testsuite/g++.dg/opt/noreturn-1.C new file mode 100644 index 0000000..9b2fc0c --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/noreturn-1.C @@ -0,0 +1,87 @@ +// PR optimization/12965 +// Origin: +// Reduced testcase: Falk Hueffner + +// This ICEd on Alpha because the reload pass emitted save/restore +// insns around a no-return call. + +// { dg-do compile } +// { dg-options "-O2" } + +template class allocator; +template struct char_traits; +template , + typename _Alloc = allocator<_CharT> > +class basic_string; +typedef basic_string string; + +static inline int __exchange_and_add(volatile int * __mem, int __val) { + int __result; + asm("" : "=&r"(__result)); + return __result; +} + +template struct allocator { + allocator() throw() { } + allocator(const allocator &) throw() {} +}; + +template +struct basic_string { + typedef _Alloc allocator_type; + struct _Rep { + int _M_references; + void _M_dispose(const _Alloc & __a) { + if (__exchange_and_add(&_M_references, -1) <= 0) + _M_destroy(__a); + } void _M_destroy(const _Alloc &) throw(); + }; + struct _Alloc_hider : _Alloc { + _CharT *_M_p; + }; + mutable _Alloc_hider _M_dataplus; + _CharT *_M_data() const { return _M_dataplus._M_p; } + _Rep *_M_rep() const { + return &((reinterpret_cast<_Rep *>(_M_data()))[-1]); + } + basic_string(); + basic_string(const _CharT * __s, const _Alloc & __a = _Alloc()); + ~basic_string() { + _M_rep()->_M_dispose(this->get_allocator()); + } + allocator_type get_allocator() const { return _M_dataplus; } +}; + +struct Egeneric { + void stack(const string & passage, const string & message = "") { } +}; + +struct infinint { + void detruit() throw(Egeneric); + template void infinint_from(T a) throw(Egeneric); + infinint(long a = 0) throw(Egeneric) { + try { + infinint_from(a); + } catch(Egeneric& e) { + e.stack("infinint::infinint", "long"); + } + } + ~infinint() throw(Egeneric) { + try { + detruit(); + } catch(Egeneric& e) { } + } +}; + +struct inode { + string x; + infinint a, c; + infinint ea_offset; + inode(); +}; + +inode::inode() +{ + ea_offset = 0; +}