On Tue, Jul 21, 2015 at 02:45:39PM -0700, H.J. Lu wrote:
> When __builtin_frame_address is used to retrieve the address of the
> function stack frame, the frame pointer is always kept, 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_ia32_stack_top, to x86 backend. It
> returns the stack address when the function is called.
>
> Any comments, feedbacks?
>
Although this function is generic, but implementation is target
specific. I submitted a generic patch:
https://gcc.gnu.org/ml/gcc-patches/2015-07/msg01859.html
So far there are no interests from other backends. Here is a patch
to implement __builtin_stack_top in x86 backend. We can update x86
backedn after it is added to middle-end. OK for trunk?
Thanks.
H.J.
--
gcc/
PR target/66960
* config/i386/i386.c (ix86_expand_prologue): Sorry if DRAP is
used and the stack address has been taken.
(ix86_builtins): Add IX86_BUILTIN_STACK_TOP.
(ix86_init_mmx_sse_builtins): Add __builtin_stack_top.
(ix86_expand_builtin): Handle IX86_BUILTIN_STACK_TOP.
* config/i386/i386.h (machine_function): Add stack_top_taken.
* doc/extend.texi: Document __builtin_stack_top.
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/config/i386/i386.c| 28 ++
gcc/config/i386/i386.h| 4
gcc/doc/extend.texi | 6 ++
gcc/testsuite/gcc.target/i386/pr66960-1.c | 33 +++
gcc/testsuite/gcc.target/i386/pr66960-2.c | 33 +++
gcc/testsuite/gcc.target/i386/pr66960-3.c | 17
gcc/testsuite/gcc.target/i386/pr66960-4.c | 21
gcc/testsuite/gcc.target/i386/pr66960-5.c | 21
8 files changed, 163 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/config/i386/i386.c b/gcc/config/i386/i386.c
index ede8ea0..ef7ba6d 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -11575,6 +11575,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->machine->stack_top_taken)
+ sorry ("%<__builtin_stack_top%> not supported with stack"
+ " realignment. This may be worked around by adding"
+ " -maccumulate-outgoing-arg.");
+
/* Only need to push parameter pointer reg if it is caller saved. */
if (!call_used_regs[REGNO (crtl->drap_reg)])
{
@@ -30741,6 +30747,9 @@ enum ix86_builtins
IX86_BUILTIN_READ_FLAGS,
IX86_BUILTIN_WRITE_FLAGS,
+ /* Get the stack address when the function is called. */
+ IX86_BUILTIN_STACK_TOP,
+
IX86_BUILTIN_MAX
};
@@ -34353,6 +34362,10 @@ ix86_init_mmx_sse_builtins (void)
def_builtin (OPTION_MASK_ISA_MWAITX, "__builtin_ia32_mwaitx",
VOID_FTYPE_UNSIGNED_UNSIGNED_UNSIGNED, IX86_BUILTIN_MWAITX);
+ /* Get the stack address when the function is called. */
+ def_builtin (0, "__builtin_stack_top",
+ PVOID_FTYPE_VOID, IX86_BUILTIN_STACK_TOP);
+
/* Add FMA4 multi-arg argument instructions */
for (i = 0, d = bdesc_multi_arg; i < ARRAY_SIZE (bdesc_multi_arg); i++, d++)
{
@@ -40291,6 +40304,21 @@ addcarryx:
emit_insn (gen_xabort (op0));
return 0;
+case IX86_BUILTIN_STACK_TOP:
+ cfun->machine->stack_top_taken = true;
+
+ if (!target
+ || GET_MODE (target) != Pmode
+ || !register_operand (target, Pmode))
+ target = gen_reg_rtx (Pmode);
+
+ /* After the prologue, stack top is at -WORD(AP) in the current
+frame. */
+ emit_insn (gen_rtx_SET (target,
+ plus_constant (Pmode, arg_pointer_rtx,
+-UNITS_PER_WORD)));
+ return target;
+
default:
break;
}
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 7bd23ec..3781a22 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2492,6 +2492,10 @@ struct GTY(()) machine_function {
/* If true, it is safe to not save/restore DRAP register. */
BOOL_BITFIELD no_drap_save_restore : 1;
+ /* If true, the stack address of the current function has been
+ taken. */
+ BOOL_BITFIE