mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 22:41:28 +08:00
re PR rtl-optimization/23585 (mem_fun* code fine with -O1, bus error with -O2)
PR rtl-optimization/23585 * rtlanal.c (rtx_addr_can_trap_p_1): New predicate extracted from... (rtx_addr_can_trap_p): ... here. Invoke rtx_addr_can_trap_p_1. (may_trap_p_1): New predicate extracted from... (may_trap_p): ... here. Invoke may_trap_p_1. (may_trap_or_fault_p): New predicate. * rtl.h (may_trap_or_fault_p): Declare it. * reorg.c (steal_delay_list_from_target): Use may_trap_or_fault_p instead of may_trap_p. (steal_delay_list_from_fallthrough): Likewise. (fill_simple_delay_slots): Likewise. (fill_slots_from_thread): Likewise. * function.c (pad_to_arg_alignment): Rework comment about SPARC_STACK_BOUNDARY_HACK. * config/sparc/sparc.h: Likewise. From-SVN: r105671
This commit is contained in:
parent
b88a7564ad
commit
2358ff9116
@ -1,3 +1,21 @@
|
||||
2005-10-20 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
|
||||
PR rtl-optimization/23585
|
||||
* rtlanal.c (rtx_addr_can_trap_p_1): New predicate extracted from...
|
||||
(rtx_addr_can_trap_p): ... here. Invoke rtx_addr_can_trap_p_1.
|
||||
(may_trap_p_1): New predicate extracted from...
|
||||
(may_trap_p): ... here. Invoke may_trap_p_1.
|
||||
(may_trap_or_fault_p): New predicate.
|
||||
* rtl.h (may_trap_or_fault_p): Declare it.
|
||||
* reorg.c (steal_delay_list_from_target): Use may_trap_or_fault_p
|
||||
instead of may_trap_p.
|
||||
(steal_delay_list_from_fallthrough): Likewise.
|
||||
(fill_simple_delay_slots): Likewise.
|
||||
(fill_slots_from_thread): Likewise.
|
||||
* function.c (pad_to_arg_alignment): Rework comment about
|
||||
SPARC_STACK_BOUNDARY_HACK.
|
||||
* config/sparc/sparc.h: Likewise.
|
||||
|
||||
2005-10-19 Adrian Straetling <straetling@de.ibm.com>
|
||||
|
||||
* config/s390/s390.c (s390_expand_insv): New.
|
||||
|
@ -624,11 +624,9 @@ if (TARGET_ARCH64 \
|
||||
|
||||
/* Boundary (in *bits*) on which stack pointer should be aligned. */
|
||||
/* FIXME, this is wrong when TARGET_ARCH64 and TARGET_STACK_BIAS, because
|
||||
then sp+2047 is 128-bit aligned so sp is really only byte-aligned. */
|
||||
then %sp+2047 is 128-bit aligned so %sp is really only byte-aligned. */
|
||||
#define STACK_BOUNDARY (TARGET_ARCH64 ? 128 : 64)
|
||||
/* Temporary hack until the FIXME above is fixed. This macro is used
|
||||
only in pad_to_arg_alignment in function.c; see the comment there
|
||||
for details about what it does. */
|
||||
/* Temporary hack until the FIXME above is fixed. */
|
||||
#define SPARC_STACK_BOUNDARY_HACK (TARGET_ARCH64 && TARGET_STACK_BIAS)
|
||||
|
||||
/* ALIGN FRAMES on double word boundaries */
|
||||
|
@ -3370,10 +3370,9 @@ pad_to_arg_alignment (struct args_size *offset_ptr, int boundary,
|
||||
HOST_WIDE_INT sp_offset = STACK_POINTER_OFFSET;
|
||||
|
||||
#ifdef SPARC_STACK_BOUNDARY_HACK
|
||||
/* The sparc port has a bug. It sometimes claims a STACK_BOUNDARY
|
||||
higher than the real alignment of %sp. However, when it does this,
|
||||
the alignment of %sp+STACK_POINTER_OFFSET will be STACK_BOUNDARY.
|
||||
This is a temporary hack while the sparc port is fixed. */
|
||||
/* ??? The SPARC port may claim a STACK_BOUNDARY higher than
|
||||
the real alignment of %sp. However, when it does this, the
|
||||
alignment of %sp+STACK_POINTER_OFFSET is STACK_BOUNDARY. */
|
||||
if (SPARC_STACK_BOUNDARY_HACK)
|
||||
sp_offset = 0;
|
||||
#endif
|
||||
|
10
gcc/reorg.c
10
gcc/reorg.c
@ -1337,7 +1337,7 @@ steal_delay_list_from_target (rtx insn, rtx condition, rtx seq,
|
||||
if (! must_annul
|
||||
&& ((condition == const_true_rtx
|
||||
|| (! insn_sets_resource_p (trial, other_needed, 0)
|
||||
&& ! may_trap_p (PATTERN (trial)))))
|
||||
&& ! may_trap_or_fault_p (PATTERN (trial)))))
|
||||
? eligible_for_delay (insn, total_slots_filled, trial, flags)
|
||||
: (must_annul || (delay_list == NULL && new_delay_list == NULL))
|
||||
&& (must_annul = 1,
|
||||
@ -1431,7 +1431,7 @@ steal_delay_list_from_fallthrough (rtx insn, rtx condition, rtx seq,
|
||||
if (! must_annul
|
||||
&& ((condition == const_true_rtx
|
||||
|| (! insn_sets_resource_p (trial, other_needed, 0)
|
||||
&& ! may_trap_p (PATTERN (trial)))))
|
||||
&& ! may_trap_or_fault_p (PATTERN (trial)))))
|
||||
? eligible_for_delay (insn, *pslots_filled, trial, flags)
|
||||
: (must_annul || delay_list == NULL) && (must_annul = 1,
|
||||
check_annul_list_true_false (1, delay_list)
|
||||
@ -2323,7 +2323,7 @@ fill_simple_delay_slots (int non_jumps_p)
|
||||
#ifdef HAVE_cc0
|
||||
&& ! (reg_mentioned_p (cc0_rtx, pat) && ! sets_cc0_p (pat))
|
||||
#endif
|
||||
&& ! (maybe_never && may_trap_p (pat))
|
||||
&& ! (maybe_never && may_trap_or_fault_p (pat))
|
||||
&& (trial = try_split (pat, trial, 0))
|
||||
&& eligible_for_delay (insn, slots_filled, trial, flags)
|
||||
&& ! can_throw_internal(trial))
|
||||
@ -2376,7 +2376,7 @@ fill_simple_delay_slots (int non_jumps_p)
|
||||
#ifdef HAVE_cc0
|
||||
&& ! reg_mentioned_p (cc0_rtx, PATTERN (next_trial))
|
||||
#endif
|
||||
&& ! (maybe_never && may_trap_p (PATTERN (next_trial)))
|
||||
&& ! (maybe_never && may_trap_or_fault_p (PATTERN (next_trial)))
|
||||
&& (next_trial = try_split (PATTERN (next_trial), next_trial, 0))
|
||||
&& eligible_for_delay (insn, slots_filled, next_trial, flags)
|
||||
&& ! can_throw_internal (trial))
|
||||
@ -2656,7 +2656,7 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
|
||||
if (!must_annul
|
||||
&& (condition == const_true_rtx
|
||||
|| (! insn_sets_resource_p (trial, &opposite_needed, 1)
|
||||
&& ! may_trap_p (pat))))
|
||||
&& ! may_trap_or_fault_p (pat))))
|
||||
{
|
||||
old_trial = trial;
|
||||
trial = try_split (pat, trial, 0);
|
||||
|
@ -1611,6 +1611,7 @@ extern int side_effects_p (rtx);
|
||||
extern int volatile_refs_p (rtx);
|
||||
extern int volatile_insn_p (rtx);
|
||||
extern int may_trap_p (rtx);
|
||||
extern int may_trap_or_fault_p (rtx);
|
||||
extern int inequality_comparisons_p (rtx);
|
||||
extern rtx replace_rtx (rtx, rtx, rtx);
|
||||
extern rtx replace_regs (rtx, rtx *, unsigned int, int);
|
||||
|
134
gcc/rtlanal.c
134
gcc/rtlanal.c
@ -223,10 +223,13 @@ rtx_varies_p (rtx x, int for_alias)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return 0 if the use of X as an address in a MEM can cause a trap. */
|
||||
/* Return nonzero if the use of X as an address in a MEM can cause a trap.
|
||||
MODE is the mode of the MEM (not that of X) and UNALIGNED_MEMS controls
|
||||
whether nonzero is returned for unaligned memory accesses on strict
|
||||
alignment machines. */
|
||||
|
||||
int
|
||||
rtx_addr_can_trap_p (rtx x)
|
||||
static int
|
||||
rtx_addr_can_trap_p_1 (rtx x, enum machine_mode mode, bool unaligned_mems)
|
||||
{
|
||||
enum rtx_code code = GET_CODE (x);
|
||||
|
||||
@ -252,27 +255,52 @@ rtx_addr_can_trap_p (rtx x)
|
||||
return 1;
|
||||
|
||||
case CONST:
|
||||
return rtx_addr_can_trap_p (XEXP (x, 0));
|
||||
return rtx_addr_can_trap_p_1 (XEXP (x, 0), mode, unaligned_mems);
|
||||
|
||||
case PLUS:
|
||||
/* An address is assumed not to trap if it is an address that can't
|
||||
trap plus a constant integer or it is the pic register plus a
|
||||
constant. */
|
||||
return ! ((! rtx_addr_can_trap_p (XEXP (x, 0))
|
||||
&& GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
|| (XEXP (x, 0) == pic_offset_table_rtx
|
||||
&& CONSTANT_P (XEXP (x, 1))));
|
||||
/* An address is assumed not to trap if:
|
||||
- it is an address that can't trap plus a constant integer,
|
||||
with the proper remainder modulo the mode size if we are
|
||||
considering unaligned memory references. */
|
||||
if (!rtx_addr_can_trap_p_1 (XEXP (x, 0), mode, unaligned_mems)
|
||||
&& GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
{
|
||||
HOST_WIDE_INT offset;
|
||||
|
||||
if (!STRICT_ALIGNMENT || !unaligned_mems)
|
||||
return 0;
|
||||
|
||||
offset = INTVAL (XEXP (x, 1));
|
||||
|
||||
#ifdef SPARC_STACK_BOUNDARY_HACK
|
||||
/* ??? The SPARC port may claim a STACK_BOUNDARY higher than
|
||||
the real alignment of %sp. However, when it does this, the
|
||||
alignment of %sp+STACK_POINTER_OFFSET is STACK_BOUNDARY. */
|
||||
if (SPARC_STACK_BOUNDARY_HACK
|
||||
&& (XEXP (x, 0) == stack_pointer_rtx
|
||||
|| XEXP (x, 0) == hard_frame_pointer_rtx))
|
||||
offset -= STACK_POINTER_OFFSET;
|
||||
#endif
|
||||
|
||||
return offset % GET_MODE_SIZE (mode) != 0;
|
||||
}
|
||||
|
||||
/* - or it is the pic register plus a constant. */
|
||||
if (XEXP (x, 0) == pic_offset_table_rtx && CONSTANT_P (XEXP (x, 1)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
||||
case LO_SUM:
|
||||
case PRE_MODIFY:
|
||||
return rtx_addr_can_trap_p (XEXP (x, 1));
|
||||
return rtx_addr_can_trap_p_1 (XEXP (x, 1), mode, unaligned_mems);
|
||||
|
||||
case PRE_DEC:
|
||||
case PRE_INC:
|
||||
case POST_DEC:
|
||||
case POST_INC:
|
||||
case POST_MODIFY:
|
||||
return rtx_addr_can_trap_p (XEXP (x, 0));
|
||||
return rtx_addr_can_trap_p_1 (XEXP (x, 0), mode, unaligned_mems);
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -282,6 +310,14 @@ rtx_addr_can_trap_p (rtx x)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return nonzero if the use of X as an address in a MEM can cause a trap. */
|
||||
|
||||
int
|
||||
rtx_addr_can_trap_p (rtx x)
|
||||
{
|
||||
return rtx_addr_can_trap_p_1 (x, VOIDmode, false);
|
||||
}
|
||||
|
||||
/* Return true if X is an address that is known to not be zero. */
|
||||
|
||||
bool
|
||||
@ -2065,10 +2101,12 @@ side_effects_p (rtx x)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return nonzero if evaluating rtx X might cause a trap. */
|
||||
/* Return nonzero if evaluating rtx X might cause a trap. UNALIGNED_MEMS
|
||||
controls whether nonzero is returned for unaligned memory accesses on
|
||||
strict alignment machines. */
|
||||
|
||||
int
|
||||
may_trap_p (rtx x)
|
||||
static int
|
||||
may_trap_p_1 (rtx x, bool unaligned_mems)
|
||||
{
|
||||
int i;
|
||||
enum rtx_code code;
|
||||
@ -2102,9 +2140,11 @@ may_trap_p (rtx x)
|
||||
|
||||
/* Memory ref can trap unless it's a static var or a stack slot. */
|
||||
case MEM:
|
||||
if (MEM_NOTRAP_P (x))
|
||||
if (MEM_NOTRAP_P (x)
|
||||
&& (!STRICT_ALIGNMENT || !unaligned_mems))
|
||||
return 0;
|
||||
return rtx_addr_can_trap_p (XEXP (x, 0));
|
||||
return
|
||||
rtx_addr_can_trap_p_1 (XEXP (x, 0), GET_MODE (x), unaligned_mems);
|
||||
|
||||
/* Division by a non-constant might trap. */
|
||||
case DIV:
|
||||
@ -2180,19 +2220,73 @@ may_trap_p (rtx x)
|
||||
{
|
||||
if (fmt[i] == 'e')
|
||||
{
|
||||
if (may_trap_p (XEXP (x, i)))
|
||||
if (may_trap_p_1 (XEXP (x, i), unaligned_mems))
|
||||
return 1;
|
||||
}
|
||||
else if (fmt[i] == 'E')
|
||||
{
|
||||
int j;
|
||||
for (j = 0; j < XVECLEN (x, i); j++)
|
||||
if (may_trap_p (XVECEXP (x, i, j)))
|
||||
if (may_trap_p_1 (XVECEXP (x, i, j), unaligned_mems))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return nonzero if evaluating rtx X might cause a trap. */
|
||||
|
||||
int
|
||||
may_trap_p (rtx x)
|
||||
{
|
||||
return may_trap_p_1 (x, false);
|
||||
}
|
||||
|
||||
/* Same as above, but additionally return non-zero if evaluating rtx X might
|
||||
cause a fault. We define a fault for the purpose of this function as a
|
||||
erroneous execution condition that cannot be encountered during the normal
|
||||
execution of a valid program; the typical example is an unaligned memory
|
||||
access on a strict alignment machine. The compiler guarantees that it
|
||||
doesn't generate code that will fault from a valid program, but this
|
||||
guarantee doesn't mean anything for individual instructions. Consider
|
||||
the following example:
|
||||
|
||||
struct S { int d; union { char *cp; int *ip; }; };
|
||||
|
||||
int foo(struct S *s)
|
||||
{
|
||||
if (s->d == 1)
|
||||
return *s->ip;
|
||||
else
|
||||
return *s->cp;
|
||||
}
|
||||
|
||||
on a strict alignment machine. In a valid program, foo will never be
|
||||
invoked on a structure for which d is equal to 1 and the underlying
|
||||
unique field of the union not aligned on a 4-byte boundary, but the
|
||||
expression *s->ip might cause a fault if considered individually.
|
||||
|
||||
At the RTL level, potentially problematic expressions will almost always
|
||||
verify may_trap_p; for example, the above dereference can be emitted as
|
||||
(mem:SI (reg:P)) and this expression is may_trap_p for a generic register.
|
||||
However, suppose that foo is inlined in a caller that causes s->cp to
|
||||
point to a local character variable and guarantees that s->d is not set
|
||||
to 1; foo may have been effectively translated into pseudo-RTL as:
|
||||
|
||||
if ((reg:SI) == 1)
|
||||
(set (reg:SI) (mem:SI (%fp - 7)))
|
||||
else
|
||||
(set (reg:QI) (mem:QI (%fp - 7)))
|
||||
|
||||
Now (mem:SI (%fp - 7)) is considered as not may_trap_p since it is a
|
||||
memory reference to a stack slot, but it will certainly cause a fault
|
||||
on a strict alignment machine. */
|
||||
|
||||
int
|
||||
may_trap_or_fault_p (rtx x)
|
||||
{
|
||||
return may_trap_p_1 (x, true);
|
||||
}
|
||||
|
||||
/* Return nonzero if X contains a comparison that is not either EQ or NE,
|
||||
i.e., an inequality. */
|
||||
|
@ -1,3 +1,7 @@
|
||||
2005-10-20 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
|
||||
* g++.dg/opt/delay-slot-1.C: New test.
|
||||
|
||||
2005-10-20 Erik Edelmann <erik.edelmann@iki.fi>
|
||||
|
||||
PR fortran/21625
|
||||
|
111
gcc/testsuite/g++.dg/opt/delay-slot-1.C
Normal file
111
gcc/testsuite/g++.dg/opt/delay-slot-1.C
Normal file
@ -0,0 +1,111 @@
|
||||
/* PR rtl-optimization/23585 */
|
||||
/* Testcase by Matti Rintala <matti.rintala@iki.fi> */
|
||||
|
||||
/* { dg-do run } */
|
||||
/* { dg-options "-O2" } */
|
||||
|
||||
template <class _Ret, class _Tp>
|
||||
class const_mem_fun_t
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
const_mem_fun_t(_Ret (_Tp::*__pf)() const)
|
||||
: _M_f(__pf) {}
|
||||
|
||||
_Ret
|
||||
operator()(const _Tp* __p) const
|
||||
{ return (__p->*_M_f)(); }
|
||||
private:
|
||||
_Ret (_Tp::*_M_f)() const;
|
||||
};
|
||||
|
||||
template <class _Ret, class _Tp>
|
||||
class const_mem_fun_ref_t
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
const_mem_fun_ref_t(_Ret (_Tp::*__pf)() const)
|
||||
: _M_f(__pf) {}
|
||||
|
||||
_Ret
|
||||
operator()(const _Tp& __r) const
|
||||
{ return (__r.*_M_f)(); }
|
||||
private:
|
||||
_Ret (_Tp::*_M_f)() const;
|
||||
};
|
||||
|
||||
template <class _Ret, class _Tp, class _Arg>
|
||||
class const_mem_fun1_t
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
const_mem_fun1_t(_Ret (_Tp::*__pf)(_Arg) const)
|
||||
: _M_f(__pf) {}
|
||||
|
||||
_Ret
|
||||
operator()(const _Tp* __p, _Arg __x) const
|
||||
{ return (__p->*_M_f)(__x); }
|
||||
private:
|
||||
_Ret (_Tp::*_M_f)(_Arg) const;
|
||||
};
|
||||
|
||||
|
||||
template <class _Ret, class _Tp, class _Arg>
|
||||
class const_mem_fun1_ref_t
|
||||
{
|
||||
public:
|
||||
explicit
|
||||
const_mem_fun1_ref_t(_Ret (_Tp::*__pf)(_Arg) const)
|
||||
: _M_f(__pf) {}
|
||||
|
||||
_Ret
|
||||
operator()(const _Tp& __r, _Arg __x) const
|
||||
{ return (__r.*_M_f)(__x); }
|
||||
private:
|
||||
_Ret (_Tp::*_M_f)(_Arg) const;
|
||||
};
|
||||
|
||||
template <class _Ret, class _Tp>
|
||||
inline const_mem_fun_t<_Ret, _Tp>
|
||||
mem_fun(_Ret (_Tp::*__f)() const)
|
||||
{ return const_mem_fun_t<_Ret, _Tp>(__f); }
|
||||
|
||||
template <class _Ret, class _Tp>
|
||||
inline const_mem_fun_ref_t<_Ret, _Tp>
|
||||
mem_fun_ref(_Ret (_Tp::*__f)() const)
|
||||
{ return const_mem_fun_ref_t<_Ret, _Tp>(__f); }
|
||||
|
||||
template <class _Ret, class _Tp, class _Arg>
|
||||
inline const_mem_fun1_t<_Ret, _Tp, _Arg>
|
||||
mem_fun(_Ret (_Tp::*__f)(_Arg) const)
|
||||
{ return const_mem_fun1_t<_Ret, _Tp, _Arg>(__f); }
|
||||
|
||||
template <class _Ret, class _Tp, class _Arg>
|
||||
inline const_mem_fun1_ref_t<_Ret, _Tp, _Arg>
|
||||
mem_fun_ref(_Ret (_Tp::*__f)(_Arg) const)
|
||||
{ return const_mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); }
|
||||
|
||||
class Class {
|
||||
public:
|
||||
void vf0c() const;
|
||||
void vf1c(const int&) const;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
Class obj;
|
||||
const Class& objc = obj;
|
||||
|
||||
mem_fun(&Class::vf0c)(&objc);
|
||||
mem_fun(&Class::vf1c)(&objc, 1);
|
||||
|
||||
mem_fun_ref(&Class::vf0c)(objc);
|
||||
mem_fun_ref(&Class::vf1c)(objc, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Class::vf0c() const
|
||||
{}
|
||||
|
||||
void Class::vf1c(const int&) const
|
||||
{}
|
Loading…
x
Reference in New Issue
Block a user