From patchwork Tue Sep 14 18:57:28 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 64736 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id CF290B6EF1 for ; Wed, 15 Sep 2010 04:57:48 +1000 (EST) Received: (qmail 2291 invoked by alias); 14 Sep 2010 18:57:45 -0000 Received: (qmail 2282 invoked by uid 22791); 14 Sep 2010 18:57:43 -0000 X-SWARE-Spam-Status: No, hits=-2.0 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, SPF_HELO_PASS, TW_CC, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (74.125.121.35) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 14 Sep 2010 18:57:37 +0000 Received: from hpaq1.eem.corp.google.com (hpaq1.eem.corp.google.com [172.25.149.1]) by smtp-out.google.com with ESMTP id o8EIvYrr017712 for ; Tue, 14 Sep 2010 11:57:34 -0700 Received: from ywa6 (ywa6.prod.google.com [10.192.1.6]) by hpaq1.eem.corp.google.com with ESMTP id o8EIutFc001892 for ; Tue, 14 Sep 2010 11:57:33 -0700 Received: by ywa6 with SMTP id 6so1760263ywa.1 for ; Tue, 14 Sep 2010 11:57:33 -0700 (PDT) Received: by 10.100.154.3 with SMTP id b3mr379040ane.245.1284490650730; Tue, 14 Sep 2010 11:57:30 -0700 (PDT) Received: from coign.google.com (dhcp-172-22-123-203.mtv.corp.google.com [172.22.123.203]) by mx.google.com with ESMTPS id w10sm659330ank.34.2010.09.14.11.57.29 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 14 Sep 2010 11:57:30 -0700 (PDT) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com Subject: [gccgo] Simplify stack check code Date: Tue, 14 Sep 2010 11:57:28 -0700 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 X-System-Of-Record: true X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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 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; }