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@" } } */