Discussion:
RFA: Merge definitions of get_some_local_dynamic_name
Richard Sandiford
2014-09-02 18:36:01 UTC
Permalink
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<machine_function> ();
}

-/* 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. */
Richard Biener
2014-09-03 09:55:48 UTC
Permalink
On Tue, Sep 2, 2014 at 8:36 PM, Richard Sandiford
Post by Richard Sandiford
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
alpha-linux-gnu powerpc64-linux-gnu s390x-linux-gnu sparc64-linux-gnu
OK to install?
Ok.

Thanks,
Richard.
Post by Richard Sandiford
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;
- 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;
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;
-}
-
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;
- 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;
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;
/* 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;
@@ -11484,41 +11484,6 @@ sparc_init_machine_status (void)
return ggc_cleared_alloc<machine_function> ();
}
-/* 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. */
Jeff Law
2014-09-03 18:50:46 UTC
Permalink
Post by Richard Sandiford
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
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.
OK.
Jeff
Gerald Pfeifer
2014-09-04 17:03:08 UTC
Permalink
Post by Richard Sandiford
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
alpha-linux-gnu powerpc64-linux-gnu s390x-linux-gnu sparc64-linux-gnu
Is it possible this is related to the following new (set of) bootstrap
failure(s) my i386-unknown-freebsd10.0 tester shows as new in the last
24 hours?

/scratch2/tmp/gerald/gcc-HEAD/libgcc/libgcc2.c: In function '__lshrdi3':
/scratch2/tmp/gerald/gcc-HEAD/libgcc/libgcc2.c:426:1: internal compiler error: in gen_variable_die, at dwarf2out.c:19017
}
^
/scratch2/tmp/gerald/gcc-HEAD/libgcc/libgcc2.c: In function '__ashrdi3':
/scratch2/tmp/gerald/gcc-HEAD/libgcc/libgcc2.c: In function '__ashldi3':
/scratch2/tmp/gerald/gcc-HEAD/libgcc/libgcc2.c:483:1: internal compiler error: in gen_variable_die, at dwarf2out.c:19017
}
^
/scratch2/tmp/gerald/gcc-HEAD/libgcc/libgcc2.c:454:1: internal compiler error: in gen_variable_die, at dwarf2out.c:19017
}
^

Parallel build, hence three ICEs at once. :-)

Gerald
Richard Sandiford
2014-09-04 17:45:49 UTC
Permalink
Post by Gerald Pfeifer
Post by Richard Sandiford
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
alpha-linux-gnu powerpc64-linux-gnu s390x-linux-gnu sparc64-linux-gnu
Is it possible this is related to the following new (set of) bootstrap
failure(s) my i386-unknown-freebsd10.0 tester shows as new in the last
24 hours?
/scratch2/tmp/gerald/gcc-HEAD/libgcc/libgcc2.c:426:1: internal compiler
error: in gen_variable_die, at dwarf2out.c:19017
}
^
/scratch2/tmp/gerald/gcc-HEAD/libgcc/libgcc2.c:483:1: internal compiler
error: in gen_variable_die, at dwarf2out.c:19017
}
^
/scratch2/tmp/gerald/gcc-HEAD/libgcc/libgcc2.c:454:1: internal compiler
error: in gen_variable_die, at dwarf2out.c:19017
}
^
Parallel build, hence three ICEs at once. :-)
Is this stage 1 libgcc or a later libgcc? Seems unlikely if stage 1.

Thanks,
Richard
Gerald Pfeifer
2014-09-04 19:16:33 UTC
Permalink
Post by Richard Sandiford
Is this stage 1 libgcc or a later libgcc? Seems unlikely if stage 1.
Stage 1. I kicked off a non-parallel build, which just failed as
follows:

/scratch2/tmp/gerald/OBJ-0904-1719/./gcc/xgcc -B/scratch2/tmp/gerald/OBJ-0904-1719/./gcc/ -B/home/gerald/gcc-ref10-i386/i386-unknown-freebsd10.0/bin/ -B/home/gerald/gcc-ref10-i386/i386-unknown-freebsd10.0/lib/ -isystem /home/gerald/gcc-ref10-i386/i386-unknown-freebsd10.0/include -isystem /home/gerald/gcc-ref10-i386/i386-unknown-freebsd10.0/sys-include -g -O2 -O2 -g -O2 -DIN_GCC -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wno-format -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -isystem ./include -fpic -pthread -g -DIN_LIBGCC2 -fbuilding-libgcc -fno-stack-protector -fpic -pthread -I. -I. -I../.././gcc -I/scratch2/tmp/gerald/gcc-HEAD/libgcc -I/scratch2/tmp/gerald/gcc-HEAD/libgcc/. -I/scratch2/tmp/gerald/gcc-HEAD/libgcc/../gcc -I/scratch2/tmp/gerald/gcc-
HEAD/libgcc/../include -DHAVE_CC_TLS -o _muldi3.o -MT _muldi3.o -MD -MP -MF _muldi3.dep -DL_muldi3 -c /scratch2/tmp/gerald/gcc-HEAD/libgcc/libgcc2.c -fvisibility=hidden -DHIDE_EXPORTS
/scratch2/tmp/gerald/gcc-HEAD/libgcc/libgcc2.c: In function ¡__muldi3¢:
/scratch2/tmp/gerald/gcc-HEAD/libgcc/libgcc2.c:557:1: internal compiler
error: in gen_variable_die, at dwarf2out.c:19017
}
^
no stack trace because unwind library not available
gmake[3]: *** [_muldi3.o] Error 1
gmake[3]: Leaving directory
`/scratch2/tmp/gerald/OBJ-0904-1719/i386-unknown-freebsd10.0/libgcc'
gmake[2]: *** [all-stage1-target-libgcc] Error 2

Any ideas which recent commit this might be due to?

Gerald
Richard Sandiford
2014-09-04 19:24:25 UTC
Permalink
Post by Gerald Pfeifer
Post by Richard Sandiford
Is this stage 1 libgcc or a later libgcc? Seems unlikely if stage 1.
Stage 1. I kicked off a non-parallel build, which just failed as
/scratch2/tmp/gerald/OBJ-0904-1719/./gcc/xgcc
-B/scratch2/tmp/gerald/OBJ-0904-1719/./gcc/
-B/home/gerald/gcc-ref10-i386/i386-unknown-freebsd10.0/bin/
-B/home/gerald/gcc-ref10-i386/i386-unknown-freebsd10.0/lib/ -isystem
/home/gerald/gcc-ref10-i386/i386-unknown-freebsd10.0/include -isystem
/home/gerald/gcc-ref10-i386/i386-unknown-freebsd10.0/sys-include -g -O2
-O2 -g -O2 -DIN_GCC -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual
-Wno-format -Wstrict-prototypes -Wmissing-prototypes
-Wold-style-definition -isystem ./include -fpic -pthread -g -DIN_LIBGCC2
-fbuilding-libgcc -fno-stack-protector -fpic -pthread
-I. -I. -I../.././gcc -I/scratch2/tmp/gerald/gcc-HEAD/libgcc
-I/scratch2/tmp/gerald/gcc-HEAD/libgcc/. -I/scratch2/tmp/gerald/gcc-HEAD/libgcc/../gcc
-I/scratch2/tmp/gerald/gcc-HEAD/libgcc/../include -DHAVE_CC_TLS -o
_muldi3.o -MT _muldi3.o -MD -MP -MF _muldi3.dep -DL_muldi3 -c
/scratch2/tmp/gerald/gcc-HEAD/libgcc/libgcc2.c -fvisibility=hidden
-DHIDE_EXPORTS
/scratch2/tmp/gerald/gcc-HEAD/libgcc/libgcc2.c:557:1: internal compiler
error: in gen_variable_die, at dwarf2out.c:19017
}
^
no stack trace because unwind library not available
gmake[3]: *** [_muldi3.o] Error 1
gmake[3]: Leaving directory
`/scratch2/tmp/gerald/OBJ-0904-1719/i386-unknown-freebsd10.0/libgcc'
gmake[2]: *** [all-stage1-target-libgcc] Error 2
Any ideas which recent commit this might be due to?
It was the debug-early stuff. Everything should be OK if you update
and retest.

Thanks,
Richard
Rainer Orth
2014-09-08 11:56:54 UTC
Permalink
Hi Richard,
Post by Richard Sandiford
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
alpha-linux-gnu powerpc64-linux-gnu s390x-linux-gnu sparc64-linux-gnu
OK to install?
this patch broke Solaris/SPARC bootstrap: compiling libgo/runtime/proc.c
with -fPIC SEGVs:

/vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c: In function 'procresize':
/vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:2727:1: internal compiler error: Segmentation Fault
}
^
0x731c97 crash_signal
/vol/gcc/src/hg/trunk/local/gcc/toplev.c:339
0x45facc get_some_local_dynamic_name()
/vol/gcc/src/hg/trunk/local/gcc/final.c:1742
0xa0886f sparc_print_operand
/vol/gcc/src/hg/trunk/local/gcc/config/sparc/sparc.c:8789
0x4606a3 output_operand(rtx_def*, int)
/vol/gcc/src/hg/trunk/local/gcc/final.c:3848
0x460fdf output_asm_insn(char const*, rtx_def**)
/vol/gcc/src/hg/trunk/local/gcc/final.c:3778
0x46254b output_asm_insn(char const*, rtx_def**)
/vol/gcc/src/hg/trunk/local/gcc/recog.h:169
0x46254b final_scan_insn(rtx_insn*, __FILE*, int, int, int*)
/vol/gcc/src/hg/trunk/local/gcc/final.c:3027
0x462b53 final(rtx_insn*, __FILE*, int)
/vol/gcc/src/hg/trunk/local/gcc/final.c:2063
0x46470f rest_of_handle_final
/vol/gcc/src/hg/trunk/local/gcc/final.c:4470
0x46470f execute
/vol/gcc/src/hg/trunk/local/gcc/final.c:4545

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1 (LWP 1)]
get_some_local_dynamic_name () at /vol/gcc/src/hg/trunk/local/gcc/final.c:1742
1742 if (GET_CODE (x) == SYMBOL_REF)

1: x/i $pc
=> 0x45facc <get_some_local_dynamic_name()+84>: lduh [ %o0 ], %g1
(gdb) p $o0
$1 = 0

(gdb) where
#0 get_some_local_dynamic_name () at /vol/gcc/src/hg/trunk/local/gcc/final.c:1742
#1 0x00a08870 in sparc_print_operand (file=0x10ab0f0 <_iob+48>, x=0x0, code=<optimized out>) at /vol/gcc/src/hg/trunk/local/gcc/config/sparc/sparc.c:8789
#2 0x004606a4 in output_operand (x=0x0, code=38) at /vol/gcc/src/hg/trunk/local/gcc/final.c:3848
#3 0x00460fe0 in output_asm_insn (templ=***@entry=0xf1e5c8 "sethi\t%%tldm_hi22(%&), %0", operands=0x107feb0 <recog_data>) at /vol/gcc/src/hg/trunk/local/gcc/final.c:3778
#4 0x0046254c in output_asm_insn (operands=<optimized out>, templ=0xf1e5c8 "sethi\t%%tldm_hi22(%&), %0") at /vol/gcc/src/hg/trunk/local/gcc/recog.h:169
#5 final_scan_insn (insn=***@entry=0xfac70de8, file=***@entry=0x10ab0f0 <_iob+48>, optimize_p=***@entry=2, nopeepholes=***@entry=0, seen=***@entry=0xffbfef0c) at /vol/gcc/src/hg/trunk/local/gcc/final.c:3027
#6 0x00462b54 in final (first=0xfac62020, file=0x10ab0f0 <_iob+48>, optimize_p=2) at /vol/gcc/src/hg/trunk/local/gcc/final.c:2063
#7 0x00464710 in rest_of_handle_final () at /vol/gcc/src/hg/trunk/local/gcc/final.c:4470
#8 (anonymous namespace)::pass_final::execute (this=0x10d9050) at /vol/gcc/src/hg/trunk/local/gcc/final.c:4545
#9 0x00661cf4 in execute_one_pass (pass=***@entry=0x10d9050) at /vol/gcc/src/hg/trunk/local/gcc/passes.c:2151
#10 0x0066235c in execute_pass_list_1 (pass=0x10d9050) at /vol/gcc/src/hg/trunk/local/gcc/passes.c:2203
#11 0x00662380 in execute_pass_list_1 (pass=0x10d8630) at /vol/gcc/src/hg/trunk/local/gcc/passes.c:2204
#12 0x00662380 in execute_pass_list_1 (pass=0x10d7988, ***@entry=0x10d54a8) at /vol/gcc/src/hg/trunk/local/gcc/passes.c:2204
#13 0x006623c4 in execute_pass_list (fn=0xfb5fc5b0, pass=0x10d54a8) at /vol/gcc/src/hg/trunk/local/gcc/passes.c:2214
#14 0x0037d728 in cgraph_node::expand (this=***@entry=0xfb5f5180) at /vol/gcc/src/hg/trunk/local/gcc/cgraphunit.c:1744
#15 0x0037f078 in expand_all_functions () at /vol/gcc/src/hg/trunk/local/gcc/cgraphunit.c:1880
#16 symbol_table::compile (this=0xfb410000) at /vol/gcc/src/hg/trunk/local/gcc/cgraphunit.c:2209
#17 0x00380ee4 in symbol_table::finalize_compilation_unit (this=0xfb410000) at /vol/gcc/src/hg/trunk/local/gcc/cgraphunit.c:2286
#18 0x0020ee34 in c_write_global_declarations () at /vol/gcc/src/hg/trunk/local/gcc/c/c-decl.c:10431
#19 0x00731d58 in compile_file () at /vol/gcc/src/hg/trunk/local/gcc/toplev.c:564
#20 0x00734604 in do_compile () at /vol/gcc/src/hg/trunk/local/gcc/toplev.c:1945
#21 toplev_main (argc=10, argv=0xffbff424) at /vol/gcc/src/hg/trunk/local/gcc/toplev.c:2021
#22 0x001f1184 in _start ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

It seems the new get_some_local_dynamic_name implementation in
function.c lost the non-NULL check the sparc.c version had. I'm
currently testing the following patch:
Richard Sandiford
2014-09-08 18:20:02 UTC
Permalink
Post by Rainer Orth
Hi Richard,
Post by Richard Sandiford
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
alpha-linux-gnu powerpc64-linux-gnu s390x-linux-gnu sparc64-linux-gnu
OK to install?
this patch broke Solaris/SPARC bootstrap: compiling libgo/runtime/proc.c
/vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:2727:1: internal compiler error: Segmentation Fault
}
^
0x731c97 crash_signal
/vol/gcc/src/hg/trunk/local/gcc/toplev.c:339
0x45facc get_some_local_dynamic_name()
/vol/gcc/src/hg/trunk/local/gcc/final.c:1742
0xa0886f sparc_print_operand
/vol/gcc/src/hg/trunk/local/gcc/config/sparc/sparc.c:8789
0x4606a3 output_operand(rtx_def*, int)
/vol/gcc/src/hg/trunk/local/gcc/final.c:3848
0x460fdf output_asm_insn(char const*, rtx_def**)
/vol/gcc/src/hg/trunk/local/gcc/final.c:3778
0x46254b output_asm_insn(char const*, rtx_def**)
/vol/gcc/src/hg/trunk/local/gcc/recog.h:169
0x46254b final_scan_insn(rtx_insn*, __FILE*, int, int, int*)
/vol/gcc/src/hg/trunk/local/gcc/final.c:3027
0x462b53 final(rtx_insn*, __FILE*, int)
/vol/gcc/src/hg/trunk/local/gcc/final.c:2063
0x46470f rest_of_handle_final
/vol/gcc/src/hg/trunk/local/gcc/final.c:4470
0x46470f execute
/vol/gcc/src/hg/trunk/local/gcc/final.c:4545
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 1 (LWP 1)]
get_some_local_dynamic_name () at /vol/gcc/src/hg/trunk/local/gcc/final.c:1742
1742 if (GET_CODE (x) == SYMBOL_REF)
1: x/i $pc
=> 0x45facc <get_some_local_dynamic_name()+84>: lduh [ %o0 ], %g1
(gdb) p $o0
$1 = 0
(gdb) where
#0 get_some_local_dynamic_name () at /vol/gcc/src/hg/trunk/local/gcc/final.c:1742
#1 0x00a08870 in sparc_print_operand (file=0x10ab0f0 <_iob+48>, x=0x0, code=<optimized out>) at /vol/gcc/src/hg/trunk/local/gcc/config/sparc/sparc.c:8789
#2 0x004606a4 in output_operand (x=0x0, code=38) at /vol/gcc/src/hg/trunk/local/gcc/final.c:3848
#4 0x0046254c in output_asm_insn (operands=<optimized out>, templ=0xf1e5c8 "sethi\t%%tldm_hi22(%&), %0") at /vol/gcc/src/hg/trunk/local/gcc/recog.h:169
#6 0x00462b54 in final (first=0xfac62020, file=0x10ab0f0 <_iob+48>, optimize_p=2) at /vol/gcc/src/hg/trunk/local/gcc/final.c:2063
#7 0x00464710 in rest_of_handle_final () at /vol/gcc/src/hg/trunk/local/gcc/final.c:4470
#8 (anonymous namespace)::pass_final::execute (this=0x10d9050) at /vol/gcc/src/hg/trunk/local/gcc/final.c:4545
#10 0x0066235c in execute_pass_list_1 (pass=0x10d9050) at /vol/gcc/src/hg/trunk/local/gcc/passes.c:2203
#11 0x00662380 in execute_pass_list_1 (pass=0x10d8630) at /vol/gcc/src/hg/trunk/local/gcc/passes.c:2204
#13 0x006623c4 in execute_pass_list (fn=0xfb5fc5b0, pass=0x10d54a8) at /vol/gcc/src/hg/trunk/local/gcc/passes.c:2214
#15 0x0037f078 in expand_all_functions () at /vol/gcc/src/hg/trunk/local/gcc/cgraphunit.c:1880
#16 symbol_table::compile (this=0xfb410000) at /vol/gcc/src/hg/trunk/local/gcc/cgraphunit.c:2209
#17 0x00380ee4 in symbol_table::finalize_compilation_unit (this=0xfb410000) at /vol/gcc/src/hg/trunk/local/gcc/cgraphunit.c:2286
#18 0x0020ee34 in c_write_global_declarations () at /vol/gcc/src/hg/trunk/local/gcc/c/c-decl.c:10431
#19 0x00731d58 in compile_file () at /vol/gcc/src/hg/trunk/local/gcc/toplev.c:564
#20 0x00734604 in do_compile () at /vol/gcc/src/hg/trunk/local/gcc/toplev.c:1945
#21 toplev_main (argc=10, argv=0xffbff424) at /vol/gcc/src/hg/trunk/local/gcc/toplev.c:2021
#22 0x001f1184 in _start ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
It seems the new get_some_local_dynamic_name implementation in
function.c lost the non-NULL check the sparc.c version had. I'm
Could you do a:

call debug_rtx (...)

on the insn that contains a null pointer? Normally insn patterns
shouldn't contain nulls, so I was wondering whether this was some
SPARC-specific construct.

Thanks,
Richard
Rainer Orth
2014-09-09 18:21:00 UTC
Permalink
Hi Richard,
Post by Richard Sandiford
Post by Rainer Orth
It seems the new get_some_local_dynamic_name implementation in
function.c lost the non-NULL check the sparc.c version had. I'm
call debug_rtx (...)
on the insn that contains a null pointer? Normally insn patterns
shouldn't contain nulls, so I was wondering whether this was some
SPARC-specific construct.
proved a bit difficult to do: at the default -O2, insn was optimized
away, at -g3 -O0, I only got

can't compute CFA for this frame

with gdb 7.8 even after recompiling all of the gcc dir with -g3 -O0.

Here's what I find after inserting the call in the source:

(insn 30 6 28 (sequence [
(call_insn:TI 8 6 7 (parallel [
(set (reg:SI 8 %o0)
(call (mem:SI (unspec:SI [
(symbol_ref:SI ("__tls_get_addr"))
] UNSPEC_TLSLDM) [0 S4 A32])
(const_int 1 [0x1])))
(clobber (reg:SI 15 %o7))
]) /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:936 390 {tldm_call32}
(expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000])
(nil))
(expr_list (use (reg:SI 8 %o0))
(nil)))
(insn 7 8 28 (set (reg:SI 8 %o0)
(plus:SI (reg:SI 23 %l7)
(unspec:SI [
(reg:SI 8 %o0 [112])
] UNSPEC_TLSLDM))) 388 {tldm_add32}
(nil))
]) /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:936 -1
(nil))

Rainer
--
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University
Richard Sandiford
2014-09-09 18:40:11 UTC
Permalink
Post by Rainer Orth
Hi Richard,
Post by Richard Sandiford
Post by Rainer Orth
It seems the new get_some_local_dynamic_name implementation in
function.c lost the non-NULL check the sparc.c version had. I'm
call debug_rtx (...)
on the insn that contains a null pointer? Normally insn patterns
shouldn't contain nulls, so I was wondering whether this was some
SPARC-specific construct.
proved a bit difficult to do: at the default -O2, insn was optimized
away, at -g3 -O0, I only got
can't compute CFA for this frame
with gdb 7.8 even after recompiling all of the gcc dir with -g3 -O0.
(insn 30 6 28 (sequence [
(call_insn:TI 8 6 7 (parallel [
(set (reg:SI 8 %o0)
(call (mem:SI (unspec:SI [
(symbol_ref:SI ("__tls_get_addr"))
] UNSPEC_TLSLDM) [0 S4 A32])
(const_int 1 [0x1])))
(clobber (reg:SI 15 %o7))
]) /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:936 390 {tldm_call32}
(expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000])
(nil))
(expr_list (use (reg:SI 8 %o0))
(nil)))
(insn 7 8 28 (set (reg:SI 8 %o0)
(plus:SI (reg:SI 23 %l7)
(unspec:SI [
(reg:SI 8 %o0 [112])
] UNSPEC_TLSLDM))) 388 {tldm_add32}
(nil))
]) /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:936 -1
(nil))
Bah, a sequence. Hadn't thought of that.

IMO it's a bug for a walk on a PATTERN to pull in non-PATTERN parts
of an insn. We should really be looking at the patterns of the two
subinsns instead and ignore the other stuff. Let me have a think
about it.

Now that we know the underlying cause, I personally wouldn't mind the
null check being committed as a workaround. If you do though, please
could you add a comment saying that this is for SEQUENCEs?

Thanks,
Richard
Rainer Orth
2014-10-06 13:14:35 UTC
Permalink
Hi Richard,
Post by Richard Sandiford
Post by Rainer Orth
Hi Richard,
Post by Richard Sandiford
Post by Rainer Orth
It seems the new get_some_local_dynamic_name implementation in
function.c lost the non-NULL check the sparc.c version had. I'm
call debug_rtx (...)
on the insn that contains a null pointer? Normally insn patterns
shouldn't contain nulls, so I was wondering whether this was some
SPARC-specific construct.
proved a bit difficult to do: at the default -O2, insn was optimized
away, at -g3 -O0, I only got
can't compute CFA for this frame
with gdb 7.8 even after recompiling all of the gcc dir with -g3 -O0.
(insn 30 6 28 (sequence [
(call_insn:TI 8 6 7 (parallel [
(set (reg:SI 8 %o0)
(call (mem:SI (unspec:SI [
(symbol_ref:SI ("__tls_get_addr"))
] UNSPEC_TLSLDM) [0 S4 A32])
(const_int 1 [0x1])))
(clobber (reg:SI 15 %o7))
]) /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:936 390 {tldm_call32}
(expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000])
(nil))
(expr_list (use (reg:SI 8 %o0))
(nil)))
(insn 7 8 28 (set (reg:SI 8 %o0)
(plus:SI (reg:SI 23 %l7)
(unspec:SI [
(reg:SI 8 %o0 [112])
] UNSPEC_TLSLDM))) 388 {tldm_add32}
(nil))
]) /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:936 -1
(nil))
Bah, a sequence. Hadn't thought of that.
IMO it's a bug for a walk on a PATTERN to pull in non-PATTERN parts
of an insn. We should really be looking at the patterns of the two
subinsns instead and ignore the other stuff. Let me have a think
about it.
did you come to a conclusion here?
Post by Richard Sandiford
Now that we know the underlying cause, I personally wouldn't mind the
null check being committed as a workaround. If you do though, please
could you add a comment saying that this is for SEQUENCEs?
I've had the following in my local tree for some weeks now to keep SPARC
bootstrap working:

2014-10-06 Rainer Orth <***@CeBiTec.Uni-Bielefeld.DE>

* final.c (get_some_local_dynamic_name): Guard against NULL
const_rtx.
Richard Sandiford
2014-10-06 18:10:23 UTC
Permalink
Post by Rainer Orth
Hi Richard,
Post by Richard Sandiford
Post by Rainer Orth
Hi Richard,
Post by Richard Sandiford
Post by Rainer Orth
It seems the new get_some_local_dynamic_name implementation in
function.c lost the non-NULL check the sparc.c version had. I'm
call debug_rtx (...)
on the insn that contains a null pointer? Normally insn patterns
shouldn't contain nulls, so I was wondering whether this was some
SPARC-specific construct.
proved a bit difficult to do: at the default -O2, insn was optimized
away, at -g3 -O0, I only got
can't compute CFA for this frame
with gdb 7.8 even after recompiling all of the gcc dir with -g3 -O0.
(insn 30 6 28 (sequence [
(call_insn:TI 8 6 7 (parallel [
(set (reg:SI 8 %o0)
(call (mem:SI (unspec:SI [
(symbol_ref:SI ("__tls_get_addr"))
] UNSPEC_TLSLDM) [0 S4 A32])
(const_int 1 [0x1])))
(clobber (reg:SI 15 %o7))
]) /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:936 390 {tldm_call32}
(expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000])
(nil))
(expr_list (use (reg:SI 8 %o0))
(nil)))
(insn 7 8 28 (set (reg:SI 8 %o0)
(plus:SI (reg:SI 23 %l7)
(unspec:SI [
(reg:SI 8 %o0 [112])
] UNSPEC_TLSLDM))) 388 {tldm_add32}
(nil))
]) /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:936 -1
(nil))
Bah, a sequence. Hadn't thought of that.
IMO it's a bug for a walk on a PATTERN to pull in non-PATTERN parts
of an insn. We should really be looking at the patterns of the two
subinsns instead and ignore the other stuff. Let me have a think
about it.
did you come to a conclusion here?
Sorry, forgot to come back to this. I have a patch that iterates over
PATTERNs of a SEQUENCE if the SEQUENCE (rather than its containing insn)
is the topmost iterated rtx. So if PATTERN (insn) is a SEQUENCE:

FOR_EACH_SUBRTX (...., insn, x)
...

will iterate over the insns in the SEQUENCE (including pattern, notes,
jump label, etc.), whereas:

FOR_EACH_SUBRTX (...., PATTERN (insn), x)
...

would only iterate over the patterns of the insns in the SEQUENCE.

I'll need to pass it through internal review before sending, but hope
to post soon.

Thanks,
Richard
Richard Sandiford
2014-10-07 12:50:31 UTC
Permalink
Post by Richard Sandiford
Post by Rainer Orth
Hi Richard,
Post by Richard Sandiford
Post by Rainer Orth
Hi Richard,
Post by Richard Sandiford
Post by Rainer Orth
It seems the new get_some_local_dynamic_name implementation in
function.c lost the non-NULL check the sparc.c version had. I'm
call debug_rtx (...)
on the insn that contains a null pointer? Normally insn patterns
shouldn't contain nulls, so I was wondering whether this was some
SPARC-specific construct.
proved a bit difficult to do: at the default -O2, insn was optimized
away, at -g3 -O0, I only got
can't compute CFA for this frame
with gdb 7.8 even after recompiling all of the gcc dir with -g3 -O0.
(insn 30 6 28 (sequence [
(call_insn:TI 8 6 7 (parallel [
(set (reg:SI 8 %o0)
(call (mem:SI (unspec:SI [
(symbol_ref:SI ("__tls_get_addr"))
] UNSPEC_TLSLDM) [0 S4 A32])
(const_int 1 [0x1])))
(clobber (reg:SI 15 %o7))
]) /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:936 390 {tldm_call32}
(expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000])
(nil))
(expr_list (use (reg:SI 8 %o0))
(nil)))
(insn 7 8 28 (set (reg:SI 8 %o0)
(plus:SI (reg:SI 23 %l7)
(unspec:SI [
(reg:SI 8 %o0 [112])
] UNSPEC_TLSLDM))) 388 {tldm_add32}
(nil))
]) /vol/gcc/src/hg/trunk/local/libgo/runtime/proc.c:936 -1
(nil))
Bah, a sequence. Hadn't thought of that.
IMO it's a bug for a walk on a PATTERN to pull in non-PATTERN parts
of an insn. We should really be looking at the patterns of the two
subinsns instead and ignore the other stuff. Let me have a think
about it.
did you come to a conclusion here?
Sorry, forgot to come back to this. I have a patch that iterates over
PATTERNs of a SEQUENCE if the SEQUENCE (rather than its containing insn)
FOR_EACH_SUBRTX (...., insn, x)
...
will iterate over the insns in the SEQUENCE (including pattern, notes,
FOR_EACH_SUBRTX (...., PATTERN (insn), x)
...
would only iterate over the patterns of the insns in the SEQUENCE.
Does this work for you? I tested it on x86_64-linux-gnu but obviously
that's not particularly useful for SEQUENCEs.

Thanks,
Richard

gcc/
* rtlanal.c (generic_subrtx_iterator <T>::add_subrtxes_to_queue):
Add the parts of an insn in reverse order, with the pattern at
the top of the queue. Detect when we're iterating over a SEQUENCE
pattern and in that case just consider patterns of subinstructions.

Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c 2014-09-25 16:40:44.944406590 +0100
+++ gcc/rtlanal.c 2014-10-07 13:13:57.698132753 +0100
@@ -128,29 +128,58 @@ generic_subrtx_iterator <T>::add_subrtxe
value_type *base,
size_t end, rtx_type x)
{
- const char *format = GET_RTX_FORMAT (GET_CODE (x));
+ enum rtx_code code = GET_CODE (x);
+ const char *format = GET_RTX_FORMAT (code);
size_t orig_end = end;
- for (int i = 0; format[i]; ++i)
- if (format[i] == 'e')
- {
- value_type subx = T::get_value (x->u.fld[i].rt_rtx);
- if (__builtin_expect (end < LOCAL_ELEMS, true))
- base[end++] = subx;
- else
- base = add_single_to_queue (array, base, end++, subx);
- }
- else if (format[i] == 'E')
- {
- int length = GET_NUM_ELEM (x->u.fld[i].rt_rtvec);
- rtx *vec = x->u.fld[i].rt_rtvec->elem;
- if (__builtin_expect (end + length <= LOCAL_ELEMS, true))
- for (int j = 0; j < length; j++)
- base[end++] = T::get_value (vec[j]);
- else
- for (int j = 0; j < length; j++)
- base = add_single_to_queue (array, base, end++,
- T::get_value (vec[j]));
- }
+ if (__builtin_expect (INSN_P (x), false))
+ {
+ /* Put the pattern at the top of the queue, since that's what
+ we're likely to want most. It also allows for the SEQUENCE
+ code below. */
+ for (int i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; --i)
+ if (format[i] == 'e')
+ {
+ value_type subx = T::get_value (x->u.fld[i].rt_rtx);
+ if (__builtin_expect (end < LOCAL_ELEMS, true))
+ base[end++] = subx;
+ else
+ base = add_single_to_queue (array, base, end++, subx);
+ }
+ }
+ else
+ for (int i = 0; format[i]; ++i)
+ if (format[i] == 'e')
+ {
+ value_type subx = T::get_value (x->u.fld[i].rt_rtx);
+ if (__builtin_expect (end < LOCAL_ELEMS, true))
+ base[end++] = subx;
+ else
+ base = add_single_to_queue (array, base, end++, subx);
+ }
+ else if (format[i] == 'E')
+ {
+ unsigned int length = GET_NUM_ELEM (x->u.fld[i].rt_rtvec);
+ rtx *vec = x->u.fld[i].rt_rtvec->elem;
+ if (__builtin_expect (end + length <= LOCAL_ELEMS, true))
+ for (unsigned int j = 0; j < length; j++)
+ base[end++] = T::get_value (vec[j]);
+ else
+ for (unsigned int j = 0; j < length; j++)
+ base = add_single_to_queue (array, base, end++,
+ T::get_value (vec[j]));
+ if (code == SEQUENCE && end == length)
+ /* If the subrtxes of the sequence fill the entire array then
+ we know that no other parts of a containing insn are queued.
+ The caller is therefore iterating over the sequence as a
+ PATTERN (...), so we also want the patterns of the
+ subinstructions. */
+ for (unsigned int j = 0; j < length; j++)
+ {
+ typename T::rtx_type x = T::get_rtx (base[j]);
+ if (INSN_P (x))
+ base[j] = T::get_value (PATTERN (x));
+ }
+ }
return end - orig_end;
}
Rainer Orth
2014-10-08 07:50:08 UTC
Permalink
Hi Richard,
Post by Richard Sandiford
Does this work for you? I tested it on x86_64-linux-gnu but obviously
that's not particularly useful for SEQUENCEs.
the patch is fine, as tested on both sparc-sun-solaris2.11 and (for good
measure) i386-pc-solaris2.11.

Thanks.
Rainer
--
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University
Richard Sandiford
2014-10-08 16:04:31 UTC
Permalink
Post by Rainer Orth
Hi Richard,
Post by Richard Sandiford
Does this work for you? I tested it on x86_64-linux-gnu but obviously
that's not particularly useful for SEQUENCEs.
the patch is fine, as tested on both sparc-sun-solaris2.11 and (for good
measure) i386-pc-solaris2.11.
OK, great.

To recap, the idea is that if PATTERN (insn) is a SEQUENCE:

FOR_EACH_SUBRTX (...., insn, x)
...

should iterate over the insns in the SEQUENCE (including pattern, notes,
jump label, etc.). However:

FOR_EACH_SUBRTX (...., PATTERN (insn), x)
...

should only iterate over the patterns of the insns in the SEQUENCE,
since the user of FOR_EACH_SUBRTX isn't expecting to see things like
REG_NOTES (and might not handle them correctly).

Also tested on x86_64-linux-gnu. OK to install?

Thanks,
Richard


gcc/
* rtlanal.c (generic_subrtx_iterator <T>::add_subrtxes_to_queue):
Add the parts of an insn in reverse order, with the pattern at
the top of the queue. Detect when we're iterating over a SEQUENCE
pattern and in that case just consider patterns of subinstructions.

Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c 2014-09-25 16:40:44.944406590 +0100
+++ gcc/rtlanal.c 2014-10-07 13:13:57.698132753 +0100
@@ -128,29 +128,58 @@ generic_subrtx_iterator <T>::add_subrtxe
value_type *base,
size_t end, rtx_type x)
{
- const char *format = GET_RTX_FORMAT (GET_CODE (x));
+ enum rtx_code code = GET_CODE (x);
+ const char *format = GET_RTX_FORMAT (code);
size_t orig_end = end;
- for (int i = 0; format[i]; ++i)
- if (format[i] == 'e')
- {
- value_type subx = T::get_value (x->u.fld[i].rt_rtx);
- if (__builtin_expect (end < LOCAL_ELEMS, true))
- base[end++] = subx;
- else
- base = add_single_to_queue (array, base, end++, subx);
- }
- else if (format[i] == 'E')
- {
- int length = GET_NUM_ELEM (x->u.fld[i].rt_rtvec);
- rtx *vec = x->u.fld[i].rt_rtvec->elem;
- if (__builtin_expect (end + length <= LOCAL_ELEMS, true))
- for (int j = 0; j < length; j++)
- base[end++] = T::get_value (vec[j]);
- else
- for (int j = 0; j < length; j++)
- base = add_single_to_queue (array, base, end++,
- T::get_value (vec[j]));
- }
+ if (__builtin_expect (INSN_P (x), false))
+ {
+ /* Put the pattern at the top of the queue, since that's what
+ we're likely to want most. It also allows for the SEQUENCE
+ code below. */
+ for (int i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; --i)
+ if (format[i] == 'e')
+ {
+ value_type subx = T::get_value (x->u.fld[i].rt_rtx);
+ if (__builtin_expect (end < LOCAL_ELEMS, true))
+ base[end++] = subx;
+ else
+ base = add_single_to_queue (array, base, end++, subx);
+ }
+ }
+ else
+ for (int i = 0; format[i]; ++i)
+ if (format[i] == 'e')
+ {
+ value_type subx = T::get_value (x->u.fld[i].rt_rtx);
+ if (__builtin_expect (end < LOCAL_ELEMS, true))
+ base[end++] = subx;
+ else
+ base = add_single_to_queue (array, base, end++, subx);
+ }
+ else if (format[i] == 'E')
+ {
+ unsigned int length = GET_NUM_ELEM (x->u.fld[i].rt_rtvec);
+ rtx *vec = x->u.fld[i].rt_rtvec->elem;
+ if (__builtin_expect (end + length <= LOCAL_ELEMS, true))
+ for (unsigned int j = 0; j < length; j++)
+ base[end++] = T::get_value (vec[j]);
+ else
+ for (unsigned int j = 0; j < length; j++)
+ base = add_single_to_queue (array, base, end++,
+ T::get_value (vec[j]));
+ if (code == SEQUENCE && end == length)
+ /* If the subrtxes of the sequence fill the entire array then
+ we know that no other parts of a containing insn are queued.
+ The caller is therefore iterating over the sequence as a
+ PATTERN (...), so we also want the patterns of the
+ subinstructions. */
+ for (unsigned int j = 0; j < length; j++)
+ {
+ typename T::rtx_type x = T::get_rtx (base[j]);
+ if (INSN_P (x))
+ base[j] = T::get_value (PATTERN (x));
+ }
+ }
return end - orig_end;
}

Loading...