* How can INITIAL_FRAME_POINTER_OFFSET be made correct? @ 2004-03-19 16:46 Dave Korn 2004-03-19 16:59 ` Joern Rennecke 2004-03-19 21:02 ` Richard Henderson 0 siblings, 2 replies; 11+ messages in thread From: Dave Korn @ 2004-03-19 16:46 UTC (permalink / raw) To: gcc Erm. Bit confused here. INITIAL_FRAME_POINTER_OFFSET is supposed to be "the difference between the frame pointer and the stack pointer values immediately after the function prologue", according to gccint. It goes on to suggest " The value would be computed from information such as the result of `get_frame_size ()' and the tables of registers `regs_ever_live' and `call_used_regs'. " 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. In the particular port I'm working with, we decide whether or not to allocate a stack slot for saving the link register according to whether or not we ever use it - i.e. we use code that looks like: info->lr_save_size = !current_function_is_leaf || regs_ever_live[LINK_REGNUM] ? 4 : 0; [info is just a struct where I'm keeping the sizes and offsets of the various areas of the stack frame]. There's a bit of a problem, however. regs_ever_live[LINK_REGNUM] is zero when INITIAL_FRAME_POINTER_OFFSET is called, but something has set it to one by the time we get to the emit prologue function. The result is that the two of them disagree about the size and layout of my stackframes, and I get a lot of FAILs in the varargs tests. Is it valid that regs_ever_live[] changes between IFPO and emit_prologue? If so, the documentation should warn *against* using it in IFPO. If not, I've got to get finding out why it changes when it shouldn't....... cheers, DaveK -- Can't think of a witty .sigline today.... ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: How can INITIAL_FRAME_POINTER_OFFSET be made correct? 2004-03-19 16:46 How can INITIAL_FRAME_POINTER_OFFSET be made correct? Dave Korn @ 2004-03-19 16:59 ` Joern Rennecke 2004-03-19 17:55 ` Dave Korn 2004-03-19 21:02 ` Richard Henderson 1 sibling, 1 reply; 11+ messages in thread From: Joern Rennecke @ 2004-03-19 16:59 UTC (permalink / raw) To: Dave Korn; +Cc: gcc > There's a bit of a problem, however. regs_ever_live[LINK_REGNUM] is zero > when INITIAL_FRAME_POINTER_OFFSET is called, but something has set it to one > by the time we get to the emit prologue function. The result is that the > two of them disagree about the size and layout of my stackframes, and I get > a lot of FAILs in the varargs tests. Is LINK_RENUM eliminable, or can something else be eliminated to it? ^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: How can INITIAL_FRAME_POINTER_OFFSET be made correct? 2004-03-19 16:59 ` Joern Rennecke @ 2004-03-19 17:55 ` Dave Korn 2004-03-19 18:31 ` Joern Rennecke 2004-03-21 18:08 ` Hans-Peter Nilsson 0 siblings, 2 replies; 11+ messages in thread From: Dave Korn @ 2004-03-19 17:55 UTC (permalink / raw) To: 'Joern Rennecke'; +Cc: gcc > -----Original Message----- > From: Joern Rennecke > Sent: 19 March 2004 15:59 > To: Dave Korn > > There's a bit of a problem, however. > regs_ever_live[LINK_REGNUM] is > > zero when INITIAL_FRAME_POINTER_OFFSET is called, but something has > > set it to one by the time we get to the emit prologue > function. The > > result is that the two of them disagree about the size and > layout of > > my stackframes, and I get a lot of FAILs in the varargs tests. > > Is LINK_RENUM eliminable, or can something else be eliminated to it? There is no ELIMINABLE_REGS definition, but FRAME_POINTER_REQUIRED is zero so gcc can do its default eliminate-lr-vs-sp. cheers, DaveK -- Can't think of a witty .sigline today.... ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: How can INITIAL_FRAME_POINTER_OFFSET be made correct? 2004-03-19 17:55 ` Dave Korn @ 2004-03-19 18:31 ` Joern Rennecke 2004-03-19 18:41 ` Dave Korn 2004-03-21 18:08 ` Hans-Peter Nilsson 1 sibling, 1 reply; 11+ messages in thread From: Joern Rennecke @ 2004-03-19 18:31 UTC (permalink / raw) To: Dave Korn; +Cc: 'Joern Rennecke', gcc > There is no ELIMINABLE_REGS definition, but FRAME_POINTER_REQUIRED is zero > so gcc can do its default eliminate-lr-vs-sp. Are you saying here that LINK_REGNUM is the same as FRAME_POINTER_REGNUM? ^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: How can INITIAL_FRAME_POINTER_OFFSET be made correct? 2004-03-19 18:31 ` Joern Rennecke @ 2004-03-19 18:41 ` Dave Korn 2004-03-19 18:57 ` Joern Rennecke 0 siblings, 1 reply; 11+ messages in thread From: Dave Korn @ 2004-03-19 18:41 UTC (permalink / raw) To: 'Joern Rennecke'; +Cc: gcc > -----Original Message----- > From: Joern Rennecke > Sent: 19 March 2004 17:02 > To: Dave Korn > > > There is no ELIMINABLE_REGS definition, but > FRAME_POINTER_REQUIRED is > > zero so gcc can do its default eliminate-lr-vs-sp. > > Are you saying here that LINK_REGNUM is the same as > FRAME_POINTER_REGNUM? Sorry, no, I made a thinko. I meant eliminate-fp-vs-sp. cheers, DaveK -- Can't think of a witty .sigline today.... ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: How can INITIAL_FRAME_POINTER_OFFSET be made correct? 2004-03-19 18:41 ` Dave Korn @ 2004-03-19 18:57 ` Joern Rennecke 2004-03-19 19:49 ` Dave Korn 0 siblings, 1 reply; 11+ messages in thread From: Joern Rennecke @ 2004-03-19 18:57 UTC (permalink / raw) To: Dave Korn; +Cc: 'Joern Rennecke', gcc If you mention LINK_REGS in EPILOGUE_USES, you'll have to assume that it is always 'used', and use REG_N_SETS to check if it's clobbered. Otherwise, I'd suggest setting a watchpoint to find out where exactly regs_ever_live[LINK_REGS] is set. ^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: How can INITIAL_FRAME_POINTER_OFFSET be made correct? 2004-03-19 18:57 ` Joern Rennecke @ 2004-03-19 19:49 ` Dave Korn 0 siblings, 0 replies; 11+ messages in thread From: Dave Korn @ 2004-03-19 19:49 UTC (permalink / raw) To: 'Joern Rennecke'; +Cc: gcc > -----Original Message----- > From: Joern Rennecke > Sent: 19 March 2004 17:24 > If you mention LINK_REGS in EPILOGUE_USES, you'll have to > assume that it is always 'used', and use REG_N_SETS to check > if it's clobbered. Hmmm, actually there's no definition for EPILOGUE_USES at all, despite the fact that it does actually use LINK_REGNUM. Dunno if that's really a problem or not. It *is* marked as a CALL_USED register. > Otherwise, I'd suggest setting a watchpoint to find out where > exactly regs_ever_live[LINK_REGS] is set. Yeh, I guess that'll give me the definitive answer. I was kinda hoping that someone would be able to give me a definite answer about the scope of validity of regs_ever_live, such as "It's only guaranteed to be completely up-to-date by the time emit_prologue is called". ISTM that it would be very bad of the docs to suggest using regs_ever_live at a time when the information in it was incorrect or incomplete, but maybe it's not meant to change after IFPO and it's just a bug that is causing the inconsistency. cheers, DaveK -- Can't think of a witty .sigline today.... ^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: How can INITIAL_FRAME_POINTER_OFFSET be made correct? 2004-03-19 17:55 ` Dave Korn 2004-03-19 18:31 ` Joern Rennecke @ 2004-03-21 18:08 ` Hans-Peter Nilsson 1 sibling, 0 replies; 11+ messages in thread From: Hans-Peter Nilsson @ 2004-03-21 18:08 UTC (permalink / raw) To: Dave Korn; +Cc: gcc On Fri, 19 Mar 2004, Dave Korn wrote: > There is no ELIMINABLE_REGS definition, but FRAME_POINTER_REQUIRED is zero > so gcc can do its default eliminate-lr-vs-sp. You really want to define ELIMINABLE_REGS when the frame-pointer can be eliminated and you don't have a separate argument pointer. (Make a fake argument pointer which is always eliminated.) I'm deliberately hazy on the details, because I don't quite remember, but playing catch-up with the saved frame-pointer regarding the offset to the arguments was IIRC key. The docs may need an update. brgds, H-P ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: How can INITIAL_FRAME_POINTER_OFFSET be made correct? 2004-03-19 16:46 How can INITIAL_FRAME_POINTER_OFFSET be made correct? Dave Korn 2004-03-19 16:59 ` Joern Rennecke @ 2004-03-19 21:02 ` Richard Henderson 2004-03-22 17:31 ` Dave Korn 1 sibling, 1 reply; 11+ messages in thread From: Richard Henderson @ 2004-03-19 21:02 UTC (permalink / raw) To: Dave Korn; +Cc: gcc 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. > 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. I don't suppose your link register is marked CALL_USED? That's probably a mistake... r~ ^ permalink raw reply [flat|nested] 11+ messages in thread
* RE: How can INITIAL_FRAME_POINTER_OFFSET be made correct? 2004-03-19 21:02 ` Richard Henderson @ 2004-03-22 17:31 ` Dave Korn 2004-03-22 23:09 ` Richard Henderson 0 siblings, 1 reply; 11+ messages in thread From: Dave Korn @ 2004-03-22 17:31 UTC (permalink / raw) To: 'Richard Henderson'; +Cc: gcc > -----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.... ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: How can INITIAL_FRAME_POINTER_OFFSET be made correct? 2004-03-22 17:31 ` Dave Korn @ 2004-03-22 23:09 ` Richard Henderson 0 siblings, 0 replies; 11+ messages in thread From: Richard Henderson @ 2004-03-22 23:09 UTC (permalink / raw) To: Dave Korn; +Cc: gcc On Mon, Mar 22, 2004 at 03:04:20PM -0000, Dave Korn wrote: > > I don't suppose your link register is marked CALL_USED? > > 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? It's wrong because any function that clobbers the link register is very likely to need to save the link register so that it can be restored for the return. Not looking at sources, but I can well imagine that reload has an optimization that says that it needn't go back through the allocation loop if the new register it chose to use is call clobbered. r~ ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2004-03-22 18:21 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2004-03-19 16:46 How can INITIAL_FRAME_POINTER_OFFSET be made correct? Dave Korn 2004-03-19 16:59 ` Joern Rennecke 2004-03-19 17:55 ` Dave Korn 2004-03-19 18:31 ` Joern Rennecke 2004-03-19 18:41 ` Dave Korn 2004-03-19 18:57 ` Joern Rennecke 2004-03-19 19:49 ` Dave Korn 2004-03-21 18:08 ` Hans-Peter Nilsson 2004-03-19 21:02 ` Richard Henderson 2004-03-22 17:31 ` Dave Korn 2004-03-22 23:09 ` Richard Henderson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).