> Here is an alternative, almost completely untested, patch, which > uses DW_OP_fbreg <N> for the arguments of dynamically realigned functions. > draptest.c now works...
I've attached a slightly revamped, IMO easier to understand version. Stack realignment with DRAP is quite seldom on the mainline (because everything is ACCUMULATE_OUTGOING_ARGS now) so I don't think this will make any difference in practice. Tested on i586 and x86-64. * var-tracking.c (vt_add_function_parameter): Remap incoming MEMs with crtl->args.internal_arg_pointer based address to arg_pointer_rtx if there is a DRAP register. (vt_init_cfa_base): Don't equate cfa_base_rtx if stack was realigned. (vt_initialize): Initialize cfa_base_rtx if there is a DRAP register. -- Eric Botcazou
Index: var-tracking.c =================================================================== --- var-tracking.c (revision 174377) +++ var-tracking.c (working copy) @@ -8398,6 +8398,27 @@ vt_add_function_parameter (tree parm) if (GET_MODE (decl_rtl) == BLKmode || GET_MODE (incoming) == BLKmode) return; + /* If there is a DRAP register, rewrite the incoming location of parameters + passed on the stack into MEMs based on the argument pointer, as the DRAP + register can be reused for other purposes and we do not track locations + based on generic registers. See also vt_initialize. */ + if (MEM_P (incoming) + && stack_realign_drap + && cfa_base_rtx + && (XEXP (incoming, 0) == crtl->args.internal_arg_pointer + || (GET_CODE (XEXP (incoming, 0)) == PLUS + && XEXP (XEXP (incoming, 0), 0) + == crtl->args.internal_arg_pointer + && CONST_INT_P (XEXP (XEXP (incoming, 0), 1))))) + { + HOST_WIDE_INT off = -FIRST_PARM_OFFSET (current_function_decl); + if (GET_CODE (XEXP (incoming, 0)) == PLUS) + off += INTVAL (XEXP (XEXP (incoming, 0), 1)); + incoming + = replace_equiv_address_nv (incoming, + plus_constant (arg_pointer_rtx, off)); + } + if (!vt_get_decl_and_offset (incoming, &decl, &offset)) { if (REG_P (incoming) || MEM_P (incoming)) @@ -8647,9 +8668,11 @@ vt_init_cfa_base (void) /* Tell alias analysis that cfa_base_rtx should share find_base_term value with stack pointer or hard frame pointer. */ - vt_equate_reg_base_value (cfa_base_rtx, - frame_pointer_needed - ? hard_frame_pointer_rtx : stack_pointer_rtx); + if (!frame_pointer_needed) + vt_equate_reg_base_value (cfa_base_rtx, stack_pointer_rtx); + else if (!crtl->stack_realign_tried) + vt_equate_reg_base_value (cfa_base_rtx, hard_frame_pointer_rtx); + val = cselib_lookup_from_insn (cfa_base_rtx, GET_MODE (cfa_base_rtx), 1, VOIDmode, get_insns ()); preserve_value (val); @@ -8780,6 +8803,31 @@ vt_initialize (void) fp_cfa_offset = -1; } + /* If the stack is realigned and a DRAP register is used, we're going to + rewrite MEMs based on it representing incoming locations of parameters + passed on the stack into MEMs based on the argument pointer. Although + we aren't going to rewrite other MEMs, we need to set up the virtual + CFA pointer in order to ensure that the argument pointer will be seen + as a constant throughout the function. */ + else if (stack_realign_drap) + { + rtx reg, elim; + +#ifdef FRAME_POINTER_CFA_OFFSET + reg = frame_pointer_rtx; +#else + reg = arg_pointer_rtx; +#endif + elim = eliminate_regs (reg, VOIDmode, NULL_RTX); + if (elim != reg) + { + if (GET_CODE (elim) == PLUS) + elim = XEXP (elim, 0); + if (elim == hard_frame_pointer_rtx) + vt_init_cfa_base (); + } + } + if (frame_pointer_needed) { rtx insn;