------- Comment #32 from jakub at gcc dot gnu dot org 2008-05-09 14:32 ------- Actually find_constant_pool_expr can be simplified, given that constant_pool_expr_1 had to return 1 each time.
--- gcc/config/rs6000/rs6000.c.jj 2008-04-24 18:30:39.000000000 +0200 +++ gcc/config/rs6000/rs6000.c 2008-05-09 16:28:39.000000000 +0200 @@ -723,6 +723,7 @@ static unsigned rs6000_hash_constant (rt 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 void find_constant_pool_expr (rtx *, rtx **, rtx **); 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); @@ -3335,6 +3336,32 @@ constant_pool_expr_1 (rtx op, int *have_ } } +static void +find_constant_pool_expr (rtx *op, rtx **sym, rtx **toc) +{ + switch (GET_CODE (*op)) + { + case SYMBOL_REF: + if (CONSTANT_POOL_ADDRESS_P (*op)) + *sym = op; + else + *toc = op; + break; + case PLUS: + case MINUS: + find_constant_pool_expr (&XEXP (*op, 0), sym, toc); + find_constant_pool_expr (&XEXP (*op, 1), sym, toc); + break; + case CONST: + find_constant_pool_expr (&XEXP (*op, 0), sym, toc); + break; + case CONST_INT: + break; + default: + gcc_unreachable (); + } +} + static bool constant_pool_expr_p (rtx op) { @@ -12268,32 +12295,36 @@ print_operand_address (FILE *file, rtx x { if (TARGET_AIX && (!TARGET_ELF || !TARGET_MINIMAL_TOC)) { - rtx contains_minus = XEXP (x, 1); - rtx minus, symref; + rtx *symref = NULL, *tocref = NULL, toc = NULL, addr; 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); - XEXP (contains_minus, 0) = symref; + find_constant_pool_expr (&XEXP (x, 1), &symref, &tocref); + if (tocref) + { + toc = *tocref; + *tocref = const0_rtx; + } if (TARGET_ELF) { char *newname; - name = XSTR (symref, 0); + name = XSTR (*symref, 0); newname = alloca (strlen (name) + sizeof ("@toc")); strcpy (newname, name); strcat (newname, "@toc"); - XSTR (symref, 0) = newname; + XSTR (*symref, 0) = newname; } - output_addr_const (file, XEXP (x, 1)); + addr = XEXP (x, 1); + if (GET_CODE (addr) == CONST) + addr = XEXP (addr, 0); + addr = simplify_rtx (addr); + if (!addr) + addr = XEXP (x, 1); + output_addr_const (file, addr); if (TARGET_ELF) - XSTR (symref, 0) = name; - XEXP (contains_minus, 0) = minus; + XSTR (*symref, 0) = name; + if (tocref) + *tocref = toc; } else output_addr_const (file, XEXP (x, 1)); -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36090