From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5470 invoked by alias); 22 Mar 2004 15:05:14 -0000 Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org Received: (qmail 5444 invoked from network); 22 Mar 2004 15:05:10 -0000 Received: from unknown (HELO NUTMEG.CAM.ARTIMI.COM) (217.40.111.177) by sources.redhat.com with SMTP; 22 Mar 2004 15:05:10 -0000 Received: from mace ([192.168.1.25]) by NUTMEG.CAM.ARTIMI.COM with Microsoft SMTPSVC(6.0.3790.0); Mon, 22 Mar 2004 15:04:20 +0000 From: "Dave Korn" To: "'Richard Henderson'" Cc: Subject: RE: How can INITIAL_FRAME_POINTER_OFFSET be made correct? Date: Mon, 22 Mar 2004 17:31:00 -0000 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit In-Reply-To: <20040319194927.GA26527@redhat.com> Message-ID: X-OriginalArrivalTime: 22 Mar 2004 15:04:20.0984 (UTC) FILETIME=[F478D780:01C4101E] X-SW-Source: 2004-03/txt/msg01301.txt.bz2 > -----Original Message----- > From: Richard Henderson > Sent: 19 March 2004 19:49 >On Fri, Mar 19, 2004 at 03:30:03PM -0000, Dave Korn wrote: >> INITIAL_FRAME_POINTER_OFFSET is called before the md emit prologue >> function has has a chance to run. So it has to duplicate the exact >> calculations that the prologue function does when it's deciding on >> the stack frame layout for the current function. > > Yes. This is true for everyone. Preferred technique is to > use a common function to be used here and in the > prologue/epilogue code. Yep, that's exactly how I do it: I defined a nice struct to wrap it all up in struct dlx_frame_info { int lr_save_size; int lr_save_pointer; int fp_save_size; int fp_save_pointer; int gpr_save_size; int gpr_save_pointer; int aligned_outarg_size; int aligned_vars_size; int stack_size; }; and a generic routine to perform the calculations: void dlx_init_frame_info (info, vars) struct dlx_frame_info *info; int vars; { /* Start by initing all sizes to zero. */ memset (info, 0, sizeof *info); /* Calculate space needed for various areas. These magic 4s are bad really. */ info->lr_save_size = !current_function_is_leaf || regs_ever_live[LINK_REGNUM] ? 4 : 0; /* fp_save_size MUST be setup correctly before we iterate across gprs */ info->fp_save_size = frame_pointer_needed ? 4 : 0; info->gpr_save_size = dlx_gpr_save_area_iterate (info, NULL, NULL) * 4; info->aligned_outarg_size = DLX_ALIGN(current_function_outgoing_args_size,4); info->aligned_vars_size = DLX_ALIGN(vars,4); info->stack_size = info->aligned_outarg_size + info->lr_save_size + info->fp_save_size + info->gpr_save_size + info->aligned_vars_size; info->lr_save_pointer = info->aligned_outarg_size; info->fp_save_pointer = info->lr_save_pointer + info->lr_save_size; info->gpr_save_pointer = info->aligned_outarg_size + info->lr_save_size + info->fp_save_size; } which I then call like this: static void dlx_output_function_prologue(file, vars) FILE *file; int vars; { struct dlx_frame_info info; int regno; /* Allocate space in the stack frame and lay it out. */ dlx_init_frame_info (&info, vars); ....more.... and like this: static void dlx_output_function_epilogue(file, vars) FILE *file; int vars; { struct dlx_frame_info info; /* Allocate space in the stack frame and lay it out. */ dlx_init_frame_info (&info, vars); ....more.... and like this: #define INITIAL_FRAME_POINTER_OFFSET(DEPTH) \ { \ struct dlx_frame_info info; \ dlx_init_frame_info (&info, get_frame_size ()); \ (DEPTH) = info.stack_size; \ } When I started to suspect that I might be getting inconsistent results, I added a machine_function structure as well to cache the resulting frame info struct in and actually verify with a memcmp that subsequent calls were generating the same data in that struct; that's what gave me the clue that something was changing in the input data the function was relying on. > > Is it valid that regs_ever_live[] changes between IFPO > and emit_prologue? > > No. Whenever reload adds a new spill register, it's supposed > to go back through the allocation loop, which will recompute > that offset. Gotcha. I added trace code which shows me that IFPO is the first one of those points to get called, followed by emit_prologue and then emit_epilogue. I noticed also that IFPO gets called several times per function (and the others just once each): I suppose that's each time the allocation loop needs to recompute the offset, and it's not important that all those calls agree with each other, just so long as the very last call produces the same state as is used in the prologue and epilogue. > I don't suppose your link register is marked CALL_USED? Bingo! > That's probably a mistake... > > > r~ Turns out it certainly is, or at any rate it fixes my va-arg-11.c failure and several others too. I'm not sure why it's a mistake, though: function calls are performed by a jump-and-link instruction that clobbers the LR; in the definition of CALL_USED_REGISTERS in the documentation, it seems to suggest that means I should include it. Is it wrong because that counts as being clobbered by the caller, rather than by the callee, perhaps? Aha: I've just noticed that the call* patterns in the .md file explicitly include the link register as a clobber in the parallel. So yes, it does count as being clobbered by the call insn, rather than CALL_USED. I'm unsure why declaring it call used in addition doesn't just result in needless loads and saves but actual inconsistent state, but there you go: it seems to be playing nicely now. Thanks for catching that one. cheers, DaveK -- Can't think of a witty .sigline today....