+2007-11-07 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ PR rtl-optimization/33822
+ * rtl.h (REG_OFFSET): Fix comment.
+ * var-tracking.c (INT_MEM_OFFSET): New macro.
+ (var_mem_set): Use it.
+ (var_mem_delete_and_set): Likewise.
+ (var_mem_delete): Likewise.
+ (vt_get_decl_and_offset): Likewise.
+ (offset_valid_for_tracked_p): New predicate.
+ (count_uses): Do not track locations with invalid offsets.
+ (add_uses): Likewise.
+ (add_stores): Likewise.
+
2007-11-04 Hirohisa Yamaguchi <umq@ueo.co.jp>
* config/freebsd-spec.h (FBSD_TARGET_OS_CPP_BUILTINS): Fix
/* Pointer to the BB's information specific to variable tracking pass. */
#define VTI(BB) ((variable_tracking_info) (BB)->aux)
+/* Macro to access MEM_OFFSET as an HOST_WIDE_INT. Evaluates MEM twice. */
+#define INT_MEM_OFFSET(mem) (MEM_OFFSET (mem) ? INTVAL (MEM_OFFSET (mem)) : 0)
+
/* Alloc pool for struct attrs_def. */
static alloc_pool attrs_pool;
var_mem_delete_and_set (dataflow_set *set, rtx loc)
{
tree decl = MEM_EXPR (loc);
- HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
+ HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
set_variable_part (set, loc, decl, offset);
}
var_mem_delete (dataflow_set *set, rtx loc)
{
tree decl = MEM_EXPR (loc);
- HOST_WIDE_INT offset = MEM_OFFSET (loc) ? INTVAL (MEM_OFFSET (loc)) : 0;
+ HOST_WIDE_INT offset = INT_MEM_OFFSET (loc);
delete_variable_part (set, loc, decl, offset);
}
return 1;
}
+/* Return true if OFFSET is a valid offset for a register or memory
+ access we want to track. This is used to reject out-of-bounds
+ accesses that can cause assertions to fail later. Note that we
+ don't reject negative offsets because they can be generated for
+ paradoxical subregs on big-endian architectures. */
+
+static inline bool
+offset_valid_for_tracked_p (HOST_WIDE_INT offset)
+{
+ return (-MAX_VAR_PARTS < offset) && (offset < MAX_VAR_PARTS);
+}
+
/* Count uses (register and memory references) LOC which will be tracked.
INSN is instruction which the LOC is part of. */
}
else if (MEM_P (*loc)
&& MEM_EXPR (*loc)
- && track_expr_p (MEM_EXPR (*loc)))
+ && track_expr_p (MEM_EXPR (*loc))
+ && offset_valid_for_tracked_p (INT_MEM_OFFSET (*loc)))
{
VTI (bb)->n_mos++;
}
basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
- mo->type = ((REG_EXPR (*loc) && track_expr_p (REG_EXPR (*loc)))
- ? MO_USE : MO_USE_NO_VAR);
+ if (REG_EXPR (*loc)
+ && track_expr_p (REG_EXPR (*loc))
+ && offset_valid_for_tracked_p (REG_OFFSET (*loc)))
+ mo->type = MO_USE;
+ else
+ mo->type = MO_USE_NO_VAR;
mo->u.loc = *loc;
mo->insn = (rtx) insn;
}
else if (MEM_P (*loc)
&& MEM_EXPR (*loc)
- && track_expr_p (MEM_EXPR (*loc)))
+ && track_expr_p (MEM_EXPR (*loc))
+ && offset_valid_for_tracked_p (INT_MEM_OFFSET (*loc)))
{
basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
- mo->type = ((GET_CODE (expr) != CLOBBER && REG_EXPR (loc)
- && track_expr_p (REG_EXPR (loc)))
- ? MO_SET : MO_CLOBBER);
+ if (GET_CODE (expr) != CLOBBER
+ && REG_EXPR (loc)
+ && track_expr_p (REG_EXPR (loc))
+ && offset_valid_for_tracked_p (REG_OFFSET (loc)))
+ mo->type = MO_SET;
+ else
+ mo->type = MO_CLOBBER;
mo->u.loc = loc;
mo->insn = (rtx) insn;
}
else if (MEM_P (loc)
&& MEM_EXPR (loc)
- && track_expr_p (MEM_EXPR (loc)))
+ && track_expr_p (MEM_EXPR (loc))
+ && offset_valid_for_tracked_p (INT_MEM_OFFSET (loc)))
{
basic_block bb = BLOCK_FOR_INSN ((rtx) insn);
micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
if (MEM_ATTRS (rtl))
{
*declp = MEM_EXPR (rtl);
- *offsetp = MEM_OFFSET (rtl) ? INTVAL (MEM_OFFSET (rtl)) : 0;
+ *offsetp = INT_MEM_OFFSET (rtl);
return true;
}
}