This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR optimization/12965
- From: Eric Botcazou <ebotcazou at libertysurf dot fr>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 6 Dec 2003 12:42:57 +0100
- Subject: [PATCH] Fix PR optimization/12965
Hi,
This is a regression at -O2 on Alpha, present on the 3.3 branch. The compiler
ICEs in fixup_abnormal_edges (called at the end of reload) when trying to
insert an insn on a non-existent fallthrough edge.
We have before reload:
;; Start of basic block 15, registers live: 29 [$29] 30 [$30] 31 [AP] 63 [FP]
69 73 388
(note 2605 516 517 15 [bb 15] NOTE_INSN_BASIC_BLOCK)
(insn 517 2605 518 15 0x4020ed00 (set (reg:DI 16 $16)
(reg:DI 73)) 256 {*movdi_nofix} (nil)
(expr_list:REG_DEAD (reg:DI 73)
(nil)))
(call_insn 518 517 519 15 0x4020ed00 (parallel [
(call (mem:DI (symbol_ref:DI ("__cxa_call_unexpected")) [0 S8
A64])
(const_int 0 [0x0]))
(use (reg:DI 29 $29))
(clobber (reg:DI 26 $26))
]) 212 {*call_osf_1_noreturn} (insn_list 517 (nil))
(expr_list:REG_DEAD (reg:DI 16 $16)
(expr_list:REG_UNUSED (reg:DI 26 $26)
(expr_list:REG_EH_REGION (const_int 1 [0x1])
(expr_list:REG_NORETURN (const_int 0 [0x0])
(nil)))))
(expr_list (use (reg:DI 16 $16))
(nil)))
;; End of basic block 15, registers live:
29 [$29] 30 [$30] 31 [AP] 63 [FP] 69 388
(reg 388) is live because it is live in the EH handler. Now it is renamed to
(reg 3), which is call-used. So save_call_clobbered_regs thinks it must
save it and inserts the two needed instructions around the call. Then
fixup_abnormal_edges dies because it can't push the second instruction on the
fallthrough edge, since there is no fallthrough edge.
Bootstrapped/regtested on i586-redhat-linux-gnu (mainline except Ada). Ok for
mainline and 3.3 branch?
2003-12-06 Eric Botcazou <ebotcazou@libertysurf.fr>
PR optimization/12965
* caller-save.c (save_call_clobbered_regs): Do not save/restore
registers around no-return calls.
2003-12-06 Falk Hueffner <falk@debian.org>
* g++.dg/opt/noreturn-1.C: New test.
--
Eric Botcazou
Index: caller-save.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/caller-save.c,v
retrieving revision 1.53
diff -u -p -r1.53 caller-save.c
--- caller-save.c 13 Jun 2002 12:24:00 -0000 1.53
+++ caller-save.c 5 Dec 2003 13:18:42 -0000
@@ -407,7 +407,7 @@ save_call_clobbered_regs ()
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;
// PR optimization/12965
// Origin: <qboosh@pld-linux.org>
// Reduced testcase: Falk Hueffner <falk@debian.org>
// This ICEd on Alpha because the reload pass emitted save/restore
// insns around a no-return call.
// { dg-do compile }
// { dg-options "-O2" }
template <typename _Alloc> class allocator;
template <class _CharT> struct char_traits;
template <typename _CharT,
typename _Traits = char_traits<_CharT>,
typename _Alloc = allocator<_CharT> >
class basic_string;
typedef basic_string<char> string;
static inline int __exchange_and_add(volatile int * __mem, int __val) {
int __result;
asm("" : "=&r"(__result));
return __result;
}
template<typename _Tp> struct allocator {
allocator() throw() { }
allocator(const allocator &) throw() {}
};
template<typename _CharT, typename _Traits, typename _Alloc>
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<class T> 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;
}