Paolo Bonzini <[EMAIL PROTECTED]> writes: >> would in some cases be accurate.) I think using an unspec in rs6000 >> would solve some of the port-specific issues. In particular, I don't >> think 36090 would have happened with an unspec representation. > > I agree. So your plan would be to change rs6000 to an unspec, and drop > the problematic hunk in simplify-rtx.c? That would be okay with me, but > it's not a small change for rs6000.
Yeah, this is very much my preferred option. FWIW, here's a proof-of-concept patch for GNU/Linux and AIX. It knowingly breaks Darwin, so it can't be applied as-is. But if the idea seems OK to David, I'll volunteer to do the Darwin stuff too (including x86 if necessary). I compared the gcc.c-torture, gcc.dg and g++.dg output for the following options: -O2 -O2 -fpic -O2 -fPIC -O2 -mminimal-toc on the following targets: powerpc-linux-gnu powerpc64-linux-gnu powerpc-aix4.3 and there were no differences. diffstat says: 4 files changed, 49 insertions(+), 81 deletions(-) Richard gcc/ * config/rs6000/rs6000-protos.h (rs6000_output_addr_const_extra): Declare. * config/rs6000/rs6000.h (OUTPUT_ADDR_CONST_EXTRA): New macro. * config/rs6000/rs6000.md (UNSPEC_TOCREL): New constant. * config/rs6000/rs6000.c (constant_pool_expr_1): Delete. (constant_pool_expr_p): Use split_const and check the base. (toc_relative_expr_p): Likewise, checking for an UNSPEC_TOCREL instead of a MINUS. (legitimate_constant_pool_address_p): Check toc_relative_p instead of constant_pool_expr_p. (print_operand_address): Always use output_addr_const for constant pool addresses. (rs6000_output_addr_const_extra): New function. (create_TOC_reference): Create an UNSPEC_TOCREL instead of a MINUS. Index: gcc/config/rs6000/rs6000-protos.h =================================================================== --- gcc/config/rs6000/rs6000-protos.h 2008-09-07 11:22:24.000000000 +0100 +++ gcc/config/rs6000/rs6000-protos.h 2008-09-07 12:32:01.000000000 +0100 @@ -77,6 +77,7 @@ extern int extract_ME (rtx); extern void rs6000_output_function_entry (FILE *, const char *); extern void print_operand (FILE *, rtx, int); extern void print_operand_address (FILE *, rtx); +extern bool rs6000_output_addr_const_extra (FILE *, rtx); extern enum rtx_code rs6000_reverse_condition (enum machine_mode, enum rtx_code); extern void rs6000_emit_sCOND (enum rtx_code, rtx); Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h 2008-09-07 11:20:37.000000000 +0100 +++ gcc/config/rs6000/rs6000.h 2008-09-07 12:31:43.000000000 +0100 @@ -2344,6 +2344,12 @@ #define PRINT_OPERAND_PUNCT_VALID_P(CODE #define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR) +#define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \ + do \ + if (!rs6000_output_addr_const_extra (STREAM, X)) \ + goto FAIL; \ + while (0) + /* uncomment for disabling the corresponding default options */ /* #define MACHINE_no_sched_interblock */ /* #define MACHINE_no_sched_speculative */ Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md 2008-09-07 11:13:27.000000000 +0100 +++ gcc/config/rs6000/rs6000.md 2008-09-07 12:02:53.000000000 +0100 @@ -99,6 +99,7 @@ (define_constants (UNSPEC_DLMZB_CR 46) (UNSPEC_DLMZB_STRLEN 47) (UNSPEC_RSQRT 48) + (UNSPEC_TOCREL 49) ]) ;; Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c 2008-09-07 10:53:53.000000000 +0100 +++ gcc/config/rs6000/rs6000.c 2008-09-07 16:17:05.000000000 +0100 @@ -765,7 +765,6 @@ static void rs6000_emit_allocate_stack ( static unsigned rs6000_hash_constant (rtx); static unsigned toc_hash_function (const void *); static int toc_hash_eq (const void *, const void *); -static int constant_pool_expr_1 (rtx, int *, int *); static bool constant_pool_expr_p (rtx); static bool legitimate_small_data_p (enum machine_mode, rtx); static bool legitimate_lo_sum_address_p (enum machine_mode, rtx, int); @@ -3456,58 +3455,28 @@ gpr_or_gpr_p (rtx op0, rtx op1) /* Subroutines of rs6000_legitimize_address and rs6000_legitimate_address. */ -static int -constant_pool_expr_1 (rtx op, int *have_sym, int *have_toc) -{ - switch (GET_CODE (op)) - { - case SYMBOL_REF: - if (RS6000_SYMBOL_REF_TLS_P (op)) - return 0; - else if (CONSTANT_POOL_ADDRESS_P (op)) - { - if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (op), Pmode)) - { - *have_sym = 1; - return 1; - } - else - return 0; - } - else if (! strcmp (XSTR (op, 0), toc_label_name)) - { - *have_toc = 1; - return 1; - } - else - return 0; - case PLUS: - case MINUS: - return (constant_pool_expr_1 (XEXP (op, 0), have_sym, have_toc) - && constant_pool_expr_1 (XEXP (op, 1), have_sym, have_toc)); - case CONST: - return constant_pool_expr_1 (XEXP (op, 0), have_sym, have_toc); - case CONST_INT: - return 1; - default: - return 0; - } -} - static bool constant_pool_expr_p (rtx op) { - int have_sym = 0; - int have_toc = 0; - return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_sym; + rtx base, offset; + + split_const (op, &base, &offset); + return (GET_CODE (base) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (base) + && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (base), Pmode)); } bool toc_relative_expr_p (rtx op) { - int have_sym = 0; - int have_toc = 0; - return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_toc; + rtx base, offset; + + if (!CONSTANT_P (op)) + return false; + + split_const (op, &base, &offset); + return (GET_CODE (base) == UNSPEC + && XINT (base, 1) == UNSPEC_TOCREL); } bool @@ -3517,7 +3486,7 @@ legitimate_constant_pool_address_p (rtx && GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == REG && (TARGET_MINIMAL_TOC || REGNO (XEXP (x, 0)) == TOC_REGISTER) - && constant_pool_expr_p (XEXP (x, 1))); + && toc_relative_expr_p (XEXP (x, 1))); } static bool @@ -12465,45 +12434,37 @@ print_operand_address (FILE *file, rtx x #endif else if (legitimate_constant_pool_address_p (x)) { - if (TARGET_AIX && (!TARGET_ELF || !TARGET_MINIMAL_TOC)) - { - rtx contains_minus = XEXP (x, 1); - rtx minus, symref; - const char *name; - - /* Find the (minus (sym) (toc)) buried in X, and temporarily - turn it into (sym) for output_addr_const. */ - while (GET_CODE (XEXP (contains_minus, 0)) != MINUS) - contains_minus = XEXP (contains_minus, 0); - - minus = XEXP (contains_minus, 0); - symref = XEXP (minus, 0); - gcc_assert (GET_CODE (XEXP (minus, 1)) == SYMBOL_REF); - XEXP (contains_minus, 0) = symref; - if (TARGET_ELF) - { - char *newname; - - name = XSTR (symref, 0); - newname = XALLOCAVEC (char, strlen (name) + sizeof ("@toc")); - strcpy (newname, name); - strcat (newname, "@toc"); - XSTR (symref, 0) = newname; - } - output_addr_const (file, XEXP (x, 1)); - if (TARGET_ELF) - XSTR (symref, 0) = name; - XEXP (contains_minus, 0) = minus; - } - else - output_addr_const (file, XEXP (x, 1)); - + output_addr_const (file, XEXP (x, 1)); fprintf (file, "(%s)", reg_names[REGNO (XEXP (x, 0))]); } else gcc_unreachable (); } +/* Implement OUTPUT_ADDR_CONST_EXTRA for address X. */ + +bool +rs6000_output_addr_const_extra (FILE *file, rtx x) +{ + if (GET_CODE (x) == UNSPEC) + switch (XINT (x, 1)) + { + case UNSPEC_TOCREL: + x = XVECEXP (x, 0, 0); + gcc_assert (GET_CODE (x) == SYMBOL_REF); + output_addr_const (file, x); + if (!TARGET_AIX || (TARGET_ELF && TARGET_MINIMAL_TOC)) + { + putc ('-', file); + assemble_name (file, toc_label_name); + } + else if (TARGET_ELF) + fputs ("@toc", file); + return true; + } + return false; +} + /* Target hook for assembling integer objects. The PowerPC version has to handle fixup entries for relocatable code if RELOCATABLE_NEEDS_FIXUP is defined. It also needs to handle DI-mode objects on 64-bit @@ -15322,8 +15283,7 @@ create_TOC_reference (rtx symbol) return gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, TOC_REGISTER), gen_rtx_CONST (Pmode, - gen_rtx_MINUS (Pmode, symbol, - gen_rtx_SYMBOL_REF (Pmode, toc_label_name)))); + gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol), UNSPEC_TOCREL))); } /* If _Unwind_* has been called from within the same module,