This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[ia64] Rotate stack checking loop


Hi,

this patch rotates the loop generated in the prologue to do stack checking 
when -fstack-check is specified, thereby saving one branch instruction.  It 
was initially implemented as a WHILE loop to match the generic implementation 
but can be turned into a DO-WHILE loop because the amount of stack to be 
checked is known at compile time (since it's the static part of the frame).

The patch also fixes an error in the instruction count for the loop.

Tested on IA-64/Linux, OK for the mainline?


2015-11-12  Eric Botcazou  <ebotcazou@adacore.com>

	* config/ia64/ia64.c (ia64_emit_probe_stack_range): Adjust.
	(output_probe_stack_range): Rotate the loop and simplify.

-- 
Eric Botcazou
Index: config/ia64/ia64.c
===================================================================
--- config/ia64/ia64.c	(revision 230204)
+++ config/ia64/ia64.c	(working copy)
@@ -3293,7 +3293,7 @@ ia64_emit_probe_stack_range (HOST_WIDE_I
   else if (size <= PROBE_INTERVAL)
     emit_stack_probe (r2);
 
-  /* The run-time loop is made up of 8 insns in the generic case while this
+  /* The run-time loop is made up of 9 insns in the generic case while this
      compile-time loop is made up of 5+2*(n-2) insns for n # of intervals.  */
   else if (size <= 4 * PROBE_INTERVAL)
     {
@@ -3356,11 +3356,12 @@ ia64_emit_probe_stack_range (HOST_WIDE_I
 
       /* Step 3: the loop
 
-	 while (TEST_ADDR != LAST_ADDR)
+	 do
 	   {
 	     TEST_ADDR = TEST_ADDR + PROBE_INTERVAL
 	     probe at TEST_ADDR
 	   }
+	 while (TEST_ADDR != LAST_ADDR)
 
 	 probes at FIRST + N * PROBE_INTERVAL for values of N from 1
 	 until it is equal to ROUNDED_SIZE.  */
@@ -3391,36 +3392,33 @@ const char *
 output_probe_stack_range (rtx reg1, rtx reg2)
 {
   static int labelno = 0;
-  char loop_lab[32], end_lab[32];
+  char loop_lab[32];
   rtx xops[3];
 
-  ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno);
-  ASM_GENERATE_INTERNAL_LABEL (end_lab, "LPSRE", labelno++);
+  ASM_GENERATE_INTERNAL_LABEL (loop_lab, "LPSRL", labelno++);
 
+  /* Loop.  */
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, loop_lab);
 
-  /* Jump to END_LAB if TEST_ADDR == LAST_ADDR.  */
-  xops[0] = reg1;
-  xops[1] = reg2;
-  xops[2] = gen_rtx_REG (BImode, PR_REG (6));
-  output_asm_insn ("cmp.eq %2, %I2 = %0, %1", xops);
-  fprintf (asm_out_file, "\t(%s) br.cond.dpnt ", reg_names [REGNO (xops[2])]);
-  assemble_name_raw (asm_out_file, end_lab);
-  fputc ('\n', asm_out_file);
-
   /* TEST_ADDR = TEST_ADDR + PROBE_INTERVAL.  */
+  xops[0] = reg1;
   xops[1] = GEN_INT (-PROBE_INTERVAL);
   output_asm_insn ("addl %0 = %1, %0", xops);
   fputs ("\t;;\n", asm_out_file);
 
-  /* Probe at TEST_ADDR and branch.  */
+  /* Probe at TEST_ADDR.  */
   output_asm_insn ("probe.w.fault %0, 0", xops);
-  fprintf (asm_out_file, "\tbr ");
+
+  /* Test if TEST_ADDR == LAST_ADDR.  */
+  xops[1] = reg2;
+  xops[2] = gen_rtx_REG (BImode, PR_REG (6));
+  output_asm_insn ("cmp.eq %2, %I2 = %0, %1", xops);
+
+  /* Branch.  */
+  fprintf (asm_out_file, "\t(%s) br.cond.dpnt ", reg_names [PR_REG (7)]);
   assemble_name_raw (asm_out_file, loop_lab);
   fputc ('\n', asm_out_file);
 
-  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, end_lab);
-
   return "";
 }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]