aboutsummaryrefslogtreecommitdiffstats
path: root/community/gcc6/0011-i386-Update-mfunction-return-for-return-with-pop.patch
diff options
context:
space:
mode:
Diffstat (limited to 'community/gcc6/0011-i386-Update-mfunction-return-for-return-with-pop.patch')
-rw-r--r--community/gcc6/0011-i386-Update-mfunction-return-for-return-with-pop.patch456
1 files changed, 0 insertions, 456 deletions
diff --git a/community/gcc6/0011-i386-Update-mfunction-return-for-return-with-pop.patch b/community/gcc6/0011-i386-Update-mfunction-return-for-return-with-pop.patch
deleted file mode 100644
index 3d528395b94..00000000000
--- a/community/gcc6/0011-i386-Update-mfunction-return-for-return-with-pop.patch
+++ /dev/null
@@ -1,456 +0,0 @@
-From 771535dec733e4b85924f00a3a94c29683d614e5 Mon Sep 17 00:00:00 2001
-From: hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4>
-Date: Mon, 26 Feb 2018 15:29:30 +0000
-Subject: [PATCH 11/13] i386: Update -mfunction-return= for return with pop
-
-When -mfunction-return= is used, simple_return_pop_internal should pop
-return address into ECX register, adjust stack by bytes to pop from stack
-and jump to the return thunk via ECX register.
-
-Revision 257992 removed the bool argument from ix86_output_indirect_jmp.
-Update comments to reflect it.
-
-Tested on i686 and x86-64.
-
-gcc/
-
- Backport from mainline
- 2018-02-26 H.J. Lu <hongjiu.lu@intel.com>
-
- * config/i386/i386.c (ix86_output_indirect_jmp): Update comments.
-
- 2018-02-26 H.J. Lu <hongjiu.lu@intel.com>
-
- PR target/84530
- * config/i386/i386-protos.h (ix86_output_indirect_jmp): Remove
- the bool argument.
- (ix86_output_indirect_function_return): New prototype.
- (ix86_split_simple_return_pop_internal): Likewise.
- * config/i386/i386.c (indirect_return_via_cx): New.
- (indirect_return_via_cx_bnd): Likewise.
- (indirect_thunk_name): Handle return va CX_REG.
- (output_indirect_thunk_function): Create alias for
- __x86_return_thunk_[re]cx and __x86_return_thunk_[re]cx_bnd.
- (ix86_output_indirect_jmp): Remove the bool argument.
- (ix86_output_indirect_function_return): New function.
- (ix86_split_simple_return_pop_internal): Likewise.
- * config/i386/i386.md (*indirect_jump): Don't pass false
- to ix86_output_indirect_jmp.
- (*tablejump_1): Likewise.
- (simple_return_pop_internal): Change it to define_insn_and_split.
- Call ix86_split_simple_return_pop_internal to split it for
- -mfunction-return=.
- (simple_return_indirect_internal): Call
- ix86_output_indirect_function_return instead of
- ix86_output_indirect_jmp.
-
-gcc/testsuite/
-
- Backport from mainline
- 2018-02-26 H.J. Lu <hongjiu.lu@intel.com>
-
- PR target/84530
- * gcc.target/i386/ret-thunk-22.c: New test.
- * gcc.target/i386/ret-thunk-23.c: Likewise.
- * gcc.target/i386/ret-thunk-24.c: Likewise.
- * gcc.target/i386/ret-thunk-25.c: Likewise.
- * gcc.target/i386/ret-thunk-26.c: Likewise.
----
- gcc/config/i386/i386-protos.h | 4 +-
- gcc/config/i386/i386.c | 127 +++++++++++++++++++++++----
- gcc/config/i386/i386.md | 11 ++-
- gcc/testsuite/gcc.target/i386/ret-thunk-22.c | 15 ++++
- gcc/testsuite/gcc.target/i386/ret-thunk-23.c | 15 ++++
- gcc/testsuite/gcc.target/i386/ret-thunk-24.c | 15 ++++
- gcc/testsuite/gcc.target/i386/ret-thunk-25.c | 15 ++++
- gcc/testsuite/gcc.target/i386/ret-thunk-26.c | 40 +++++++++
- 8 files changed, 222 insertions(+), 20 deletions(-)
- create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-22.c
- create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-23.c
- create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-24.c
- create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-25.c
- create mode 100644 gcc/testsuite/gcc.target/i386/ret-thunk-26.c
-
-diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
-index 620d70ef9f6..c7a0ccb58d3 100644
---- a/gcc/config/i386/i386-protos.h
-+++ b/gcc/config/i386/i386-protos.h
-@@ -311,8 +311,10 @@ extern enum attr_cpu ix86_schedule;
- #endif
-
- extern const char * ix86_output_call_insn (rtx_insn *insn, rtx call_op);
--extern const char * ix86_output_indirect_jmp (rtx call_op, bool ret_p);
-+extern const char * ix86_output_indirect_jmp (rtx call_op);
- extern const char * ix86_output_function_return (bool long_p);
-+extern const char * ix86_output_indirect_function_return (rtx ret_op);
-+extern void ix86_split_simple_return_pop_internal (rtx);
- extern bool ix86_operands_ok_for_move_multiple (rtx *operands, bool load,
- enum machine_mode mode);
-
-diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
-index 66502ee6da6..21c3c18bd3c 100644
---- a/gcc/config/i386/i386.c
-+++ b/gcc/config/i386/i386.c
-@@ -11080,6 +11080,12 @@ static int indirect_thunks_used;
- by call and return thunks functions with the BND prefix. */
- static int indirect_thunks_bnd_used;
-
-+/* True if return thunk function via CX is needed. */
-+static bool indirect_return_via_cx;
-+/* True if return thunk function via CX with the BND prefix is
-+ needed. */
-+static bool indirect_return_via_cx_bnd;
-+
- #ifndef INDIRECT_LABEL
- # define INDIRECT_LABEL "LIND"
- #endif
-@@ -11090,12 +11096,13 @@ static void
- indirect_thunk_name (char name[32], unsigned int regno,
- bool need_bnd_p, bool ret_p)
- {
-- if (regno != INVALID_REGNUM && ret_p)
-+ if (regno != INVALID_REGNUM && regno != CX_REG && ret_p)
- gcc_unreachable ();
-
- if (USE_HIDDEN_LINKONCE)
- {
- const char *bnd = need_bnd_p ? "_bnd" : "";
-+ const char *ret = ret_p ? "return" : "indirect";
- if (regno != INVALID_REGNUM)
- {
- const char *reg_prefix;
-@@ -11103,14 +11110,11 @@ indirect_thunk_name (char name[32], unsigned int regno,
- reg_prefix = TARGET_64BIT ? "r" : "e";
- else
- reg_prefix = "";
-- sprintf (name, "__x86_indirect_thunk%s_%s%s",
-- bnd, reg_prefix, reg_names[regno]);
-+ sprintf (name, "__x86_%s_thunk%s_%s%s",
-+ ret, bnd, reg_prefix, reg_names[regno]);
- }
- else
-- {
-- const char *ret = ret_p ? "return" : "indirect";
-- sprintf (name, "__x86_%s_thunk%s", ret, bnd);
-- }
-+ sprintf (name, "__x86_%s_thunk%s", ret, bnd);
- }
- else
- {
-@@ -11274,9 +11278,23 @@ output_indirect_thunk_function (bool need_bnd_p, unsigned int regno)
- ASM_OUTPUT_LABEL (asm_out_file, name);
- }
-
-+ /* Create alias for __x86_return_thunk/__x86_return_thunk_bnd or
-+ __x86_return_thunk_ecx/__x86_return_thunk_ecx_bnd. */
-+ bool need_alias;
- if (regno == INVALID_REGNUM)
-+ need_alias = true;
-+ else if (regno == CX_REG)
-+ {
-+ if (need_bnd_p)
-+ need_alias = indirect_return_via_cx_bnd;
-+ else
-+ need_alias = indirect_return_via_cx;
-+ }
-+ else
-+ need_alias = false;
-+
-+ if (need_alias)
- {
-- /* Create alias for __x86.return_thunk/__x86.return_thunk_bnd. */
- char alias[32];
-
- indirect_thunk_name (alias, regno, need_bnd_p, true);
-@@ -28019,18 +28037,17 @@ ix86_output_indirect_branch (rtx call_op, const char *xasm,
- else
- ix86_output_indirect_branch_via_push (call_op, xasm, sibcall_p);
- }
--/* Output indirect jump. CALL_OP is the jump target. Jump is a
-- function return if RET_P is true. */
-+
-+/* Output indirect jump. CALL_OP is the jump target. */
-
- const char *
--ix86_output_indirect_jmp (rtx call_op, bool ret_p)
-+ix86_output_indirect_jmp (rtx call_op)
- {
- if (cfun->machine->indirect_branch_type != indirect_branch_keep)
- {
-- /* We can't have red-zone if this isn't a function return since
-- "call" in the indirect thunk pushes the return address onto
-- stack, destroying red-zone. */
-- if (!ret_p && ix86_red_zone_size != 0)
-+ /* We can't have red-zone since "call" in the indirect thunk
-+ pushes the return address onto stack, destroying red-zone. */
-+ if (ix86_red_zone_size != 0)
- gcc_unreachable ();
-
- ix86_output_indirect_branch (call_op, "%0", true);
-@@ -28081,6 +28098,86 @@ ix86_output_function_return (bool long_p)
- return "rep%; ret";
- }
-
-+/* Output indirect function return. RET_OP is the function return
-+ target. */
-+
-+const char *
-+ix86_output_indirect_function_return (rtx ret_op)
-+{
-+ if (cfun->machine->function_return_type != indirect_branch_keep)
-+ {
-+ char thunk_name[32];
-+ bool need_bnd_p = ix86_bnd_prefixed_insn_p (current_output_insn);
-+ unsigned int regno = REGNO (ret_op);
-+ gcc_assert (regno == CX_REG);
-+
-+ if (cfun->machine->function_return_type
-+ != indirect_branch_thunk_inline)
-+ {
-+ bool need_thunk = (cfun->machine->function_return_type
-+ == indirect_branch_thunk);
-+ indirect_thunk_name (thunk_name, regno, need_bnd_p, true);
-+ if (need_bnd_p)
-+ {
-+ if (need_thunk)
-+ {
-+ indirect_return_via_cx_bnd = true;
-+ indirect_thunks_bnd_used |= 1 << CX_REG;
-+ }
-+ fprintf (asm_out_file, "\tbnd jmp\t%s\n", thunk_name);
-+ }
-+ else
-+ {
-+ if (need_thunk)
-+ {
-+ indirect_return_via_cx = true;
-+ indirect_thunks_used |= 1 << CX_REG;
-+ }
-+ fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name);
-+ }
-+ }
-+ else
-+ output_indirect_thunk (need_bnd_p, regno);
-+
-+ return "";
-+ }
-+ else
-+ return "%!jmp\t%A0";
-+}
-+
-+/* Split simple return with popping POPC bytes from stack to indirect
-+ branch with stack adjustment . */
-+
-+void
-+ix86_split_simple_return_pop_internal (rtx popc)
-+{
-+ struct machine_function *m = cfun->machine;
-+ rtx ecx = gen_rtx_REG (SImode, CX_REG);
-+ rtx_insn *insn;
-+
-+ /* There is no "pascal" calling convention in any 64bit ABI. */
-+ gcc_assert (!TARGET_64BIT);
-+
-+ insn = emit_insn (gen_pop (ecx));
-+ m->fs.cfa_offset -= UNITS_PER_WORD;
-+ m->fs.sp_offset -= UNITS_PER_WORD;
-+
-+ rtx x = plus_constant (Pmode, stack_pointer_rtx, UNITS_PER_WORD);
-+ x = gen_rtx_SET (stack_pointer_rtx, x);
-+ add_reg_note (insn, REG_CFA_ADJUST_CFA, x);
-+ add_reg_note (insn, REG_CFA_REGISTER, gen_rtx_SET (ecx, pc_rtx));
-+ RTX_FRAME_RELATED_P (insn) = 1;
-+
-+ x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, popc);
-+ x = gen_rtx_SET (stack_pointer_rtx, x);
-+ insn = emit_insn (x);
-+ add_reg_note (insn, REG_CFA_ADJUST_CFA, x);
-+ RTX_FRAME_RELATED_P (insn) = 1;
-+
-+ /* Now return address is in ECX. */
-+ emit_jump_insn (gen_simple_return_indirect_internal (ecx));
-+}
-+
- /* Output the assembly for a call instruction. */
-
- const char *
-diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
-index 05a88fff356..857466a6361 100644
---- a/gcc/config/i386/i386.md
-+++ b/gcc/config/i386/i386.md
-@@ -11813,7 +11813,7 @@
- (define_insn "*indirect_jump"
- [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))]
- ""
-- "* return ix86_output_indirect_jmp (operands[0], false);"
-+ "* return ix86_output_indirect_jmp (operands[0]);"
- [(set (attr "type")
- (if_then_else (match_test "(cfun->machine->indirect_branch_type
- != indirect_branch_keep)")
-@@ -11868,7 +11868,7 @@
- [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rBw"))
- (use (label_ref (match_operand 1)))]
- ""
-- "* return ix86_output_indirect_jmp (operands[0], false);"
-+ "* return ix86_output_indirect_jmp (operands[0]);"
- [(set (attr "type")
- (if_then_else (match_test "(cfun->machine->indirect_branch_type
- != indirect_branch_keep)")
-@@ -12520,11 +12520,14 @@
- (set_attr "prefix_rep" "1")
- (set_attr "modrm" "0")])
-
--(define_insn "simple_return_pop_internal"
-+(define_insn_and_split "simple_return_pop_internal"
- [(simple_return)
- (use (match_operand:SI 0 "const_int_operand"))]
- "reload_completed"
- "%!ret\t%0"
-+ "&& cfun->machine->function_return_type != indirect_branch_keep"
-+ [(const_int 0)]
-+ "ix86_split_simple_return_pop_internal (operands[0]); DONE;"
- [(set_attr "length" "3")
- (set_attr "atom_unit" "jeu")
- (set_attr "length_immediate" "2")
-@@ -12535,7 +12538,7 @@
- [(simple_return)
- (use (match_operand:SI 0 "register_operand" "r"))]
- "reload_completed"
-- "* return ix86_output_indirect_jmp (operands[0], true);"
-+ "* return ix86_output_indirect_function_return (operands[0]);"
- [(set (attr "type")
- (if_then_else (match_test "(cfun->machine->indirect_branch_type
- != indirect_branch_keep)")
-diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-22.c b/gcc/testsuite/gcc.target/i386/ret-thunk-22.c
-new file mode 100644
-index 00000000000..89e086de97b
---- /dev/null
-+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-22.c
-@@ -0,0 +1,15 @@
-+/* PR target/r84530 */
-+/* { dg-do compile { target ia32 } } */
-+/* { dg-options "-O2 -mfunction-return=thunk" } */
-+
-+struct s { _Complex unsigned short x; };
-+struct s gs = { 100 + 200i };
-+struct s __attribute__((noinline)) foo (void) { return gs; }
-+
-+/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */
-+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */
-+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk_ecx" } } */
-+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
-+/* { dg-final { scan-assembler {\tpause} } } */
-+/* { dg-final { scan-assembler {\tlfence} } } */
-diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-23.c b/gcc/testsuite/gcc.target/i386/ret-thunk-23.c
-new file mode 100644
-index 00000000000..43f0ccaa854
---- /dev/null
-+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-23.c
-@@ -0,0 +1,15 @@
-+/* PR target/r84530 */
-+/* { dg-do compile { target ia32 } } */
-+/* { dg-options "-O2 -mfunction-return=thunk-extern" } */
-+
-+struct s { _Complex unsigned short x; };
-+struct s gs = { 100 + 200i };
-+struct s __attribute__((noinline)) foo (void) { return gs; }
-+
-+/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */
-+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */
-+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk_ecx" } } */
-+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */
-+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */
-+/* { dg-final { scan-assembler-not {\tpause} } } */
-+/* { dg-final { scan-assembler-not {\tlfence} } } */
-diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-24.c b/gcc/testsuite/gcc.target/i386/ret-thunk-24.c
-new file mode 100644
-index 00000000000..8729e35147e
---- /dev/null
-+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-24.c
-@@ -0,0 +1,15 @@
-+/* PR target/r84530 */
-+/* { dg-do compile { target ia32 } } */
-+/* { dg-options "-O2 -mfunction-return=thunk-inline" } */
-+
-+struct s { _Complex unsigned short x; };
-+struct s gs = { 100 + 200i };
-+struct s __attribute__((noinline)) foo (void) { return gs; }
-+
-+/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */
-+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */
-+/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk_ecx" } } */
-+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
-+/* { dg-final { scan-assembler {\tpause} } } */
-+/* { dg-final { scan-assembler {\tlfence} } } */
-diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-25.c b/gcc/testsuite/gcc.target/i386/ret-thunk-25.c
-new file mode 100644
-index 00000000000..f73553c9a9f
---- /dev/null
-+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-25.c
-@@ -0,0 +1,15 @@
-+/* PR target/r84530 */
-+/* { dg-do compile { target ia32 } } */
-+/* { dg-options "-O2 -mfunction-return=thunk -fcheck-pointer-bounds -mmpx -fno-pic" } */
-+
-+struct s { _Complex unsigned short x; };
-+struct s gs = { 100 + 200i };
-+struct s __attribute__((noinline)) foo (void) { return gs; }
-+
-+/* { dg-final { scan-assembler-times "popl\[\\t \]*%ecx" 1 } } */
-+/* { dg-final { scan-assembler "lea\[l\]?\[\\t \]*4\\(%esp\\), %esp" } } */
-+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk_bnd_ecx" } } */
-+/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */
-+/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */
-+/* { dg-final { scan-assembler {\tpause} } } */
-+/* { dg-final { scan-assembler {\tlfence} } } */
-diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-26.c b/gcc/testsuite/gcc.target/i386/ret-thunk-26.c
-new file mode 100644
-index 00000000000..9144e988735
---- /dev/null
-+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-26.c
-@@ -0,0 +1,40 @@
-+/* PR target/r84530 */
-+/* { dg-do run } */
-+/* { dg-options "-Os -mfunction-return=thunk" } */
-+
-+struct S { int i; };
-+__attribute__((const, noinline, noclone))
-+struct S foo (int x)
-+{
-+ struct S s;
-+ s.i = x;
-+ return s;
-+}
-+
-+int a[2048], b[2048], c[2048], d[2048];
-+struct S e[2048];
-+
-+__attribute__((noinline, noclone)) void
-+bar (void)
-+{
-+ int i;
-+ for (i = 0; i < 1024; i++)
-+ {
-+ e[i] = foo (i);
-+ a[i+2] = a[i] + a[i+1];
-+ b[10] = b[10] + i;
-+ c[i] = c[2047 - i];
-+ d[i] = d[i + 1];
-+ }
-+}
-+
-+int
-+main ()
-+{
-+ int i;
-+ bar ();
-+ for (i = 0; i < 1024; i++)
-+ if (e[i].i != i)
-+ __builtin_abort ();
-+ return 0;
-+}
---
-2.16.3
-