basebuilder_pel7ppc64bebuilder0
6 years ago
119 changed files with 9005 additions and 3823 deletions
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
2015-07-14 Matthias Klose <doko@ubuntu.com> |
||||
|
||||
PR target/66840 |
||||
* config/rs6000/t-rs6000 (TM_H): Add rs6000-cpus.def. |
||||
|
||||
diff -Nrup a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000 |
||||
--- /gcc/config/rs6000/t-rs6000 2013-08-14 05:55:11.000000000 -0600 |
||||
+++ gcc/config/rs6000/t-rs6000 2018-04-18 12:09:30.614737081 -0600 |
||||
@@ -19,6 +19,7 @@ |
||||
# <http://www.gnu.org/licenses/>. |
||||
|
||||
TM_H += $(srcdir)/config/rs6000/rs6000-builtin.def |
||||
+TM_H += $(srcdir)/config/rs6000/rs6000-cpus.def |
||||
|
||||
rs6000.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ |
||||
$(RTL_H) $(REGS_H) hard-reg-set.h \ |
@ -0,0 +1,87 @@
@@ -0,0 +1,87 @@
|
||||
2016-12-13 Michael Meissner <meissner@linux.vnet.ibm.com> |
||||
|
||||
Backport from mainline |
||||
2016-12-07 Michael Meissner <meissner@linux.vnet.ibm.com> |
||||
|
||||
PR target/72717 |
||||
* config/rs6000/rs6000.c (rs6000_expand_vector_init): If the |
||||
V2DImode elements are SUBREG's convert the result into DImode |
||||
rather than failing in emit_move_insn. |
||||
|
||||
--- gcc/testsuite/gcc.target/powerpc/pr72717.c (nonexistent) |
||||
+++ gcc/testsuite/gcc.target/powerpc/pr72717.c (revision 243626) |
||||
@@ -0,0 +1,18 @@ |
||||
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ |
||||
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ |
||||
+/* { dg-require-effective-target powerpc_p8vector_ok } */ |
||||
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */ |
||||
+/* { dg-options "-mcpu=power8 -O2" } */ |
||||
+ |
||||
+typedef long V __attribute__((__vector_size__(32))); |
||||
+ |
||||
+extern void foo (V *, V*); |
||||
+ |
||||
+/* This test generated an failure in emit_move_insn. */ |
||||
+ |
||||
+void |
||||
+foo(V *p, V *q) |
||||
+{ |
||||
+ V v = *q; |
||||
+ *p = v << v[0]; |
||||
+} |
||||
--- gcc/config/rs6000/rs6000.c (revision 243625) |
||||
+++ gcc/config/rs6000/rs6000.c (revision 243626) |
||||
@@ -6667,25 +6667,43 @@ |
||||
/* Double word values on VSX can use xxpermdi or lxvdsx. */ |
||||
if (VECTOR_MEM_VSX_P (mode) && (mode == V2DFmode || mode == V2DImode)) |
||||
{ |
||||
- rtx op0 = XVECEXP (vals, 0, 0); |
||||
- rtx op1 = XVECEXP (vals, 0, 1); |
||||
+ rtx op[2]; |
||||
+ size_t i; |
||||
+ size_t num_elements = (all_same) ? 1 : 2; |
||||
+ for (i = 0; i < num_elements; i++) |
||||
+ { |
||||
+ op[i] = XVECEXP (vals, 0, i); |
||||
+ /* Just in case there is a SUBREG with a smaller mode, do a |
||||
+ conversion. */ |
||||
+ if (GET_MODE (op[i]) != inner_mode) |
||||
+ { |
||||
+ rtx tmp = gen_reg_rtx (inner_mode); |
||||
+ convert_move (tmp, op[i], 0); |
||||
+ op[i] = tmp; |
||||
+ } |
||||
+ /* Allow load with splat double word. */ |
||||
+ else if (MEM_P (op[i])) |
||||
+ { |
||||
+ if (!all_same) |
||||
+ op[i] = force_reg (inner_mode, op[i]); |
||||
+ } |
||||
+ else if (!REG_P (op[i])) |
||||
+ op[i] = force_reg (inner_mode, op[i]); |
||||
+ } |
||||
+ |
||||
if (all_same) |
||||
{ |
||||
- if (!MEM_P (op0) && !REG_P (op0)) |
||||
- op0 = force_reg (inner_mode, op0); |
||||
if (mode == V2DFmode) |
||||
- emit_insn (gen_vsx_splat_v2df (target, op0)); |
||||
+ emit_insn (gen_vsx_splat_v2df (target, op[0])); |
||||
else |
||||
- emit_insn (gen_vsx_splat_v2di (target, op0)); |
||||
+ emit_insn (gen_vsx_splat_v2di (target, op[0])); |
||||
} |
||||
else |
||||
{ |
||||
- op0 = force_reg (inner_mode, op0); |
||||
- op1 = force_reg (inner_mode, op1); |
||||
if (mode == V2DFmode) |
||||
- emit_insn (gen_vsx_concat_v2df (target, op0, op1)); |
||||
+ emit_insn (gen_vsx_concat_v2df (target, op[0], op[1])); |
||||
else |
||||
- emit_insn (gen_vsx_concat_v2di (target, op0, op1)); |
||||
+ emit_insn (gen_vsx_concat_v2di (target, op[0], op[1])); |
||||
} |
||||
return; |
||||
} |
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
2017-07-18 Jonathan Wakely <jwakely@redhat.com> |
||||
|
||||
PR libstdc++/81395 |
||||
* include/bits/fstream.tcc (basic_filebuf::xsgetn): Don't set buffer |
||||
pointers for write mode after reading. |
||||
* testsuite/27_io/basic_filebuf/sgetn/char/81395.cc: New. |
||||
|
||||
--- libstdc++-v3/include/bits/fstream.tcc (revision 254017) |
||||
+++ libstdc++-v3/include/bits/fstream.tcc (revision 254018) |
||||
@@ -699,7 +699,7 @@ |
||||
|
||||
if (__n == 0) |
||||
{ |
||||
- _M_set_buffer(0); |
||||
+ // Set _M_reading. Buffer is already in initial 'read' mode. |
||||
_M_reading = true; |
||||
} |
||||
else if (__len == 0) |
||||
--- libstdc++-v3/testsuite/27_io/basic_filebuf/sgetn/char/81395.cc (nonexistent) |
||||
+++ libstdc++-v3/testsuite/27_io/basic_filebuf/sgetn/char/81395.cc (revision 254018) |
||||
@@ -0,0 +1,46 @@ |
||||
+// Copyright (C) 2017 Free Software Foundation, Inc. |
||||
+// |
||||
+// This file is part of the GNU ISO C++ Library. This library is free |
||||
+// software; you can redistribute it and/or modify it under the |
||||
+// terms of the GNU General Public License as published by the |
||||
+// Free Software Foundation; either version 3, or (at your option) |
||||
+// any later version. |
||||
+ |
||||
+// This library is distributed in the hope that it will be useful, |
||||
+// but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
+// GNU General Public License for more details. |
||||
+ |
||||
+// You should have received a copy of the GNU General Public License along |
||||
+// with this library; see the file COPYING3. If not see |
||||
+// <http://www.gnu.org/licenses/>. |
||||
+ |
||||
+// { dg-require-fileio "" } |
||||
+ |
||||
+// PR libstdc++/81395 |
||||
+ |
||||
+#include <fstream> |
||||
+#include <cstring> // for std::memset |
||||
+#include <cstdio> // For BUFSIZ |
||||
+ |
||||
+using std::memset; |
||||
+ |
||||
+int main() |
||||
+{ |
||||
+ { |
||||
+ std::filebuf fb; |
||||
+ fb.open("test.txt", std::ios::out); |
||||
+ char data[BUFSIZ]; |
||||
+ memset(data, 'A', sizeof(data)); |
||||
+ fb.sputn(data, sizeof(data)); |
||||
+ } |
||||
+ |
||||
+ std::filebuf fb; |
||||
+ fb.open("test.txt", std::ios::in|std::ios::out); |
||||
+ char buf[BUFSIZ]; |
||||
+ memset(buf, 0, sizeof(buf)); |
||||
+ fb.sgetn(buf, sizeof(buf)); |
||||
+ // Switch from reading to writing without seeking first: |
||||
+ fb.sputn("B", 1); |
||||
+ fb.pubsync(); |
||||
+} |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
2018-04-10 Segher Boessenkool <segher@kernel.crashing.org> |
||||
|
||||
PR target/85287 |
||||
* gcc/config/rs6000/rs6000.md (allocate_stack): Put the residual size |
||||
for stack clash protection in a register whenever we need it to be in |
||||
a register. |
||||
|
||||
|
||||
--- a/gcc/config/rs6000/rs6000.md 2018/04/10 21:09:30 259298 |
||||
+++ b/gcc/config/rs6000/rs6000.md 2018/04/10 21:37:34 259299 |
||||
@@ -9783,14 +9783,12 @@ |
||||
/* Now handle residuals. We just have to set operands[1] correctly |
||||
and let the rest of the expander run. */ |
||||
operands[1] = residual; |
||||
- if (!CONST_INT_P (residual)) |
||||
- operands[1] = force_reg (Pmode, operands[1]); |
||||
} |
||||
|
||||
- if (GET_CODE (operands[1]) != CONST_INT |
||||
- || INTVAL (operands[1]) < -32767 |
||||
- || INTVAL (operands[1]) > 32768) |
||||
+ if (!(CONST_INT_P (operands[1]) |
||||
+ && IN_RANGE (INTVAL (operands[1]), -32767, 32768))) |
||||
{ |
||||
+ operands[1] = force_reg (Pmode, operands[1]); |
||||
neg_op0 = gen_reg_rtx (Pmode); |
||||
if (TARGET_32BIT) |
||||
emit_insn (gen_negsi2 (neg_op0, operands[1])); |
||||
@@ -9798,7 +9796,7 @@ |
||||
emit_insn (gen_negdi2 (neg_op0, operands[1])); |
||||
} |
||||
else |
||||
- neg_op0 = GEN_INT (- INTVAL (operands[1])); |
||||
+ neg_op0 = GEN_INT (-INTVAL (operands[1])); |
||||
|
||||
insn = emit_insn ((* ((TARGET_32BIT) ? gen_movsi_update_stack |
||||
: gen_movdi_di_update_stack)) |
||||
|
@ -0,0 +1,91 @@
@@ -0,0 +1,91 @@
|
||||
diff --git a/gcc/testsuite/gcc.dg/stack-check-5.c b/gcc/testsuite/gcc.dg/stack-check-5.c |
||||
index 850e023ea4e..604fa3cf6c5 100644 |
||||
--- a/gcc/testsuite/gcc.dg/stack-check-5.c |
||||
+++ b/gcc/testsuite/gcc.dg/stack-check-5.c |
||||
@@ -1,7 +1,7 @@ |
||||
/* { dg-do compile } */ |
||||
/* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */ |
||||
/* { dg-require-effective-target supports_stack_clash_protection } */ |
||||
-/* { dg-skip-if "" { *-*-* } { "-fstack-protector" } { "" } } */ |
||||
+/* { dg-skip-if "" { *-*-* } { "-fstack-protector*" } { "" } } */ |
||||
|
||||
|
||||
/* Otherwise the S/390 back-end might save the stack pointer in f2 () |
||||
diff --git a/gcc/testsuite/gcc.dg/stack-check-6.c b/gcc/testsuite/gcc.dg/stack-check-6.c |
||||
index ab4b0e8894c..fe75612b737 100644 |
||||
--- a/gcc/testsuite/gcc.dg/stack-check-6.c |
||||
+++ b/gcc/testsuite/gcc.dg/stack-check-6.c |
||||
@@ -1,7 +1,7 @@ |
||||
/* { dg-do compile } */ |
||||
/* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=12" } */ |
||||
/* { dg-require-effective-target supports_stack_clash_protection } */ |
||||
-/* { dg-skip-if "" { *-*-* } { "-fstack-protector" } { "" } } */ |
||||
+/* { dg-skip-if "" { *-*-* } { "-fstack-protector*" } { "" } } */ |
||||
|
||||
|
||||
extern void foo (char *); |
||||
diff --git a/gcc/testsuite/gcc.dg/stack-check-6a.c b/gcc/testsuite/gcc.dg/stack-check-6a.c |
||||
index 468d649a4fa..8fb9c621585 100644 |
||||
--- a/gcc/testsuite/gcc.dg/stack-check-6a.c |
||||
+++ b/gcc/testsuite/gcc.dg/stack-check-6a.c |
||||
@@ -4,7 +4,7 @@ |
||||
/* { dg-do compile } */ |
||||
/* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls --param stack-clash-protection-probe-interval=12 --param stack-clash-protection-guard-size=16" } */ |
||||
/* { dg-require-effective-target supports_stack_clash_protection } */ |
||||
-/* { dg-skip-if "" { *-*-* } { "-fstack-protector" } { "" } } */ |
||||
+/* { dg-skip-if "" { *-*-* } { "-fstack-protector*" } { "" } } */ |
||||
|
||||
|
||||
#include "stack-check-6.c" |
||||
diff --git a/gcc/testsuite/gcc.target/i386/stack-check-11.c b/gcc/testsuite/gcc.target/i386/stack-check-11.c |
||||
index fe5b2c2b844..43a291857b6 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/stack-check-11.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/stack-check-11.c |
||||
@@ -1,6 +1,8 @@ |
||||
/* { dg-do compile } */ |
||||
/* { dg-options "-O2 -fstack-clash-protection" } */ |
||||
/* { dg-require-effective-target supports_stack_clash_protection } */ |
||||
+/* { dg-skip-if "" { *-*-* } { "-fstack-protector*" } { "" } } */ |
||||
+ |
||||
|
||||
#include <stdint.h> |
||||
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/stack-check-17.c b/gcc/testsuite/gcc.target/i386/stack-check-17.c |
||||
index dcd29305a2c..da6ea016815 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/stack-check-17.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/stack-check-17.c |
||||
@@ -1,6 +1,8 @@ |
||||
/* { dg-do compile } */ |
||||
/* { dg-options "-O2 -fstack-clash-protection -mtune=generic -fomit-frame-pointer" } */ |
||||
/* { dg-require-effective-target supports_stack_clash_protection } */ |
||||
+/* { dg-skip-if "" { *-*-* } { "-fstack-protector*" } { "" } } */ |
||||
+ |
||||
|
||||
|
||||
int x0, x1; |
||||
diff --git a/gcc/testsuite/gcc.target/i386/stack-check-18.c b/gcc/testsuite/gcc.target/i386/stack-check-18.c |
||||
index 1638f776267..1cf4bbcfafb 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/stack-check-18.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/stack-check-18.c |
||||
@@ -1,7 +1,7 @@ |
||||
/* { dg-do compile } */ |
||||
/* { dg-options "-O2 -fstack-clash-protection -mtune=generic -fdump-rtl-expand" } */ |
||||
/* { dg-require-effective-target supports_stack_clash_protection } */ |
||||
-/* { dg-skip-if "" { *-*-* } { "-fstack-protector" } { "" } } */ |
||||
+/* { dg-skip-if "" { *-*-* } { "-fstack-protector*" } { "" } } */ |
||||
|
||||
int f1 (char *); |
||||
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/stack-check-19.c b/gcc/testsuite/gcc.target/i386/stack-check-19.c |
||||
index c341801189c..49f3a20af8b 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/stack-check-19.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/stack-check-19.c |
||||
@@ -1,7 +1,7 @@ |
||||
/* { dg-do compile } */ |
||||
/* { dg-options "-O2 -fstack-clash-protection -mtune=generic -fdump-rtl-expand" } */ |
||||
/* { dg-require-effective-target supports_stack_clash_protection } */ |
||||
-/* { dg-skip-if "" { *-*-* } { "-fstack-protector" } { "" } } */ |
||||
+/* { dg-skip-if "" { *-*-* } { "-fstack-protector*" } { "" } } */ |
||||
|
||||
int f1 (char *); |
||||
|
@ -0,0 +1,114 @@
@@ -0,0 +1,114 @@
|
||||
commit f7765f70e0e254fd9ce4469c7281c69cd06c9467 |
||||
Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4> |
||||
Date: Wed Jan 24 21:57:16 2018 +0000 |
||||
|
||||
PR target/83994 |
||||
* i386.c (get_probe_interval): Move to earlier point. |
||||
(ix86_compute_frame_layout): If -fstack-clash-protection and |
||||
the frame is larger than the probe interval, then use pushes |
||||
to save registers rather than reg->mem moves. |
||||
(ix86_expand_prologue): Remove conditional for int_registers_saved |
||||
assertion. |
||||
|
||||
PR target/83994 |
||||
* gcc.target/i386/pr83994.c: New test. |
||||
|
||||
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c |
||||
index 15cfe83..5230227 100644 |
||||
--- a/gcc/config/i386/i386.c |
||||
+++ b/gcc/config/i386/i386.c |
||||
@@ -9371,6 +9371,18 @@ ix86_builtin_setjmp_frame_value (void) |
||||
return stack_realign_fp ? hard_frame_pointer_rtx : virtual_stack_vars_rtx; |
||||
} |
||||
|
||||
+/* Return the probing interval for -fstack-clash-protection. */ |
||||
+ |
||||
+static HOST_WIDE_INT |
||||
+get_probe_interval (void) |
||||
+{ |
||||
+ if (flag_stack_clash_protection) |
||||
+ return (HOST_WIDE_INT_1U |
||||
+ << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL)); |
||||
+ else |
||||
+ return (HOST_WIDE_INT_1U << STACK_CHECK_PROBE_INTERVAL_EXP); |
||||
+} |
||||
+ |
||||
/* When using -fsplit-stack, the allocation routines set a field in |
||||
the TCB to the bottom of the stack plus this much space, measured |
||||
in bytes. */ |
||||
@@ -9545,7 +9557,15 @@ ix86_compute_frame_layout (struct ix86_frame *frame) |
||||
to_allocate = offset - frame->sse_reg_save_offset; |
||||
|
||||
if ((!to_allocate && frame->nregs <= 1) |
||||
- || (TARGET_64BIT && to_allocate >= (HOST_WIDE_INT) 0x80000000)) |
||||
+ || (TARGET_64BIT && to_allocate >= (HOST_WIDE_INT) 0x80000000) |
||||
+ /* If stack clash probing needs a loop, then it needs a |
||||
+ scratch register. But the returned register is only guaranteed |
||||
+ to be safe to use after register saves are complete. So if |
||||
+ stack clash protections are enabled and the allocated frame is |
||||
+ larger than the probe interval, then use pushes to save |
||||
+ callee saved registers. */ |
||||
+ || (flag_stack_clash_protection && to_allocate > get_probe_interval ())) |
||||
+ |
||||
frame->save_regs_using_mov = false; |
||||
|
||||
if (ix86_using_red_zone () |
||||
@@ -10181,18 +10201,6 @@ release_scratch_register_on_entry (struct scratch_reg *sr) |
||||
} |
||||
} |
||||
|
||||
-/* Return the probing interval for -fstack-clash-protection. */ |
||||
- |
||||
-static HOST_WIDE_INT |
||||
-get_probe_interval (void) |
||||
-{ |
||||
- if (flag_stack_clash_protection) |
||||
- return (HOST_WIDE_INT_1U |
||||
- << PARAM_VALUE (PARAM_STACK_CLASH_PROTECTION_PROBE_INTERVAL)); |
||||
- else |
||||
- return (HOST_WIDE_INT_1U << STACK_CHECK_PROBE_INTERVAL_EXP); |
||||
-} |
||||
- |
||||
/* Emit code to adjust the stack pointer by SIZE bytes while probing it. |
||||
|
||||
This differs from the next routine in that it tries hard to prevent |
||||
@@ -11064,12 +11072,11 @@ ix86_expand_prologue (void) |
||||
&& (flag_stack_check == STATIC_BUILTIN_STACK_CHECK |
||||
|| flag_stack_clash_protection)) |
||||
{ |
||||
- /* This assert wants to verify that integer registers were saved |
||||
- prior to probing. This is necessary when probing may be implemented |
||||
- as a function call (Windows). It is not necessary for stack clash |
||||
- protection probing. */ |
||||
- if (!flag_stack_clash_protection) |
||||
- gcc_assert (int_registers_saved); |
||||
+ /* We expect the GP registers to be saved when probes are used |
||||
+ as the probing sequences might need a scratch register and |
||||
+ the routine to allocate one assumes the integer registers |
||||
+ have already been saved. */ |
||||
+ gcc_assert (int_registers_saved); |
||||
|
||||
if (flag_stack_clash_protection) |
||||
{ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/pr83994.c b/gcc/testsuite/gcc.target/i386/pr83994.c |
||||
new file mode 100644 |
||||
index 0000000..dc0b7cb |
||||
--- /dev/null |
||||
+++ b/gcc/testsuite/gcc.target/i386/pr83994.c |
||||
@@ -0,0 +1,16 @@ |
||||
+/* { dg-do compile } */ |
||||
+/* { dg-options "-O2 -march=i686 -fpic -fstack-clash-protection" } */ |
||||
+/* { dg-require-effective-target ia32 } */ |
||||
+ |
||||
+void f1 (char *); |
||||
+ |
||||
+__attribute__ ((regparm (3))) |
||||
+int |
||||
+f2 (int arg1, int arg2, int arg3) |
||||
+{ |
||||
+ char buf[16384]; |
||||
+ f1 (buf); |
||||
+ f1 (buf); |
||||
+ return 0; |
||||
+} |
||||
+ |
@ -0,0 +1,163 @@
@@ -0,0 +1,163 @@
|
||||
commit 33839c8f8aa7857cc5f22ddb3f0960999cb0dfc7 |
||||
Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4> |
||||
Date: Wed Jan 31 05:02:30 2018 +0000 |
||||
|
||||
PR target/84064 |
||||
* i386.c (ix86_adjust_stack_and_probe_stack_clash): New argument |
||||
INT_REGISTERS_SAVED. Check it prior to calling |
||||
get_scratch_register_on_entry. |
||||
(ix86_adjust_stack_and_probe): Similarly. |
||||
(ix86_emit_probe_stack_range): Similarly. |
||||
(ix86_expand_prologue): Corresponding changes. |
||||
|
||||
PR target/84064 |
||||
* gcc.target/i386/pr84064: New test. |
||||
|
||||
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c |
||||
index 5230227..2fe2a0c 100644 |
||||
--- a/gcc/config/i386/i386.c |
||||
+++ b/gcc/config/i386/i386.c |
||||
@@ -10206,10 +10206,14 @@ release_scratch_register_on_entry (struct scratch_reg *sr) |
||||
This differs from the next routine in that it tries hard to prevent |
||||
attacks that jump the stack guard. Thus it is never allowed to allocate |
||||
more than PROBE_INTERVAL bytes of stack space without a suitable |
||||
- probe. */ |
||||
+ probe. |
||||
+ |
||||
+ INT_REGISTERS_SAVED is true if integer registers have already been |
||||
+ pushed on the stack. */ |
||||
|
||||
static void |
||||
-ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size) |
||||
+ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size, |
||||
+ const bool int_registers_saved) |
||||
{ |
||||
struct machine_function *m = cfun->machine; |
||||
struct ix86_frame frame; |
||||
@@ -10318,6 +10322,12 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size) |
||||
} |
||||
else |
||||
{ |
||||
+ /* We expect the GP registers to be saved when probes are used |
||||
+ as the probing sequences might need a scratch register and |
||||
+ the routine to allocate one assumes the integer registers |
||||
+ have already been saved. */ |
||||
+ gcc_assert (int_registers_saved); |
||||
+ |
||||
struct scratch_reg sr; |
||||
get_scratch_register_on_entry (&sr); |
||||
|
||||
@@ -10376,10 +10386,14 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size) |
||||
emit_insn (gen_blockage ()); |
||||
} |
||||
|
||||
-/* Emit code to adjust the stack pointer by SIZE bytes while probing it. */ |
||||
+/* Emit code to adjust the stack pointer by SIZE bytes while probing it. |
||||
+ |
||||
+ INT_REGISTERS_SAVED is true if integer registers have already been |
||||
+ pushed on the stack. */ |
||||
|
||||
static void |
||||
-ix86_adjust_stack_and_probe (const HOST_WIDE_INT size) |
||||
+ix86_adjust_stack_and_probe (const HOST_WIDE_INT size, |
||||
+ const bool int_registers_saved) |
||||
{ |
||||
/* We skip the probe for the first interval + a small dope of 4 words and |
||||
probe that many bytes past the specified size to maintain a protection |
||||
@@ -10440,6 +10454,12 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size) |
||||
equality test for the loop condition. */ |
||||
else |
||||
{ |
||||
+ /* We expect the GP registers to be saved when probes are used |
||||
+ as the probing sequences might need a scratch register and |
||||
+ the routine to allocate one assumes the integer registers |
||||
+ have already been saved. */ |
||||
+ gcc_assert (int_registers_saved); |
||||
+ |
||||
HOST_WIDE_INT rounded_size; |
||||
struct scratch_reg sr; |
||||
|
||||
@@ -10564,10 +10584,14 @@ output_adjust_stack_and_probe (rtx reg) |
||||
} |
||||
|
||||
/* Emit code to probe a range of stack addresses from FIRST to FIRST+SIZE, |
||||
- inclusive. These are offsets from the current stack pointer. */ |
||||
+ inclusive. These are offsets from the current stack pointer. |
||||
+ |
||||
+ INT_REGISTERS_SAVED is true if integer registers have already been |
||||
+ pushed on the stack. */ |
||||
|
||||
static void |
||||
-ix86_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size) |
||||
+ix86_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size, |
||||
+ const bool int_registers_saved) |
||||
{ |
||||
/* See if we have a constant small number of probes to generate. If so, |
||||
that's the easy case. The run-time loop is made up of 7 insns in the |
||||
@@ -10595,6 +10619,12 @@ ix86_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size) |
||||
equality test for the loop condition. */ |
||||
else |
||||
{ |
||||
+ /* We expect the GP registers to be saved when probes are used |
||||
+ as the probing sequences might need a scratch register and |
||||
+ the routine to allocate one assumes the integer registers |
||||
+ have already been saved. */ |
||||
+ gcc_assert (int_registers_saved); |
||||
+ |
||||
HOST_WIDE_INT rounded_size, last; |
||||
struct scratch_reg sr; |
||||
|
||||
@@ -11072,20 +11102,15 @@ ix86_expand_prologue (void) |
||||
&& (flag_stack_check == STATIC_BUILTIN_STACK_CHECK |
||||
|| flag_stack_clash_protection)) |
||||
{ |
||||
- /* We expect the GP registers to be saved when probes are used |
||||
- as the probing sequences might need a scratch register and |
||||
- the routine to allocate one assumes the integer registers |
||||
- have already been saved. */ |
||||
- gcc_assert (int_registers_saved); |
||||
- |
||||
if (flag_stack_clash_protection) |
||||
{ |
||||
- ix86_adjust_stack_and_probe_stack_clash (allocate); |
||||
+ ix86_adjust_stack_and_probe_stack_clash (allocate, |
||||
+ int_registers_saved); |
||||
allocate = 0; |
||||
} |
||||
else if (STACK_CHECK_MOVING_SP) |
||||
{ |
||||
- ix86_adjust_stack_and_probe (allocate); |
||||
+ ix86_adjust_stack_and_probe (allocate, int_registers_saved); |
||||
allocate = 0; |
||||
} |
||||
else |
||||
@@ -11096,9 +11121,11 @@ ix86_expand_prologue (void) |
||||
size = 0x80000000 - get_stack_check_protect () - 1; |
||||
|
||||
if (TARGET_STACK_PROBE) |
||||
- ix86_emit_probe_stack_range (0, size + get_stack_check_protect ()); |
||||
+ ix86_emit_probe_stack_range (0, size + get_stack_check_protect (), |
||||
+ int_registers_saved); |
||||
else |
||||
- ix86_emit_probe_stack_range (get_stack_check_protect (), size); |
||||
+ ix86_emit_probe_stack_range (get_stack_check_protect (), size, |
||||
+ int_registers_saved); |
||||
} |
||||
} |
||||
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/pr84064.c b/gcc/testsuite/gcc.target/i386/pr84064.c |
||||
new file mode 100644 |
||||
index 0000000..01f8d9e |
||||
--- /dev/null |
||||
+++ b/gcc/testsuite/gcc.target/i386/pr84064.c |
||||
@@ -0,0 +1,10 @@ |
||||
+/* { dg-do compile } */ |
||||
+/* { dg-options "-O2 -march=i686 -fstack-clash-protection" } */ |
||||
+/* { dg-require-effective-target ia32 } */ |
||||
+ |
||||
+void |
||||
+f (void *p1, void *p2) |
||||
+{ |
||||
+ __builtin_memcpy (p1, p2, 1000); |
||||
+} |
||||
+ |
@ -0,0 +1,182 @@
@@ -0,0 +1,182 @@
|
||||
commit 14041afe24556efd5845564aa183b6451fd9d6cc |
||||
Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4> |
||||
Date: Thu Feb 1 16:22:56 2018 +0000 |
||||
|
||||
PR target/84128 |
||||
* config/i386/i386.c (release_scratch_register_on_entry): Add new |
||||
OFFSET and RELEASE_VIA_POP arguments. Use SP+OFFSET to restore |
||||
the scratch if RELEASE_VIA_POP is false. |
||||
(ix86_adjust_stack_and_probe_stack_clash): Un-constify SIZE. |
||||
If we have to save a temporary register, decrement SIZE appropriately. |
||||
Pass new arguments to release_scratch_register_on_entry. |
||||
(ix86_adjust_stack_and_probe): Likewise. |
||||
(ix86_emit_probe_stack_range): Pass new arguments to |
||||
release_scratch_register_on_entry. |
||||
|
||||
PR target/84128 |
||||
* gcc.target/i386/pr84128.c: New test. |
||||
|
||||
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c |
||||
index 2fe2a0c..c25d26c 100644 |
||||
--- a/gcc/config/i386/i386.c |
||||
+++ b/gcc/config/i386/i386.c |
||||
@@ -10182,22 +10182,39 @@ get_scratch_register_on_entry (struct scratch_reg *sr) |
||||
} |
||||
} |
||||
|
||||
-/* Release a scratch register obtained from the preceding function. */ |
||||
+/* Release a scratch register obtained from the preceding function. |
||||
+ |
||||
+ If RELEASE_VIA_POP is true, we just pop the register off the stack |
||||
+ to release it. This is what non-Linux systems use with -fstack-check. |
||||
+ |
||||
+ Otherwise we use OFFSET to locate the saved register and the |
||||
+ allocated stack space becomes part of the local frame and is |
||||
+ deallcated by the epilogue. */ |
||||
|
||||
static void |
||||
-release_scratch_register_on_entry (struct scratch_reg *sr) |
||||
+release_scratch_register_on_entry (struct scratch_reg *sr, HOST_WIDE_INT offset, |
||||
+ bool release_via_pop) |
||||
{ |
||||
if (sr->saved) |
||||
{ |
||||
- struct machine_function *m = cfun->machine; |
||||
- rtx x, insn = emit_insn (gen_pop (sr->reg)); |
||||
+ if (release_via_pop) |
||||
+ { |
||||
+ struct machine_function *m = cfun->machine; |
||||
+ rtx x, insn = emit_insn (gen_pop (sr->reg)); |
||||
|
||||
- /* The RTX_FRAME_RELATED_P mechanism doesn't know about pop. */ |
||||
- RTX_FRAME_RELATED_P (insn) = 1; |
||||
- x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (UNITS_PER_WORD)); |
||||
- x = gen_rtx_SET (VOIDmode, stack_pointer_rtx, x); |
||||
- add_reg_note (insn, REG_FRAME_RELATED_EXPR, x); |
||||
- m->fs.sp_offset -= UNITS_PER_WORD; |
||||
+ /* The RTX FRAME_RELATED_P mechanism doesn't know about pop. */ |
||||
+ RTX_FRAME_RELATED_P (insn) = 1; |
||||
+ x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (UNITS_PER_WORD)); |
||||
+ x = gen_rtx_SET (VOIDmode, stack_pointer_rtx, x); |
||||
+ add_reg_note (insn, REG_FRAME_RELATED_EXPR, x); |
||||
+ m->fs.sp_offset -= UNITS_PER_WORD; |
||||
+ } |
||||
+ else |
||||
+ { |
||||
+ rtx x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset)); |
||||
+ x = gen_rtx_SET (VOIDmode, sr->reg, gen_rtx_MEM (word_mode, x)); |
||||
+ emit_insn (x); |
||||
+ } |
||||
} |
||||
} |
||||
|
||||
@@ -10212,7 +10229,7 @@ release_scratch_register_on_entry (struct scratch_reg *sr) |
||||
pushed on the stack. */ |
||||
|
||||
static void |
||||
-ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size, |
||||
+ix86_adjust_stack_and_probe_stack_clash (HOST_WIDE_INT size, |
||||
const bool int_registers_saved) |
||||
{ |
||||
struct machine_function *m = cfun->machine; |
||||
@@ -10331,6 +10348,12 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size, |
||||
struct scratch_reg sr; |
||||
get_scratch_register_on_entry (&sr); |
||||
|
||||
+ /* If we needed to save a register, then account for any space |
||||
+ that was pushed (we are not going to pop the register when |
||||
+ we do the restore). */ |
||||
+ if (sr.saved) |
||||
+ size -= UNITS_PER_WORD; |
||||
+ |
||||
/* Step 1: round SIZE down to a multiple of the interval. */ |
||||
HOST_WIDE_INT rounded_size = size & -probe_interval; |
||||
|
||||
@@ -10379,7 +10402,9 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size, |
||||
m->fs.cfa_reg == stack_pointer_rtx); |
||||
dump_stack_clash_frame_info (PROBE_LOOP, size != rounded_size); |
||||
|
||||
- release_scratch_register_on_entry (&sr); |
||||
+ /* This does not deallocate the space reserved for the scratch |
||||
+ register. That will be deallocated in the epilogue. */ |
||||
+ release_scratch_register_on_entry (&sr, size, false); |
||||
} |
||||
|
||||
/* Make sure nothing is scheduled before we are done. */ |
||||
@@ -10392,7 +10417,7 @@ ix86_adjust_stack_and_probe_stack_clash (const HOST_WIDE_INT size, |
||||
pushed on the stack. */ |
||||
|
||||
static void |
||||
-ix86_adjust_stack_and_probe (const HOST_WIDE_INT size, |
||||
+ix86_adjust_stack_and_probe (HOST_WIDE_INT size, |
||||
const bool int_registers_saved) |
||||
{ |
||||
/* We skip the probe for the first interval + a small dope of 4 words and |
||||
@@ -10465,6 +10490,11 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size, |
||||
|
||||
get_scratch_register_on_entry (&sr); |
||||
|
||||
+ /* If we needed to save a register, then account for any space |
||||
+ that was pushed (we are not going to pop the register when |
||||
+ we do the restore). */ |
||||
+ if (sr.saved) |
||||
+ size -= UNITS_PER_WORD; |
||||
|
||||
/* Step 1: round SIZE to the previous multiple of the interval. */ |
||||
|
||||
@@ -10516,7 +10546,9 @@ ix86_adjust_stack_and_probe (const HOST_WIDE_INT size, |
||||
(get_probe_interval () |
||||
+ dope)))); |
||||
|
||||
- release_scratch_register_on_entry (&sr); |
||||
+ /* This does not deallocate the space reserved for the scratch |
||||
+ register. That will be deallocated in the epilogue. */ |
||||
+ release_scratch_register_on_entry (&sr, size, false); |
||||
} |
||||
|
||||
gcc_assert (cfun->machine->fs.cfa_reg != stack_pointer_rtx); |
||||
@@ -10669,7 +10701,7 @@ ix86_emit_probe_stack_range (HOST_WIDE_INT first, HOST_WIDE_INT size, |
||||
sr.reg), |
||||
rounded_size - size)); |
||||
|
||||
- release_scratch_register_on_entry (&sr); |
||||
+ release_scratch_register_on_entry (&sr, size, true); |
||||
} |
||||
|
||||
/* Make sure nothing is scheduled before we are done. */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/pr84128.c b/gcc/testsuite/gcc.target/i386/pr84128.c |
||||
new file mode 100644 |
||||
index 0000000..a8323fd |
||||
--- /dev/null |
||||
+++ b/gcc/testsuite/gcc.target/i386/pr84128.c |
||||
@@ -0,0 +1,30 @@ |
||||
+/* { dg-do run } */ |
||||
+/* { dg-options "-O2 -march=i686 -mtune=generic -fstack-clash-protection" } */ |
||||
+/* { dg-require-effective-target ia32 } */ |
||||
+ |
||||
+__attribute__ ((noinline, noclone, weak, regparm (3))) |
||||
+int |
||||
+f1 (long arg0, int (*pf) (long, void *)) |
||||
+{ |
||||
+ unsigned char buf[32768]; |
||||
+ return pf (arg0, buf); |
||||
+} |
||||
+ |
||||
+__attribute__ ((noinline, noclone, weak)) |
||||
+int |
||||
+f2 (long arg0, void *ignored) |
||||
+{ |
||||
+ if (arg0 != 17) |
||||
+ __builtin_abort (); |
||||
+ return 19; |
||||
+} |
||||
+ |
||||
+int |
||||
+main (void) |
||||
+{ |
||||
+ if (f1 (17, f2) != 19) |
||||
+ __builtin_abort (); |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+ |
@ -0,0 +1,80 @@
@@ -0,0 +1,80 @@
|
||||
commit 5fdcac79eb72406c59fa72073dfb3ba21380f56d |
||||
Author: ktkachov <ktkachov@138bc75d-0d04-0410-961f-82ee72b054a4> |
||||
Date: Tue Apr 10 09:58:57 2018 +0000 |
||||
|
||||
[explow] PR target/85173: validize memory before passing it on to target probe_stack |
||||
|
||||
In this PR the expansion code emits an invalid memory address for the stack probe, which the backend fails to recognise. |
||||
The address is created explicitly in anti_adjust_stack_and_probe_stack_clash in explow.c and passed down to gen_probe_stack |
||||
without any validation in emit_stack_probe. |
||||
|
||||
This patch fixes the ICE by calling validize_mem on the memory location before passing it down to the target. |
||||
Jakub pointed out that we also want to create valid addresses for the probe_stack_address case, so this patch |
||||
creates an expand operand and legitimizes it before passing it down to the probe_stack_address expander. |
||||
|
||||
This patch passes bootstrap and testing on arm-none-linux-gnueabihf and aarch64-none-linux-gnu |
||||
and ppc64le-redhat-linux on gcc112 in the compile farm. |
||||
|
||||
PR target/85173 |
||||
* explow.c (emit_stack_probe): Call validize_mem on memory location |
||||
before passing it to gen_probe_stack. Create address operand and |
||||
legitimize it for the probe_stack_address case. |
||||
|
||||
* gcc.target/arm/pr85173.c: New test. |
||||
|
||||
|
||||
|
||||
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@259266 138bc75d-0d04-0410-961f-82ee72b054a4 |
||||
|
||||
diff --git a/gcc/explow.c b/gcc/explow.c |
||||
index 9386489..e2253ae 100644 |
||||
--- a/gcc/explow.c |
||||
+++ b/gcc/explow.c |
||||
@@ -1549,13 +1549,20 @@ emit_stack_probe (rtx address) |
||||
{ |
||||
#ifdef HAVE_probe_stack_address |
||||
if (HAVE_probe_stack_address) |
||||
- emit_insn (gen_probe_stack_address (address)); |
||||
+ { |
||||
+ struct expand_operand ops[1]; |
||||
+ insn_code icode = targetm.code_for_probe_stack_address; |
||||
+ create_address_operand (ops, address); |
||||
+ maybe_legitimize_operands (icode, 0, 1, ops); |
||||
+ expand_insn (icode, 1, ops); |
||||
+ } |
||||
else |
||||
#endif |
||||
{ |
||||
rtx memref = gen_rtx_MEM (word_mode, address); |
||||
|
||||
MEM_VOLATILE_P (memref) = 1; |
||||
+ memref = validize_mem (memref); |
||||
|
||||
/* See if we have an insn to probe the stack. */ |
||||
#ifdef HAVE_probe_stack |
||||
diff --git a/gcc/testsuite/gcc.target/arm/pr85173.c b/gcc/testsuite/gcc.target/arm/pr85173.c |
||||
new file mode 100644 |
||||
index 0000000..36105c9 |
||||
--- /dev/null |
||||
+++ b/gcc/testsuite/gcc.target/arm/pr85173.c |
||||
@@ -0,0 +1,20 @@ |
||||
+/* PR target/85173. */ |
||||
+ |
||||
+/* { dg-do compile } */ |
||||
+/* { dg-options "-O2 -fstack-clash-protection --param stack-clash-protection-probe-interval=14" } */ |
||||
+/* { dg-require-effective-target arm_thumb2_ok } */ |
||||
+ |
||||
+__attribute__((noinline, noclone)) void |
||||
+foo (char *p) |
||||
+{ |
||||
+ asm volatile ("" : : "r" (p) : "memory"); |
||||
+} |
||||
+ |
||||
+/* Nonconstant alloca, small local frame. */ |
||||
+__attribute__((noinline, noclone)) void |
||||
+f5 (int x) |
||||
+{ |
||||
+ char locals[128]; |
||||
+ char *vla = __builtin_alloca (x); |
||||
+ foo (vla); |
||||
+} |
@ -0,0 +1,64 @@
@@ -0,0 +1,64 @@
|
||||
commit 49033c9c57a415db02ac5d98badf5f53342bca83 |
||||
Author: krebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4> |
||||
Date: Thu Apr 12 09:14:57 2018 +0000 |
||||
|
||||
IBM Z: Spectre: Prevent thunk cfi to be emitted with -fno-dwarf2-cfi-asm |
||||
|
||||
The CFI magic we emit as part of the indirect branch thunks in order to |
||||
have somewhat sane unwind information must not be emitted with |
||||
-fno-dwarf2-cfi-asm. |
||||
|
||||
gcc/ChangeLog: |
||||
|
||||
2018-04-12 Andreas Krebbel <krebbel@linux.vnet.ibm.com> |
||||
|
||||
* config/s390/s390.c (s390_output_indirect_thunk_function): Check |
||||
also for flag_dwarf2_cfi_asm. |
||||
|
||||
gcc/testsuite/ChangeLog: |
||||
|
||||
2018-04-12 Andreas Krebbel <krebbel@linux.vnet.ibm.com> |
||||
|
||||
* gcc.target/s390/nobp-no-dwarf2-cfi.c: New test. |
||||
|
||||
|
||||
|
||||
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@259340 138bc75d-0d04-0410-961f-82ee72b054a4 |
||||
|
||||
diff -Nrup gcc/config/s390/s390.c gcc/config/s390/s390.c |
||||
--- gcc/config/s390/s390.c 2018-04-18 13:35:43.856279249 -0600 |
||||
+++ gcc/config/s390/s390.c 2018-04-18 13:36:21.037007877 -0600 |
||||
@@ -14091,7 +14091,7 @@ s390_output_indirect_thunk_function (uns |
||||
|
||||
calls: Instead of caller->thunk the backtrace will be |
||||
caller->callee->thunk */ |
||||
- if (flag_asynchronous_unwind_tables) |
||||
+ if (flag_asynchronous_unwind_tables && flag_dwarf2_cfi_asm) |
||||
{ |
||||
fputs ("\t.cfi_signal_frame\n", asm_out_file); |
||||
fprintf (asm_out_file, "\t.cfi_return_column %d\n", regno); |
||||
diff --git gcc/testsuite/gcc.target/s390/nobp-no-dwarf2-cfi.c gcc/testsuite/gcc.target/s390/nobp-no-dwarf2-cfi.c |
||||
new file mode 100644 |
||||
index 0000000..75e32a1 |
||||
--- /dev/null |
||||
+++ gcc/testsuite/gcc.target/s390/nobp-no-dwarf2-cfi.c |
||||
@@ -0,0 +1,19 @@ |
||||
+/* { dg-do run } */ |
||||
+/* { dg-options "-O3 -march=z900 --save-temps -mfunction-return-reg=thunk -mindirect-branch-table -fno-dwarf2-cfi-asm" } */ |
||||
+ |
||||
+/* Make sure that we do not emit .cfi directives when -fno-dwarf2-cfi-asm is being used. */ |
||||
+ |
||||
+int |
||||
+main () |
||||
+{ |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
+/* 1 x main |
||||
+/* { dg-final { scan-assembler-times "jg\t__s390_indirect_jump" 1 } } */ |
||||
+/* { dg-final { scan-assembler "ex\t" } } */ |
||||
+ |
||||
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_jump" } } */ |
||||
+/* { dg-final { scan-assembler-not "section\t.s390_indirect_call" } } */ |
||||
+/* { dg-final { scan-assembler "section\t.s390_return_reg" } } */ |
||||
+/* { dg-final { scan-assembler-not "section\t.s390_return_mem" } } */ |
@ -0,0 +1,414 @@
@@ -0,0 +1,414 @@
|
||||
commit 4361c221ff4b53f585a2e8c0ba38956c8132609f |
||||
Author: hjl <hjl@138bc75d-0d04-0410-961f-82ee72b054a4> |
||||
Date: Mon Feb 26 15:29:30 2018 +0000 |
||||
|
||||
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. |
||||
|
||||
Tested on i686 and x86-64. |
||||
|
||||
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/ |
||||
|
||||
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. |
||||
|
||||
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257992 138bc75d-0d04-0410-961f-82ee72b054a4 |
||||
|
||||
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h |
||||
index 4e4b2100f79..394d4aebf96 100644 |
||||
--- a/gcc/config/i386/i386-protos.h |
||||
+++ b/gcc/config/i386/i386-protos.h |
||||
@@ -306,8 +306,10 @@ extern enum attr_cpu ix86_schedule; |
||||
#endif |
||||
|
||||
extern const char * ix86_output_call_insn (rtx 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); |
||||
|
||||
#ifdef RTX_CODE |
||||
/* Target data for multipass lookahead scheduling. |
||||
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c |
||||
index c25d26ca826..a8238a001ee 100644 |
||||
--- a/gcc/config/i386/i386.c |
||||
+++ b/gcc/config/i386/i386.c |
||||
@@ -8777,6 +8777,9 @@ static bool indirect_thunk_needed = false; |
||||
by call and return thunks functions. */ |
||||
static int indirect_thunks_used; |
||||
|
||||
+/* True if return thunk function via CX is needed. */ |
||||
+static bool indirect_return_via_cx; |
||||
+ |
||||
#ifndef INDIRECT_LABEL |
||||
# define INDIRECT_LABEL "LIND" |
||||
#endif |
||||
@@ -8786,26 +8789,29 @@ static int indirect_thunks_used; |
||||
static void |
||||
indirect_thunk_name (char name[32], int regno, bool ret_p) |
||||
{ |
||||
- if (regno >= 0 && ret_p) |
||||
+ if (regno != INVALID_REGNUM && regno != CX_REG && ret_p) |
||||
gcc_unreachable (); |
||||
|
||||
if (USE_HIDDEN_LINKONCE) |
||||
{ |
||||
- if (regno >= 0) |
||||
+ const char *prefix; |
||||
+ |
||||
+ prefix = ""; |
||||
+ |
||||
+ const char *ret = ret_p ? "return" : "indirect"; |
||||
+ |
||||
+ if (regno != INVALID_REGNUM) |
||||
{ |
||||
const char *reg_prefix; |
||||
if (LEGACY_INT_REGNO_P (regno)) |
||||
reg_prefix = TARGET_64BIT ? "r" : "e"; |
||||
else |
||||
reg_prefix = ""; |
||||
- sprintf (name, "__x86_indirect_thunk_%s%s", |
||||
- reg_prefix, reg_names[regno]); |
||||
+ sprintf (name, "__x86_%s_thunk%s_%s%s", |
||||
+ ret, prefix, reg_prefix, reg_names[regno]); |
||||
} |
||||
else |
||||
- { |
||||
- const char *ret = ret_p ? "return" : "indirect"; |
||||
- sprintf (name, "__x86_%s_thunk", ret); |
||||
- } |
||||
+ sprintf (name, "__x86_%s_thunk%s", ret, prefix); |
||||
} |
||||
else |
||||
{ |
||||
@@ -8947,9 +8953,18 @@ output_indirect_thunk_function (int regno) |
||||
ASM_OUTPUT_LABEL (asm_out_file, name); |
||||
} |
||||
|
||||
- if (regno < 0) |
||||
+ /* Create alias for __x86_return_thunk or |
||||
+ __x86_return_thunk_ecx. */ |
||||
+ bool need_alias; |
||||
+ if (regno == INVALID_REGNUM) |
||||
+ need_alias = true; |
||||
+ else if (regno == CX_REG) |
||||
+ 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, true); |
||||
@@ -24704,21 +24719,21 @@ 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. */ |
||||
|
||||
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) |
||||
{ |
||||
struct ix86_frame frame; |
||||
ix86_compute_frame_layout (&frame); |
||||
|
||||
- /* 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 && frame.red_zone_size != 0) |
||||
+ /* We can't have red-zone since "call" in the indirect thunk |
||||
+ pushes the return address onto the stack, destroying the red-zone. */ |
||||
+ if (frame.red_zone_size != 0) |
||||
gcc_unreachable (); |
||||
|
||||
ix86_output_indirect_branch (call_op, "%0", true); |
||||
@@ -24759,6 +24774,75 @@ 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]; |
||||
+ enum indirect_thunk_prefix need_prefix |
||||
+ = indirect_thunk_need_prefix (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_prefix, true); |
||||
+ 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_prefix, 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; |
||||
+ |
||||
+ /* 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 (VOIDmode, stack_pointer_rtx, x); |
||||
+ add_reg_note (insn, REG_CFA_ADJUST_CFA, x); |
||||
+ add_reg_note (insn, REG_CFA_REGISTER, gen_rtx_SET (VOIDmode, ecx, pc_rtx)); |
||||
+ RTX_FRAME_RELATED_P (insn) = 1; |
||||
+ |
||||
+ x = gen_rtx_PLUS (Pmode, stack_pointer_rtx, popc); |
||||
+ x = gen_rtx_SET (VOIDmode, 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 228f8f6d77a..3320ec233d2 100644 |
||||
--- a/gcc/config/i386/i386.md |
||||
+++ b/gcc/config/i386/i386.md |
||||
@@ -11282,7 +11282,7 @@ |
||||
(define_insn "*indirect_jump" |
||||
[(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))] |
||||
"" |
||||
- "* 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)") |
||||
@@ -11336,7 +11336,7 @@ |
||||
[(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw")) |
||||
(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)") |
||||
@@ -11769,11 +11769,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") |
||||
@@ -11783,7 +11786,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,14 @@ |
||||
+/* PR target/r84530 */ |
||||
+/* { dg-do compile { target ia32 } } */ |
||||
+/* { dg-options "-O2 -mfunction-return=thunk -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\]*\.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; |
||||
+} |
@ -0,0 +1,175 @@
@@ -0,0 +1,175 @@
|
||||
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c |
||||
index a8238a001ee..34f27c597a2 100644 |
||||
--- a/gcc/config/i386/i386.c |
||||
+++ b/gcc/config/i386/i386.c |
||||
@@ -8770,13 +8770,16 @@ ix86_setup_frame_addresses (void) |
||||
labels in call and return thunks. */ |
||||
static int indirectlabelno; |
||||
|
||||
-/* True if call and return thunk functions are needed. */ |
||||
+/* True if call thunk function is needed. */ |
||||
static bool indirect_thunk_needed = false; |
||||
|
||||
/* Bit masks of integer registers, which contain branch target, used |
||||
- by call and return thunks functions. */ |
||||
+ by call thunk functions. */ |
||||
static int indirect_thunks_used; |
||||
|
||||
+/* True if return thunk function is needed. */ |
||||
+static bool indirect_return_needed = false; |
||||
+ |
||||
/* True if return thunk function via CX is needed. */ |
||||
static bool indirect_return_via_cx; |
||||
|
||||
@@ -8899,17 +8902,19 @@ output_indirect_thunk (int regno) |
||||
} |
||||
|
||||
/* Output a funtion with a call and return thunk for indirect branch. |
||||
- If REGNO != -1, the function address is in REGNO. Otherwise, the |
||||
- function address is on the top of stack. */ |
||||
+ If REGNO != UNVALID_REGNUM, |
||||
+ the function address is in REGNO. Otherwise, the function address is |
||||
+ on the top of stack. Thunk is used for function return if RET_P is |
||||
+ true. */ |
||||
|
||||
static void |
||||
-output_indirect_thunk_function (int regno) |
||||
+output_indirect_thunk_function (unsigned int regno, bool ret_p) |
||||
{ |
||||
char name[32]; |
||||
tree decl; |
||||
|
||||
/* Create __x86_indirect_thunk. */ |
||||
- indirect_thunk_name (name, regno, false); |
||||
+ indirect_thunk_name (name, regno, ret_p); |
||||
decl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL, |
||||
get_identifier (name), |
||||
build_function_type_list (void_type_node, NULL_TREE)); |
||||
@@ -8953,45 +8958,6 @@ output_indirect_thunk_function (int regno) |
||||
ASM_OUTPUT_LABEL (asm_out_file, name); |
||||
} |
||||
|
||||
- /* Create alias for __x86_return_thunk or |
||||
- __x86_return_thunk_ecx. */ |
||||
- bool need_alias; |
||||
- if (regno == INVALID_REGNUM) |
||||
- need_alias = true; |
||||
- else if (regno == CX_REG) |
||||
- need_alias = indirect_return_via_cx; |
||||
- else |
||||
- need_alias = false; |
||||
- |
||||
- if (need_alias) |
||||
- { |
||||
- char alias[32]; |
||||
- |
||||
- indirect_thunk_name (alias, regno, true); |
||||
-#if TARGET_MACHO |
||||
- if (TARGET_MACHO) |
||||
- { |
||||
- fputs ("\t.weak_definition\t", asm_out_file); |
||||
- assemble_name (asm_out_file, alias); |
||||
- fputs ("\n\t.private_extern\t", asm_out_file); |
||||
- assemble_name (asm_out_file, alias); |
||||
- putc ('\n', asm_out_file); |
||||
- ASM_OUTPUT_LABEL (asm_out_file, alias); |
||||
- } |
||||
-#else |
||||
- ASM_OUTPUT_DEF (asm_out_file, alias, name); |
||||
- if (USE_HIDDEN_LINKONCE) |
||||
- { |
||||
- fputs ("\t.globl\t", asm_out_file); |
||||
- assemble_name (asm_out_file, alias); |
||||
- putc ('\n', asm_out_file); |
||||
- fputs ("\t.hidden\t", asm_out_file); |
||||
- assemble_name (asm_out_file, alias); |
||||
- putc ('\n', asm_out_file); |
||||
- } |
||||
-#endif |
||||
- } |
||||
- |
||||
DECL_INITIAL (decl) = make_node (BLOCK); |
||||
current_function_decl = decl; |
||||
allocate_struct_function (decl, false); |
||||
@@ -9038,14 +9004,19 @@ ix86_code_end (void) |
||||
rtx xops[2]; |
||||
int regno; |
||||
|
||||
+ if (indirect_return_needed) |
||||
+ output_indirect_thunk_function (INVALID_REGNUM, true); |
||||
+ if (indirect_return_via_cx) |
||||
+ output_indirect_thunk_function (CX_REG, true); |
||||
if (indirect_thunk_needed) |
||||
- output_indirect_thunk_function (-1); |
||||
+ output_indirect_thunk_function (INVALID_REGNUM, false); |
||||
|
||||
for (regno = FIRST_REX_INT_REG; regno <= LAST_REX_INT_REG; regno++) |
||||
{ |
||||
int i = regno - FIRST_REX_INT_REG + LAST_INT_REG + 1; |
||||
if ((indirect_thunks_used & (1 << i))) |
||||
- output_indirect_thunk_function (regno); |
||||
+ output_indirect_thunk_function (regno, false); |
||||
+ |
||||
} |
||||
|
||||
for (regno = AX_REG; regno <= SP_REG; regno++) |
||||
@@ -9054,7 +9025,7 @@ ix86_code_end (void) |
||||
tree decl; |
||||
|
||||
if ((indirect_thunks_used & (1 << regno))) |
||||
- output_indirect_thunk_function (regno); |
||||
+ output_indirect_thunk_function (regno, false); |
||||
|
||||
if (!(pic_labels_used & (1 << regno))) |
||||
continue; |
||||
@@ -24758,8 +24729,8 @@ ix86_output_function_return (bool long_p) |
||||
{ |
||||
bool need_thunk = (cfun->machine->function_return_type |
||||
== indirect_branch_thunk); |
||||
- indirect_thunk_name (thunk_name, -1, true); |
||||
- indirect_thunk_needed |= need_thunk; |
||||
+ indirect_thunk_name (thunk_name, INVALID_REGNUM, true); |
||||
+ indirect_return_needed |= need_thunk; |
||||
fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name); |
||||
} |
||||
else |
||||
@@ -24783,8 +24754,6 @@ ix86_output_indirect_function_return (rtx ret_op) |
||||
if (cfun->machine->function_return_type != indirect_branch_keep) |
||||
{ |
||||
char thunk_name[32]; |
||||
- enum indirect_thunk_prefix need_prefix |
||||
- = indirect_thunk_need_prefix (current_output_insn); |
||||
unsigned int regno = REGNO (ret_op); |
||||
gcc_assert (regno == CX_REG); |
||||
|
||||
@@ -24793,7 +24762,7 @@ ix86_output_indirect_function_return (rtx ret_op) |
||||
{ |
||||
bool need_thunk = (cfun->machine->function_return_type |
||||
== indirect_branch_thunk); |
||||
- indirect_thunk_name (thunk_name, regno, need_prefix, true); |
||||
+ indirect_thunk_name (thunk_name, regno, true); |
||||
if (need_thunk) |
||||
{ |
||||
indirect_return_via_cx = true; |
||||
@@ -24802,7 +24771,7 @@ ix86_output_indirect_function_return (rtx ret_op) |
||||
fprintf (asm_out_file, "\tjmp\t%s\n", thunk_name); |
||||
} |
||||
else |
||||
- output_indirect_thunk (need_prefix, regno); |
||||
+ output_indirect_thunk (regno); |
||||
|
||||
return ""; |
||||
} |
||||
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c |
||||
index d1db41cc128..a605c26c46f 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c |
||||
@@ -13,7 +13,7 @@ foo (void) |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
-/* { dg-final { scan-assembler "__x86_indirect_thunk:" } } */ |
||||
+/* { dg-final { scan-assembler "__x86_return_thunk:" } } */ |
||||
/* { dg-final { scan-assembler-times {\tpause} 1 { target { ! x32 } } } } */ |
||||
/* { dg-final { scan-assembler-times {\tlfence} 1 { target { ! x32 } } } } */ |
||||
/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { { ! x32 } && *-*-linux* } } } } */ |
@ -0,0 +1,516 @@
@@ -0,0 +1,516 @@
|
||||
diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md |
||||
index 43faabb7e87..328a90f45d1 100644 |
||||
--- a/gcc/config/i386/constraints.md |
||||
+++ b/gcc/config/i386/constraints.md |
||||
@@ -135,7 +135,7 @@ |
||||
|
||||
(define_constraint "w" |
||||
"@internal Call memory operand." |
||||
- (and (not (match_test "ix86_indirect_branch_register")) |
||||
+ (and (not (match_test "TARGET_INDIRECT_BRANCH_REGISTER")) |
||||
(not (match_test "TARGET_X32")) |
||||
(match_operand 0 "memory_operand"))) |
||||
|
||||
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h |
||||
index 8ff702615b6..95206478001 100644 |
||||
--- a/gcc/config/i386/i386.h |
||||
+++ b/gcc/config/i386/i386.h |
||||
@@ -2413,6 +2413,10 @@ extern void debug_dispatch_window (int); |
||||
#define TARGET_RECIP_VEC_DIV ((recip_mask & RECIP_MASK_VEC_DIV) != 0) |
||||
#define TARGET_RECIP_VEC_SQRT ((recip_mask & RECIP_MASK_VEC_SQRT) != 0) |
||||
|
||||
+#define TARGET_INDIRECT_BRANCH_REGISTER \ |
||||
+ (ix86_indirect_branch_register \ |
||||
+ || cfun->machine->indirect_branch_type != indirect_branch_keep) |
||||
+ |
||||
#define IX86_HLE_ACQUIRE (1 << 16) |
||||
#define IX86_HLE_RELEASE (1 << 17) |
||||
|
||||
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md |
||||
index 3320ec233d2..7a83d079bfc 100644 |
||||
--- a/gcc/config/i386/i386.md |
||||
+++ b/gcc/config/i386/i386.md |
||||
@@ -11274,7 +11274,7 @@ |
||||
[(set (pc) (match_operand 0 "indirect_branch_operand"))] |
||||
"" |
||||
{ |
||||
- if (TARGET_X32 || ix86_indirect_branch_register) |
||||
+ if (TARGET_X32 || TARGET_INDIRECT_BRANCH_REGISTER) |
||||
operands[0] = convert_memory_address (word_mode, operands[0]); |
||||
cfun->machine->has_local_indirect_jump = true; |
||||
}) |
||||
@@ -11327,7 +11327,7 @@ |
||||
OPTAB_DIRECT); |
||||
} |
||||
|
||||
- if (TARGET_X32 || ix86_indirect_branch_register) |
||||
+ if (TARGET_X32 || TARGET_INDIRECT_BRANCH_REGISTER) |
||||
operands[0] = convert_memory_address (word_mode, operands[0]); |
||||
cfun->machine->has_local_indirect_jump = true; |
||||
}) |
||||
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md |
||||
index 6c7a593084c..f6cf50ad6f5 100644 |
||||
--- a/gcc/config/i386/predicates.md |
||||
+++ b/gcc/config/i386/predicates.md |
||||
@@ -540,7 +540,7 @@ |
||||
;; Test for a valid operand for indirect branch. |
||||
(define_predicate "indirect_branch_operand" |
||||
(ior (match_operand 0 "register_operand") |
||||
- (and (not (match_test "ix86_indirect_branch_register")) |
||||
+ (and (not (match_test "TARGET_INDIRECT_BRANCH_REGISTER")) |
||||
(not (match_test "TARGET_X32")) |
||||
(match_operand 0 "memory_operand")))) |
||||
|
||||
@@ -550,7 +550,7 @@ |
||||
(ior (match_test "constant_call_address_operand |
||||
(op, mode == VOIDmode ? mode : Pmode)") |
||||
(match_operand 0 "call_register_no_elim_operand") |
||||
- (and (not (match_test "ix86_indirect_branch_register")) |
||||
+ (and (not (match_test "TARGET_INDIRECT_BRANCH_REGISTER")) |
||||
(and (not (match_test "TARGET_X32")) |
||||
(match_operand 0 "memory_operand"))))) |
||||
|
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c |
||||
index 321db770c35..135bc73b9ce 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-1.c |
||||
@@ -14,7 +14,7 @@ male_indirect_jump (long offset) |
||||
/* Our gcc-4.8 based compiler is not as aggressive at sibcalls |
||||
where the target is in a MEM. Thus we have to scan for different |
||||
patterns here than in newer compilers. */ |
||||
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c |
||||
index d58451660f8..867df67143b 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-2.c |
||||
@@ -14,7 +14,7 @@ male_indirect_jump (long offset) |
||||
/* Our gcc-4.8 based compiler is not as aggressive at sibcalls |
||||
where the target is in a MEM. Thus we have to scan for different |
||||
patterns here than in newer compilers. */ |
||||
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c |
||||
index 9e24a385387..2c7fb52b59d 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-3.c |
||||
@@ -12,9 +12,8 @@ male_indirect_jump (long offset) |
||||
return 0; |
||||
} |
||||
|
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler {\tpause} } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c |
||||
index 127b5d94523..0d3f895009d 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-4.c |
||||
@@ -12,9 +12,8 @@ male_indirect_jump (long offset) |
||||
return 0; |
||||
} |
||||
|
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler {\tpause} } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c |
||||
index 17c2d0faf88..3c72036dbaf 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-7.c |
||||
@@ -35,9 +35,8 @@ bar (int i) |
||||
} |
||||
} |
||||
|
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */ |
||||
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler {\tpause} } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c |
||||
index cd7e8d78199..e20816781f9 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-1.c |
||||
@@ -17,7 +17,7 @@ male_indirect_jump (long offset) |
||||
/* Our gcc-4.8 based compiler is not as aggressive at sibcalls |
||||
where the target is in a MEM. Thus we have to scan for different |
||||
patterns here than in newer compilers. */ |
||||
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c |
||||
index 4dbd7a5e5d3..0f30d74ee37 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-2.c |
||||
@@ -15,7 +15,7 @@ male_indirect_jump (long offset) |
||||
/* Our gcc-4.8 based compiler is not as aggressive at sibcalls |
||||
where the target is in a MEM. Thus we have to scan for different |
||||
patterns here than in newer compilers. */ |
||||
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c |
||||
index 4aeec1833cd..89a2bac8403 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-3.c |
||||
@@ -14,10 +14,9 @@ male_indirect_jump (long offset) |
||||
return 0; |
||||
} |
||||
|
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */ |
||||
/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */ |
||||
/* { dg-final { scan-assembler {\tpause} } } */ |
||||
/* { dg-final { scan-assembler {\tlfence} } } */ |
||||
/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */ |
||||
-/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c |
||||
index ac0e5999f63..3eb83c3779a 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-4.c |
||||
@@ -13,10 +13,9 @@ male_indirect_jump (long offset) |
||||
return 0; |
||||
} |
||||
|
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */ |
||||
/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */ |
||||
/* { dg-final { scan-assembler {\tpause} } } */ |
||||
/* { dg-final { scan-assembler {\tlfence} } } */ |
||||
/* { dg-final { scan-assembler-not "__x86_indirect_thunk" } } */ |
||||
-/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c |
||||
index 573cf1ef09e..0098dd1133d 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-5.c |
||||
@@ -14,9 +14,8 @@ male_indirect_jump (long offset) |
||||
return 0; |
||||
} |
||||
|
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */ |
||||
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */ |
||||
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c |
||||
index b2b37fc6e2e..ece8de15a4b 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-6.c |
||||
@@ -13,9 +13,8 @@ male_indirect_jump (long offset) |
||||
return 0; |
||||
} |
||||
|
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */ |
||||
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */ |
||||
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c |
||||
index 4a43e199931..d53fc887dcc 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-attr-7.c |
||||
@@ -36,9 +36,8 @@ bar (int i) |
||||
} |
||||
} |
||||
|
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */ |
||||
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */ |
||||
/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c |
||||
index 72de88e04aa..1f78b07f84a 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-1.c |
||||
@@ -14,7 +14,7 @@ male_indirect_jump (long offset) |
||||
/* Our gcc-4.8 based compiler is not as aggressive at sibcalls |
||||
where the target is in a MEM. Thus we have to scan for different |
||||
patterns here than in newer compilers. */ |
||||
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */ |
||||
/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c |
||||
index d4137b38a1e..5397a5874aa 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-2.c |
||||
@@ -14,7 +14,7 @@ male_indirect_jump (long offset) |
||||
/* Our gcc-4.8 based compiler is not as aggressive at sibcalls |
||||
where the target is in a MEM. Thus we have to scan for different |
||||
patterns here than in newer compilers. */ |
||||
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */ |
||||
/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c |
||||
index d9964c25bbd..385626850a2 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-3.c |
||||
@@ -12,9 +12,8 @@ male_indirect_jump (long offset) |
||||
return 0; |
||||
} |
||||
|
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */ |
||||
+/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */ |
||||
+/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c |
||||
index d4dca4dc5fe..1ae49b137ca 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-4.c |
||||
@@ -12,9 +12,7 @@ male_indirect_jump (long offset) |
||||
return 0; |
||||
} |
||||
|
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 1 { target { ! x32 } } } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c |
||||
index aece9383697..2b9a33e93dc 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-extern-7.c |
||||
@@ -35,9 +35,8 @@ bar (int i) |
||||
} |
||||
} |
||||
|
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */ |
||||
+/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler-not {\t(lfence|pause)} } } */ |
||||
/* { dg-final { scan-assembler-not "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler-not "call\[ \t\]*\.LIND" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c |
||||
index e3cea3fa3c2..dbda34ab038 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-1.c |
||||
@@ -14,7 +14,7 @@ male_indirect_jump (long offset) |
||||
/* Our gcc-4.8 based compiler is not as aggressive at sibcalls |
||||
where the target is in a MEM. Thus we have to scan for different |
||||
patterns here than in newer compilers. */ |
||||
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler {\tpause} } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c |
||||
index 62229969c90..810824666ef 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-2.c |
||||
@@ -14,7 +14,7 @@ male_indirect_jump (long offset) |
||||
/* Our gcc-4.8 based compiler is not as aggressive at sibcalls |
||||
where the target is in a MEM. Thus we have to scan for different |
||||
patterns here than in newer compilers. */ |
||||
-/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler {\tpause} } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c |
||||
index 2eef6f35a75..4a63ebed8ab 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-3.c |
||||
@@ -12,7 +12,7 @@ male_indirect_jump (long offset) |
||||
return 0; |
||||
} |
||||
|
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */ |
||||
/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */ |
||||
/* { dg-final { scan-assembler-times {\tpause} 1 } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c |
||||
index e825a10f14c..a395ffca018 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-4.c |
||||
@@ -12,7 +12,7 @@ male_indirect_jump (long offset) |
||||
return 0; |
||||
} |
||||
|
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?dispatch" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?dispatch" { target *-*-linux* } } } */ |
||||
/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 2 } } */ |
||||
/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 2 } } */ |
||||
/* { dg-final { scan-assembler-times {\tpause} 1 } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c |
||||
index c67066cf197..ea009245a58 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-inline-7.c |
||||
@@ -35,8 +35,8 @@ bar (int i) |
||||
} |
||||
} |
||||
|
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
-/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*\.L\[0-9\]+\\(,%" { target *-*-linux* } } } */ |
||||
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%(r|e)ax" } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler {\tpause} } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c |
||||
index e6fea84a4d9..af9023af613 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-10.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-10.c |
||||
@@ -15,9 +15,6 @@ foo (void) |
||||
/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */ |
||||
/* { dg-final { scan-assembler-times {\tpause} 2 } } */ |
||||
/* { dg-final { scan-assembler-times {\tlfence} 2 } } */ |
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */ |
||||
-/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
+/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" } } */ |
||||
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c |
||||
index e239ec4542f..ba467c59b36 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-11.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-11.c |
||||
@@ -15,9 +15,6 @@ foo (void) |
||||
/* { dg-final { scan-assembler-times {\tlfence} 1 } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */ |
||||
-/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
+/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" } } */ |
||||
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c |
||||
index fa3181303c9..43e57cac2c3 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-12.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-12.c |
||||
@@ -15,8 +15,6 @@ foo (void) |
||||
/* { dg-final { scan-assembler-times {\tlfence} 1 } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "__x86_indirect_thunk:" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" { target { x32 } } } } */ |
||||
-/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
+/* { dg-final { scan-assembler "__x86_indirect_thunk_(r|e)ax:" } } */ |
||||
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c |
||||
index fd5b41fdd3f..55f156c4376 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-13.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-13.c |
||||
@@ -14,9 +14,8 @@ foo (void) |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_return_thunk" } } */ |
||||
/* { dg-final { scan-assembler-times {\tpause} 2 } } */ |
||||
/* { dg-final { scan-assembler-times {\tlfence} 2 } } */ |
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
/* { dg-final { scan-assembler-times "jmp\[ \t\]*\.LIND" 3 } } */ |
||||
/* { dg-final { scan-assembler-times "call\[ \t\]*\.LIND" 3 } } */ |
||||
/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_indirect_thunk" } } */ |
||||
-/* { dg-final { scan-assembler-not "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */ |
||||
-/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler-not "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c |
||||
index d606373ead1..1c790436a53 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-14.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-14.c |
||||
@@ -16,7 +16,6 @@ foo (void) |
||||
/* { dg-final { scan-assembler-not "jmp\[ \t\]*__x86_return_thunk" } } */ |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */ |
||||
-/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?bar" { target *-*-linux* } } } */ |
||||
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c |
||||
index 75e45e226b8..58aba319cba 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-15.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-15.c |
||||
@@ -16,7 +16,6 @@ foo (void) |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler-times {\tpause} 1 } } */ |
||||
/* { dg-final { scan-assembler-times {\tlfence} 1 } } */ |
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target x32 } } } */ |
||||
-/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?bar" { target *-*-linux* } } } */ |
||||
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */ |
||||
diff --git a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c |
||||
index a605c26c46f..eee230ca2f6 100644 |
||||
--- a/gcc/testsuite/gcc.target/i386/ret-thunk-9.c |
||||
+++ b/gcc/testsuite/gcc.target/i386/ret-thunk-9.c |
||||
@@ -14,11 +14,8 @@ foo (void) |
||||
/* { dg-final { scan-assembler "jmp\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "call\[ \t\]*\.LIND" } } */ |
||||
/* { dg-final { scan-assembler "__x86_return_thunk:" } } */ |
||||
-/* { dg-final { scan-assembler-times {\tpause} 1 { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler-times {\tlfence} 1 { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "push(?:l|q)\[ \t\]*_?bar" { target { { ! x32 } && *-*-linux* } } } } */ |
||||
-/* { dg-final { scan-assembler "jmp\[ \t\]*__x86_indirect_thunk" { target { ! x32 } } } } */ |
||||
-/* { dg-final { scan-assembler-times {\tpause} 2 { target { x32 } } } } */ |
||||
-/* { dg-final { scan-assembler-times {\tlfence} 2 { target { x32 } } } } */ |
||||
-/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" { target { x32 } } } } */ |
||||
-/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" { target x32 } } } */ |
||||
+/* { dg-final { scan-assembler "mov(?:l|q)\[ \t\]*_?bar" { target *-*-linux* } } } */ |
||||
+/* { dg-final { scan-assembler-times {\tpause} 2 } } */ |
||||
+/* { dg-final { scan-assembler-times {\tlfence} 2 } } */ |
||||
+/* { dg-final { scan-assembler "call\[ \t\]*__x86_indirect_thunk_(r|e)ax" } } */ |
||||
+/* { dg-final { scan-assembler-not "pushq\[ \t\]%rax" } } */ |
@ -0,0 +1,162 @@
@@ -0,0 +1,162 @@
|
||||
* cif-code.def: Add NEVER_EXECUTED. |
||||
* ipa-inline-analysis.c (reset_inline_summary, |
||||
compute_inline_parameters, estimate_calls_size_and_time, |
||||
inline_update_overall_summary): Track number of calls. |
||||
(never_executed_edge_p): New predicate. |
||||
* ipa-inline.c (want_inline_self_recursive_call_p): do not inline |
||||
recursively for calls that are not going to be executed. |
||||
(inline_small_functions): Do not inline never exeucted edge if callee |
||||
has too many calls. |
||||
* ipa-inline.h (inline_summary): Add num calls. |
||||
(never_executed_edge_p): New. |
||||
|
||||
--- gcc/cif-code.def (revision 257016) |
||||
+++ gcc/cif-code.def (working copy) |
||||
@@ -103,3 +103,6 @@ DEFCIFCODE(TARGET_OPTION_MISMATCH, N_("t |
||||
|
||||
/* We can't inline because of mismatched optimization levels. */ |
||||
DEFCIFCODE(OPTIMIZATION_MISMATCH, N_("optimization level attribute mismatch")) |
||||
+ |
||||
+/* We know that the call will be optimized out. */ |
||||
+DEFCIFCODE(NEVER_EXECUTED, N_("never executed")) |
||||
--- gcc/ipa-inline-analysis.c (revision 257016) |
||||
+++ gcc/ipa-inline-analysis.c (working copy) |
||||
@@ -990,6 +990,7 @@ reset_inline_summary (struct cgraph_node |
||||
info->stack_frame_offset = 0; |
||||
info->size = 0; |
||||
info->time = 0; |
||||
+ info->num_calls = 0; |
||||
info->growth = 0; |
||||
info->scc_no = 0; |
||||
if (info->loop_iterations) |
||||
@@ -2704,6 +2705,7 @@ compute_inline_parameters (struct cgraph |
||||
/* Inlining characteristics are maintained by the cgraph_mark_inline. */ |
||||
info->time = info->self_time; |
||||
info->size = info->self_size; |
||||
+ info->num_calls = 0; |
||||
info->stack_frame_offset = 0; |
||||
info->estimated_stack_size = info->estimated_self_stack_size; |
||||
#ifdef ENABLE_CHECKING |
||||
@@ -2816,7 +2818,7 @@ estimate_edge_size_and_time (struct cgra |
||||
|
||||
static void |
||||
estimate_calls_size_and_time (struct cgraph_node *node, int *size, int *time, |
||||
- inline_hints *hints, |
||||
+ inline_hints *hints, int *num, |
||||
clause_t possible_truths, |
||||
vec<tree> known_vals, |
||||
vec<tree> known_binfos, |
||||
@@ -2826,6 +2828,7 @@ estimate_calls_size_and_time (struct cgr |
||||
for (e = node->callees; e; e = e->next_callee) |
||||
{ |
||||
struct inline_edge_summary *es = inline_edge_summary (e); |
||||
+ (*num)++; |
||||
if (!es->predicate |
||||
|| evaluate_predicate (es->predicate, possible_truths)) |
||||
{ |
||||
@@ -2838,7 +2841,7 @@ estimate_calls_size_and_time (struct cgr |
||||
known_aggs, hints); |
||||
} |
||||
else |
||||
- estimate_calls_size_and_time (e->callee, size, time, hints, |
||||
+ estimate_calls_size_and_time (e->callee, size, time, hints, num, |
||||
possible_truths, |
||||
known_vals, known_binfos, |
||||
known_aggs); |
||||
@@ -2846,6 +2849,7 @@ estimate_calls_size_and_time (struct cgr |
||||
} |
||||
for (e = node->indirect_calls; e; e = e->next_callee) |
||||
{ |
||||
+ (*num)++; |
||||
struct inline_edge_summary *es = inline_edge_summary (e); |
||||
if (!es->predicate |
||||
|| evaluate_predicate (es->predicate, possible_truths)) |
||||
@@ -2936,7 +2940,8 @@ estimate_node_size_and_time (struct cgra |
||||
if (DECL_DECLARED_INLINE_P (node->symbol.decl)) |
||||
hints |= INLINE_HINT_declared_inline; |
||||
|
||||
- estimate_calls_size_and_time (node, &size, &time, &hints, possible_truths, |
||||
+ int num = 0; |
||||
+ estimate_calls_size_and_time (node, &size, &time, &hints, &num, possible_truths, |
||||
known_vals, known_binfos, known_aggs); |
||||
gcc_checking_assert (size >= 0); |
||||
gcc_checking_assert (time >= 0); |
||||
@@ -3369,13 +3374,14 @@ inline_update_overall_summary (struct cg |
||||
|
||||
info->size = 0; |
||||
info->time = 0; |
||||
+ info->num_calls = 0; |
||||
for (i = 0; vec_safe_iterate (info->entry, i, &e); i++) |
||||
{ |
||||
info->size += e->size, info->time += e->time; |
||||
if (info->time > MAX_TIME * INLINE_TIME_SCALE) |
||||
info->time = MAX_TIME * INLINE_TIME_SCALE; |
||||
} |
||||
- estimate_calls_size_and_time (node, &info->size, &info->time, NULL, |
||||
+ estimate_calls_size_and_time (node, &info->size, &info->time, NULL, &info->num_calls, |
||||
~(clause_t) (1 << predicate_false_condition), |
||||
vNULL, vNULL, vNULL); |
||||
info->time = (info->time + INLINE_TIME_SCALE / 2) / INLINE_TIME_SCALE; |
||||
@@ -3528,6 +3534,14 @@ do_estimate_edge_hints (struct cgraph_ed |
||||
return hints; |
||||
} |
||||
|
||||
+/* Return true if edge is never executed. */ |
||||
+bool |
||||
+never_executed_edge_p (struct cgraph_edge *e) |
||||
+{ |
||||
+ struct inline_edge_summary *es = inline_edge_summary (e); |
||||
+ return es->predicate && false_predicate_p (es->predicate); |
||||
+} |
||||
+ |
||||
|
||||
/* Estimate self time of the function NODE after inlining EDGE. */ |
||||
|
||||
--- gcc/ipa-inline.c (revision 257016) |
||||
+++ gcc/ipa-inline.c (working copy) |
||||
@@ -656,6 +656,11 @@ want_inline_self_recursive_call_p (struc |
||||
reason = "--param max-inline-recursive-depth exceeded."; |
||||
want_inline = false; |
||||
} |
||||
+ else if (never_executed_edge_p (edge)) |
||||
+ { |
||||
+ reason = "edge is never executed."; |
||||
+ want_inline = false; |
||||
+ } |
||||
|
||||
if (outer_node->global.inlined_to) |
||||
caller_freq = outer_node->callers->frequency; |
||||
@@ -1597,6 +1602,14 @@ inline_small_functions (void) |
||||
outer_node = where, depth++; |
||||
where = where->callers->caller; |
||||
} |
||||
+ if (never_executed_edge_p (edge) |
||||
+ && inline_summary (edge->callee)->num_calls > 30) |
||||
+ { |
||||
+ if (dump_file) |
||||
+ fprintf (dump_file, "Never executed edge\n"); |
||||
+ edge->inline_failed = CIF_NEVER_EXECUTED; |
||||
+ continue; |
||||
+ } |
||||
if (outer_node |
||||
&& !want_inline_self_recursive_call_p (edge, outer_node, |
||||
true, depth)) |
||||
--- gcc/ipa-inline.h (revision 257016) |
||||
+++ gcc/ipa-inline.h (working copy) |
||||
@@ -132,6 +132,7 @@ struct GTY(()) inline_summary |
||||
/* Estimated size of the function after inlining. */ |
||||
int time; |
||||
int size; |
||||
+ int num_calls; |
||||
|
||||
/* Conditional size/time information. The summaries are being |
||||
merged during inlining. */ |
||||
@@ -226,6 +227,7 @@ inline_hints do_estimate_edge_hints (str |
||||
void initialize_growth_caches (void); |
||||
void free_growth_caches (void); |
||||
void compute_inline_parameters (struct cgraph_node *, bool); |
||||
+bool never_executed_edge_p (struct cgraph_edge *); |
||||
|
||||
/* In ipa-inline-transform.c */ |
||||
bool inline_call (struct cgraph_edge *, bool, vec<cgraph_edge_p> *, int *, bool); |
||||
|
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
2015-09-03 Bill Schmidt <wschmidt@linux.vnet.ibm.com> |
||||
|
||||
* optabs.c (expand_binop): Don't create a broadcast vector with a |
||||
source element wider than the inner mode. |
||||
|
||||
* gcc.target/powerpc/vec-shift.c: New test. |
||||
|
||||
--- gcc/optabs.c |
||||
+++ gcc/optabs.c |
||||
@@ -1608,6 +1608,15 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1, |
||||
|
||||
if (otheroptab && optab_handler (otheroptab, mode) != CODE_FOR_nothing) |
||||
{ |
||||
+ /* The scalar may have been extended to be too wide. Truncate |
||||
+ it back to the proper size to fit in the broadcast vector. */ |
||||
+ machine_mode inner_mode = GET_MODE_INNER (mode); |
||||
+ if (!CONST_INT_P (op1) |
||||
+ && (GET_MODE_BITSIZE (inner_mode) |
||||
+ < GET_MODE_BITSIZE (GET_MODE (op1)))) |
||||
+ op1 = force_reg (inner_mode, |
||||
+ simplify_gen_unary (TRUNCATE, inner_mode, op1, |
||||
+ GET_MODE (op1))); |
||||
rtx vop1 = expand_vector_broadcast (mode, op1); |
||||
if (vop1) |
||||
{ |
||||
--- /dev/null |
||||
+++ gcc/testsuite/gcc.target/powerpc/vec-shift.c |
||||
@@ -0,0 +1,20 @@ |
||||
+/* { dg-do compile { target { powerpc*-*-* } } } */ |
||||
+/* { dg-require-effective-target powerpc_altivec_ok } */ |
||||
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ |
||||
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */ |
||||
+/* { dg-options "-mcpu=power7 -O2" } */ |
||||
+ |
||||
+/* This used to ICE. During gimplification, "i" is widened to an unsigned |
||||
+ int. We used to fail at expand time as we tried to cram an SImode item |
||||
+ into a QImode memory slot. This has been fixed to properly truncate the |
||||
+ shift amount when splatting it into a vector. */ |
||||
+ |
||||
+typedef unsigned char v16ui __attribute__((vector_size(16))); |
||||
+ |
||||
+v16ui vslb(v16ui v, unsigned char i) |
||||
+{ |
||||
+ return v << i; |
||||
+} |
||||
+ |
||||
+/* { dg-final { scan-assembler "vspltb" } } */ |
||||
+/* { dg-final { scan-assembler "vslb" } } */ |
@ -0,0 +1,263 @@
@@ -0,0 +1,263 @@
|
||||
2017-06-28 Andreas Krebbel <krebbel@linux.vnet.ibm.com> |
||||
|
||||
* config/s390/predicates.md: Use s390_rel_address_ok_p. |
||||
* config/s390/s390-protos.h: Add prototype of |
||||
s390_rel_address_ok_p. |
||||
* config/s390/s390.c (s390_got_symbol): New function. |
||||
(s390_rel_address_ok_p): New function. |
||||
(legitimize_pic_address): Use s390_rel_address_ok_p. |
||||
(s390_load_got): Use s390_got_symbol. |
||||
(s390_option_override): Issue error if |
||||
-mno-pic-data-is-text-relative is used without -fpic/-fPIC. |
||||
* config/s390/s390.h (TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE): |
||||
New macro. |
||||
* config/s390/s390.opt: New option mpic-data-is-text-relative. |
||||
|
||||
--- gcc/config/s390/predicates.md 2013-08-14 07:55:12.000000000 -0400 |
||||
+++ gcc/config/s390/predicates.md 2018-04-09 21:36:49.428209951 -0400 |
||||
@@ -116,7 +116,7 @@ |
||||
if (GET_CODE (op) == SYMBOL_REF) |
||||
return (!SYMBOL_REF_ALIGN1_P (op) |
||||
&& SYMBOL_REF_TLS_MODEL (op) == 0 |
||||
- && (!flag_pic || SYMBOL_REF_LOCAL_P (op))); |
||||
+ && s390_rel_address_ok_p (op)); |
||||
|
||||
/* Everything else must have a CONST, so strip it. */ |
||||
if (GET_CODE (op) != CONST) |
||||
@@ -141,7 +141,7 @@ |
||||
if (GET_CODE (op) == SYMBOL_REF) |
||||
return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0 |
||||
&& SYMBOL_REF_TLS_MODEL (op) == 0 |
||||
- && (!flag_pic || SYMBOL_REF_LOCAL_P (op))); |
||||
+ && s390_rel_address_ok_p (op)); |
||||
|
||||
/* Now we must have a @GOTENT offset or @PLT stub |
||||
or an @INDNTPOFF TLS offset. */ |
||||
--- gcc/config/s390/s390.c 2015-06-18 10:33:04.000000000 -0400 |
||||
+++ gcc/config/s390/s390.c 2018-04-09 21:32:43.489851529 -0400 |
||||
@@ -491,6 +491,23 @@ s390_label_align (rtx label) |
||||
return align_labels_log; |
||||
} |
||||
|
||||
+static GTY(()) rtx got_symbol; |
||||
+ |
||||
+/* Return the GOT table symbol. The symbol will be created when the |
||||
+ function is invoked for the first time. */ |
||||
+ |
||||
+static rtx |
||||
+s390_got_symbol (void) |
||||
+{ |
||||
+ if (!got_symbol) |
||||
+ { |
||||
+ got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); |
||||
+ SYMBOL_REF_FLAGS (got_symbol) = SYMBOL_FLAG_LOCAL; |
||||
+ } |
||||
+ |
||||
+ return got_symbol; |
||||
+} |
||||
+ |
||||
static enum machine_mode |
||||
s390_libgcc_cmp_return_mode (void) |
||||
{ |
||||
@@ -1863,6 +1880,9 @@ s390_option_override (void) |
||||
if (flag_prefetch_loop_arrays < 0 && HAVE_prefetch && optimize >= 3) |
||||
flag_prefetch_loop_arrays = 1; |
||||
|
||||
+ if (!s390_pic_data_is_text_relative && !flag_pic) |
||||
+ error ("-mno-pic-data-is-text-relative cannot be used without -fpic/-fPIC"); |
||||
+ |
||||
/* Use the alternative scheduling-pressure algorithm by default. */ |
||||
maybe_set_param_value (PARAM_SCHED_PRESSURE_ALGORITHM, 2, |
||||
global_options.x_param_values, |
||||
@@ -3557,6 +3577,26 @@ s390_load_address (rtx dst, rtx src) |
||||
emit_insn (gen_force_la_31 (dst, src)); |
||||
} |
||||
|
||||
+/* Return true if it ok to use SYMBOL_REF in a relative address. */ |
||||
+ |
||||
+bool |
||||
+s390_rel_address_ok_p (rtx symbol_ref) |
||||
+{ |
||||
+ tree decl; |
||||
+ |
||||
+ if (symbol_ref == s390_got_symbol () || CONSTANT_POOL_ADDRESS_P (symbol_ref)) |
||||
+ return true; |
||||
+ |
||||
+ decl = SYMBOL_REF_DECL (symbol_ref); |
||||
+ |
||||
+ if (!flag_pic || SYMBOL_REF_LOCAL_P (symbol_ref)) |
||||
+ return (s390_pic_data_is_text_relative |
||||
+ || (decl |
||||
+ && TREE_CODE (decl) == FUNCTION_DECL)); |
||||
+ |
||||
+ return false; |
||||
+} |
||||
+ |
||||
/* Return a legitimate reference for ORIG (an address) using the |
||||
register REG. If REG is 0, a new pseudo is generated. |
||||
|
||||
@@ -3594,7 +3634,7 @@ legitimize_pic_address (rtx orig, rtx re |
||||
} |
||||
|
||||
if ((GET_CODE (addr) == LABEL_REF |
||||
- || (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (addr)) |
||||
+ || (GET_CODE (addr) == SYMBOL_REF && s390_rel_address_ok_p (addr)) |
||||
|| (GET_CODE (addr) == UNSPEC && |
||||
(XINT (addr, 1) == UNSPEC_GOTENT |
||||
|| (TARGET_CPU_ZARCH && XINT (addr, 1) == UNSPEC_PLT)))) |
||||
@@ -8545,7 +8585,6 @@ restore_gprs (rtx base, int offset, int |
||||
|
||||
/* Return insn sequence to load the GOT register. */ |
||||
|
||||
-static GTY(()) rtx got_symbol; |
||||
rtx |
||||
s390_load_got (void) |
||||
{ |
||||
@@ -8557,23 +8596,17 @@ s390_load_got (void) |
||||
aren't usable. */ |
||||
rtx got_rtx = gen_rtx_REG (Pmode, 12); |
||||
|
||||
- if (!got_symbol) |
||||
- { |
||||
- got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); |
||||
- SYMBOL_REF_FLAGS (got_symbol) = SYMBOL_FLAG_LOCAL; |
||||
- } |
||||
- |
||||
start_sequence (); |
||||
|
||||
if (TARGET_CPU_ZARCH) |
||||
{ |
||||
- emit_move_insn (got_rtx, got_symbol); |
||||
+ emit_move_insn (got_rtx, s390_got_symbol ()); |
||||
} |
||||
else |
||||
{ |
||||
rtx offset; |
||||
|
||||
- offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, got_symbol), |
||||
+ offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, s390_got_symbol ()), |
||||
UNSPEC_LTREL_OFFSET); |
||||
offset = gen_rtx_CONST (Pmode, offset); |
||||
offset = force_const_mem (Pmode, offset); |
||||
--- gcc/config/s390/s390.h 2014-01-14 10:37:03.000000000 -0500 |
||||
+++ gcc/config/s390/s390.h 2018-04-09 21:21:28.076858052 -0400 |
||||
@@ -814,6 +814,10 @@ do { \ |
||||
|
||||
#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X) |
||||
|
||||
+#ifndef TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE |
||||
+#define TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE 1 |
||||
+#endif |
||||
+ |
||||
|
||||
/* Assembler file format. */ |
||||
|
||||
--- gcc/config/s390/s390.opt 2015-06-18 10:33:05.000000000 -0400 |
||||
+++ gcc/config/s390/s390.opt 2018-04-09 21:28:18.842465842 -0400 |
||||
@@ -158,6 +158,10 @@ mzarch |
||||
Target Report RejectNegative Negative(mesa) Mask(ZARCH) |
||||
z/Architecture |
||||
|
||||
+mpic-data-is-text-relative |
||||
+Target Report Var(s390_pic_data_is_text_relative) Init(TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE) |
||||
+Assume data segments are relative to text segment. |
||||
+ |
||||
mbranch-cost= |
||||
Target Report Joined RejectNegative UInteger Var(s390_branch_cost) Init(1) |
||||
Set the branch costs for conditional branch instructions. Reasonable |
||||
--- gcc/config/s390/s390-protos.h 2014-01-14 10:37:04.000000000 -0500 |
||||
+++ gcc/config/s390/s390-protos.h 2018-04-09 21:21:28.072858046 -0400 |
||||
@@ -52,6 +52,7 @@ extern bool s390_contiguous_bitmask_p (u |
||||
extern bool s390_split_ok_p (rtx, rtx, enum machine_mode, int); |
||||
extern bool s390_overlap_p (rtx, rtx, HOST_WIDE_INT); |
||||
extern bool s390_offset_p (rtx, rtx, rtx); |
||||
+extern bool s390_rel_address_ok_p (rtx); |
||||
extern int tls_symbolic_operand (rtx); |
||||
|
||||
extern bool s390_match_ccmode (rtx, enum machine_mode); |
||||
--- gcc/testsuite/gcc.target/s390/nodatarel-1.c 1969-12-31 19:00:00.000000000 -0500 |
||||
+++ gcc/testsuite/gcc.target/s390/nodatarel-1.c 2018-04-09 21:21:28.077858053 -0400 |
||||
@@ -0,0 +1,83 @@ |
||||
+/* Test -mno-pic-data-is-text-relative option. No relative addressing |
||||
+ of elements in .data and .bss are allowed with that option. */ |
||||
+ |
||||
+/* { dg-do compile } */ |
||||
+/* { dg-options "-O3 -fno-optimize-sibling-calls -fpic -mno-pic-data-is-text-relative -march=z10 -mtune=z9-109 -mzarch" } */ |
||||
+ |
||||
+static int a = 3; |
||||
+ |
||||
+/* With -mno-pic-data-is-text-relative these must be addressed via |
||||
+ GOT. */ |
||||
+ |
||||
+int __attribute__((noinline,noclone)) |
||||
+foo () |
||||
+{ |
||||
+ return a; |
||||
+} |
||||
+ |
||||
+static int __attribute__((noinline,noclone)) |
||||
+foostatic (void) |
||||
+{ |
||||
+ return a; |
||||
+} |
||||
+ |
||||
+/* Just to make a potentially modified. */ |
||||
+ |
||||
+void |
||||
+bar (int b) |
||||
+{ |
||||
+ a = b; |
||||
+} |
||||
+ |
||||
+/* { dg-final { scan-assembler-times "a@GOTENT" 3 } } */ |
||||
+ |
||||
+/* The exrl target is a label_ref which should not be affected at |
||||
+ all. */ |
||||
+ |
||||
+void |
||||
+mymemcpy (char *dst, char *src, long size) |
||||
+{ |
||||
+ __builtin_memcpy (dst, src, size); |
||||
+} |
||||
+ |
||||
+/* { dg-final { scan-assembler "exrl" } } */ |
||||
+ |
||||
+ |
||||
+/* PLT slots can still be addressed relatively. */ |
||||
+ |
||||
+int |
||||
+callfoo () |
||||
+{ |
||||
+ return foo (); |
||||
+} |
||||
+ |
||||
+/* { dg-final { scan-assembler-times "foo@PLT" 1 } } */ |
||||
+ |
||||
+ |
||||
+/* GOT entries can still be addressed relatively. */ |
||||
+ |
||||
+void * |
||||
+fooptr () |
||||
+{ |
||||
+ return &foo; |
||||
+} |
||||
+ |
||||
+/* { dg-final { scan-assembler-times "foo@GOTENT" 1 } } */ |
||||
+ |
||||
+ |
||||
+/* A static function can be addressed relatively. */ |
||||
+ |
||||
+int |
||||
+callfoostatic () |
||||
+{ |
||||
+ return foostatic (); |
||||
+} |
||||
+ |
||||
+void * |
||||
+foostaticptr () |
||||
+{ |
||||
+ return &foostatic; |
||||
+} |
||||
+ |
||||
+ |
||||
+/* { dg-final { scan-assembler-not "foostatic@" } } */ |
Loading…
Reference in new issue