rfg@nsc.nsc.com (Ron Guilmette) (10/27/88)
ENHANCEMENT for GCC 1.30 -- Faster function prologue/epilogue code for ns32k If you are using GCC on a National 32000 series system (e.g. Sequent, Encore), you may want to look at this. It seems that, quite unexpectedly, it is (much?) faster to do a whole series of pushes and pops that it is to use the 32000's enter & leave (and maybe also save & restore) instructions. This seems to be true EVEN if you have to push & pop a whole complement (i.e. 5) of non-temporary general registers (i.e. r3-r7) for a given function prologue & epilogue. Don't ask me why this is true, but I checked it on a '532 and on a '332 and its faster on both. Could somebody please check it on a Sequent-Balance (i.e. an '032 based system). Anyway, the following patches to tm-ns32k.h cause the faster prologue/epilogue code to be used, but only if you use the -fomit-frame-pointer flag. It should be easy to change my changes to get them to do pushes & pops even when the -fomit-frame-pointer is not used, but why bother. If you don't care how fast you code runs, then you probably won't use -fomit-frame-pointer. If you do care then you probably always will. diff -rc2 1.30/tm-ns32k.h 1.30-gnx/tm-ns32k.h *** 1.30/tm-ns32k.h Sat Oct 8 10:09:40 1988 --- 1.30-gnx/tm-ns32k.h Wed Oct 26 12:19:15 1988 *************** *** 447,452 #define FUNCTION_PROLOGUE(FILE, SIZE) \ { register int regno; \ ! register int nregs; \ ! char used_regs_buf[32], *bufp = used_regs_buf; \ int used_fregs_buf[8], *fbufp = used_fregs_buf; \ extern char call_used_regs[]; \ --- 447,451 ----- #define FUNCTION_PROLOGUE(FILE, SIZE) \ { register int regno; \ ! int used_regs_buf[8], *bufp = used_regs_buf; \ int used_fregs_buf[8], *fbufp = used_fregs_buf; \ extern char call_used_regs[]; \ *************** *** 452,456 extern char call_used_regs[]; \ MAIN_FUNCTION_PROLOGUE; \ ! for (regno = 0, nregs = 0; regno < 8; regno++) \ if (regs_ever_live[regno] && !call_used_regs[regno]) { \ nregs += 1; \ --- 451,455 ----- extern char call_used_regs[]; \ MAIN_FUNCTION_PROLOGUE; \ ! for (regno = 0; regno < 8; regno++) \ if (regs_ever_live[regno] && !call_used_regs[regno]) { \ *bufp++ = regno; \ *************** *** 454,459 for (regno = 0, nregs = 0; regno < 8; regno++) \ if (regs_ever_live[regno] && !call_used_regs[regno]) { \ ! nregs += 1; \ ! *bufp++ = 'r'; *bufp++ = regno+'0'; *bufp++ = ','; \ } \ for (; regno < 16; regno++) \ --- 453,457 ----- for (regno = 0; regno < 8; regno++) \ if (regs_ever_live[regno] && !call_used_regs[regno]) { \ ! *bufp++ = regno; \ } \ *bufp = -1; \ *************** *** 457,460 *bufp++ = 'r'; *bufp++ = regno+'0'; *bufp++ = ','; \ } \ for (; regno < 16; regno++) \ if (regs_ever_live[regno] && !call_used_regs[regno]) { \ --- 455,459 ----- *bufp++ = regno; \ } \ + *bufp = -1; \ for (; regno < 16; regno++) \ if (regs_ever_live[regno] && !call_used_regs[regno]) { \ *************** *** 461,471 *fbufp++ = regno; \ } \ - if (bufp > used_regs_buf) --bufp; \ - *bufp = '\0'; \ - if (frame_pointer_needed) \ - fprintf (FILE, "\tenter [%s],%d\n", used_regs_buf,SIZE); \ - else if (nregs == 1) \ - fprintf (FILE, "\tmovd %s,tos\n", used_regs_buf); \ - else if (nregs) fprintf (FILE, "\tsave [%s]\n", used_regs_buf); \ *fbufp = -1; \ fbufp = used_fregs_buf; \ --- 460,463 ----- *fbufp++ = regno; \ } \ *fbufp = -1; \ bufp = used_regs_buf; \ *************** *** 469,472 else if (nregs) fprintf (FILE, "\tsave [%s]\n", used_regs_buf); \ *fbufp = -1; \ fbufp = used_fregs_buf; \ while (*fbufp >= 0) \ --- 461,477 ----- } \ *fbufp = -1; \ + bufp = used_regs_buf; \ + if (frame_pointer_needed) { \ + fprintf (FILE, "\tenter ["); \ + while (*bufp >= 0) { \ + fprintf (FILE, "r%d", *bufp++); \ + if (*bufp >= 0) \ + fputc (',', FILE); \ + } \ + fprintf (FILE, "],%d\n", SIZE); \ + } else { \ + while (*bufp >= 0) \ + fprintf (FILE, "\tmovd r%d,tos\n", *bufp++); \ + } \ fbufp = used_fregs_buf; \ while (*fbufp >= 0) \ *************** *** 511,516 extern int current_function_args_size; \ register int regno; \ ! register int nregs; \ ! char used_regs_buf[32], *bufp = used_regs_buf; \ int used_fregs_buf[8], *fbufp = used_fregs_buf; \ extern char call_used_regs[]; \ --- 516,520 ----- extern int current_function_args_size; \ register int regno; \ ! int used_regs_buf[8], *bufp = used_regs_buf; \ int used_fregs_buf[8], *fbufp = used_fregs_buf; \ extern char call_used_regs[]; \ *************** *** 530,534 else fprintf (FILE, "\tmovf tos,f%d\n", *fbufp-- - 8); \ } \ ! for (regno = 0, nregs = 0; regno < 8; regno++) \ if (regs_ever_live[regno] && ! call_used_regs[regno]) { \ nregs++; \ --- 534,538 ----- else fprintf (FILE, "\tmovf tos,f%d\n", *fbufp-- - 8); \ } \ ! for (regno = 0; regno < 8; regno++) \ if (regs_ever_live[regno] && ! call_used_regs[regno]) { \ *bufp++ = regno; \ *************** *** 532,537 for (regno = 0, nregs = 0; regno < 8; regno++) \ if (regs_ever_live[regno] && ! call_used_regs[regno]) { \ ! nregs++; \ ! *bufp++ = 'r'; *bufp++ = regno+'0'; *bufp++ = ','; \ } \ if (bufp > used_regs_buf) --bufp; \ --- 536,540 ----- for (regno = 0; regno < 8; regno++) \ if (regs_ever_live[regno] && ! call_used_regs[regno]) { \ ! *bufp++ = regno; \ } \ if (frame_pointer_needed) { \ *************** *** 535,546 *bufp++ = 'r'; *bufp++ = regno+'0'; *bufp++ = ','; \ } \ ! if (bufp > used_regs_buf) --bufp; \ ! *bufp = '\0'; \ ! if (frame_pointer_needed) \ ! fprintf (FILE, "\texit [%s]\n", used_regs_buf); \ ! else if (nregs == 1) \ ! fprintf (FILE, "\tmovd tos,%s\n", used_regs_buf); \ ! else if (nregs) \ ! fprintf (FILE, "\trestore [%s]\n", used_regs_buf); \ if (current_function_pops_args && current_function_args_size) \ fprintf (FILE, "\tret %d\n", current_function_args_size); \ --- 538,553 ----- *bufp++ = regno; \ } \ ! if (frame_pointer_needed) { \ ! fprintf (FILE, "\texit ["); \ ! while (bufp > used_regs_buf) { \ ! fprintf (FILE, "r%d", *--bufp); \ ! if (bufp > used_regs_buf) \ ! fputc (',', FILE); \ ! } \ ! fprintf (FILE, "]\n"); \ ! } else { \ ! while (bufp > used_regs_buf) \ ! fprintf (FILE, "\tmovd tos,r%d\n", *--bufp); \ ! } \ if (current_function_pops_args && current_function_args_size) \ fprintf (FILE, "\tret %d\n", current_function_args_size); \