dv_is_decl_p (decl_or_value dv)
{
if (!dv)
- return false;
+ return true;
- if (GET_CODE ((rtx)dv) == VALUE)
- return false;
+ /* Make sure relevant codes don't overlap. */
+ switch ((int)TREE_CODE ((tree)dv))
+ {
+ case (int)VAR_DECL:
+ case (int)PARM_DECL:
+ case (int)RESULT_DECL:
+ case (int)FUNCTION_DECL:
+ case (int)DEBUG_EXPR_DECL:
+ case (int)COMPONENT_REF:
+ return true;
- return true;
+ case (int)VALUE:
+ return false;
+
+ default:
+ gcc_unreachable ();
+ }
}
/* Return true if a decl_or_value is a VALUE rtl. */
return dv_onepart_p (dv) ? valvar_pool : var_pool;
}
-#define IS_DECL_CODE(C) ((C) == VAR_DECL || (C) == PARM_DECL \
- || (C) == RESULT_DECL || (C) == COMPONENT_REF)
-
-/* Check that VALUE won't ever look like a DECL. */
-static char check_value_is_not_decl [(!IS_DECL_CODE ((enum tree_code)VALUE))
- ? 1 : -1] ATTRIBUTE_UNUSED;
-
-
/* Build a decl_or_value out of a decl. */
static inline decl_or_value
dv_from_decl (tree decl)
{
decl_or_value dv;
- gcc_assert (!decl || IS_DECL_CODE (TREE_CODE (decl)));
dv = decl;
+ gcc_assert (dv_is_decl_p (dv));
return dv;
}
dv_from_value (rtx value)
{
decl_or_value dv;
- gcc_assert (value);
dv = value;
+ gcc_assert (dv_is_value_p (dv));
return dv;
}
/* Whether the value is currently being expanded. */
#define VALUE_RECURSED_INTO(x) \
- (RTL_FLAG_CHECK1 ("VALUE_RECURSED_INTO", (x), VALUE)->used)
+ (RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
/* Whether the value is in changed_variables hash table. */
#define VALUE_CHANGED(x) \
(RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
rtx decl_rtl;
tree realdecl;
+ if (TREE_CODE (expr) == DEBUG_EXPR_DECL)
+ return DECL_RTL_SET_P (expr);
+
/* If EXPR is not a parameter or a variable do not track it. */
if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
return 0;
return NULL;
else if (MEM_P (loc))
{
- cselib_val *addr = cselib_lookup (XEXP (loc, 0), Pmode, 0);
+ enum machine_mode address_mode
+ = targetm.addr_space.address_mode (MEM_ADDR_SPACE (loc));
+ cselib_val *addr = cselib_lookup (XEXP (loc, 0), address_mode, 0);
if (addr)
return replace_equiv_address_nv (loc, addr->val_rtx);
else
if (MEM_P (*loc)
&& !REG_P (XEXP (*loc, 0)) && !MEM_P (XEXP (*loc, 0)))
{
- val = cselib_lookup (XEXP (*loc, 0), Pmode, false);
+ enum machine_mode address_mode
+ = targetm.addr_space.address_mode (MEM_ADDR_SPACE (*loc));
+ val = cselib_lookup (XEXP (*loc, 0), address_mode, false);
if (val && !cselib_preserved_value_p (val))
{
&& !REG_P (XEXP (vloc, 0)) && !MEM_P (XEXP (vloc, 0)))
{
rtx mloc = vloc;
- cselib_val *val = cselib_lookup (XEXP (mloc, 0), Pmode, 0);
+ enum machine_mode address_mode
+ = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mloc));
+ cselib_val *val
+ = cselib_lookup (XEXP (mloc, 0), address_mode, 0);
if (val && !cselib_preserved_value_p (val))
{
cselib_preserve_value (val);
mo->type = MO_VAL_USE;
mloc = cselib_subst_to_values (XEXP (mloc, 0));
- mo->u.loc = gen_rtx_CONCAT (Pmode, val->val_rtx, mloc);
+ mo->u.loc = gen_rtx_CONCAT (address_mode,
+ val->val_rtx, mloc);
if (dump_file && (dump_flags & TDF_DETAILS))
log_op_type (mo->u.loc, cui->bb, cui->insn,
mo->type, dump_file);
&& !REG_P (XEXP (oloc, 0)) && !MEM_P (XEXP (oloc, 0)))
{
rtx mloc = oloc;
- cselib_val *val = cselib_lookup (XEXP (mloc, 0), Pmode, 0);
+ enum machine_mode address_mode
+ = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mloc));
+ cselib_val *val
+ = cselib_lookup (XEXP (mloc, 0), address_mode, 0);
if (val && !cselib_preserved_value_p (val))
{
cselib_preserve_value (val);
mo->type = MO_VAL_USE;
mloc = cselib_subst_to_values (XEXP (mloc, 0));
- mo->u.loc = gen_rtx_CONCAT (Pmode, val->val_rtx, mloc);
+ mo->u.loc = gen_rtx_CONCAT (address_mode,
+ val->val_rtx, mloc);
mo->insn = cui->insn;
if (dump_file && (dump_flags & TDF_DETAILS))
log_op_type (mo->u.loc, cui->bb, cui->insn,
&& !REG_P (XEXP (loc, 0)) && !MEM_P (XEXP (loc, 0)))
{
rtx mloc = loc;
- cselib_val *val = cselib_lookup (XEXP (mloc, 0), Pmode, 0);
+ enum machine_mode address_mode
+ = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mloc));
+ cselib_val *val = cselib_lookup (XEXP (mloc, 0), address_mode, 0);
if (val && !cselib_preserved_value_p (val))
{
cselib_preserve_value (val);
mo->type = MO_VAL_USE;
mloc = cselib_subst_to_values (XEXP (mloc, 0));
- mo->u.loc = gen_rtx_CONCAT (Pmode, val->val_rtx, mloc);
+ mo->u.loc = gen_rtx_CONCAT (address_mode, val->val_rtx, mloc);
mo->insn = cui->insn;
if (dump_file && (dump_flags & TDF_DETAILS))
log_op_type (mo->u.loc, cui->bb, cui->insn,
note_uses (&PATTERN (insn), add_uses_1, &cui);
n2 = VTI (bb)->n_mos - 1;
- /* Order the MO_USEs to be before MO_USE_NO_VARs,
- MO_VAL_LOC and MO_VAL_USE. */
+ /* Order the MO_USEs to be before MO_USE_NO_VARs and MO_VAL_USE, and
+ MO_VAL_LOC last. */
while (n1 < n2)
{
while (n1 < n2 && VTI (bb)->mos[n1].type == MO_USE)
}
}
+ n2 = VTI (bb)->n_mos - 1;
+
+ while (n1 < n2)
+ {
+ while (n1 < n2 && VTI (bb)->mos[n1].type != MO_VAL_LOC)
+ n1++;
+ while (n1 < n2 && VTI (bb)->mos[n2].type == MO_VAL_LOC)
+ n2--;
+ if (n1 < n2)
+ {
+ micro_operation sw;
+
+ sw = VTI (bb)->mos[n1];
+ VTI (bb)->mos[n1] = VTI (bb)->mos[n2];
+ VTI (bb)->mos[n2] = sw;
+ }
+ }
+
if (CALL_P (insn))
{
micro_operation *mo = VTI (bb)->mos + VTI (bb)->n_mos++;
slot = delete_slot_part (set, loc, slot, offset);
}
-/* Wrap result in CONST:MODE if needed to preserve the mode. */
-
-static rtx
-check_wrap_constant (enum machine_mode mode, rtx result)
-{
- if (!result || GET_MODE (result) == mode)
- return result;
-
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, " wrapping result in const to preserve mode %s\n",
- GET_MODE_NAME (mode));
-
- result = wrap_constant (mode, result);
- gcc_assert (GET_MODE (result) == mode);
-
- return result;
-}
-
/* Callback for cselib_expand_value, that looks for expressions
- holding the value in the var-tracking hash tables. */
+ holding the value in the var-tracking hash tables. Return X for
+ standard processing, anything else is to be used as-is. */
static rtx
vt_expand_loc_callback (rtx x, bitmap regs, int max_depth, void *data)
decl_or_value dv;
variable var;
location_chain loc;
- rtx result;
+ rtx result, subreg, xret;
+
+ switch (GET_CODE (x))
+ {
+ case SUBREG:
+ subreg = SUBREG_REG (x);
+
+ if (GET_CODE (SUBREG_REG (x)) != VALUE)
+ return x;
+
+ subreg = cselib_expand_value_rtx_cb (SUBREG_REG (x), regs,
+ max_depth - 1,
+ vt_expand_loc_callback, data);
+
+ if (!subreg)
+ return NULL;
+
+ result = simplify_gen_subreg (GET_MODE (x), subreg,
+ GET_MODE (SUBREG_REG (x)),
+ SUBREG_BYTE (x));
+
+ /* Invalid SUBREGs are ok in debug info. ??? We could try
+ alternate expansions for the VALUE as well. */
+ if (!result && (REG_P (subreg) || MEM_P (subreg)))
+ result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
+
+ return result;
+
+ case DEBUG_EXPR:
+ dv = dv_from_decl (DEBUG_EXPR_TREE_DECL (x));
+ xret = NULL;
+ break;
- gcc_assert (GET_CODE (x) == VALUE);
+ case VALUE:
+ dv = dv_from_value (x);
+ xret = x;
+ break;
+
+ default:
+ return x;
+ }
if (VALUE_RECURSED_INTO (x))
return NULL;
- dv = dv_from_value (x);
var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
if (!var)
- return NULL;
+ return xret;
if (var->n_var_parts == 0)
- return NULL;
+ return xret;
gcc_assert (var->n_var_parts == 1);
{
result = cselib_expand_value_rtx_cb (loc->loc, regs, max_depth,
vt_expand_loc_callback, vars);
- result = check_wrap_constant (GET_MODE (loc->loc), result);
if (result)
break;
}
VALUE_RECURSED_INTO (x) = false;
- return result;
+ if (result)
+ return result;
+ else
+ return xret;
}
/* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
static rtx
vt_expand_loc (rtx loc, htab_t vars)
{
- rtx newloc;
-
if (!MAY_HAVE_DEBUG_INSNS)
return loc;
- newloc = cselib_expand_value_rtx_cb (loc, scratch_regs, 5,
- vt_expand_loc_callback, vars);
- loc = check_wrap_constant (GET_MODE (loc), newloc);
+ loc = cselib_expand_value_rtx_cb (loc, scratch_regs, 5,
+ vt_expand_loc_callback, vars);
if (loc && MEM_P (loc))
loc = targetm.delegitimize_address (loc);
decl = dv_as_decl (var->dv);
+ if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
+ goto clear;
+
gcc_assert (decl);
complete = true;
continue;
}
loc[n_var_parts] = loc2;
- mode = GET_MODE (loc[n_var_parts]);
+ mode = GET_MODE (var->var_part[i].loc_chain->loc);
initialized = var->var_part[i].loc_chain->init;
last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
break;
if (j < var->n_var_parts
&& wider_mode != VOIDmode
+ && mode == GET_MODE (var->var_part[j].loc_chain->loc)
+ && (REG_P (loc[n_var_parts]) || MEM_P (loc[n_var_parts]))
&& (loc2 = vt_expand_loc (var->var_part[j].loc_chain->loc, vars))
&& GET_CODE (loc[n_var_parts]) == GET_CODE (loc2)
- && mode == GET_MODE (loc2)
&& last_limit == var->var_part[j].offset)
{
rtx new_loc = NULL;
if (!vt_get_decl_and_offset (incoming, &decl, &offset))
{
- if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
- continue;
- offset += byte_lowpart_offset (GET_MODE (incoming),
- GET_MODE (decl_rtl));
+ if (REG_P (incoming) || MEM_P (incoming))
+ {
+ /* This means argument is passed by invisible reference. */
+ offset = 0;
+ decl = parm;
+ incoming = gen_rtx_MEM (GET_MODE (decl_rtl), incoming);
+ }
+ else
+ {
+ if (!vt_get_decl_and_offset (decl_rtl, &decl, &offset))
+ continue;
+ offset += byte_lowpart_offset (GET_MODE (incoming),
+ GET_MODE (decl_rtl));
+ }
}
if (!decl)