aboutsummaryrefslogtreecommitdiff
path: root/gcc/rtlanal.c
diff options
context:
space:
mode:
authorPaolo Bonzini <bonzini@gnu.org>2009-02-04 20:54:36 +0000
committerPaolo Bonzini <bonzini@gcc.gnu.org>2009-02-04 20:54:36 +0000
commit48e8382e95ddc134f5f3c577b87558f11ad8ebeb (patch)
tree18492e6dd523a8d915f6d21a6db7b043ec15a9dd /gcc/rtlanal.c
parent69349ea551c84f1a40c8cb51342ea8075eece875 (diff)
downloadgcc-48e8382e95ddc134f5f3c577b87558f11ad8ebeb.zip
gcc-48e8382e95ddc134f5f3c577b87558f11ad8ebeb.tar.gz
gcc-48e8382e95ddc134f5f3c577b87558f11ad8ebeb.tar.bz2
re PR rtl-optimization/37889 (SEGV, conditional execution proactively executed the false arm.)
2009-02-04 Paolo Bonzini <bonzini@gnu.org> Hans-Peter Nilsson <hp@axis.com> PR rtl-optimization/37889 * rtlanal.c (rtx_addr_can_trap_p_1): Add offset and size arguments. Move offset handling from PLUS to before the switch. Use new arguments when considering SYMBOL_REFs too. (rtx_addr_can_trap_p): Pass dummy offset and size. (enum may_trap_p_flags): Remove. (may_trap_p_1): Pass size from MEM_SIZE. PR rtl-optimization/38921 * loop-invariant.c (find_invariant_insn): Use may_trap_or_fault_p. * rtl.h (may_trap_after_code_motion_p): Delete prototype. * rtlanal.c (may_trap_after_code_motion_p): Delete. (may_trap_p, may_trap_or_fault_p): Pass 0/1 as flags. Co-Authored-By: Hans-Peter Nilsson <hp@axis.com> From-SVN: r143939
Diffstat (limited to 'gcc/rtlanal.c')
-rw-r--r--gcc/rtlanal.c154
1 files changed, 91 insertions, 63 deletions
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 5d9df2c..cc7775f 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -263,14 +263,68 @@ rtx_varies_p (const_rtx x, bool for_alias)
alignment machines. */
static int
-rtx_addr_can_trap_p_1 (const_rtx x, enum machine_mode mode, bool unaligned_mems)
+rtx_addr_can_trap_p_1 (const_rtx x, HOST_WIDE_INT offset, HOST_WIDE_INT size,
+ enum machine_mode mode, bool unaligned_mems)
{
enum rtx_code code = GET_CODE (x);
+ if (STRICT_ALIGNMENT
+ && unaligned_mems
+ && GET_MODE_SIZE (mode) != 0)
+ {
+ HOST_WIDE_INT actual_offset = offset;
+#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
+ && (x == stack_pointer_rtx || x == hard_frame_pointer_rtx))
+ actual_offset -= STACK_POINTER_OFFSET;
+#endif
+
+ return actual_offset % GET_MODE_SIZE (mode) != 0;
+ }
+
switch (code)
{
case SYMBOL_REF:
- return SYMBOL_REF_WEAK (x);
+ if (SYMBOL_REF_WEAK (x))
+ return 1;
+ if (!CONSTANT_POOL_ADDRESS_P (x))
+ {
+ tree decl;
+ HOST_WIDE_INT decl_size;
+
+ if (offset < 0)
+ return 1;
+ if (size == 0)
+ size = GET_MODE_SIZE (mode);
+ if (size == 0)
+ return offset != 0;
+
+ /* If the size of the access or of the symbol is unknown,
+ assume the worst. */
+ decl = SYMBOL_REF_DECL (x);
+
+ /* Else check that the access is in bounds. TODO: restructure
+ expr_size/lhd_expr_size/int_expr_size and just use the latter. */
+ if (!decl)
+ decl_size = -1;
+ else if (DECL_P (decl) && DECL_SIZE_UNIT (decl))
+ decl_size = (host_integerp (DECL_SIZE_UNIT (decl), 0)
+ ? tree_low_cst (DECL_SIZE_UNIT (decl), 0)
+ : -1);
+ else if (TREE_CODE (decl) == STRING_CST)
+ decl_size = TREE_STRING_LENGTH (decl);
+ else if (TYPE_SIZE_UNIT (TREE_TYPE (decl)))
+ decl_size = int_size_in_bytes (TREE_TYPE (decl));
+ else
+ decl_size = -1;
+
+ return (decl_size <= 0 ? offset != 0 : offset + size > decl_size);
+ }
+
+ return 0;
case LABEL_REF:
return 0;
@@ -289,54 +343,37 @@ rtx_addr_can_trap_p_1 (const_rtx x, enum machine_mode mode, bool unaligned_mems)
return 1;
case CONST:
- return rtx_addr_can_trap_p_1 (XEXP (x, 0), mode, unaligned_mems);
+ return rtx_addr_can_trap_p_1 (XEXP (x, 0), offset, size,
+ 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,
+ - it is the pic register plus a constant. */
+ if (XEXP (x, 0) == pic_offset_table_rtx && CONSTANT_P (XEXP (x, 1)))
+ return 0;
+
+ /* - or 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
- || GET_MODE_SIZE (mode) == 0)
- 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)))
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT
+ && !rtx_addr_can_trap_p_1 (XEXP (x, 0), offset + INTVAL (XEXP (x, 1)),
+ size, mode, unaligned_mems))
return 0;
return 1;
case LO_SUM:
case PRE_MODIFY:
- return rtx_addr_can_trap_p_1 (XEXP (x, 1), mode, unaligned_mems);
+ return rtx_addr_can_trap_p_1 (XEXP (x, 1), offset, size,
+ mode, unaligned_mems);
case PRE_DEC:
case PRE_INC:
case POST_DEC:
case POST_INC:
case POST_MODIFY:
- return rtx_addr_can_trap_p_1 (XEXP (x, 0), mode, unaligned_mems);
+ return rtx_addr_can_trap_p_1 (XEXP (x, 0), offset, size,
+ mode, unaligned_mems);
default:
break;
@@ -351,7 +388,7 @@ rtx_addr_can_trap_p_1 (const_rtx x, enum machine_mode mode, bool unaligned_mems)
int
rtx_addr_can_trap_p (const_rtx x)
{
- return rtx_addr_can_trap_p_1 (x, VOIDmode, false);
+ return rtx_addr_can_trap_p_1 (x, 0, 0, VOIDmode, false);
}
/* Return true if X is an address that is known to not be zero. */
@@ -2170,17 +2207,10 @@ side_effects_p (const_rtx x)
return 0;
}
-enum may_trap_p_flags
-{
- MTP_UNALIGNED_MEMS = 1,
- MTP_AFTER_MOVE = 2
-};
/* Return nonzero if evaluating rtx X might cause a trap.
- (FLAGS & MTP_UNALIGNED_MEMS) controls whether nonzero is returned for
- unaligned memory accesses on strict alignment machines. If
- (FLAGS & AFTER_MOVE) is true, returns nonzero even in case the expression
- cannot trap at its current location, but it might become trapping if moved
- elsewhere. */
+ FLAGS controls how to consider MEMs. A nonzero means the context
+ of the access may have changed from the original, such that the
+ address may have become invalid. */
int
may_trap_p_1 (const_rtx x, unsigned flags)
@@ -2188,7 +2218,11 @@ may_trap_p_1 (const_rtx x, unsigned flags)
int i;
enum rtx_code code;
const char *fmt;
- bool unaligned_mems = (flags & MTP_UNALIGNED_MEMS) != 0;
+
+ /* We make no distinction currently, but this function is part of
+ the internal target-hooks ABI so we keep the parameter as
+ "unsigned flags". */
+ bool code_changed = flags != 0;
if (x == 0)
return 0;
@@ -2223,14 +2257,17 @@ may_trap_p_1 (const_rtx x, unsigned flags)
/* Memory ref can trap unless it's a static var or a stack slot. */
case MEM:
if (/* MEM_NOTRAP_P only relates to the actual position of the memory
- reference; moving it out of condition might cause its address
- become invalid. */
- !(flags & MTP_AFTER_MOVE)
- && MEM_NOTRAP_P (x)
- && (!STRICT_ALIGNMENT || !unaligned_mems))
- return 0;
- return
- rtx_addr_can_trap_p_1 (XEXP (x, 0), GET_MODE (x), unaligned_mems);
+ reference; moving it out of context such as when moving code
+ when optimizing, might cause its address to become invalid. */
+ code_changed
+ || !MEM_NOTRAP_P (x))
+ {
+ HOST_WIDE_INT size = MEM_SIZE (x) ? INTVAL (MEM_SIZE (x)) : 0;
+ return rtx_addr_can_trap_p_1 (XEXP (x, 0), 0, size,
+ GET_MODE (x), code_changed);
+ }
+
+ return 0;
/* Division by a non-constant might trap. */
case DIV:
@@ -2328,15 +2365,6 @@ may_trap_p (const_rtx x)
return may_trap_p_1 (x, 0);
}
-/* Return nonzero if evaluating rtx X might cause a trap, when the expression
- is moved from its current location by some optimization. */
-
-int
-may_trap_after_code_motion_p (const_rtx x)
-{
- return may_trap_p_1 (x, MTP_AFTER_MOVE);
-}
-
/* Same as above, but additionally return nonzero 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
@@ -2380,7 +2408,7 @@ may_trap_after_code_motion_p (const_rtx x)
int
may_trap_or_fault_p (const_rtx x)
{
- return may_trap_p_1 (x, MTP_UNALIGNED_MEMS);
+ return may_trap_p_1 (x, 1);
}
/* Return nonzero if X contains a comparison that is not either EQ or NE,