diff --git a/SOURCES/gcc48-pr66840.patch b/SOURCES/gcc48-pr66840.patch new file mode 100644 index 0000000..721ee03 --- /dev/null +++ b/SOURCES/gcc48-pr66840.patch @@ -0,0 +1,16 @@ +2015-07-14 Matthias Klose + + 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 @@ + # . + + 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 \ diff --git a/SOURCES/gcc48-pr72717.patch b/SOURCES/gcc48-pr72717.patch new file mode 100644 index 0000000..0aa4d2e --- /dev/null +++ b/SOURCES/gcc48-pr72717.patch @@ -0,0 +1,87 @@ +2016-12-13 Michael Meissner + + Backport from mainline + 2016-12-07 Michael Meissner + + 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; + } diff --git a/SOURCES/gcc48-pr81395.patch b/SOURCES/gcc48-pr81395.patch new file mode 100644 index 0000000..b99fb74 --- /dev/null +++ b/SOURCES/gcc48-pr81395.patch @@ -0,0 +1,67 @@ +2017-07-18 Jonathan Wakely + + 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 ++// . ++ ++// { dg-require-fileio "" } ++ ++// PR libstdc++/81395 ++ ++#include ++#include // for std::memset ++#include // 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(); ++} diff --git a/SOURCES/gcc48-rh1537828-1.patch b/SOURCES/gcc48-rh1537828-1.patch new file mode 100644 index 0000000..45ac7eb --- /dev/null +++ b/SOURCES/gcc48-rh1537828-1.patch @@ -0,0 +1,38 @@ +2018-04-10 Segher Boessenkool + + 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)) + diff --git a/SOURCES/gcc48-rh1537828-10.patch b/SOURCES/gcc48-rh1537828-10.patch new file mode 100644 index 0000000..5097874 --- /dev/null +++ b/SOURCES/gcc48-rh1537828-10.patch @@ -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 + +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 *); + diff --git a/SOURCES/gcc48-rh1537828-2.patch b/SOURCES/gcc48-rh1537828-2.patch new file mode 100644 index 0000000..7729d2c --- /dev/null +++ b/SOURCES/gcc48-rh1537828-2.patch @@ -0,0 +1,114 @@ +commit f7765f70e0e254fd9ce4469c7281c69cd06c9467 +Author: law +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; ++} ++ diff --git a/SOURCES/gcc48-rh1537828-3.patch b/SOURCES/gcc48-rh1537828-3.patch new file mode 100644 index 0000000..4493a80 --- /dev/null +++ b/SOURCES/gcc48-rh1537828-3.patch @@ -0,0 +1,163 @@ +commit 33839c8f8aa7857cc5f22ddb3f0960999cb0dfc7 +Author: law +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); ++} ++ diff --git a/SOURCES/gcc48-rh1537828-4.patch b/SOURCES/gcc48-rh1537828-4.patch new file mode 100644 index 0000000..4750f19 --- /dev/null +++ b/SOURCES/gcc48-rh1537828-4.patch @@ -0,0 +1,182 @@ +commit 14041afe24556efd5845564aa183b6451fd9d6cc +Author: law +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; ++} ++ ++ diff --git a/SOURCES/gcc48-rh1537828-5.patch b/SOURCES/gcc48-rh1537828-5.patch new file mode 100644 index 0000000..83597ad --- /dev/null +++ b/SOURCES/gcc48-rh1537828-5.patch @@ -0,0 +1,80 @@ +commit 5fdcac79eb72406c59fa72073dfb3ba21380f56d +Author: ktkachov +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); ++} diff --git a/SOURCES/gcc48-rh1537828-6.patch b/SOURCES/gcc48-rh1537828-6.patch new file mode 100644 index 0000000..0122698 --- /dev/null +++ b/SOURCES/gcc48-rh1537828-6.patch @@ -0,0 +1,64 @@ +commit 49033c9c57a415db02ac5d98badf5f53342bca83 +Author: krebbel +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 + + * config/s390/s390.c (s390_output_indirect_thunk_function): Check + also for flag_dwarf2_cfi_asm. + + gcc/testsuite/ChangeLog: + + 2018-04-12 Andreas Krebbel + + * 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" } } */ diff --git a/SOURCES/gcc48-rh1537828-7.patch b/SOURCES/gcc48-rh1537828-7.patch new file mode 100644 index 0000000..d8bd816 --- /dev/null +++ b/SOURCES/gcc48-rh1537828-7.patch @@ -0,0 +1,414 @@ +commit 4361c221ff4b53f585a2e8c0ba38956c8132609f +Author: hjl +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; ++} diff --git a/SOURCES/gcc48-rh1537828-8.patch b/SOURCES/gcc48-rh1537828-8.patch new file mode 100644 index 0000000..4f309a7 --- /dev/null +++ b/SOURCES/gcc48-rh1537828-8.patch @@ -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* } } } } */ diff --git a/SOURCES/gcc48-rh1537828-9.patch b/SOURCES/gcc48-rh1537828-9.patch new file mode 100644 index 0000000..7d26b7e --- /dev/null +++ b/SOURCES/gcc48-rh1537828-9.patch @@ -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" } } */ diff --git a/SOURCES/gcc48-rh1546372.patch b/SOURCES/gcc48-rh1546372.patch new file mode 100644 index 0000000..7fb0c3f --- /dev/null +++ b/SOURCES/gcc48-rh1546372.patch @@ -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 known_vals, + vec 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 *, int *, bool); + diff --git a/SOURCES/gcc48-rh1546728.patch b/SOURCES/gcc48-rh1546728.patch new file mode 100644 index 0000000..e9944e5 --- /dev/null +++ b/SOURCES/gcc48-rh1546728.patch @@ -0,0 +1,48 @@ +2015-09-03 Bill Schmidt + + * 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" } } */ diff --git a/SOURCES/gcc48-rh1555397.patch b/SOURCES/gcc48-rh1555397.patch new file mode 100644 index 0000000..317859f --- /dev/null +++ b/SOURCES/gcc48-rh1555397.patch @@ -0,0 +1,263 @@ +2017-06-28 Andreas Krebbel + + * 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@" } } */ diff --git a/SPECS/gcc.spec b/SPECS/gcc.spec index 97b73d9..21365f4 100644 --- a/SPECS/gcc.spec +++ b/SPECS/gcc.spec @@ -2,7 +2,7 @@ %global SVNREV 225304 # Note, gcc_release must be integer, if you want to add suffixes to # %{release}, append them after %{gcc_release} on Release: line. -%global gcc_release 28 +%global gcc_release 36 %global _unpackaged_files_terminate_build 0 %global _performance_build 1 %global multilib_64_archs sparc64 ppc64 ppc64p7 s390x x86_64 @@ -79,7 +79,7 @@ Name: gcc %global gcc_version 4.8.5 %endif Version: 4.8.5 -Release: %{gcc_release}%{?dist}.1 +Release: %{gcc_release}%{?dist} %if "%{version}" != "%{gcc_version}" %define gcc_provides %{gcc_version}-16%{?dist} %endif @@ -262,6 +262,12 @@ Patch62: gcc48-pr80362.patch Patch63: gcc48-pr80692.patch Patch64: gcc48-pr82274.patch Patch65: gcc48-pr78416.patch +Patch66: gcc48-rh1546728.patch +Patch67: gcc48-rh1555397.patch +Patch68: gcc48-pr81395.patch +Patch69: gcc48-pr72717.patch +Patch70: gcc48-pr66840.patch +Patch71: gcc48-rh1546372.patch Patch1000: fastjar-0.97-segfault.patch Patch1001: fastjar-0.97-len1.patch @@ -299,6 +305,12 @@ Patch1320: gcc48-rh1469697-20.patch Patch1321: gcc48-rh1469697-21.patch Patch1322: gcc48-rh1469697-22.patch Patch1323: gcc48-rh1469697-23.patch +Patch1324: gcc48-rh1537828-1.patch +Patch1325: gcc48-rh1537828-2.patch +Patch1326: gcc48-rh1537828-3.patch +Patch1327: gcc48-rh1537828-4.patch +Patch1328: gcc48-rh1537828-5.patch +Patch1329: gcc48-rh1537828-10.patch Patch1401: gcc48-rh1535655-1.patch Patch1402: gcc48-rh1535655-2.patch @@ -307,6 +319,10 @@ Patch1404: gcc48-rh1535655-4.patch Patch1405: gcc48-rh1535655-5.patch Patch1406: gcc48-rh1535655-6.patch Patch1407: gcc48-rh1552021.patch +Patch1408: gcc48-rh1537828-6.patch +Patch1409: gcc48-rh1537828-7.patch +Patch1410: gcc48-rh1537828-8.patch +Patch1411: gcc48-rh1537828-9.patch # On ARM EABI systems, we do want -gnueabi to be part of the # target triple. @@ -1037,6 +1053,12 @@ touch -r %{PATCH27} libstdc++-v3/python/libstdcxx/v6/printers.py %patch63 -p0 -b .pr80692~ %patch64 -p0 -b .pr82274~ %patch65 -p0 -b .pr78416~ +%patch66 -p0 -b .rh1546728~ +%patch67 -p0 -b .rh1555397~ +%patch68 -p0 -b .pr81395~ +%patch69 -p0 -b .pr72717~ +%patch70 -p0 -b .pr66840~ +%patch71 -p0 -b .rh1546372~ %if 0%{?_enable_debug_packages} cat > split-debuginfo.sh <<\EOF @@ -1130,6 +1152,12 @@ tar xjf %{SOURCE10} %patch1321 -p1 -b .stack-clash-21~ %patch1322 -p1 -b .stack-clash-22~ %patch1323 -p1 -b .stack-clash-23~ +%patch1324 -p1 -b .stack-clash-24~ +%patch1325 -p1 -b .stack-clash-25~ +%patch1326 -p1 -b .stack-clash-26~ +%patch1327 -p1 -b .stack-clash-27~ +%patch1328 -p1 -b .stack-clash-28~ +%patch1329 -p1 -b .stack-clash-29~ %patch1401 -p1 -b .retpolines-1~ %patch1402 -p1 -b .retpolines-2~ @@ -1138,6 +1166,10 @@ tar xjf %{SOURCE10} %patch1405 -p1 -b .retpolines-5~ %patch1406 -p1 -b .retpolines-6~ %patch1407 -p0 -b .retpolines-7~ +%patch1408 -p0 -b .retpolines-8~ +%patch1409 -p1 -b .retpolines-9~ +%patch1410 -p1 -b .retpolines-10~ +%patch1411 -p1 -b .retpolines-11~ sed -i -e 's/4\.8\.5/4.8.5/' gcc/BASE-VER @@ -3516,6 +3548,33 @@ fi %{_prefix}/libexec/gcc/%{gcc_target_platform}/%{gcc_version}/plugin %changelog +* Tue Jun 12 2018 Marek Polacek 4.8.5-36 +- back out the last change + +* Tue Jun 5 2018 Marek Polacek 4.8.5-35 +- adjust C++11 signatures to take a const_iterator (#1575888) + +* Thu Apr 26 2018 Marek Polacek 4.8.5-34 +- fix infinite looping in -fipa-cp-clone (#1546372) +- don't look for vsld gcc.target/powerpc/pr72717.c + +* Wed Apr 25 2018 Jeff Law 4.8.5-33 +- Fix two minor problems with the backported spectre updates + from upstream. (#1537828) + +* Thu Apr 19 2018 Jeff Law 4.8.5-32 +- Backport various stack-clash and spectre fixes from upstream +(#1537828) + +* Tue Apr 10 2018 Marek Polacek 4.8.5-31 +- backport s390 -mpic-data-is-text-relative feature (#1555397) +- fix crash when write follows large read (#1463706) +- fix emit_move_insn ICE (#1565536) +- add missing rs6000-cpus.def (#1512202) + +* Wed Apr 4 2018 Marek Polacek 4.8.5-30 +- fix ICE when generating a vector shift by scalar (#1546728) + * Tue Mar 27 2018 Jeff Law 4.8.5-29 - s390 retpoline support for spectre mitigation (#1552021)