From patchwork Tue Sep 2 18:36:01 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 385252 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id ED69B140179 for ; Wed, 3 Sep 2014 04:36:20 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type; q=dns; s= default; b=kDEM1PiPB0zWMQxv21i0LXUOQvjYk8ndvra3qBRl1wMszoJ+QDOYq gs/JLkXmpOI8db2R2xE/axbSAcPulYiX/N4IRoQiFSu20gNhXki9cu0AT34yjTq8 tVO1CO4p72F0uCXTMB7uEruDcSMGTyXvcG7FvkaCj/V7fVBLzObSaQ= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type; s= default; bh=T6qVQ1o11jnGLvssLj5U0qDYyfI=; b=N0MlRfaCiUEte0D/t7fY haYgm28w33XK649N6XPBjy/lhBl2NQj2f3h4PbIYPH5+n2I/m415KQS35XVrnR9F 9TINPEiewPg0E1f4vI9KwNs/2OwT+V0n1bYDMrvaTQZXZ3TLbzp7iBubAMiRVhgF WoRQz17mhZ37hj2gyHotuFw= Received: (qmail 15822 invoked by alias); 2 Sep 2014 18:36:12 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 15799 invoked by uid 89); 2 Sep 2014 18:36:08 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, KAM_STOCKGEN, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=no version=3.3.2 X-HELO: mail-wg0-f50.google.com Received: from mail-wg0-f50.google.com (HELO mail-wg0-f50.google.com) (74.125.82.50) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Tue, 02 Sep 2014 18:36:06 +0000 Received: by mail-wg0-f50.google.com with SMTP id x12so7220268wgg.21 for ; Tue, 02 Sep 2014 11:36:03 -0700 (PDT) X-Received: by 10.194.95.8 with SMTP id dg8mr42016389wjb.1.1409682962959; Tue, 02 Sep 2014 11:36:02 -0700 (PDT) Received: from localhost ([2.25.234.45]) by mx.google.com with ESMTPSA id lh5sm11200128wjb.12.2014.09.02.11.36.01 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 02 Sep 2014 11:36:02 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, rdsandiford@googlemail.com Subject: RFA: Merge definitions of get_some_local_dynamic_name Date: Tue, 02 Sep 2014 19:36:01 +0100 Message-ID: <87bnqxna3y.fsf@googlemail.com> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 Several targets define a function like i386's get_some_local_dynamic_name. The function looks through the current output function and returns the first (arbitrary) local-dynamic symbol that it finds. The result can be used in a call to __tls_get_addr, since all local-dynamic symbols have the same base. This patch replaces the various target functions with a single generic one. The only difference between the implementations was that s390 checked for constant pool references while the others didn't need to (because they don't allow TLS symbols to be forced into the pool). Checking for constant pool references is unnecessary but harmless for the other ports. Also, the walk is needed only once per TLS-referencing output function, so it's hardly critical in terms of compile time. All uses of this function are in final. In general it wouldn't be safe to call the function earlier than that, since the symbol reference could in principle be deleted by any rtl pass. I've therefore cached it in a variable local to final rather than in cfun (which is where the ports used to cache it). Also, i386 was robust against uses of %& in inline asm. The patch makes sure the other ports are too. Using %& in inline asm would often be a mistake, but it should at least trigger a proper error rather than an ICE. Tested on x86_64-linux-gnu. Also tested by building cross compilers before and after the change on: alpha-linux-gnu powerpc64-linux-gnu s390x-linux-gnu sparc64-linux-gnu OK to install? Thanks, Richard gcc/ * output.h (get_some_local_dynamic_name): Declare. * final.c (some_local_dynamic_name): New variable. (get_some_local_dynamic_name): New function. (final_end_function): Clear some_local_dynamic_name. * config/alpha/alpha.c (machine_function): Remove some_ld_name. (get_some_local_dynamic_name, get_some_local_dynamic_name_1): Delete. (print_operand): Report an error if '%&' is used inappropriately. * config/i386/i386.c (get_some_local_dynamic_name): Delete. (get_some_local_dynamic_name_1): Delete. * config/rs6000/rs6000.c (machine_function): Remove some_ld_name. (rs6000_get_some_local_dynamic_name): Delete. (rs6000_get_some_local_dynamic_name_1): Delete. (print_operand): Report an error if '%&' is used inappropriately. * config/s390/s390.c (machine_function): Remove some_ld_name. (get_some_local_dynamic_name, get_some_local_dynamic_name_1): Delete. (print_operand): Assert that get_some_local_dynamic_name is nonnull. * config/sparc/sparc.c: Include rtl-iter.h. (machine_function): Remove some_ld_name. (sparc_print_operand): Report an error if '%&' is used inappropriately. (get_some_local_dynamic_name, get_some_local_dynamic_name_1): Delete. Index: gcc/output.h =================================================================== --- gcc/output.h 2014-08-31 21:05:04.701330252 +0100 +++ gcc/output.h 2014-09-02 19:02:59.820482510 +0100 @@ -52,6 +52,8 @@ extern int get_attr_min_length (rtx); any branches of variable length if possible. */ extern void shorten_branches (rtx_insn *); +const char *get_some_local_dynamic_name (); + /* Output assembler code for the start of a function, and initialize some of the variables in this file for the new function. The label for the function and associated Index: gcc/final.c =================================================================== --- gcc/final.c 2014-08-31 21:05:04.701330252 +0100 +++ gcc/final.c 2014-09-02 19:17:08.573876805 +0100 @@ -1719,6 +1719,38 @@ reemit_insn_block_notes (void) reorder_blocks (); } +static const char *some_local_dynamic_name; + +/* Locate some local-dynamic symbol still in use by this function + so that we can print its name in local-dynamic base patterns. + Return null if there are no local-dynamic references. */ + +const char * +get_some_local_dynamic_name () +{ + subrtx_iterator::array_type array; + rtx_insn *insn; + + if (some_local_dynamic_name) + return some_local_dynamic_name; + + for (insn = get_insns (); insn ; insn = NEXT_INSN (insn)) + if (NONDEBUG_INSN_P (insn)) + FOR_EACH_SUBRTX (iter, array, PATTERN (insn), ALL) + { + const_rtx x = *iter; + if (GET_CODE (x) == SYMBOL_REF) + { + if (SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC) + return some_local_dynamic_name = XSTR (x, 0); + if (CONSTANT_POOL_ADDRESS_P (x)) + iter.substitute (get_pool_constant (x)); + } + } + + return 0; +} + /* Output assembler code for the start of a function, and initialize some of the variables in this file for the new function. The label for the function and associated @@ -1904,6 +1936,8 @@ final_end_function (void) if (!dwarf2_debug_info_emitted_p (current_function_decl) && dwarf2out_do_frame ()) dwarf2out_end_epilogue (last_linenum, last_filename); + + some_local_dynamic_name = 0; } Index: gcc/config/alpha/alpha.c =================================================================== --- gcc/config/alpha/alpha.c 2014-08-31 21:05:04.701330252 +0100 +++ gcc/config/alpha/alpha.c 2014-09-02 19:02:59.552479551 +0100 @@ -4858,9 +4858,6 @@ struct GTY(()) alpha_links; struct GTY(()) machine_function { - /* For OSF. */ - const char *some_ld_name; - /* For flag_reorder_blocks_and_partition. */ rtx gp_save_rtx; @@ -5120,40 +5117,6 @@ get_round_mode_suffix (void) gcc_unreachable (); } -/* Locate some local-dynamic symbol still in use by this function - so that we can print its name in some movdi_er_tlsldm pattern. */ - -static int -get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED) -{ - rtx x = *px; - - if (GET_CODE (x) == SYMBOL_REF - && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC) - { - cfun->machine->some_ld_name = XSTR (x, 0); - return 1; - } - - return 0; -} - -static const char * -get_some_local_dynamic_name (void) -{ - rtx_insn *insn; - - if (cfun->machine->some_ld_name) - return cfun->machine->some_ld_name; - - for (insn = get_insns (); insn ; insn = NEXT_INSN (insn)) - if (INSN_P (insn) - && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0)) - return cfun->machine->some_ld_name; - - gcc_unreachable (); -} - /* Print an operand. Recognize special options, documented below. */ void @@ -5169,7 +5132,11 @@ print_operand (FILE *file, rtx x, int co break; case '&': - assemble_name (file, get_some_local_dynamic_name ()); + if (const char *name = get_some_local_dynamic_name ()) + assemble_name (file, name); + else + output_operand_lossage ("'%%&' used without any " + "local dynamic TLS references"); break; case '/': Index: gcc/config/i386/i386.c =================================================================== --- gcc/config/i386/i386.c 2014-08-31 21:05:04.701330252 +0100 +++ gcc/config/i386/i386.c 2014-09-02 19:02:59.669480843 +0100 @@ -14756,41 +14756,6 @@ print_reg (rtx x, int code, FILE *file) } } -/* Locate some local-dynamic symbol still in use by this function - so that we can print its name in some tls_local_dynamic_base - pattern. */ - -static int -get_some_local_dynamic_name_1 (rtx *px, void *) -{ - rtx x = *px; - - if (GET_CODE (x) == SYMBOL_REF - && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC) - { - cfun->machine->some_ld_name = XSTR (x, 0); - return 1; - } - - return 0; -} - -static const char * -get_some_local_dynamic_name (void) -{ - rtx_insn *insn; - - if (cfun->machine->some_ld_name) - return cfun->machine->some_ld_name; - - for (insn = get_insns (); insn ; insn = NEXT_INSN (insn)) - if (NONDEBUG_INSN_P (insn) - && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0)) - return cfun->machine->some_ld_name; - - return NULL; -} - /* Meaning of CODE: L,W,B,Q,S,T -- print the opcode suffix for specified size of operand. C -- print opcode suffix for set/cmov insn. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c 2014-08-31 21:05:04.701330252 +0100 +++ gcc/config/rs6000/rs6000.c 2014-09-02 19:02:59.699481175 +0100 @@ -142,8 +142,6 @@ typedef struct rs6000_stack { This is added to the cfun structure. */ typedef struct GTY(()) machine_function { - /* Some local-dynamic symbol. */ - const char *some_ld_name; /* Whether the instruction chain has been scanned already. */ int insn_chain_scanned_p; /* Flags if __builtin_return_address (n) with n >= 1 was used. */ @@ -1103,7 +1101,6 @@ static void is_altivec_return_reg (rtx, int easy_vector_constant (rtx, enum machine_mode); static rtx rs6000_debug_legitimize_address (rtx, rtx, enum machine_mode); static rtx rs6000_legitimize_tls_address (rtx, enum tls_model); -static int rs6000_get_some_local_dynamic_name_1 (rtx *, void *); static rtx rs6000_darwin64_record_arg (CUMULATIVE_ARGS *, const_tree, bool, bool); #if TARGET_MACHO @@ -17937,46 +17934,6 @@ extract_ME (rtx op) return i; } -/* Locate some local-dynamic symbol still in use by this function - so that we can print its name in some tls_ld pattern. */ - -static const char * -rs6000_get_some_local_dynamic_name (void) -{ - rtx_insn *insn; - - if (cfun->machine->some_ld_name) - return cfun->machine->some_ld_name; - - for (insn = get_insns (); insn ; insn = NEXT_INSN (insn)) - if (INSN_P (insn) - && for_each_rtx (&PATTERN (insn), - rs6000_get_some_local_dynamic_name_1, 0)) - return cfun->machine->some_ld_name; - - gcc_unreachable (); -} - -/* Helper function for rs6000_get_some_local_dynamic_name. */ - -static int -rs6000_get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED) -{ - rtx x = *px; - - if (GET_CODE (x) == SYMBOL_REF) - { - const char *str = XSTR (x, 0); - if (SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC) - { - cfun->machine->some_ld_name = str; - return 1; - } - } - - return 0; -} - /* Write out a function code label. */ void @@ -18652,7 +18609,11 @@ print_operand (FILE *file, rtx x, int co return; case '&': - assemble_name (file, rs6000_get_some_local_dynamic_name ()); + if (const char *name = get_some_local_dynamic_name ()) + assemble_name (file, name); + else + output_operand_lossage ("'%%&' used without any " + "local dynamic TLS references"); return; default: Index: gcc/config/s390/s390.c =================================================================== --- gcc/config/s390/s390.c 2014-08-31 21:05:04.701330252 +0100 +++ gcc/config/s390/s390.c 2014-09-02 19:02:59.742481649 +0100 @@ -387,9 +387,6 @@ struct GTY(()) machine_function /* True if we may need to perform branch splitting. */ bool split_branches_pending_p; - /* Some local-dynamic TLS symbol name. */ - const char *some_ld_name; - bool has_landing_pad_p; /* True if the current function may contain a tbegin clobbering @@ -5197,48 +5194,6 @@ print_shift_count_operand (FILE *file, r fprintf (file, "(%s)", reg_names[REGNO (base)]); } -/* See 'get_some_local_dynamic_name'. */ - -static int -get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED) -{ - rtx x = *px; - - if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x)) - { - x = get_pool_constant (x); - return for_each_rtx (&x, get_some_local_dynamic_name_1, 0); - } - - if (GET_CODE (x) == SYMBOL_REF - && tls_symbolic_operand (x) == TLS_MODEL_LOCAL_DYNAMIC) - { - cfun->machine->some_ld_name = XSTR (x, 0); - return 1; - } - - return 0; -} - -/* Locate some local-dynamic symbol still in use by this function - so that we can print its name in local-dynamic base patterns. */ - -static const char * -get_some_local_dynamic_name (void) -{ - rtx_insn *insn; - - if (cfun->machine->some_ld_name) - return cfun->machine->some_ld_name; - - for (insn = get_insns (); insn ; insn = NEXT_INSN (insn)) - if (INSN_P (insn) - && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0)) - return cfun->machine->some_ld_name; - - gcc_unreachable (); -} - /* Returns -1 if the function should not be made hotpatchable. Otherwise it returns a number >= 0 that is the desired size of the hotpatch trampoline in halfwords. */ @@ -5508,7 +5463,9 @@ print_operand (FILE *file, rtx x, int co else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSLDM) { fprintf (file, "%s", ":tls_ldcall:"); - assemble_name (file, get_some_local_dynamic_name ()); + const char *name = get_some_local_dynamic_name (); + gcc_assert (name); + assemble_name (file, name); } else output_operand_lossage ("invalid reference for 'J' output modifier"); Index: gcc/config/sparc/sparc.c =================================================================== --- gcc/config/sparc/sparc.c 2014-08-31 21:05:04.701330252 +0100 +++ gcc/config/sparc/sparc.c 2014-09-02 19:02:59.800482290 +0100 @@ -70,6 +70,7 @@ the Free Software Foundation; either ver #include "context.h" #include "wide-int.h" #include "builtins.h" +#include "rtl-iter.h" /* Processor costs */ @@ -500,9 +501,6 @@ struct GTY(()) machine_function rtx frame_base_reg; HOST_WIDE_INT frame_base_offset; - /* Some local-dynamic TLS symbol name. */ - const char *some_ld_name; - /* Number of global or FP registers to be saved (as 4-byte quantities). */ int n_global_fp_regs; @@ -584,8 +582,6 @@ static struct machine_function * sparc_i static bool sparc_cannot_force_const_mem (enum machine_mode, rtx); static rtx sparc_tls_get_addr (void); static rtx sparc_tls_got (void); -static const char *get_some_local_dynamic_name (void); -static int get_some_local_dynamic_name_1 (rtx *, void *); static int sparc_register_move_cost (enum machine_mode, reg_class_t, reg_class_t); static bool sparc_rtx_costs (rtx, int, int, int, int *, bool); @@ -8790,7 +8786,11 @@ sparc_print_operand (FILE *file, rtx x, return; case '&': /* Print some local dynamic TLS name. */ - assemble_name (file, get_some_local_dynamic_name ()); + if (const char *name = get_some_local_dynamic_name ()) + assemble_name (file, name); + else + output_operand_lossage ("'%%&' used without any " + "local dynamic TLS references"); return; case 'Y': @@ -11484,41 +11484,6 @@ sparc_init_machine_status (void) return ggc_cleared_alloc (); } -/* Locate some local-dynamic symbol still in use by this function - so that we can print its name in local-dynamic base patterns. */ - -static const char * -get_some_local_dynamic_name (void) -{ - rtx_insn *insn; - - if (cfun->machine->some_ld_name) - return cfun->machine->some_ld_name; - - for (insn = get_insns (); insn ; insn = NEXT_INSN (insn)) - if (INSN_P (insn) - && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0)) - return cfun->machine->some_ld_name; - - gcc_unreachable (); -} - -static int -get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED) -{ - rtx x = *px; - - if (x - && GET_CODE (x) == SYMBOL_REF - && SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC) - { - cfun->machine->some_ld_name = XSTR (x, 0); - return 1; - } - - return 0; -} - /* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL. We need to emit DTP-relative relocations. */