Patchwork [gccgo] Simplify stack check code

login
register
mail settings
Submitter Ian Taylor
Date Sept. 14, 2010, 6:57 p.m.
Message ID <mcrtylsxief.fsf@google.com>
Download mbox | patch
Permalink /patch/64736/
State New
Headers show

Comments

Ian Taylor - Sept. 14, 2010, 6:57 p.m.
This patch simplifies the stack check code used for -fsplit-stack to
avoid having special purpose insns.  Instead we just an UNSPEC operand
and print it out as appropriate.  The generated code is the same.
Committed to gccgo branch.

Ian

Patch

Index: gcc/config/i386/i386.md
===================================================================
--- gcc/config/i386/i386.md	(revision 162799)
+++ gcc/config/i386/i386.md	(working copy)
@@ -15091,130 +15091,6 @@ 
   DONE;
 })
 
-;; For -fsplit-stack, check whether we have enough stack space at the
-;; start of a function which allocates 256 bytes or less on the stack.
-;; Branch to the label if we have enough space.
-
-(define_expand "split_stack_check_small"
-  [(set (pc)
-        (if_then_else
-         (ltu (reg SP_REG) (unspec [(const_int 0)] UNSPEC_STACK_CHECK))
-         (label_ref
-	  (match_operand 0 "" ""))
-         (pc)))]
-  ""
-{
-  rtx ssp_offset;
-
-#ifdef TARGET_THREAD_SPLIT_STACK_OFFSET
-  ssp_offset = GEN_INT (TARGET_THREAD_SPLIT_STACK_OFFSET);
-#else
-  gcc_unreachable ();
-#endif
-
-  if (TARGET_64BIT)
-    emit_insn (gen_split_stack_compare_small_64 (ssp_offset));
-  else
-    emit_insn (gen_split_stack_compare_small_32 (ssp_offset));
-  ix86_compare_op0 = gen_rtx_REG (CCmode, FLAGS_REG);
-  ix86_compare_op1 = GEN_INT (0);
-  ix86_expand_branch (GEU, operands[0]);
-  JUMP_LABEL (get_last_insn ()) = operands[0];
-  DONE;
-})
-
-;; Compare the stack pointer with the -fsplit-stack limit.
-
-(define_insn "split_stack_compare_small_32"
-  [(set (reg:CC FLAGS_REG)
-	(compare (reg:SI SP_REG)
-                 (unspec:SI [(match_operand 0 "const_int_operand" "i")]
-                            UNSPEC_STACK_CHECK)))]
-  "!TARGET_64BIT"
-  "cmp{l}\t{%%gs:%P0, %%esp|%%esp, %%gs:%P0}"
-  [(set_attr "type" "icmp")
-   (set_attr "mode" "SI")
-   (set_attr "length_immediate" "4")
-   (set_attr "memory" "none")
-   (set_attr "imm_disp" "false")])
-
-;; 64-bit version of split_stack_compare_small_32.
-
-(define_insn "split_stack_compare_small_64"
-  [(set (reg:CC FLAGS_REG)
-	(compare (reg:DI SP_REG)
-                 (unspec:DI [(match_operand 0 "const_int_operand" "i")]
-                            UNSPEC_STACK_CHECK)))]
-  "TARGET_64BIT"
-  "cmp{q}\t{%%fs:%P0, %%rsp|%%rsp, %%fs:%P0}"
-  [(set_attr "type" "icmp")
-   (set_attr "mode" "DI")
-   (set_attr "length_immediate" "4")
-   (set_attr "memory" "none")
-   (set_attr "imm_disp" "false")])
-
-;; For -fsplit-stack, check whether we have enough stack space at the
-;; start of a function which allocates more than 256 bytes on the
-;; stack.  Branch to the label if we have enough space.
-
-(define_expand "split_stack_check_large"
-  [(set (pc)
-        (if_then_else
-         (ltu (match_operand 0 "" "")
-	      (unspec [(const_int 0)] UNSPEC_STACK_CHECK))
-         (label_ref (match_operand 1 "" ""))
-         (pc)))]
-  ""
-{
-  rtx ssp_offset;
-
-#ifdef TARGET_THREAD_SPLIT_STACK_OFFSET
-  ssp_offset = GEN_INT (TARGET_THREAD_SPLIT_STACK_OFFSET);
-#else
-  gcc_unreachable ();
-#endif
-
-  if (TARGET_64BIT)
-    emit_insn (gen_split_stack_compare_large_64 (operands[0], ssp_offset));
-  else
-    emit_insn (gen_split_stack_compare_large_32 (operands[0], ssp_offset));
-  ix86_compare_op0 = gen_rtx_REG (CCmode, FLAGS_REG);
-  ix86_compare_op1 = GEN_INT (0);
-  ix86_expand_branch (GEU, operands[1]);
-  JUMP_LABEL (get_last_insn ()) = operands[1];
-  DONE;
-})
-
-;; Compare operand 0 with the -fsplit-stack limit.
-
-(define_insn "split_stack_compare_large_32"
-  [(set (reg:CC FLAGS_REG)
-	(compare (match_operand:SI 0 "register_operand" "r")
-                 (unspec:SI [(match_operand 1 "const_int_operand" "i")]
-                            UNSPEC_STACK_CHECK)))]
-  "!TARGET_64BIT"
-  "cmp{l}\t{%%gs:%P1, %0|%0, %%gs:%P1}"
-  [(set_attr "type" "icmp")
-   (set_attr "mode" "SI")
-   (set_attr "length_immediate" "4")
-   (set_attr "memory" "none")
-   (set_attr "imm_disp" "false")])
-
-;; 64-bit version of split_stack_compare_large_32.
-
-(define_insn "split_stack_compare_large_64"
-  [(set (reg:CC FLAGS_REG)
-	(compare (match_operand:DI 0 "register_operand" "r")
-                 (unspec:DI [(match_operand 1 "const_int_operand" "i")]
-                            UNSPEC_STACK_CHECK)))]
-  "TARGET_64BIT"
-  "cmp{q}\t{%%fs:%P1, %0|%0, %%fs:%P1}"
-  [(set_attr "type" "icmp")
-   (set_attr "mode" "DI")
-   (set_attr "length_immediate" "4")
-   (set_attr "memory" "none")
-   (set_attr "imm_disp" "false")])
-
 ;; In order to support the call/return predictor, we use a return
 ;; instruction which the middle-end doesn't see.
 (define_insn "split_stack_return"
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 162799)
+++ gcc/config/i386/i386.c	(working copy)
@@ -9299,7 +9299,7 @@  ix86_expand_split_stack_prologue (void)
   tree decl;
   bool is_fastcall;
   int regparm, args_size;
-  rtx label, jump_insn, allocate_rtx, call_insn, call_fusage;
+  rtx label, limit, current, jump_insn, allocate_rtx, call_insn, call_fusage;
 
   gcc_assert (flag_split_stack && reload_completed);
 
@@ -9324,8 +9324,13 @@  ix86_expand_split_stack_prologue (void)
      the stack boundary in the TCB.  The stack boundary always gives
      us SPLIT_STACK_AVAILABLE bytes, so if we need less than that we
      can compare directly.  Otherwise we need to do an addition.  */
+
+  limit = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+			  UNSPEC_STACK_CHECK);
+  limit = gen_rtx_CONST (Pmode, limit);
+  limit = gen_rtx_MEM (Pmode, limit);
   if (allocate < SPLIT_STACK_AVAILABLE)
-    emit_jump_insn (gen_split_stack_check_small (label));
+    current = stack_pointer_rtx;
   else
     {
       rtx offset, scratch_reg;
@@ -9382,9 +9387,14 @@  ix86_expand_split_stack_prologue (void)
 	  emit_insn (gen_addsi3 (scratch_reg, stack_pointer_rtx, offset));
 	}
 
-      emit_jump_insn (gen_split_stack_check_large (scratch_reg, label));
+      current = scratch_reg;
     }
 
+  ix86_compare_op0 = current;
+  ix86_compare_op1 = limit;
+  ix86_expand_branch (GEU, label);
+  JUMP_LABEL (get_last_insn ()) = label;
+
   /* Mark the jump as very likely to be taken.  */
   jump_insn = get_last_insn ();
   gcc_assert (JUMP_P (jump_insn));
@@ -10103,6 +10113,10 @@  ix86_legitimate_address_p (enum machine_
 	  case UNSPEC_DTPOFF:
 	    break;
 
+	  case UNSPEC_STACK_CHECK:
+	    gcc_assert (flag_split_stack);
+	    break;
+
 	  default:
 	    /* Invalid address unspec.  */
 	    return false;
@@ -10994,6 +11008,13 @@  output_pic_addr_const (FILE *file, rtx x
       break;
 
      case UNSPEC:
+       if (XINT (x, 1) == UNSPEC_STACK_CHECK)
+	 {
+	   bool f = output_addr_const_extra (file, x);
+	   gcc_assert (f);
+	   break;
+	 }
+
        gcc_assert (XVECLEN (x, 0) == 1);
        output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
        switch (XINT (x, 1))
@@ -12357,6 +12378,22 @@  output_addr_const_extra (FILE *file, rtx
       break;
 #endif
 
+    case UNSPEC_STACK_CHECK:
+      {
+	int offset;
+
+	gcc_assert (flag_split_stack);
+
+#ifdef TARGET_THREAD_SPLIT_STACK_OFFSET
+	offset = TARGET_THREAD_SPLIT_STACK_OFFSET;
+#else
+	gcc_unreachable ();
+#endif
+
+	fprintf (file, "%s:%d", TARGET_64BIT ? "%fs" : "%gs", offset);
+      }
+      break;
+
     default:
       return false;
     }