From: David Miller <da...@davemloft.net> Date: Tue, 05 Feb 2013 18:18:39 -0500 (EST)
> The only other alternative I can see would be to get everything in > var-tracking.c and the other subsystems it uses to do leaf register > remapping, but that seems completely like the wrong way to handle > this. Following up to myself... :-) Now that I understand fully what we're trying to accomplish with the DT_OP_GNU_entry_value and DT_OP_GNU_call_site_parameter extensions, it does in fact seem like we will need to do leaf register remapping in var-tracking.c Here below is a patch I'm playing with. It's a rough draft but it definitely fixes the pr54200.c problem completely. Another way to do this would be to not translate the incoming parameter registers (leave them at %i*) if we don't see the window save. That way we only have to play the regno remapping game for these specific incoming argument pieces, rather than for everything we look at in the RTL stream. diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 714acb69..14635b9 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -1057,6 +1057,32 @@ adjust_mem_stores (rtx loc, const_rtx expr, void *data) } } +/* Given a regno from the RTL instruction stream, return the + actual register number that will be used by final and debug + info emission. */ +static unsigned int +real_regno (unsigned int regno) +{ +#ifdef LEAF_REG_REMAP + if (regno < FIRST_PSEUDO_REGISTER + && crtl->uses_only_leaf_regs) + { + int remapped = LEAF_REG_REMAP (regno); + + if (remapped >= 0) + regno = (unsigned int) remapped; + } +#endif + + return regno; +} + +static unsigned int +real_regno_rtx (rtx reg) +{ + return real_regno (REGNO (reg)); +} + /* Simplify INSN. Remove all {PRE,POST}_{INC,DEC,MODIFY} rtxes, replace them with their value in the insn and add the side-effects as other sets to the insn. */ @@ -1804,12 +1830,12 @@ var_reg_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized, if (decl_p) dv = dv_from_decl (var_debug_decl (dv_as_decl (dv))); - for (node = set->regs[REGNO (loc)]; node; node = node->next) + for (node = set->regs[real_regno_rtx (loc)]; node; node = node->next) if (dv_as_opaque (node->dv) == dv_as_opaque (dv) && node->offset == offset) break; if (!node) - attrs_list_insert (&set->regs[REGNO (loc)], dv, offset, loc); + attrs_list_insert (&set->regs[real_regno_rtx (loc)], dv, offset, loc); set_variable_part (set, loc, dv, offset, initialized, set_src, iopt); } @@ -1875,7 +1901,7 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify, if (initialized == VAR_INIT_STATUS_UNKNOWN) initialized = get_init_value (set, loc, dv_from_decl (decl)); - nextp = &set->regs[REGNO (loc)]; + nextp = &set->regs[real_regno_rtx (loc)]; for (node = *nextp; node; node = next) { next = node->next; @@ -1904,7 +1930,7 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify, static void var_reg_delete (dataflow_set *set, rtx loc, bool clobber) { - attrs *nextp = &set->regs[REGNO (loc)]; + attrs *nextp = &set->regs[real_regno_rtx (loc)]; attrs node, next; if (clobber) @@ -2386,7 +2412,7 @@ val_bind (dataflow_set *set, rtx val, rtx loc, bool modified) if (REG_P (loc)) { if (modified) - var_regno_delete (set, REGNO (loc)); + var_regno_delete (set, real_regno_rtx (loc)); var_reg_decl_set (set, loc, VAR_INIT_STATUS_INITIALIZED, dv_from_value (val), 0, NULL_RTX, INSERT); } @@ -2584,7 +2610,7 @@ val_resolve (dataflow_set *set, rtx val, rtx loc, rtx insn) { attrs node, found = NULL; - for (node = set->regs[REGNO (loc)]; node; node = node->next) + for (node = set->regs[real_regno_rtx (loc)]; node; node = node->next) if (dv_is_value_p (node->dv) && GET_MODE (dv_as_value (node->dv)) == GET_MODE (loc)) { @@ -2838,7 +2864,8 @@ variable_union (variable src, dataflow_set *set) { if (!((REG_P (node2->loc) && REG_P (node->loc) - && REGNO (node2->loc) == REGNO (node->loc)) + && (real_regno_rtx (node2->loc) + == real_regno_rtx (node->loc))) || rtx_equal_p (node2->loc, node->loc))) { if (node2->init < node->init) @@ -2871,7 +2898,8 @@ variable_union (variable src, dataflow_set *set) for (node = src->var_part[i].loc_chain; node; node = node->next) if (!((REG_P (dstnode->loc) && REG_P (node->loc) - && REGNO (dstnode->loc) == REGNO (node->loc)) + && (real_regno_rtx (dstnode->loc) + == real_regno_rtx (node->loc))) || rtx_equal_p (dstnode->loc, node->loc))) { location_chain new_node; @@ -2920,7 +2948,8 @@ variable_union (variable src, dataflow_set *set) { if ((REG_P (vui[jj].lc->loc) && REG_P (node->loc) - && REGNO (vui[jj].lc->loc) == REGNO (node->loc)) + && (real_regno_rtx (vui[jj].lc->loc) + == real_regno_rtx (node->loc))) || rtx_equal_p (vui[jj].lc->loc, node->loc)) { vui[jj].pos = jj + ii; @@ -3372,9 +3401,9 @@ loc_cmp (rtx x, rtx y) if (!REG_P (y)) return -1; gcc_assert (GET_MODE (x) == GET_MODE (y)); - if (REGNO (x) == REGNO (y)) + if (real_regno_rtx (x) == real_regno_rtx (y)) return 0; - else if (REGNO (x) < REGNO (y)) + else if (real_regno_rtx (x) < real_regno_rtx (y)) return -1; else return 1; @@ -3720,7 +3749,7 @@ canonicalize_values_star (void **slot, void *data) } else if (GET_CODE (node->loc) == REG) { - attrs list = set->regs[REGNO (node->loc)], *listp; + attrs list = set->regs[real_regno_rtx (node->loc)], *listp; /* Change an existing attribute referring to dv so that it refers to cdv, removing any duplicate this might @@ -3982,13 +4011,14 @@ variable_merge_over_cur (variable s1var, struct dfset_merge *dsm) { attrs list; - for (list = dst->regs[REGNO (node->loc)]; list; list = list->next) + for (list = dst->regs[real_regno_rtx (node->loc)]; list; + list = list->next) if (GET_MODE (node->loc) == GET_MODE (list->loc) && dv_is_value_p (list->dv)) break; if (!list) - attrs_list_insert (&dst->regs[REGNO (node->loc)], + attrs_list_insert (&dst->regs[real_regno_rtx (node->loc)], dv, 0, node->loc); /* If this value became canonical for another value that had this register, we want to leave it alone. */ @@ -4364,7 +4394,7 @@ variable_post_merge_new_vals (void **slot, void *info) goto restart; } - for (attp = &set->regs[REGNO (node->loc)]; (att = *attp); + for (attp = &set->regs[real_regno_rtx (node->loc)]; (att = *attp); attp = &att->next) if (att->offset == 0 && GET_MODE (att->loc) == GET_MODE (node->loc)) @@ -4404,7 +4434,7 @@ variable_post_merge_new_vals (void **slot, void *info) dataflow_set_init (*dfpm->permp); } - for (att = (*dfpm->permp)->regs[REGNO (node->loc)]; + for (att = (*dfpm->permp)->regs[real_regno_rtx (node->loc)]; att; att = att->next) if (GET_MODE (att->loc) == GET_MODE (node->loc)) { @@ -4437,7 +4467,7 @@ variable_post_merge_new_vals (void **slot, void *info) if (dump_file) fprintf (dump_file, "Created new value %u:%u for reg %i\n", - v->uid, v->hash, REGNO (node->loc)); + v->uid, v->hash, real_regno_rtx (node->loc)); } var_reg_decl_set (*dfpm->permp, node->loc, @@ -4500,7 +4530,7 @@ variable_post_merge_perm_vals (void **pslot, void *info) val_reset (set, dv); } - for (att = set->regs[REGNO (pnode->loc)]; att; att = att->next) + for (att = set->regs[real_regno_rtx (pnode->loc)]; att; att = att->next) if (att->offset == 0 && GET_MODE (att->loc) == GET_MODE (pnode->loc) && dv_is_value_p (att->dv)) @@ -4517,7 +4547,7 @@ variable_post_merge_perm_vals (void **pslot, void *info) } else if (!att) { - attrs_list_insert (&set->regs[REGNO (pnode->loc)], + attrs_list_insert (&set->regs[real_regno_rtx (pnode->loc)], dv, 0, pnode->loc); variable_union (pvar, set); } @@ -4836,7 +4866,7 @@ variable_part_different_p (variable_part *vp1, variable_part *vp2) { if (REG_P (lc1->loc) && REG_P (lc2->loc)) { - if (REGNO (lc1->loc) == REGNO (lc2->loc)) + if (real_regno_rtx (lc1->loc) == real_regno_rtx (lc2->loc)) break; } if (rtx_equal_p (lc1->loc, lc2->loc)) @@ -5189,7 +5219,7 @@ track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p, if ((GET_MODE_SIZE (mode) > GET_MODE_SIZE (DECL_MODE (expr)) || (store_reg_p && !COMPLEX_MODE_P (DECL_MODE (expr)) - && hard_regno_nregs[REGNO (loc)][DECL_MODE (expr)] == 1)) + && hard_regno_nregs[real_regno_rtx (loc)][DECL_MODE (expr)] == 1)) && offset + byte_lowpart_offset (DECL_MODE (expr), mode) == 0) { mode = DECL_MODE (expr); @@ -5227,8 +5257,9 @@ var_lowpart (enum machine_mode mode, rtx loc) return adjust_address_nv (loc, mode, offset); reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc)); - regno = REGNO (loc) + subreg_regno_offset (REGNO (loc), GET_MODE (loc), - reg_offset, mode); + regno = real_regno_rtx (loc) + subreg_regno_offset (real_regno_rtx (loc), + GET_MODE (loc), + reg_offset, mode); return gen_rtx_REG_offset (loc, mode, regno, offset); } @@ -6231,7 +6262,7 @@ prepare_call_arguments (basic_block bb, rtx insn) && GET_MODE (reg) == mode && GET_MODE_CLASS (mode) == MODE_INT && REG_P (x) - && REGNO (x) == REGNO (reg) + && real_regno_rtx (x) == real_regno_rtx (reg) && GET_MODE (x) == mode && item) { @@ -6747,7 +6778,7 @@ compute_bb_dataflow (basic_block bb) } } else if (REG_P (uloc)) - var_regno_delete (out, REGNO (uloc)); + var_regno_delete (out, real_regno_rtx (uloc)); else if (MEM_P (uloc)) { gcc_checking_assert (GET_CODE (vloc) == MEM); @@ -7504,11 +7535,11 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot, nextp = &node->next) if (REG_P (node->loc)) { - if (REGNO (node->loc) < REGNO (loc)) + if (real_regno_rtx (node->loc) < real_regno_rtx (loc)) c++; else { - if (REGNO (node->loc) == REGNO (loc)) + if (real_regno_rtx (node->loc) == real_regno_rtx (loc)) r = 0; else r = 1; @@ -7575,7 +7606,7 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot, if (node && ((REG_P (node->loc) && REG_P (loc) - && REGNO (node->loc) == REGNO (loc)) + && real_regno_rtx (node->loc) == real_regno_rtx (loc)) || rtx_equal_p (node->loc, loc))) { /* LOC is in the beginning of the chain so we have nothing @@ -7631,7 +7662,7 @@ set_slot_part (dataflow_set *set, rtx loc, void **slot, { next = node->next; if ((REG_P (node->loc) && REG_P (loc) - && REGNO (node->loc) == REGNO (loc)) + && real_regno_rtx (node->loc) == real_regno_rtx (loc)) || rtx_equal_p (node->loc, loc)) { /* Save these values, to assign to the new node, before @@ -7729,7 +7760,7 @@ clobber_slot_part (dataflow_set *set, rtx loc, void **slot, list, but preserve any other variable parts that might be regarded as live in that same register. */ - anextp = &set->regs[REGNO (node->loc)]; + anextp = &set->regs[real_regno_rtx (node->loc)]; for (anode = *anextp; anode; anode = anext) { anext = anode->next; @@ -7800,7 +7831,7 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot, node = node->next) { if ((REG_P (node->loc) && REG_P (loc) - && REGNO (node->loc) == REGNO (loc)) + && real_regno_rtx (node->loc) == real_regno_rtx (loc)) || rtx_equal_p (node->loc, loc)) { slot = unshare_variable (set, slot, var, @@ -7823,7 +7854,7 @@ delete_slot_part (dataflow_set *set, rtx loc, void **slot, { next = node->next; if ((REG_P (node->loc) && REG_P (loc) - && REGNO (node->loc) == REGNO (loc)) + && real_regno_rtx (node->loc) == real_regno_rtx (loc)) || rtx_equal_p (node->loc, loc)) { /* If we have deleted the location which was last emitted @@ -8596,10 +8627,10 @@ emit_note_insn_var_location (void **varp, void *data) rtx new_loc = NULL; if (REG_P (loc[n_var_parts]) - && hard_regno_nregs[REGNO (loc[n_var_parts])][mode] * 2 - == hard_regno_nregs[REGNO (loc[n_var_parts])][wider_mode] - && end_hard_regno (mode, REGNO (loc[n_var_parts])) - == REGNO (loc2)) + && hard_regno_nregs[real_regno_rtx (loc[n_var_parts])][mode] * 2 + == hard_regno_nregs[real_regno_rtx (loc[n_var_parts])][wider_mode] + && end_hard_regno (mode, real_regno_rtx (loc[n_var_parts])) + == real_regno_rtx (loc2)) { if (! WORDS_BIG_ENDIAN && ! BYTES_BIG_ENDIAN) new_loc = simplify_subreg (wider_mode, loc[n_var_parts], @@ -8609,7 +8640,7 @@ emit_note_insn_var_location (void **varp, void *data) if (new_loc) { if (!REG_P (new_loc) - || REGNO (new_loc) != REGNO (loc[n_var_parts])) + || real_regno_rtx (new_loc) != real_regno_rtx (loc[n_var_parts])) new_loc = NULL; else REG_ATTRS (new_loc) = REG_ATTRS (loc[n_var_parts]); @@ -9065,8 +9096,8 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set) && MEM_P (XEXP (XEXP (XEXP (*p, 1), 0), 0)) && REG_P (XEXP (XEXP (XEXP (XEXP (*p, 1), 0), 0), 0)) - && REGNO (XEXP (XEXP (*p, 0), 0)) - == REGNO (XEXP (XEXP (XEXP (XEXP (*p, 1), 0), + && real_regno_rtx (XEXP (XEXP (*p, 0), 0)) + == real_regno_rtx (XEXP (XEXP (XEXP (XEXP (*p, 1), 0), 0), 0))) *p = XEXP (XEXP (*p, 1), 1); /* Just drop this item. */ @@ -9255,7 +9286,7 @@ emit_notes_in_bb (basic_block bb, dataflow_set *set) } } else if (REG_P (uloc)) - var_regno_delete (set, REGNO (uloc)); + var_regno_delete (set, real_regno_rtx (uloc)); else if (MEM_P (uloc)) { gcc_checking_assert (GET_CODE (vloc) == MEM); @@ -9621,7 +9652,7 @@ vt_add_function_parameter (tree parm) { incoming = var_lowpart (mode, incoming); gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER); - attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset, + attrs_list_insert (&out->regs[real_regno_rtx (incoming)], dv, offset, incoming); set_variable_part (out, incoming, dv, offset, VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); @@ -9795,7 +9826,7 @@ vt_initialize (void) val = cselib_lookup_from_insn (reg, GET_MODE (reg), 1, VOIDmode, get_insns ()); preserve_value (val); - cselib_preserve_cfa_base_value (val, REGNO (reg)); + cselib_preserve_cfa_base_value (val, real_regno_rtx (reg)); expr = plus_constant (GET_MODE (stack_pointer_rtx), stack_pointer_rtx, -ofst); cselib_add_permanent_equiv (val, expr, get_insns ());