diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md index 15093cb4b30dfda3a568b5c935412ed8019fb390..99c343aa32c5bf5eeb7479f333793f99ce9d0d93 100644 --- a/gcc/config/s390/predicates.md +++ b/gcc/config/s390/predicates.md @@ -101,10 +101,13 @@ (define_special_predicate "bras_sym_operand" (ior (and (match_code "symbol_ref") - (match_test "!flag_pic || SYMBOL_REF_LOCAL_P (op)")) + (ior (match_test "!flag_pic") + (match_test "SYMBOL_REF_LOCAL_P (op)") + (and (match_test "TARGET_64BIT") + (match_test "SYMBOL_REF_FUNCTION_P (op)")))) (and (match_code "const") (and (match_test "GET_CODE (XEXP (op, 0)) == UNSPEC") - (match_test "XINT (XEXP (op, 0), 1) == UNSPEC_PLT"))))) + (match_test "XINT (XEXP (op, 0), 1) == UNSPEC_PLT31"))))) ;; Return true if OP is a PLUS that is not a legitimate ;; operand for the LA instruction. @@ -197,7 +200,7 @@ && XINT (op, 1) == UNSPEC_GOTENT) return true; if (GET_CODE (op) == UNSPEC - && XINT (op, 1) == UNSPEC_PLT) + && XINT (op, 1) == UNSPEC_PLT31) return true; if (GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_INDNTPOFF) diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 800e0abc016bfa93c69c53dd8c34e211c10af72c..b1d3b99784de5be41175e13fb757bb23b8e8ba02 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -3291,7 +3291,7 @@ s390_loadrelative_operand_p (rtx addr, rtx *symref, HOST_WIDE_INT *addend) if (GET_CODE (addr) == SYMBOL_REF || (GET_CODE (addr) == UNSPEC && (XINT (addr, 1) == UNSPEC_GOTENT - || XINT (addr, 1) == UNSPEC_PLT))) + || XINT (addr, 1) == UNSPEC_PLT31))) { if (symref) *symref = addr; @@ -4964,7 +4964,7 @@ legitimize_pic_address (rtx orig, rtx reg) || (SYMBOL_REF_P (addr) && s390_rel_address_ok_p (addr)) || (GET_CODE (addr) == UNSPEC && (XINT (addr, 1) == UNSPEC_GOTENT - || XINT (addr, 1) == UNSPEC_PLT))) + || XINT (addr, 1) == UNSPEC_PLT31))) && GET_CODE (addend) == CONST_INT) { /* This can be locally addressed. */ @@ -5125,7 +5125,7 @@ legitimize_pic_address (rtx orig, rtx reg) /* For @PLT larl is used. This is handled like local symbol refs. */ - case UNSPEC_PLT: + case UNSPEC_PLT31: gcc_unreachable (); break; @@ -5191,7 +5191,10 @@ s390_emit_tls_call_insn (rtx result_reg, rtx tls_call) emit_insn (s390_load_got ()); if (!s390_tls_symbol) - s390_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_offset"); + { + s390_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_offset"); + SYMBOL_REF_FLAGS (s390_tls_symbol) |= SYMBOL_FLAG_FUNCTION; + } insn = s390_emit_call (s390_tls_symbol, tls_call, result_reg, gen_rtx_REG (Pmode, RETURN_REGNUM)); @@ -7596,7 +7599,7 @@ s390_delegitimize_address (rtx orig_x) y = XEXP (x, 0); if (GET_CODE (y) == UNSPEC && (XINT (y, 1) == UNSPEC_GOTENT - || XINT (y, 1) == UNSPEC_PLT)) + || XINT (y, 1) == UNSPEC_PLT31)) y = XVECEXP (y, 0, 0); else return orig_x; @@ -7849,7 +7852,7 @@ s390_output_addr_const_extra (FILE *file, rtx x) output_addr_const (file, XVECEXP (x, 0, 0)); fprintf (file, "@GOTOFF"); return true; - case UNSPEC_PLT: + case UNSPEC_PLT31: output_addr_const (file, XVECEXP (x, 0, 0)); fprintf (file, "@PLT"); return true; @@ -7943,6 +7946,7 @@ print_operand_address (FILE *file, rtx addr) 'E': print opcode suffix for branch on index instruction. 'G': print the size of the operand in bytes. 'J': print tls_load/tls_gdcall/tls_ldcall suffix + 'K': print @PLT suffix for call targets and load address values. 'M': print the second word of a TImode operand. 'N': print the second word of a DImode operand. 'O': print only the displacement of a memory reference or address. @@ -8129,6 +8133,29 @@ print_operand (FILE *file, rtx x, int code) case 'Y': print_shift_count_operand (file, x); return; + + case 'K': + /* Append @PLT to both local and non-local symbols in order to support + Linux Kernel livepatching: patches contain individual functions and + are loaded further than 2G away from vmlinux, and therefore they must + call even static functions via PLT. ld will optimize @PLT away for + normal code, and keep it for patches. + + Do not indiscriminately add @PLT in 31-bit mode due to the %r12 + restriction, use UNSPEC_PLT31 instead. + + @PLT only makes sense for functions, data is taken care of by + -mno-pic-data-is-text-relative. + + Adding @PLT interferes with handling of weak symbols in non-PIC code, + since their addresses are loaded with larl, which then always produces + a non-NULL result, so skip them here as well. */ + if (TARGET_64BIT + && GET_CODE (x) == SYMBOL_REF + && SYMBOL_REF_FUNCTION_P (x) + && !(SYMBOL_REF_WEAK (x) && !flag_pic)) + fprintf (file, "@PLT"); + return; } switch (GET_CODE (x)) @@ -13125,9 +13152,10 @@ s390_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) op[3] = GEN_INT (UNITS_PER_LONG); op[2] = gen_rtx_SYMBOL_REF (Pmode, flag_fentry ? "__fentry__" : "_mcount"); - if (flag_pic) + SYMBOL_REF_FLAGS (op[2]) |= SYMBOL_FLAG_FUNCTION; + if (flag_pic && !TARGET_64BIT) { - op[2] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[2]), UNSPEC_PLT); + op[2] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[2]), UNSPEC_PLT31); op[2] = gen_rtx_CONST (Pmode, op[2]); } @@ -13142,7 +13170,7 @@ s390_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) warning (OPT_Wcannot_profile, "nested functions cannot be profiled " "with %<-mfentry%> on s390"); else - output_asm_insn ("brasl\t0,%2", op); + output_asm_insn ("brasl\t0,%2%K2", op); } else if (TARGET_64BIT) { @@ -13154,7 +13182,7 @@ s390_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) output_asm_insn ("stg\t%0,%1", op); if (flag_dwarf2_cfi_asm) output_asm_insn (".cfi_rel_offset\t%0,%3", op); - output_asm_insn ("brasl\t%0,%2", op); + output_asm_insn ("brasl\t%0,%2%K2", op); output_asm_insn ("lg\t%0,%1", op); if (flag_dwarf2_cfi_asm) output_asm_insn (".cfi_restore\t%0", op); @@ -13170,7 +13198,7 @@ s390_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) output_asm_insn ("st\t%0,%1", op); if (flag_dwarf2_cfi_asm) output_asm_insn (".cfi_rel_offset\t%0,%3", op); - output_asm_insn ("brasl\t%0,%2", op); + output_asm_insn ("brasl\t%0,%2%K2", op); output_asm_insn ("l\t%0,%1", op); if (flag_dwarf2_cfi_asm) output_asm_insn (".cfi_restore\t%0", op); @@ -13246,9 +13274,11 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, if (flag_pic && !SYMBOL_REF_LOCAL_P (op[0])) { nonlocal = 1; - op[0] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[0]), - TARGET_64BIT ? UNSPEC_PLT : UNSPEC_GOT); - op[0] = gen_rtx_CONST (Pmode, op[0]); + if (!TARGET_64BIT) + { + op[0] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[0]), UNSPEC_GOT); + op[0] = gen_rtx_CONST (Pmode, op[0]); + } } /* Operand 1 is the 'this' pointer. */ @@ -13338,7 +13368,7 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, } /* Jump to target. */ - output_asm_insn ("jg\t%0", op); + output_asm_insn ("jg\t%0%K0", op); /* Output literal pool if required. */ if (op[5]) @@ -13729,7 +13759,7 @@ rtx_insn * s390_emit_call (rtx addr_location, rtx tls_call, rtx result_reg, rtx retaddr_reg) { - bool plt_call = false; + bool plt31_call_p = false; rtx_insn *insn; rtx vec[4] = { NULL_RTX }; int elts = 0; @@ -13744,15 +13774,15 @@ s390_emit_call (rtx addr_location, rtx tls_call, rtx result_reg, { /* When calling a global routine in PIC mode, we must replace the symbol itself with the PLT stub. */ - if (flag_pic && !SYMBOL_REF_LOCAL_P (addr_location)) + if (flag_pic && !SYMBOL_REF_LOCAL_P (addr_location) && !TARGET_64BIT) { - if (TARGET_64BIT || retaddr_reg != NULL_RTX) + if (retaddr_reg != NULL_RTX) { addr_location = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr_location), - UNSPEC_PLT); + UNSPEC_PLT31); addr_location = gen_rtx_CONST (Pmode, addr_location); - plt_call = true; + plt31_call_p = true; } else /* For -fpic code the PLT entries might use r12 which is @@ -13773,7 +13803,7 @@ s390_emit_call (rtx addr_location, rtx tls_call, rtx result_reg, register 1. */ if (retaddr_reg == NULL_RTX && GET_CODE (addr_location) != SYMBOL_REF - && !plt_call) + && !plt31_call_p) { emit_move_insn (gen_rtx_REG (Pmode, SIBCALL_REGNUM), addr_location); addr_location = gen_rtx_REG (Pmode, SIBCALL_REGNUM); @@ -13781,7 +13811,7 @@ s390_emit_call (rtx addr_location, rtx tls_call, rtx result_reg, if (TARGET_INDIRECT_BRANCH_NOBP_CALL && GET_CODE (addr_location) != SYMBOL_REF - && !plt_call) + && !plt31_call_p) { /* Indirect branch thunks require the target to be a single GPR. */ addr_location = force_reg (Pmode, addr_location); @@ -13833,7 +13863,7 @@ s390_emit_call (rtx addr_location, rtx tls_call, rtx result_reg, insn = emit_call_insn (*call); /* 31-bit PLT stubs and tls calls use the GOT register implicitly. */ - if ((!TARGET_64BIT && plt_call) || tls_call != NULL_RTX) + if (plt31_call_p || tls_call != NULL_RTX) { /* s390_function_ok_for_sibcall should have denied sibcalls in this case. */ @@ -13889,7 +13919,10 @@ s390_emit_tpf_eh_return (rtx target) rtx reg, orig_ra; if (!s390_tpf_eh_return_symbol) - s390_tpf_eh_return_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tpf_eh_return"); + { + s390_tpf_eh_return_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tpf_eh_return"); + SYMBOL_REF_FLAGS (s390_tpf_eh_return_symbol) |= SYMBOL_FLAG_FUNCTION; + } reg = gen_rtx_REG (Pmode, 2); orig_ra = gen_rtx_REG (Pmode, 3); diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 0c5b4dc90293da99ba389e03da555184b5edea56..8ad21b0f4f70080b54a47cfd4663bd4d632bdcbf 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -79,7 +79,7 @@ UNSPEC_GOTENT UNSPEC_GOT UNSPEC_GOTOFF - UNSPEC_PLT + UNSPEC_PLT31 UNSPEC_PLTOFF ; Literal pool @@ -1906,7 +1906,7 @@ vlgvg\t%0,%v1,0 vleg\t%v0,%1,0 vsteg\t%v1,%0,0 - larl\t%0,%1" + larl\t%0,%1%K1" [(set_attr "op_type" "RI,RI,RI,RI,RI,RIL,RIL,RIL,RRE,RRE,RRE,RXY,RIL,RRE,RXY, RXY,RR,RX,RXY,RX,RXY,RIL,SIL,*,*,RS,RS,VRI,VRR,VRS,VRS, VRX,VRX,RIL") @@ -2180,7 +2180,7 @@ (match_operand:SI 1 "larl_operand" "X"))] "!TARGET_64BIT && !FP_REG_P (operands[0])" - "larl\t%0,%1" + "larl\t%0,%1%K1" [(set_attr "op_type" "RIL") (set_attr "type" "larl") (set_attr "z10prop" "z10_fwd_A1") @@ -10373,7 +10373,7 @@ [(call (mem:QI (match_operand 0 "bras_sym_operand" "X")) (match_operand 1 "const_int_operand" "n"))] "SIBLING_CALL_P (insn) && TARGET_SMALL_EXEC" - "j\t%0" + "j\t%0%K0" [(set_attr "op_type" "RI") (set_attr "type" "branch")]) @@ -10381,7 +10381,7 @@ [(call (mem:QI (match_operand 0 "bras_sym_operand" "X")) (match_operand 1 "const_int_operand" "n"))] "SIBLING_CALL_P (insn)" - "jg\t%0" + "jg\t%0%K0" [(set_attr "op_type" "RIL") (set_attr "type" "branch")]) @@ -10434,7 +10434,7 @@ (call (mem:QI (match_operand 1 "bras_sym_operand" "X")) (match_operand 2 "const_int_operand" "n")))] "SIBLING_CALL_P (insn) && TARGET_SMALL_EXEC" - "j\t%1" + "j\t%1%K1" [(set_attr "op_type" "RI") (set_attr "type" "branch")]) @@ -10443,7 +10443,7 @@ (call (mem:QI (match_operand 1 "bras_sym_operand" "X")) (match_operand 2 "const_int_operand" "n")))] "SIBLING_CALL_P (insn)" - "jg\t%1" + "jg\t%1%K1" [(set_attr "op_type" "RIL") (set_attr "type" "branch")]) @@ -10470,7 +10470,7 @@ "!SIBLING_CALL_P (insn) && TARGET_SMALL_EXEC && GET_MODE (operands[2]) == Pmode" - "bras\t%2,%0" + "bras\t%2,%0%K0" [(set_attr "op_type" "RI") (set_attr "type" "jsr") (set_attr "z196prop" "z196_cracked")]) @@ -10482,7 +10482,7 @@ "!SIBLING_CALL_P (insn) && GET_MODE (operands[2]) == Pmode" - "brasl\t%2,%0" + "brasl\t%2,%0%K0" [(set_attr "op_type" "RIL") (set_attr "type" "jsr") (set_attr "z196prop" "z196_cracked") @@ -10576,7 +10576,7 @@ "!SIBLING_CALL_P (insn) && TARGET_SMALL_EXEC && GET_MODE (operands[3]) == Pmode" - "bras\t%3,%1" + "bras\t%3,%1%K1" [(set_attr "op_type" "RI") (set_attr "type" "jsr") (set_attr "z196prop" "z196_cracked")]) @@ -10589,7 +10589,7 @@ "!SIBLING_CALL_P (insn) && GET_MODE (operands[3]) == Pmode" - "brasl\t%3,%1" + "brasl\t%3,%1%K1" [(set_attr "op_type" "RIL") (set_attr "type" "jsr") (set_attr "z196prop" "z196_cracked") @@ -10720,7 +10720,7 @@ "!SIBLING_CALL_P (insn) && TARGET_SMALL_EXEC && GET_MODE (operands[3]) == Pmode" - "bras\t%3,%1%J4" + "bras\t%3,%1%K1%J4" [(set_attr "op_type" "RI") (set_attr "type" "jsr") (set_attr "z196prop" "z196_cracked")]) @@ -10734,7 +10734,7 @@ "!SIBLING_CALL_P (insn) && GET_MODE (operands[3]) == Pmode" - "brasl\t%3,%1%J4" + "brasl\t%3,%1%K1%J4" [(set_attr "op_type" "RIL") (set_attr "type" "jsr") (set_attr "z196prop" "z196_cracked") @@ -11343,7 +11343,7 @@ [(set (match_operand 0 "register_operand" "=a") (unspec [(label_ref (match_operand 1 "" ""))] UNSPEC_MAIN_BASE))] "GET_MODE (operands[0]) == Pmode" - "larl\t%0,%1" + "larl\t%0,%1%K1" [(set_attr "op_type" "RIL") (set_attr "type" "larl") (set_attr "z10prop" "z10_fwd_A1") @@ -11363,7 +11363,7 @@ [(set (match_operand 0 "register_operand" "=a") (unspec [(label_ref (match_operand 1 "" ""))] UNSPEC_RELOAD_BASE))] "GET_MODE (operands[0]) == Pmode" - "larl\t%0,%1" + "larl\t%0,%1%K1" [(set_attr "op_type" "RIL") (set_attr "type" "larl") (set_attr "z10prop" "z10_fwd_A1")]) @@ -12220,7 +12220,7 @@ "" { s390_output_split_stack_data (operands[1], operands[2], operands[3], operands[4]); - return "jg\t%0"; + return "jg\t%0%K0"; } [(set_attr "op_type" "RIL") (set_attr "type" "branch")]) diff --git a/gcc/testsuite/g++.dg/ext/visibility/noPLT.C b/gcc/testsuite/g++.dg/ext/visibility/noPLT.C index 38af05fd6e355724155f4d92b3e2e2b77f4e7f31..b888303d56dab23665aa0a36a4eb294129f7cbd6 100644 --- a/gcc/testsuite/g++.dg/ext/visibility/noPLT.C +++ b/gcc/testsuite/g++.dg/ext/visibility/noPLT.C @@ -1,5 +1,5 @@ /* Test that -fvisibility=hidden prevents PLT. */ -/* { dg-do compile { target fpic } } */ +/* { dg-do compile { target { fpic && { ! s390x-*-* } } } } */ /* { dg-require-visibility "" } */ /* { dg-options "-fPIC -fvisibility=hidden" } */ /* { dg-final { scan-assembler-not "methodEv@PLT|indirect_symbol.*methodEv" } } */ diff --git a/gcc/testsuite/g++.target/s390/mi-thunk.C b/gcc/testsuite/g++.target/s390/mi-thunk.C new file mode 100644 index 0000000000000000000000000000000000000000..7c25dc04bba5e22196ff3dd5a8ef458993ff92ed --- /dev/null +++ b/gcc/testsuite/g++.target/s390/mi-thunk.C @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O0 -fPIC" } */ + +class A { +public: + virtual int a (void); +}; + +class B { +public: + virtual int b (void); +}; + +class C : public B, public A { +public: + virtual int a (void); +}; + +int C::a (void) { return b(); } + +/* { dg-final { scan-assembler {\n_ZThn8_N1C1aEv:\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {\n_ZThn4_N1C1aEv:\n} { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler {\n\tjg\t.LTHUNK0@PLT\n} { target lp64 } } } */ diff --git a/gcc/testsuite/gcc.target/s390/call-z10-pic-nodatarel.c b/gcc/testsuite/gcc.target/s390/call-z10-pic-nodatarel.c new file mode 100644 index 0000000000000000000000000000000000000000..49984614bc6f718ada64283c41a96ffe13a82575 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/call-z10-pic-nodatarel.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=z10 -mzarch -fPIC -mno-pic-data-is-text-relative" } */ + +#include "call.h" + +/* { dg-final { scan-assembler {brasl\t%r\d+,foo@PLT\n} } } */ +/* { dg-final { scan-assembler {lgrl\t%r2,foo@GOTENT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {lrl\t%r2,foo@GOTENT\n} { target { ! lp64 } } } } */ + +/* { dg-final { scan-assembler {brasl\t%r\d+,foostatic@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {brasl\t%r\d+,foostatic\n} { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foostatic@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foostatic\n} { target { ! lp64 } } } } */ + +/* { dg-final { scan-assembler {brasl\t%r\d+,fooweak@PLT\n} } } */ +/* { dg-final { scan-assembler {lgrl\t%r2,fooweak@GOTENT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {lrl\t%r2,fooweak@GOTENT\n} { target { ! lp64 } } } } */ + +/* { dg-final { scan-assembler {foos:\n\t.quad\tfoo\n\t.quad\tfoostatic\n\t.quad\tfooweak\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {foos:\n\t.long\tfoo\n\t.long\tfoostatic\n\t.long\tfooweak\n} { target { ! lp64 } } } } */ diff --git a/gcc/testsuite/gcc.target/s390/call-z10-pic.c b/gcc/testsuite/gcc.target/s390/call-z10-pic.c new file mode 100644 index 0000000000000000000000000000000000000000..210c56cc4cad0a30539948cbc8c4281232306459 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/call-z10-pic.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=z10 -mzarch -fPIC" } */ + +#include "call.h" + +/* { dg-final { scan-assembler {brasl\t%r\d+,foo@PLT\n} } } */ +/* { dg-final { scan-assembler {lgrl\t%r2,foo@GOTENT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {lrl\t%r2,foo@GOTENT\n} { target { ! lp64 } } } } */ + +/* { dg-final { scan-assembler {brasl\t%r\d+,foostatic@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {brasl\t%r\d+,foostatic\n} { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foostatic@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foostatic\n} { target { ! lp64 } } } } */ + +/* { dg-final { scan-assembler {brasl\t%r\d+,fooweak@PLT\n} } } */ +/* { dg-final { scan-assembler {lgrl\t%r2,fooweak@GOTENT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {lrl\t%r2,fooweak@GOTENT\n} { target { ! lp64 } } } } */ + +/* { dg-final { scan-assembler {foos:\n\t.quad\tfoo\n\t.quad\tfoostatic\n\t.quad\tfooweak\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {foos:\n\t.long\tfoo\n\t.long\tfoostatic\n\t.long\tfooweak\n} { target { ! lp64 } } } } */ diff --git a/gcc/testsuite/gcc.target/s390/call-z10.c b/gcc/testsuite/gcc.target/s390/call-z10.c new file mode 100644 index 0000000000000000000000000000000000000000..2d7dc735df4aa39338b25d89d7179c41935b9c00 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/call-z10.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=z10 -mzarch" } */ + +#include "call.h" + +/* { dg-final { scan-assembler {brasl\t%r\d+,foo@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {brasl\t%r\d+,foo\n} { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foo@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foo\n} { target { ! lp64 } } } } */ + +/* { dg-final { scan-assembler {brasl\t%r\d+,foostatic@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {brasl\t%r\d+,foostatic\n} { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foostatic@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foostatic\n} { target { ! lp64 } } } } */ + +/* { dg-final { scan-assembler {brasl\t%r\d+,fooweak\n} } } */ +/* { dg-final { scan-assembler {larl\t%r2,fooweak\n} } } */ + +/* { dg-final { scan-assembler {foos:\n\t.quad\tfoo\n\t.quad\tfoostatic\n\t.quad\tfooweak\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {foos:\n\t.long\tfoo\n\t.long\tfoostatic\n\t.long\tfooweak\n} { target { ! lp64 } } } } */ diff --git a/gcc/testsuite/gcc.target/s390/call-z9-pic-nodatarel.c b/gcc/testsuite/gcc.target/s390/call-z9-pic-nodatarel.c new file mode 100644 index 0000000000000000000000000000000000000000..b1ae318d3e99427f6fc254c7847466dbb5833242 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/call-z9-pic-nodatarel.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=z9-ec -fPIC -mno-pic-data-is-text-relative" } */ + +#include "call.h" + +/* { dg-final { scan-assembler {brasl\t%r\d+,foo@PLT\n} } } */ +/* { dg-final { scan-assembler {larl\t%r\d+,foo@GOTENT\n} } } */ + +/* { dg-final { scan-assembler {brasl\t%r\d+,foostatic@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {brasl\t%r\d+,foostatic\n} { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foostatic@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foostatic\n} { target { ! lp64 } } } } */ + +/* { dg-final { scan-assembler {brasl\t%r\d+,fooweak@PLT\n} } } */ +/* { dg-final { scan-assembler {larl\t%r\d+,fooweak@GOTENT\n} } } */ + +/* { dg-final { scan-assembler {foos:\n\t.quad\tfoo\n\t.quad\tfoostatic\n\t.quad\tfooweak\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {foos:\n\t.long\tfoo\n\t.long\tfoostatic\n\t.long\tfooweak\n} { target { ! lp64 } } } } */ diff --git a/gcc/testsuite/gcc.target/s390/call-z9-pic.c b/gcc/testsuite/gcc.target/s390/call-z9-pic.c new file mode 100644 index 0000000000000000000000000000000000000000..a89e78d8df8e5a356c2d163ac003b58e633cf0ea --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/call-z9-pic.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=z9-ec -fPIC" } */ + +#include "call.h" + +/* { dg-final { scan-assembler {brasl\t%r\d+,foo@PLT\n} } } */ +/* { dg-final { scan-assembler {larl\t%r\d+,foo@GOTENT\n} } } */ + +/* { dg-final { scan-assembler {brasl\t%r\d+,foostatic@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {brasl\t%r\d+,foostatic\n} { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foostatic@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foostatic\n} { target { ! lp64 } } } } */ + +/* { dg-final { scan-assembler {brasl\t%r\d+,fooweak@PLT\n} } } */ +/* { dg-final { scan-assembler {larl\t%r\d+,fooweak@GOTENT\n} } } */ + +/* { dg-final { scan-assembler {foos:\n\t.quad\tfoo\n\t.quad\tfoostatic\n\t.quad\tfooweak\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {foos:\n\t.long\tfoo\n\t.long\tfoostatic\n\t.long\tfooweak\n} { target { ! lp64 } } } } */ diff --git a/gcc/testsuite/gcc.target/s390/call-z9.c b/gcc/testsuite/gcc.target/s390/call-z9.c new file mode 100644 index 0000000000000000000000000000000000000000..21d035aecb6b065af2cc7398a41a02b53c91fc4f --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/call-z9.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -march=z9-ec" } */ + +#include "call.h" + +/* { dg-final { scan-assembler {brasl\t%r\d+,foo@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {brasl\t%r\d+,foo\n} { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foo@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foo\n} { target { ! lp64 } } } } */ + +/* { dg-final { scan-assembler {brasl\t%r\d+,foostatic@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {brasl\t%r\d+,foostatic\n} { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foostatic@PLT\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {larl\t%r2,foostatic\n} { target { ! lp64 } } } } */ + +/* { dg-final { scan-assembler {brasl\t%r\d+,fooweak\n} } } */ +/* { dg-final { scan-assembler {larl\t%r2,fooweak\n} } } */ + +/* { dg-final { scan-assembler {foos:\n\t.quad\tfoo\n\t.quad\tfoostatic\n\t.quad\tfooweak\n} { target lp64 } } } */ +/* { dg-final { scan-assembler {foos:\n\t.long\tfoo\n\t.long\tfoostatic\n\t.long\tfooweak\n} { target { ! lp64 } } } } */ diff --git a/gcc/testsuite/gcc.target/s390/call.h b/gcc/testsuite/gcc.target/s390/call.h new file mode 100644 index 0000000000000000000000000000000000000000..059a672288739a1e33303e80049b67aa51f440fd --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/call.h @@ -0,0 +1,40 @@ +/* Common code for testing the function call code generation. */ + +__attribute__ ((noipa)) void +foo (void) +{ + return; +} + +void * +usefoo (void) +{ + foo (); + return foo; +} + +__attribute__ ((noipa)) static void +foostatic (void) +{ + return; +} + +void * +usefoostatic (void) +{ + foostatic (); + return foostatic; +} + +__attribute__ ((weak)) void fooweak (void); + +void * +usefooweak (void) +{ + fooweak (); + return fooweak; +} + +__attribute__ ((__used__, section (".foos"), aligned (sizeof (void *)))) +static void +*foos[] = { foo, foostatic, fooweak }; diff --git a/gcc/testsuite/gcc.target/s390/mfentry-m64-pic.c b/gcc/testsuite/gcc.target/s390/mfentry-m64-pic.c new file mode 100644 index 0000000000000000000000000000000000000000..32d55ce2b75383ecf08e8c8206046d0a7c1a8a49 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/mfentry-m64-pic.c @@ -0,0 +1,9 @@ +/* { dg-do compile { target { lp64 } } } */ +/* { dg-options "-pg -mfentry -fPIC" } */ + +void +profileme (void) +{ + /* __fentry__ must be referenced through PLT. */ + /* { dg-final { scan-assembler "brasl\t0,__fentry__@PLT\n" } } */ +} diff --git a/gcc/testsuite/gcc.target/s390/nodatarel-1.c b/gcc/testsuite/gcc.target/s390/nodatarel-1.c index f53332f901dbc4c6ec65f32735e09440967595b1..02e64c3eddf02e29485c7cb92c9025e0a89aebca 100644 --- a/gcc/testsuite/gcc.target/s390/nodatarel-1.c +++ b/gcc/testsuite/gcc.target/s390/nodatarel-1.c @@ -15,12 +15,6 @@ foo () return a; } -static int __attribute__((noinline,noclone)) -foostatic (void) -{ - return a; -} - /* Just to make a potentially modified. */ void @@ -29,7 +23,7 @@ bar (int b) a = b; } -/* { dg-final { scan-assembler-times "\\.LANCHOR\\d+@GOTENT" 3 } } */ +/* { dg-final { scan-assembler-times "\\.LANCHOR\\d+@GOTENT" 2 } } */ /* The exrl target is a label_ref which should not be affected at all. */ @@ -63,21 +57,3 @@ fooptr () } /* { 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/gcc/testsuite/gcc.target/s390/pr80080-4.c b/gcc/testsuite/gcc.target/s390/pr80080-4.c index 5fc6a558008ff0502588bfba94a16c7ea748c6f5..3f16a197764eaead1d258d2a544215fccc9bd2dc 100644 --- a/gcc/testsuite/gcc.target/s390/pr80080-4.c +++ b/gcc/testsuite/gcc.target/s390/pr80080-4.c @@ -13,4 +13,4 @@ void foo4(int *mem) } } -/* { dg-final { scan-assembler {(?n)\n\tlt\t.*\n\tjne\t(\.L\d+)\n(.*\n)*\tcs\t.*\n\tber\t%r14\n\1:\n\tjg\tbar\n} } } */ +/* { dg-final { scan-assembler {(?n)\n\tlt\t.*\n\tjne\t(\.L\d+)\n(.*\n)*\tcs\t.*\n\tber\t%r14\n\1:\n\tjg\tbar(@PLT)?\n} } } */ diff --git a/gcc/testsuite/gcc.target/s390/risbg-ll-3.c b/gcc/testsuite/gcc.target/s390/risbg-ll-3.c index 864b0d6c417b8f45cbdae0d4e2aff00f68002609..02f6e046eb9d56388c82cf8609f5b7cae7a66989 100644 --- a/gcc/testsuite/gcc.target/s390/risbg-ll-3.c +++ b/gcc/testsuite/gcc.target/s390/risbg-ll-3.c @@ -23,7 +23,7 @@ i64 f1 (i64 v_a, i64 v_b) extern i64 f2_foo(); i64 f2 (i64 v_a, i64 v_b) { -/* { dg-final { scan-assembler "f2:\n\trisbg\t%r2,%r3,60,62,0\n\tbner\t%r14\n\tjg\tf2_foo\n" { target { lp64 } } } } */ +/* { dg-final { scan-assembler "f2:\n\trisbg\t%r2,%r3,60,62,0\n\tbner\t%r14\n\tjg\tf2_foo.*\n" { target { lp64 } } } } */ /* { dg-final { scan-assembler "f2:\n\trisbgn\t%r3,%r2,0,0\\\+32-1,64-0-32\n\trisbg\t%r3,%r5,60,62,0" { target { ! lp64 } } } } */ i64 v_anda = v_a & -15; i64 v_andb = v_b & 14; @@ -37,8 +37,8 @@ i64 f2 (i64 v_a, i64 v_b) void f2_bar (); void f2_cconly (i64 v_a, i64 v_b) { -/* { dg-final { scan-assembler "f2_cconly:\n\trisbg\t%r2,%r3,60,62,0\n\tber\t%r14\n\tjg\tf2_bar\n" { target { lp64 } } } } */ -/* { dg-final { scan-assembler "f2_cconly:\n\trisbgn\t%r3,%r2,0,0\\\+32-1,64-0-32\n\trisbg\t%r3,%r5,60,62,0\n\tber\t%r14\n\tjg\tf2_bar\n" { target { ! lp64 } } } } */ +/* { dg-final { scan-assembler "f2_cconly:\n\trisbg\t%r2,%r3,60,62,0\n\tber\t%r14\n\tjg\tf2_bar(@PLT)?\n" { target { lp64 } } } } */ +/* { dg-final { scan-assembler "f2_cconly:\n\trisbgn\t%r3,%r2,0,0\\\+32-1,64-0-32\n\trisbg\t%r3,%r5,60,62,0\n\tber\t%r14\n\tjg\tf2_bar(@PLT)?\n" { target { ! lp64 } } } } */ if ((v_a & -15) | (v_b & 14)) f2_bar(); } diff --git a/gcc/testsuite/gcc.target/s390/tls-pic.c b/gcc/testsuite/gcc.target/s390/tls-pic.c new file mode 100644 index 0000000000000000000000000000000000000000..17c5726be4f0a32b510f444d293fac39246f543c --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/tls-pic.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fPIC" } */ + +#include "tls.h" + +/* foo must use the global dynamic model. + __tls_get_offset must be referenced through PLT. */ + +/* { dg-final { scan-assembler-times {\tbrasl\t%r14,__tls_get_offset@PLT:tls_gdcall:foo\n} 1 } } */ + +/* foostatic must use the local dynamic model. + __tls_get_offset must be referenced through PLT. */ + +/* { dg-final { scan-assembler-times {\tbrasl\t%r14,__tls_get_offset@PLT:tls_ldcall} 1 } } */ diff --git a/gcc/testsuite/gcc.target/s390/tls.c b/gcc/testsuite/gcc.target/s390/tls.c new file mode 100644 index 0000000000000000000000000000000000000000..3d479d8e48f38a2ab105f76bcda31f8fe6004071 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/tls.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +#include "tls.h" + +/* foo must use the initial-exec model, foostatic must use the local-exec + model. */ + +/* { dg-final { scan-assembler-times {\tear} 4 { target lp64 } } } */ +/* { dg-final { scan-assembler-times {\tear} 2 { target { ! lp64 } } } } */ diff --git a/gcc/testsuite/gcc.target/s390/tls.h b/gcc/testsuite/gcc.target/s390/tls.h new file mode 100644 index 0000000000000000000000000000000000000000..f639bd38c8d74bbe911f0e201f3e6c7afcbcc7ed --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/tls.h @@ -0,0 +1,23 @@ +/* Common code for testing the TLS code generation. */ + +__thread int +foo; + +int +setfoo (int x) +{ + int result = foo; + foo = x; + return result; +} + +static __thread int +foostatic; + +int +setfoostatic (int x) +{ + int result = foostatic; + foostatic = x; + return result; +}