+2010-03-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/43051
+ PR debug/43092
+ * cselib.c (cselib_preserve_constants,
+ cfa_base_preserved_val): New static variables.
+ (preserve_only_constants): New function.
+ (cselib_reset_table): If cfa_base_preserved_val is non-NULL, don't
+ clear its REG_VALUES. If cselib_preserve_constants, don't
+ empty the whole hash table, but preserve there VALUEs with constants,
+ cfa_base_preserved_val and cfa_base_preserved_val plus constant.
+ (cselib_preserve_cfa_base_value): New function.
+ (cselib_invalidate_regno): Don't invalidate cfa_base_preserved_val.
+ (cselib_init): Change argument to int bitfield. Set
+ cselib_preserve_constants to whether CSELIB_PRESERVE_CONSTANTS
+ is in it.
+ (cselib_finish): Clear cselib_preserve_constants and
+ cfa_base_preserved_val.
+ * cselib.h (enum cselib_record_what): New enum.
+ (cselib_init): Change argument to int.
+ (cselib_preserve_cfa_base_value): New prototype.
+ * postreload.c (reload_cse_regs_1): Adjust cselib_init caller.
+ * dse.c (dse_step1): Likewise.
+ * cfgcleanup.c (thread_jump): Likewise.
+ * sched-deps.c (sched_analyze): Likewise.
+ * gcse.c (local_cprop_pass): Likewise.
+ * simplify-rtx.c (simplify_replace_fn_rtx): Add argument to callback.
+ If FN is non-NULL, call the callback always and whenever it returns
+ non-NULL just return that. Only do rtx_equal_p if FN is NULL.
+ * rtl.h (simplify_replace_fn_rtx): Add argument to callback.
+ * combine.c (propagate_for_debug_subst): Add old_rtx argument,
+ compare from with old_rtx and if it isn't rtx_equal_p, return NULL.
+ * Makefile.in (var-tracking.o): Depend on $(RECOG_H).
+ * var-tracking.c: Include recog.h.
+ (bb_stack_adjust_offset): Remove.
+ (vt_stack_adjustments): Don't call it, instead just gather the
+ adjustments using insn_stack_adjust_offset_pre_post on each bb insn.
+ (adjust_stack_reference): Remove.
+ (compute_cfa_pointer): New function.
+ (hard_frame_pointer_adjustment, cfa_base_rtx): New static variables.
+ (struct adjust_mem_data): New type.
+ (adjust_mems, adjust_mem_uses, adjust_mem_stores, adjust_insn): New
+ functions.
+ (get_address_mode): New function.
+ (replace_expr_with_values): Use it.
+ (use_type): Don't do cselib_lookup for VAR_LOC_UNKNOWN_P.
+ Use get_address_mode. For cfa_base_rtx return MO_CLOBBER.
+ (adjust_sets): Remove.
+ (add_uses): Don't add extra MO_VAL_USE for cfa_base_rtx plus constant.
+ Use get_address_mode.
+ (get_adjusted_src): Remove.
+ (add_stores): Don't call it. Never reuse expr SET. Don't add extra
+ MO_VAL_USE for cfa_base_rtx plus constant. Use get_address_mode.
+ (add_with_sets): Don't call adjust_sets.
+ (fp_setter, vt_init_cfa_base): New functions.
+ (vt_initialize): Change return type to bool. Move most of pool etc.
+ initialization to the beginning of the function from end. Pass
+ CSELIB_RECORD_MEMORY | CSELIB_PRESERVE_CONSTANTS to cselib_init.
+ If !frame_pointer_needed, call vt_stack_adjustment before mos
+ vector is filled, call vt_init_cfa_base if argp/framep has been
+ eliminated to sp. If frame_pointer_needed and argp/framep has
+ been eliminated to hard frame pointer, set
+ hard_frame_pointer_adjustment and call vt_init_cfa_base after
+ encountering fp setter in the prologue. For MO_ADJUST, call
+ log_op_type before pusing the op into mos vector, not afterwards.
+ Call adjust_insn before cselib_process_insn/add_with_sets,
+ call cancel_changes (0) afterwards.
+ (variable_tracking_main_1): Adjust for vt_initialize calling
+ vt_stack_adjustments and returning whether it succeeded or not.
+
2010-03-15 Aldy Hernandez <aldyh@redhat.com>
* graphite-sese-to-poly.c (rewrite_cross_bb_scalar_deps): Skip
}
}
-/* Compute stack adjustment in basic block BB. */
-
-static void
-bb_stack_adjust_offset (basic_block bb)
-{
- HOST_WIDE_INT offset;
- unsigned int i;
- micro_operation *mo;
-
- offset = VTI (bb)->in.stack_adjust;
- for (i = 0; VEC_iterate (micro_operation, VTI (bb)->mos, i, mo); i++)
- {
- if (mo->type == MO_ADJUST)
- offset += mo->u.adjust;
- else if (mo->type != MO_CALL)
- {
- if (MEM_P (mo->u.loc))
- mo->u.loc = adjust_stack_reference (mo->u.loc, -offset);
- }
- }
- VTI (bb)->out.stack_adjust = offset;
-}
-
/* Compute stack adjustments for all blocks by traversing DFS tree.
Return true when the adjustments on all incoming edges are consistent.
Heavily borrowed from pre_and_rev_post_order_compute. */
rtx side_effects;
};
-/* Helper for adjust_mems. Return 1 if *loc is unsuitable for
- transformation of wider mode arithmetics to narrower mode,
- -1 if it is suitable and subexpressions shouldn't be
- traversed and 0 if it is suitable and subexpressions should
- be traversed. Called through for_each_rtx. */
-
-static int
-use_narrower_mode_test (rtx *loc, void *data)
-{
- rtx subreg = (rtx) data;
-
- if (CONSTANT_P (*loc))
- return -1;
- switch (GET_CODE (*loc))
- {
- case REG:
- if (cselib_lookup (*loc, GET_MODE (SUBREG_REG (subreg)), 0))
- return 1;
- return -1;
- case PLUS:
- case MINUS:
- case MULT:
- return 0;
- case ASHIFT:
- if (for_each_rtx (&XEXP (*loc, 0), use_narrower_mode_test, data))
- return 1;
- else
- return -1;
- default:
- return 1;
- }
-}
-
-/* Transform X into narrower mode MODE from wider mode WMODE. */
-
-static rtx
-use_narrower_mode (rtx x, enum machine_mode mode, enum machine_mode wmode)
-{
- rtx op0, op1;
- if (CONSTANT_P (x))
- return lowpart_subreg (mode, x, wmode);
- switch (GET_CODE (x))
- {
- case REG:
- return lowpart_subreg (mode, x, wmode);
- case PLUS:
- case MINUS:
- case MULT:
- op0 = use_narrower_mode (XEXP (x, 0), mode, wmode);
- op1 = use_narrower_mode (XEXP (x, 1), mode, wmode);
- return simplify_gen_binary (GET_CODE (x), mode, op0, op1);
- case ASHIFT:
- op0 = use_narrower_mode (XEXP (x, 0), mode, wmode);
- return simplify_gen_binary (ASHIFT, mode, op0, XEXP (x, 1));
- default:
- gcc_unreachable ();
- }
-}
-
/* Helper function for adjusting used MEMs. */
static rtx
case POST_MODIFY:
if (addr == loc)
addr = XEXP (loc, 0);
- gcc_assert (amd->mem_mode != VOIDmode);
+ gcc_assert (amd->mem_mode != VOIDmode && amd->mem_mode != BLKmode);
addr = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
amd->side_effects = alloc_EXPR_LIST (0,
gen_rtx_SET (VOIDmode,
amd->store = store_save;
mem = simplify_replace_fn_rtx (addr, old_rtx, adjust_mems, data);
if (mem == SUBREG_REG (loc))
- {
- tem = loc;
- goto finish_subreg;
- }
+ return loc;
tem = simplify_gen_subreg (GET_MODE (loc), mem,
GET_MODE (SUBREG_REG (loc)),
SUBREG_BYTE (loc));
if (tem)
- goto finish_subreg;
+ return tem;
tem = simplify_gen_subreg (GET_MODE (loc), addr,
GET_MODE (SUBREG_REG (loc)),
SUBREG_BYTE (loc));
- if (tem == NULL_RTX)
- tem = gen_rtx_raw_SUBREG (GET_MODE (loc), addr, SUBREG_BYTE (loc));
- finish_subreg:
- if (MAY_HAVE_DEBUG_INSNS
- && GET_CODE (tem) == SUBREG
- && (GET_CODE (SUBREG_REG (tem)) == PLUS
- || GET_CODE (SUBREG_REG (tem)) == MINUS
- || GET_CODE (SUBREG_REG (tem)) == MULT
- || GET_CODE (SUBREG_REG (tem)) == ASHIFT)
- && GET_MODE_CLASS (GET_MODE (tem)) == MODE_INT
- && GET_MODE_CLASS (GET_MODE (SUBREG_REG (tem))) == MODE_INT
- && GET_MODE_SIZE (GET_MODE (tem))
- < GET_MODE_SIZE (GET_MODE (SUBREG_REG (tem)))
- && subreg_lowpart_p (tem)
- && !for_each_rtx (&SUBREG_REG (tem), use_narrower_mode_test, tem))
- return use_narrower_mode (SUBREG_REG (tem), GET_MODE (tem),
- GET_MODE (SUBREG_REG (tem)));
- return tem;
+ if (tem)
+ return tem;
+ return gen_rtx_raw_SUBREG (GET_MODE (loc), addr, SUBREG_BYTE (loc));
default:
break;
}
fputc ('\n', out);
}
-/* Adjust sets if needed. Currently this optimizes read-only MEM loads
- if REG_EQUAL/REG_EQUIV note is present. */
-
-static void
-adjust_sets (rtx insn, struct cselib_set *sets, int n_sets)
-{
- if (n_sets == 1 && MEM_P (sets[0].src) && MEM_READONLY_P (sets[0].src))
- {
- /* For read-only MEMs containing some constant, prefer those
- constants. */
- rtx note = find_reg_equal_equiv_note (insn), src;
-
- if (note && CONSTANT_P (XEXP (note, 0)))
- {
- sets[0].src = src = XEXP (note, 0);
- if (GET_CODE (PATTERN (insn)) == COND_EXEC)
- src = gen_rtx_IF_THEN_ELSE (GET_MODE (sets[0].dest),
- COND_EXEC_TEST (PATTERN (insn)),
- src, sets[0].dest);
- sets[0].src_elt = cselib_lookup (src, GET_MODE (sets[0].dest), 1);
- }
- }
-}
-
/* Tell whether the CONCAT used to holds a VALUE and its location
needs value resolution, i.e., an attempt of mapping the location
back to other incoming values. */
if (REG_P (loc))
{
+ gcc_assert (loc != cfa_base_rtx);
if ((GET_CODE (expr) == CLOBBER && type != MO_VAL_SET)
|| !(track_p = use_type (loc, NULL, &mode2) == MO_USE)
|| GET_CODE (expr) == CLOBBER)
#else
cfa_base_rtx = arg_pointer_rtx;
#endif
- if (cfa_base_rtx == hard_frame_pointer_rtx
- || !fixed_regs[REGNO (cfa_base_rtx)])
- {
- cfa_base_rtx = NULL_RTX;
- return;
- }
if (!MAY_HAVE_DEBUG_INSNS)
return;
- val = cselib_lookup_from_insn (cfa_base_rtx, GET_MODE (cfa_base_rtx), 1,
- get_insns ());
+ val = cselib_lookup (cfa_base_rtx, GET_MODE (cfa_base_rtx), 1);
preserve_value (val);
cselib_preserve_cfa_base_value (val);
+ val->locs->setting_insn = get_insns ();
var_reg_decl_set (&VTI (ENTRY_BLOCK_PTR)->out, cfa_base_rtx,
VAR_INIT_STATUS_INITIALIZED, dv_from_value (val->val_rtx),
0, NULL_RTX, INSERT);
/* Add the micro-operations to the vector. */
FOR_BB_BETWEEN (bb, first_bb, last_bb->next_bb, next_bb)
{
+ HOST_WIDE_INT offset = VTI (bb)->out.stack_adjust;
+ VTI (bb)->out.stack_adjust = VTI (bb)->in.stack_adjust;
for (insn = BB_HEAD (bb); insn != NEXT_INSN (BB_END (bb));
insn = NEXT_INSN (insn))
{
mo.type = MO_ADJUST;
mo.u.adjust = pre;
mo.insn = insn;
- VEC_safe_push (micro_operation, heap, VTI (bb)->mos,
- &mo);
-
if (dump_file && (dump_flags & TDF_DETAILS))
log_op_type (PATTERN (insn), bb, insn,
MO_ADJUST, dump_file);
mo.type = MO_ADJUST;
mo.u.adjust = post;
mo.insn = insn;
- VEC_safe_push (micro_operation, heap, VTI (bb)->mos,
- &mo);
-
if (dump_file && (dump_flags & TDF_DETAILS))
log_op_type (PATTERN (insn), bb, insn,
MO_ADJUST, dump_file);
}
}
}
+ gcc_assert (offset == VTI (bb)->out.stack_adjust);
}
bb = last_bb;