From patchwork Wed Aug 19 15:25:49 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 508765 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]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 31B0214075E for ; Thu, 20 Aug 2015 01:26:05 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=KqgB5sUn; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:date:message-id:subject :from:to:cc:content-type; q=dns; s=default; b=KTNq5Y0zRZ3AD9xL0f Aegosqs5omB0QPVlyam4AIcQ+As4hmcy8d+4T7Q4JGr1oKtgNlAHo9Ipb6SVCxtM ClY6udBlNhyv9EGv38OMGfua+88KTvwA+Aiz80K50U5BO+it/k79duW7JRMcnKrm 5urhctnWz18dbNo5PUQg2GpJY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:date:message-id:subject :from:to:cc:content-type; s=default; bh=yADRHZgcfWySeTFuZp8Aq20I OBQ=; b=KqgB5sUnNTMQDRbLnIfIePnkTm0LrXlwLlgZ0ebauxAeCPctln2JHDOp lUiSVKrQwvSAckZWVbWkK/pUfKBElHe+2zizSNv5XOa2IMRumdtFuUb5xoDLvmSP KTo6Xj1BrNVJcgnBI8UXjNg7WtwBsge1IYvB7B8hyGKLVOjFqLY= Received: (qmail 104357 invoked by alias); 19 Aug 2015 15:25:55 -0000 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 Received: (qmail 104347 invoked by uid 89); 19 Aug 2015 15:25:55 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.3 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-ob0-f169.google.com Received: from mail-ob0-f169.google.com (HELO mail-ob0-f169.google.com) (209.85.214.169) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Wed, 19 Aug 2015 15:25:52 +0000 Received: by obkg7 with SMTP id g7so7100407obk.3 for ; Wed, 19 Aug 2015 08:25:50 -0700 (PDT) MIME-Version: 1.0 X-Received: by 10.182.205.200 with SMTP id li8mr9571995obc.18.1439997949878; Wed, 19 Aug 2015 08:25:49 -0700 (PDT) Received: by 10.76.170.36 with HTTP; Wed, 19 Aug 2015 08:25:49 -0700 (PDT) In-Reply-To: References: <9652D8E5-C3B2-4C88-BC34-4591962D42D1@comcast.net> <20150804174332.GN11083@gate.crashing.org> <20150804192913.GO11083@gate.crashing.org> <20150804204506.GP11083@gate.crashing.org> <20150819125145.GC8652@gate.crashing.org> Date: Wed, 19 Aug 2015 08:25:49 -0700 Message-ID: Subject: Re: [PATCH] Add __builtin_stack_top From: "H.J. Lu" To: Segher Boessenkool Cc: Mike Stump , GCC Patches , Uros Bizjak X-IsSubscribed: yes On Wed, Aug 19, 2015 at 6:00 AM, H.J. Lu wrote: > On Wed, Aug 19, 2015 at 5:51 AM, Segher Boessenkool > wrote: >> On Wed, Aug 19, 2015 at 05:23:41AM -0700, H.J. Lu wrote: >>> >>> >> > You might have a reason why you want the entry stack address instead of the >>> >>> >> > frame address, but you didn't really explain I think? Or I missed it. >>> >> >>> >> What would a C program do with this, that it cannot do with the frame >>> >> address, that would be useful and cannot be much better done in straight >>> >> assembler? Do you actually want to expose the argument pointer, maybe? >>> > >>> > Yes, we want to use the argument pointer as shown in testcases >>> > included in my patch. >>> >>> Where do we stand on this? We need the hard stack address at >>> function entry for x86 without using frame pointer. I added >>> __builtin_stack_top since __builtin_frame_address can't give >>> us what we want. Should __builtin_stack_top be added to >>> middle-end or x86 backend? >> >> Sorry for not following up; I thought my suggestion was obvious. >> >> Can you do a __builtin_argument_pointer instead? That should work >> for all targets, afaics? > > To me, stack top is easier to understand and argument pointer isn't > very clear. Does argument pointer exist when there is no argument? > > But I can live with it. I will update my patch. > Here is a patch to add __builtin_argument_pointer. I only have -- Built-in Function: void * __builtin_argument_pointer (void) This function returns the argument pointer. as documentation. Can you suggest a better description so that it can be implemented also by other compilers? Thanks. From 9af08fdda587e1876e09840499000e35cc841e96 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 21 Jul 2015 14:32:09 -0700 Subject: [PATCH] Add __builtin_argument_pointer When __builtin_frame_address is used to retrieve the address of the function stack frame, the frame pointer register is required, which wastes one register and 2 instructions. For x86-32, one less register means significant negative impact on performance. This patch adds a new builtin function, __builtin_argument_pointer. It returns the argument pointer, which, on x86, can be used to compute the stack address when the function is called by subtracting the size of integer register. gcc/ PR target/66960 * builtin-types.def (BT_FN_PTR_VOID): New function type. * builtins.c (expand_builtin): Handle BUILT_IN_ARGUMENT_POINTER. (is_simple_builtin): Likewise. * ipa-pure-const.c (special_builtin_state): Likewise. * builtins.def: Add BUILT_IN_ARGUMENT_POINTER. * function.h (function): Add argument_pointer_taken. * config/i386/i386.c (ix86_expand_prologue): Sorry if DRAP is used and the argument pointer has been taken. * doc/extend.texi: Document __builtin_argument_pointer. gcc/testsuite/ PR target/66960 * gcc.target/i386/pr66960-1.c: New test. * gcc.target/i386/pr66960-2.c: Likewise. * gcc.target/i386/pr66960-3.c: Likewise. * gcc.target/i386/pr66960-4.c: Likewise. * gcc.target/i386/pr66960-5.c: Likewise. --- gcc/builtin-types.def | 1 + gcc/builtins.c | 5 +++++ gcc/builtins.def | 1 + gcc/config/i386/i386.c | 6 ++++++ gcc/doc/extend.texi | 4 ++++ gcc/function.h | 3 +++ gcc/ipa-pure-const.c | 1 + gcc/testsuite/gcc.target/i386/pr66960-1.c | 34 +++++++++++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr66960-2.c | 34 +++++++++++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr66960-3.c | 18 ++++++++++++++++ gcc/testsuite/gcc.target/i386/pr66960-4.c | 22 ++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr66960-5.c | 22 ++++++++++++++++++++ 12 files changed, 151 insertions(+) create mode 100644 gcc/testsuite/gcc.target/i386/pr66960-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66960-2.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66960-3.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66960-4.c create mode 100644 gcc/testsuite/gcc.target/i386/pr66960-5.c diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def index 0e34531..2b6b5ab 100644 --- a/gcc/builtin-types.def +++ b/gcc/builtin-types.def @@ -177,6 +177,7 @@ DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_LONGDOUBLE_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE, BT_LONGDOUBLE) DEF_FUNCTION_TYPE_1 (BT_FN_PTR_UINT, BT_PTR, BT_UINT) DEF_FUNCTION_TYPE_1 (BT_FN_PTR_SIZE, BT_PTR, BT_SIZE) +DEF_FUNCTION_TYPE_1 (BT_FN_PTR_VOID, BT_PTR, BT_VOID) DEF_FUNCTION_TYPE_1 (BT_FN_INT_INT, BT_INT, BT_INT) DEF_FUNCTION_TYPE_1 (BT_FN_INT_UINT, BT_INT, BT_UINT) DEF_FUNCTION_TYPE_1 (BT_FN_INT_LONG, BT_INT, BT_LONG) diff --git a/gcc/builtins.c b/gcc/builtins.c index 31969ca..b1cfa44 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -6206,6 +6206,10 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, case BUILT_IN_CONSTANT_P: return const0_rtx; + case BUILT_IN_ARGUMENT_POINTER: + cfun->argument_pointer_taken = true; + return arg_pointer_rtx; + case BUILT_IN_FRAME_ADDRESS: case BUILT_IN_RETURN_ADDRESS: return expand_builtin_frame_address (fndecl, exp); @@ -12395,6 +12399,7 @@ is_simple_builtin (tree decl) case BUILT_IN_RETURN: case BUILT_IN_AGGREGATE_INCOMING_ADDRESS: case BUILT_IN_FRAME_ADDRESS: + case BUILT_IN_ARGUMENT_POINTER: case BUILT_IN_VA_END: case BUILT_IN_STACK_SAVE: case BUILT_IN_STACK_RESTORE: diff --git a/gcc/builtins.def b/gcc/builtins.def index f7ac4a8..3bc9615 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -778,6 +778,7 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSL, "ffsl", BT_FN_INT_LONG, ATTR_CONST_NOTHRO DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSLL, "ffsll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_FORK, "fork", BT_FN_PID, ATTR_NOTHROW_LIST) DEF_GCC_BUILTIN (BUILT_IN_FRAME_ADDRESS, "frame_address", BT_FN_PTR_UINT, ATTR_NULL) +DEF_GCC_BUILTIN (BUILT_IN_ARGUMENT_POINTER, "argument_pointer", BT_FN_PTR_VOID, ATTR_NULL) /* [trans-mem]: Adjust BUILT_IN_TM_FREE if BUILT_IN_FREE is changed. */ DEF_LIB_BUILTIN (BUILT_IN_FREE, "free", BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_FROB_RETURN_ADDR, "frob_return_addr", BT_FN_PTR_PTR, ATTR_NULL) diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 05fa5e1..1594fb9 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -11577,6 +11577,12 @@ ix86_expand_prologue (void) { int align_bytes = crtl->stack_alignment_needed / BITS_PER_UNIT; + /* Can't use DRAP if the stack address has been taken. */ + if (cfun->argument_pointer_taken) + sorry ("%<__builtin_argument_pointer%> not supported with stack" + " realignment. This may be worked around by adding" + " -maccumulate-outgoing-args."); + /* Only need to push parameter pointer reg if it is caller saved. */ if (!call_used_regs[REGNO (crtl->drap_reg)]) { diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index dba8b43..620f038 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -8841,6 +8841,10 @@ option is in effect. Such calls should only be made in debugging situations. @end deftypefn +@deftypefn {Built-in Function} {void *} __builtin_argument_pointer (void) +This function returns the argument pointer. +@end deftypefn + @node Vector Extensions @section Using Vector Instructions through Built-in Functions diff --git a/gcc/function.h b/gcc/function.h index e92c17c..41bdaed 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -378,6 +378,9 @@ struct GTY(()) function { /* Set when the tail call has been identified. */ unsigned int tail_call_marked : 1; + + /* Set when argument pointer has been taken. */ + unsigned int argument_pointer_taken : 1; }; /* Add the decl D to the local_decls list of FUN. */ diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c index 8fd8c36..31c289d 100644 --- a/gcc/ipa-pure-const.c +++ b/gcc/ipa-pure-const.c @@ -480,6 +480,7 @@ special_builtin_state (enum pure_const_state_e *state, bool *looping, case BUILT_IN_CXA_END_CLEANUP: case BUILT_IN_EH_COPY_VALUES: case BUILT_IN_FRAME_ADDRESS: + case BUILT_IN_ARGUMENT_POINTER: case BUILT_IN_APPLY: case BUILT_IN_APPLY_ARGS: *looping = false; diff --git a/gcc/testsuite/gcc.target/i386/pr66960-1.c b/gcc/testsuite/gcc.target/i386/pr66960-1.c new file mode 100644 index 0000000..d8caa4f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66960-1.c @@ -0,0 +1,34 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fomit-frame-pointer" { target { lp64 } } } */ +/* { dg-options "-O2 -fomit-frame-pointer -maddress-mode=short" { target { x32 } } } */ +/* { dg-options "-O2 -fomit-frame-pointer -miamcu -fno-pic" { target { ia32 } } } */ + +extern char **environ; +extern void exit (int status); +extern int main (long argc, char **argv, char **envp); + +void +_start (void) +{ + void *argc_p = (__builtin_argument_pointer () + - sizeof (int __attribute__ ((mode (__word__))))); + char **argv = (char **) (argc_p + sizeof (void *)); + long argc = *(long *) argc_p; + int status; + + environ = argv + argc + 1; + + status = main (argc, argv, environ); + + exit (status); +} + +/* { dg-final { scan-assembler "movq\[ \t\]8\\(%rsp\\), %rdi" { target lp64 } } } */ +/* { dg-final { scan-assembler "leaq\[ \t\]16\\(%rsp\\), %rsi" { target lp64 } } } */ +/* { dg-final { scan-assembler "leaq\[ \t\]24\\(%rsp,%rdi,8\\), %rdx" { target lp64 } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]8\\(%esp\\), %edi" { target x32 } } } */ +/* { dg-final { scan-assembler "leal\[ \t\]12\\(%rsp\\), %esi" { target x32 } } } */ +/* { dg-final { scan-assembler "leal\[ \t\]4\\(%rsi,%rdi,4\\), %edx" { target x32 } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]\\(%esp\\), %eax" { target ia32 } } } */ +/* { dg-final { scan-assembler "leal\[ \t\]4\\(%esp\\), %edx" { target ia32 } } } */ +/* { dg-final { scan-assembler "leal\[ \t\]8\\(%esp,%eax,4\\), %ecx" { target ia32 } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr66960-2.c b/gcc/testsuite/gcc.target/i386/pr66960-2.c new file mode 100644 index 0000000..f4d2ef6 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66960-2.c @@ -0,0 +1,34 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -fno-omit-frame-pointer" { target { lp64 } } } */ +/* { dg-options "-O2 -fno-omit-frame-pointer -maddress-mode=short" { target { x32 } } } */ +/* { dg-options "-O2 -fno-omit-frame-pointer -miamcu" { target { ia32 } } } */ + +extern char **environ; +extern void exit (int status); +extern int main (long argc, char **argv, char **envp); + +void +_start (void) +{ + void *argc_p = (__builtin_argument_pointer () + - sizeof (int __attribute__ ((mode (__word__))))); + char **argv = (char **) (argc_p + sizeof (void *)); + long argc = *(long *) argc_p; + int status; + + environ = argv + argc + 1; + + status = main (argc, argv, environ); + + exit (status); +} + +/* { dg-final { scan-assembler "movq\[ \t\]8\\(%rbp\\), %rdi" { target lp64 } } } */ +/* { dg-final { scan-assembler "leaq\[ \t\]16\\(%rbp\\), %rsi" { target lp64 } } } */ +/* { dg-final { scan-assembler "leaq\[ \t\]24\\(%rbp,%rdi,8\\), %rdx" { target lp64 } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]8\\(%ebp\\), %edi" { target x32 } } } */ +/* { dg-final { scan-assembler "leal\[ \t\]12\\(%rbp\\), %esi" { target x32 } } } */ +/* { dg-final { scan-assembler "leal\[ \t\]4\\(%rsi,%rdi,4\\), %edx" { target x32 } } } */ +/* { dg-final { scan-assembler "movl\[ \t\]4\\(%ebp\\), %eax" { target ia32 } } } */ +/* { dg-final { scan-assembler "leal\[ \t\]8\\(%ebp\\), %edx" { target ia32 } } } */ +/* { dg-final { scan-assembler "leal\[ \t\]12\\(%ebp,%eax,4\\), %ecx" { target ia32 } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr66960-3.c b/gcc/testsuite/gcc.target/i386/pr66960-3.c new file mode 100644 index 0000000..7eb2608 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66960-3.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -mno-accumulate-outgoing-args" { target { lp64 } } } */ +/* { dg-options "-O2 -mno-accumulate-outgoing-args -maddress-mode=short" { target { x32 } } } */ +/* { dg-options "-O2 -mno-accumulate-outgoing-args -miamcu" { target { ia32 } } } */ + +extern void abort (void); +extern int check_int (int *i, int align); +typedef int aligned __attribute__((aligned(64))); + +void * +foo (void) +{ + aligned j; + if (check_int (&j, __alignof__(j)) != j) + abort (); + return (__builtin_argument_pointer () + - sizeof (int __attribute__ ((mode (__word__))))); +} /* { dg-message "sorry, unimplemented: .__builtin_argument_pointer. not supported" } */ diff --git a/gcc/testsuite/gcc.target/i386/pr66960-4.c b/gcc/testsuite/gcc.target/i386/pr66960-4.c new file mode 100644 index 0000000..361e91c --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66960-4.c @@ -0,0 +1,22 @@ +/* { dg-do compile { target *-*-linux* } } */ +/* { dg-options "-O2 -maccumulate-outgoing-args" { target { lp64 } } } */ +/* { dg-options "-O2 -maccumulate-outgoing-args -maddress-mode=short" { target { x32 } } } */ +/* { dg-options "-O2 -maccumulate-outgoing-args -miamcu" { target { ia32 } } } */ + +extern void abort (void); +extern int check_int (int *i, int align); +typedef int aligned __attribute__((aligned(64))); + +void * +foo (void) +{ + aligned j; + if (check_int (&j, __alignof__(j)) != j) + abort (); + return (__builtin_argument_pointer () + - sizeof (int __attribute__ ((mode (__word__))))); +} + +/* { dg-final { scan-assembler "leaq\[ \t\]8\\(%rbp\\), %rax" { target lp64 } } } */ +/* { dg-final { scan-assembler "leal\[ \t\]8\\(%rbp\\), %eax" { target x32 } } } */ +/* { dg-final { scan-assembler "leal\[ \t\]4\\(%ebp\\), %eax" { target ia32 } } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr66960-5.c b/gcc/testsuite/gcc.target/i386/pr66960-5.c new file mode 100644 index 0000000..f70a258 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66960-5.c @@ -0,0 +1,22 @@ +/* { dg-do link } */ +/* { dg-options "-O" } */ + +extern void link_error (void); + +__attribute__ ((noinline, noclone)) +void +foo (void) +{ + void **p = (__builtin_argument_pointer () + - sizeof (int __attribute__ ((mode (__word__))))); + void *ra = __builtin_return_address (0); + if (*p != ra) + link_error (); +} + +int +main (void) +{ + foo (); + return 0; +} -- 2.4.3