This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]