diff options
author | Richard Sandiford <rdsandiford@googlemail.com> | 2008-10-06 19:07:13 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2008-10-06 19:07:13 +0000 |
commit | 2e4316da802a3049f67686001f9dbca5711dcace (patch) | |
tree | ccf0ce9fa3c9617218e9f154f6b176a7969628ca /gcc/config/rs6000 | |
parent | 3517d3a0870e7081d4ded0fa4cc590c602713a8c (diff) | |
download | gcc-2e4316da802a3049f67686001f9dbca5711dcace.zip gcc-2e4316da802a3049f67686001f9dbca5711dcace.tar.gz gcc-2e4316da802a3049f67686001f9dbca5711dcace.tar.bz2 |
rs6000-protos.h (rs6000_output_addr_const_extra): Declare.
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.
From-SVN: r140910
Diffstat (limited to 'gcc/config/rs6000')
-rw-r--r-- | gcc/config/rs6000/rs6000-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 122 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.h | 6 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 1 |
4 files changed, 49 insertions, 81 deletions
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index a9fb2ab..42e939b 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -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); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index d230dfd..e6844dd 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -765,7 +765,6 @@ static void rs6000_emit_allocate_stack (HOST_WIDE_INT, int, int); 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); @@ -3505,58 +3504,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 (GET_CODE (op) != CONST) + return false; + + split_const (op, &base, &offset); + return (GET_CODE (base) == UNSPEC + && XINT (base, 1) == UNSPEC_TOCREL); } bool @@ -3566,7 +3535,7 @@ legitimate_constant_pool_address_p (rtx x) && 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 @@ -12572,45 +12541,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 @@ -15431,8 +15392,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, diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index e1023da..79250c8 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -2352,6 +2352,12 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */ #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 */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 71a73ad..4146c4f 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -99,6 +99,7 @@ (UNSPEC_DLMZB_CR 46) (UNSPEC_DLMZB_STRLEN 47) (UNSPEC_RSQRT 48) + (UNSPEC_TOCREL 49) ]) ;; |