This revision splits the medium/large code model toc reference after reload. I expected this to be more difficult, but it turned out surprisingly easy. Besides creating the rtl that way, and tweaking toc_relative_expr_p to match, it was just: Move the 'R' constraint handling out of various movsi/di instructions into a new instruction that is split after reload, and modify legitimize_reload_address to handle all the other splits inside MEMs.
Bootstrapped and regression tested powerpc-linux. I also intend to spec test this change. Generated code has the expected improvements: libstdc++.so saw a small reduction in code size due to removing silly uses of call-saved regs to hold the high part of a toc reference. OK to apply? * config/rs6000/predicates.md (input_operand): Don't match constant pool addresses. Remove label_ref, high and plus from match_code list. Remove redundant CONSTANT_P test. (splat_input_operand): Similarly update match_code list. (small_toc_ref): New predicate. * config/rs6000/rs6000-protos.h (toc_relative_expr_p): Update prototype. * config/rs6000/rs6000.c (tocrel_base, tocrel_offset): Make const. (legitimate_constant_pool_address_p): Move TARGET_TOC test and register checks to.. (toc_relative_expr_p): ..here. Add "strict" param. Match new rtl generated by create_TOC_reference. (rs6000_legitimize_address): Update cerate_TOC_reference call. (rs6000_delegitimize_address): Handle new rtl for toc refs. (rs6000_cannot_force_const_mem, rs6000_find_base_term): Likewise. (use_toc_relative_ref): New function, split out from.. (rs6000_emit_move): ..here. Remove redundant tests. Update create_TOC_reference calls. (rs6000_legitimize_reload_address): Formatting. Handle splitting of medium/large model toc addresses. Use use_toc_relative_ref. (print_operand): Formatting, style. Adjust for toc changes. (print_operand_address): Likewise. (rs6000_output_addr_const_extra): Likewise. (create_TOC_reference): Put TOC_REGISTER in UNSPEC_TOCREL rather than a PLUS. Use this formulation for both high and low part of -mcmodel=medium/large toc reference too. Before reload, always use the small model formulation. * config/rs6000/rs6000.md (tls_gd, tls_gd_high): Similarly avoid a PLUS in high part of addresses here. (tls_ld, tls_ld_high, tls_got_dtprel, tls_got_dtprel_high): Likewise. (tls_got_tprel, tls_got_tprel_high, largetoc_high): Likewise. (largetoc_high, largetoc_low): Move earlier. Cope when no base reg available. (largetoc_high_plus): New insn. (movsi_internal1, movsi_internal1_single, movsf_softfloat, movdi_mfpgpr, movdi_internal64): Don't handle 'R' constraint here.. (tocref): ..instead do so here, new insn and split. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 187010) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -5280,15 +5280,33 @@ constant_pool_expr_p (rtx op) && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (base), Pmode)); } -static rtx tocrel_base, tocrel_offset; +static const_rtx tocrel_base, tocrel_offset; bool -toc_relative_expr_p (rtx op) +toc_relative_expr_p (const_rtx op, bool strict) { - if (GET_CODE (op) != CONST) + if (!TARGET_TOC) return false; - split_const (op, &tocrel_base, &tocrel_offset); + if (TARGET_CMODEL != CMODEL_SMALL) + { + /* Only match the low part. */ + if (GET_CODE (op) == LO_SUM + && REG_P (XEXP (op, 0)) + && INT_REG_OK_FOR_BASE_P (XEXP (op, 0), strict)) + op = XEXP (op, 1); + else if (strict) + return false; + } + + tocrel_base = op; + tocrel_offset = const0_rtx; + if (GET_CODE (op) == PLUS && CONST_INT_P (XEXP (op, 1))) + { + tocrel_base = XEXP (op, 0); + tocrel_offset = XEXP (op, 1); + } + return (GET_CODE (tocrel_base) == UNSPEC && XINT (tocrel_base, 1) == UNSPEC_TOCREL); } @@ -5300,14 +5318,7 @@ bool legitimate_constant_pool_address_p (const_rtx x, enum machine_mode mode, bool strict) { - return (TARGET_TOC - && (GET_CODE (x) == PLUS || GET_CODE (x) == LO_SUM) - && GET_CODE (XEXP (x, 0)) == REG - && (REGNO (XEXP (x, 0)) == TOC_REGISTER - || ((TARGET_MINIMAL_TOC - || TARGET_CMODEL != CMODEL_SMALL) - && INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))) - && toc_relative_expr_p (XEXP (x, 1)) + return (toc_relative_expr_p (x, strict) && (TARGET_CMODEL != CMODEL_MEDIUM || constant_pool_expr_p (XVECEXP (tocrel_base, 0, 0)) || mode == QImode @@ -5687,10 +5698,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBU && GET_CODE (x) == SYMBOL_REF && constant_pool_expr_p (x) && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode)) - { - rtx reg = TARGET_CMODEL != CMODEL_SMALL ? gen_reg_rtx (Pmode) : NULL_RTX; - return create_TOC_reference (x, reg); - } + return create_TOC_reference (x, NULL_RTX); else return x; } @@ -5773,49 +5781,55 @@ rs6000_output_dwarf_dtprel (FILE *file, int size, static rtx rs6000_delegitimize_address (rtx orig_x) { - rtx x, y; + rtx x, y, offset; orig_x = delegitimize_mem_from_attrs (orig_x); x = orig_x; if (MEM_P (x)) x = XEXP (x, 0); - if (GET_CODE (x) == (TARGET_CMODEL != CMODEL_SMALL ? LO_SUM : PLUS) - && GET_CODE (XEXP (x, 1)) == CONST) + y = x; + if (TARGET_CMODEL != CMODEL_SMALL + && GET_CODE (y) == LO_SUM) + y = XEXP (y, 1); + + offset = NULL_RTX; + if (GET_CODE (y) == PLUS + && GET_MODE (y) == Pmode + && CONST_INT_P (XEXP (y, 1))) { - rtx offset = NULL_RTX; + offset = XEXP (y, 1); + y = XEXP (y, 0); + } - y = XEXP (XEXP (x, 1), 0); - if (GET_CODE (y) == PLUS - && GET_MODE (y) == Pmode - && CONST_INT_P (XEXP (y, 1))) + if (GET_CODE (y) == UNSPEC + && XINT (y, 1) == UNSPEC_TOCREL) + { +#ifdef ENABLE_CHECKING + if (REG_P (XVECEXP (y, 0, 1)) + && REGNO (XVECEXP (y, 0, 1)) == TOC_REGISTER) { - offset = XEXP (y, 1); - y = XEXP (y, 0); + /* All good. */ } - if (GET_CODE (y) == UNSPEC - && XINT (y, 1) == UNSPEC_TOCREL - && ((GET_CODE (XEXP (x, 0)) == REG - && (REGNO (XEXP (x, 0)) == TOC_REGISTER - || TARGET_MINIMAL_TOC - || TARGET_CMODEL != CMODEL_SMALL)) - || (TARGET_CMODEL != CMODEL_SMALL - && GET_CODE (XEXP (x, 0)) == CONST - && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS - && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == REG - && REGNO (XEXP (XEXP (XEXP (x, 0), 0), 0)) == TOC_REGISTER - && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == HIGH - && rtx_equal_p (XEXP (x, 1), - XEXP (XEXP (XEXP (XEXP (x, 0), 0), 1), 0))))) + else if (GET_CODE (XVECEXP (y, 0, 1)) == DEBUG_EXPR) { - y = XVECEXP (y, 0, 0); - if (offset != NULL_RTX) - y = gen_rtx_PLUS (Pmode, y, offset); - if (!MEM_P (orig_x)) - return y; - else - return replace_equiv_address_nv (orig_x, y); + /* Weirdness alert. df_note_compute can replace r2 with a + debug_expr when this unspec is in a debug_insn. + Seen in gcc.dg/pr51957-1.c */ } + else + { + debug_rtx (orig_x); + abort (); + } +#endif + y = XVECEXP (y, 0, 0); + if (offset != NULL_RTX) + y = gen_rtx_PLUS (Pmode, y, offset); + if (!MEM_P (orig_x)) + return y; + else + return replace_equiv_address_nv (orig_x, y); } if (TARGET_MACHO @@ -6077,9 +6091,8 @@ rs6000_tls_referenced_p (rtx x) static bool rs6000_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x) { - if (GET_CODE (x) == CONST - && GET_CODE (XEXP (x, 0)) == PLUS - && GET_CODE (XEXP (XEXP (x, 0), 1)) == HIGH) + if (GET_CODE (x) == HIGH + && GET_CODE (XEXP (x, 0)) == UNSPEC) return true; return rs6000_tls_referenced_p (x); @@ -6094,6 +6107,21 @@ rs6000_tls_symbol_ref_1 (rtx *x, void *data ATTRIB return RS6000_SYMBOL_REF_TLS_P (*x); } +/* Return true iff the given SYMBOL_REF refers to a constant pool entry + that we have put in the TOC, or for cmodel=medium, if the SYMBOL_REF + can be addressed relative to the toc pointer. */ + +static bool +use_toc_relative_ref (rtx sym) +{ + return ((constant_pool_expr_p (sym) + && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (sym), + get_pool_mode (sym))) + || (TARGET_CMODEL == CMODEL_MEDIUM + && !CONSTANT_POOL_ADDRESS_P (sym) + && SYMBOL_REF_LOCAL_P (sym))); +} + /* Our implementation of LEGITIMIZE_RELOAD_ADDRESS. Returns a value to replace the input X, or the original X if no replacement is called for. The output parameter *WIN is 1 if the calling macro should goto WIN, @@ -6131,7 +6159,7 @@ rs6000_legitimize_reload_address (rtx x, enum mach { push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, - opnum, (enum reload_type)type); + opnum, (enum reload_type) type); *win = 1; return x; } @@ -6142,7 +6170,7 @@ rs6000_legitimize_reload_address (rtx x, enum mach { push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, - opnum, (enum reload_type)type); + opnum, (enum reload_type) type); *win = 1; return x; } @@ -6160,24 +6188,18 @@ rs6000_legitimize_reload_address (rtx x, enum mach floating point constant. */ push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, - opnum, (enum reload_type)type); + opnum, (enum reload_type) type); *win = 1; return x; } #endif if (TARGET_CMODEL != CMODEL_SMALL - && GET_CODE (x) == LO_SUM - && GET_CODE (XEXP (x, 0)) == PLUS - && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG - && REGNO (XEXP (XEXP (x, 0), 0)) == TOC_REGISTER - && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST - && GET_CODE (XEXP (XEXP (XEXP (x, 0), 1), 0)) == HIGH - && GET_CODE (XEXP (x, 1)) == CONST - && GET_CODE (XEXP (XEXP (x, 1), 0)) == UNSPEC - && XINT (XEXP (XEXP (x, 1), 0), 1) == UNSPEC_TOCREL - && rtx_equal_p (XEXP (XEXP (XEXP (XEXP (x, 0), 1), 0), 0), XEXP (x, 1))) + && reg_offset_p + && small_toc_ref (x, VOIDmode)) { + rtx hi = gen_rtx_HIGH (Pmode, copy_rtx (x)); + x = gen_rtx_LO_SUM (Pmode, hi, x); push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, opnum, (enum reload_type) type); @@ -6240,7 +6262,7 @@ rs6000_legitimize_reload_address (rtx x, enum mach push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0, - opnum, (enum reload_type)type); + opnum, (enum reload_type) type); *win = 1; return x; } @@ -6281,7 +6303,7 @@ rs6000_legitimize_reload_address (rtx x, enum mach push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL, BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, - opnum, (enum reload_type)type); + opnum, (enum reload_type) type); *win = 1; return x; } @@ -6308,8 +6330,7 @@ rs6000_legitimize_reload_address (rtx x, enum mach if (TARGET_TOC && reg_offset_p && GET_CODE (x) == SYMBOL_REF - && constant_pool_expr_p (x) - && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode)) + && use_toc_relative_ref (x)) { x = create_TOC_reference (x, NULL_RTX); if (TARGET_CMODEL != CMODEL_SMALL) @@ -6544,9 +6565,13 @@ rs6000_debug_mode_dependent_address (const_rtx add rtx rs6000_find_base_term (rtx op) { - rtx base, offset; + rtx base; - split_const (op, &base, &offset); + base = op; + if (GET_CODE (base) == CONST) + base = XEXP (base, 0); + if (GET_CODE (base) == PLUS) + base = XEXP (base, 0); if (GET_CODE (base) == UNSPEC) switch (XINT (base, 1)) { @@ -7198,33 +7223,13 @@ rs6000_emit_move (rtx dest, rtx source, enum machi /* If this is a SYMBOL_REF that refers to a constant pool entry, and we have put it in the TOC, we just need to make a TOC-relative reference to it. */ - if ((TARGET_TOC - && GET_CODE (operands[1]) == SYMBOL_REF - && constant_pool_expr_p (operands[1]) - && ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (operands[1]), - get_pool_mode (operands[1]))) - || (TARGET_CMODEL == CMODEL_MEDIUM - && GET_CODE (operands[1]) == SYMBOL_REF - && !CONSTANT_POOL_ADDRESS_P (operands[1]) - && SYMBOL_REF_LOCAL_P (operands[1]))) - { - rtx reg = NULL_RTX; - if (TARGET_CMODEL != CMODEL_SMALL) - { - if (can_create_pseudo_p ()) - reg = gen_reg_rtx (Pmode); - else - reg = operands[0]; - } - operands[1] = create_TOC_reference (operands[1], reg); - } + if (TARGET_TOC + && GET_CODE (operands[1]) == SYMBOL_REF + && use_toc_relative_ref (operands[1])) + operands[1] = create_TOC_reference (operands[1], operands[0]); else if (mode == Pmode && CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != HIGH - && !(TARGET_CMODEL != CMODEL_SMALL - && GET_CODE (operands[1]) == CONST - && GET_CODE (XEXP (operands[1], 0)) == PLUS - && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == HIGH) && ((GET_CODE (operands[1]) != CONST_INT && ! easy_fp_constant (operands[1], mode)) || (GET_CODE (operands[1]) == CONST_INT @@ -7232,9 +7237,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machi > (TARGET_CMODEL != CMODEL_SMALL ? 3 : 2))) || (GET_CODE (operands[0]) == REG && FP_REGNO_P (REGNO (operands[0])))) - && ! legitimate_constant_pool_address_p (operands[1], mode, - false) - && ! toc_relative_expr_p (operands[1]) + && !toc_relative_expr_p (operands[1], false) && (TARGET_CMODEL == CMODEL_SMALL || can_create_pseudo_p () || (REG_P (operands[0]) @@ -7284,16 +7287,8 @@ rs6000_emit_move (rtx dest, rtx source, enum machi get_pool_constant (XEXP (operands[1], 0)), get_pool_mode (XEXP (operands[1], 0)))) { - rtx tocref; - rtx reg = NULL_RTX; - if (TARGET_CMODEL != CMODEL_SMALL) - { - if (can_create_pseudo_p ()) - reg = gen_reg_rtx (Pmode); - else - reg = operands[0]; - } - tocref = create_TOC_reference (XEXP (operands[1], 0), reg); + rtx tocref = create_TOC_reference (XEXP (operands[1], 0), + operands[0]); operands[1] = gen_const_mem (mode, tocref); set_mem_alias_set (operands[1], get_TOC_alias_set ()); } @@ -14704,7 +14699,7 @@ print_operand (FILE *file, rtx x, int code) case 'D': /* Like 'J' but get to the GT bit only. */ - gcc_assert (GET_CODE (x) == REG); + gcc_assert (REG_P (x)); /* Bit 1 is GT bit. */ i = 4 * (REGNO (x) - CR0_REGNO) + 1; @@ -14824,9 +14819,9 @@ print_operand (FILE *file, rtx x, int code) case 'L': /* Write second word of DImode or DFmode reference. Works on register or non-indexed memory only. */ - if (GET_CODE (x) == REG) + if (REG_P (x)) fputs (reg_names[REGNO (x) + 1], file); - else if (GET_CODE (x) == MEM) + else if (MEM_P (x)) { /* Handle possible auto-increment. Since it is pre-increment and we have already done it, we can just use an offset of word. */ @@ -14995,7 +14990,7 @@ print_operand (FILE *file, rtx x, int code) case 't': /* Like 'J' but get to the OVERFLOW/UNORDERED bit. */ - gcc_assert (GET_CODE (x) == REG && GET_MODE (x) == CCmode); + gcc_assert (REG_P (x) && GET_MODE (x) == CCmode); /* Bit 3 is OV bit. */ i = 4 * (REGNO (x) - CR0_REGNO) + 3; @@ -15035,7 +15030,7 @@ print_operand (FILE *file, rtx x, int code) case 'U': /* Print `u' if this has an auto-increment or auto-decrement. */ - if (GET_CODE (x) == MEM + if (MEM_P (x) && (GET_CODE (XEXP (x, 0)) == PRE_INC || GET_CODE (XEXP (x, 0)) == PRE_DEC || GET_CODE (XEXP (x, 0)) == PRE_MODIFY)) @@ -15144,7 +15139,7 @@ print_operand (FILE *file, rtx x, int code) return; case 'X': - if (GET_CODE (x) == MEM + if (MEM_P (x) && (legitimate_indexed_address_p (XEXP (x, 0), 0) || (GET_CODE (XEXP (x, 0)) == PRE_MODIFY && legitimate_indexed_address_p (XEXP (XEXP (x, 0), 1), 0)))) @@ -15153,9 +15148,9 @@ print_operand (FILE *file, rtx x, int code) case 'Y': /* Like 'L', for third word of TImode */ - if (GET_CODE (x) == REG) + if (REG_P (x)) fputs (reg_names[REGNO (x) + 2], file); - else if (GET_CODE (x) == MEM) + else if (MEM_P (x)) { if (GET_CODE (XEXP (x, 0)) == PRE_INC || GET_CODE (XEXP (x, 0)) == PRE_DEC) @@ -15203,9 +15198,9 @@ print_operand (FILE *file, rtx x, int code) case 'Z': /* Like 'L', for last word of TImode. */ - if (GET_CODE (x) == REG) + if (REG_P (x)) fputs (reg_names[REGNO (x) + 3], file); - else if (GET_CODE (x) == MEM) + else if (MEM_P (x)) { if (GET_CODE (XEXP (x, 0)) == PRE_INC || GET_CODE (XEXP (x, 0)) == PRE_DEC) @@ -15225,7 +15220,7 @@ print_operand (FILE *file, rtx x, int code) { rtx tmp; - gcc_assert (GET_CODE (x) == MEM); + gcc_assert (MEM_P (x)); tmp = XEXP (x, 0); @@ -15236,7 +15231,7 @@ print_operand (FILE *file, rtx x, int code) || GET_MODE (x) == TImode)) { /* Handle [reg]. */ - if (GET_CODE (tmp) == REG) + if (REG_P (tmp)) { fprintf (file, "0(%s)", reg_names[REGNO (tmp)]); break; @@ -15247,7 +15242,7 @@ print_operand (FILE *file, rtx x, int code) { int x; - gcc_assert (GET_CODE (XEXP (tmp, 0)) == REG); + gcc_assert (REG_P (XEXP (tmp, 0))); x = INTVAL (XEXP (tmp, 1)); fprintf (file, "%d(%s)", x, reg_names[REGNO (XEXP (tmp, 0))]); @@ -15264,7 +15259,7 @@ print_operand (FILE *file, rtx x, int code) else if (VECTOR_MEM_VSX_P (GET_MODE (x)) && GET_CODE (tmp) == PRE_MODIFY) tmp = XEXP (tmp, 1); - if (GET_CODE (tmp) == REG) + if (REG_P (tmp)) fprintf (file, "0,%s", reg_names[REGNO (tmp)]); else { @@ -15287,9 +15282,9 @@ print_operand (FILE *file, rtx x, int code) } case 0: - if (GET_CODE (x) == REG) + if (REG_P (x)) fprintf (file, "%s", reg_names[REGNO (x)]); - else if (GET_CODE (x) == MEM) + else if (MEM_P (x)) { /* We need to handle PRE_INC and PRE_DEC here, since we need to know the width from the mode. */ @@ -15306,14 +15301,14 @@ print_operand (FILE *file, rtx x, int code) } else { - if (toc_relative_expr_p (x)) + if (toc_relative_expr_p (x, false)) /* This hack along with a corresponding hack in rs6000_output_addr_const_extra arranges to output addends where the assembler expects to find them. eg. - (const (plus (unspec [symbol_ref ("x") tocrel]) 4)) + (plus (unspec [(symbol_ref ("x")) (reg 2)] tocrel) 4) without this hack would be output as "x@toc+4". We want "x+4@toc". */ - output_addr_const (file, tocrel_base); + output_addr_const (file, CONST_CAST_RTX (tocrel_base)); else output_addr_const (file, x); } @@ -15333,7 +15328,7 @@ print_operand (FILE *file, rtx x, int code) void print_operand_address (FILE *file, rtx x) { - if (GET_CODE (x) == REG) + if (REG_P (x)) fprintf (file, "0(%s)", reg_names[ REGNO (x) ]); else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST || GET_CODE (x) == LABEL_REF) @@ -15345,9 +15340,9 @@ print_operand_address (FILE *file, rtx x) else gcc_assert (!TARGET_TOC); } - else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == REG) + else if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) + && REG_P (XEXP (x, 1))) { - gcc_assert (REG_P (XEXP (x, 0))); if (REGNO (XEXP (x, 0)) == 0) fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 1)) ], reg_names[ REGNO (XEXP (x, 0)) ]); @@ -15355,11 +15350,12 @@ print_operand_address (FILE *file, rtx x) fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 0)) ], reg_names[ REGNO (XEXP (x, 1)) ]); } - else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT) + else if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) + && GET_CODE (XEXP (x, 1)) == CONST_INT) fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%s)", INTVAL (XEXP (x, 1)), reg_names[ REGNO (XEXP (x, 0)) ]); #if TARGET_MACHO - else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG + else if (GET_CODE (x) == LO_SUM && REG_P (XEXP (x, 0)) && CONSTANT_P (XEXP (x, 1))) { fprintf (file, "lo16("); @@ -15367,29 +15363,29 @@ print_operand_address (FILE *file, rtx x) fprintf (file, ")(%s)", reg_names[ REGNO (XEXP (x, 0)) ]); } #endif - else if (legitimate_constant_pool_address_p (x, QImode, true)) +#if TARGET_ELF + else if (GET_CODE (x) == LO_SUM && REG_P (XEXP (x, 0)) + && CONSTANT_P (XEXP (x, 1))) { + output_addr_const (file, XEXP (x, 1)); + fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]); + } +#endif + else if (toc_relative_expr_p (x, false)) + { /* This hack along with a corresponding hack in rs6000_output_addr_const_extra arranges to output addends where the assembler expects to find them. eg. (lo_sum (reg 9) - . (const (plus (unspec [symbol_ref ("x") tocrel]) 8))) + . (plus (unspec [(symbol_ref ("x")) (reg 2)] tocrel) 8)) without this hack would be output as "x@toc+8@l(9)". We want "x+8@toc@l(9)". */ - output_addr_const (file, tocrel_base); + output_addr_const (file, CONST_CAST_RTX (tocrel_base)); if (GET_CODE (x) == LO_SUM) - fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]); + fprintf (file, "@l(%s)", reg_names[REGNO (XEXP (x, 0))]); else - fprintf (file, "(%s)", reg_names[REGNO (XEXP (x, 0))]); + fprintf (file, "(%s)", reg_names[REGNO (XVECEXP (tocrel_base, 0, 1))]); } -#if TARGET_ELF - else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG - && CONSTANT_P (XEXP (x, 1))) - { - output_addr_const (file, XEXP (x, 1)); - fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]); - } -#endif else gcc_unreachable (); } @@ -15403,13 +15399,15 @@ rs6000_output_addr_const_extra (FILE *file, rtx x) switch (XINT (x, 1)) { case UNSPEC_TOCREL: - gcc_assert (GET_CODE (XVECEXP (x, 0, 0)) == SYMBOL_REF); + gcc_checking_assert (GET_CODE (XVECEXP (x, 0, 0)) == SYMBOL_REF + && REG_P (XVECEXP (x, 0, 1)) + && REGNO (XVECEXP (x, 0, 1)) == TOC_REGISTER); output_addr_const (file, XVECEXP (x, 0, 0)); if (x == tocrel_base && tocrel_offset != const0_rtx) { if (INTVAL (tocrel_offset) >= 0) fprintf (file, "+"); - output_addr_const (file, tocrel_offset); + output_addr_const (file, CONST_CAST_RTX (tocrel_offset)); } if (!TARGET_AIX || (TARGET_ELF && TARGET_MINIMAL_TOC)) { @@ -18490,7 +18488,7 @@ uses_TOC (void) rtx create_TOC_reference (rtx symbol, rtx largetoc_reg) { - rtx tocrel, tocreg; + rtx tocrel, tocreg, hi; if (TARGET_DEBUG_ADDR) { @@ -18508,24 +18506,18 @@ create_TOC_reference (rtx symbol, rtx largetoc_reg if (!can_create_pseudo_p ()) df_set_regs_ever_live (TOC_REGISTER, true); - tocrel = gen_rtx_CONST (Pmode, - gen_rtx_UNSPEC (Pmode, gen_rtvec (1, symbol), - UNSPEC_TOCREL)); tocreg = gen_rtx_REG (Pmode, TOC_REGISTER); - if (TARGET_CMODEL != CMODEL_SMALL) + tocrel = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, symbol, tocreg), UNSPEC_TOCREL); + if (TARGET_CMODEL == CMODEL_SMALL || can_create_pseudo_p ()) + return tocrel; + + hi = gen_rtx_HIGH (Pmode, copy_rtx (tocrel)); + if (largetoc_reg != NULL) { - rtx hi = gen_rtx_CONST (Pmode, - gen_rtx_PLUS (Pmode, tocreg, - gen_rtx_HIGH (Pmode, tocrel))); - if (largetoc_reg != NULL) - { - emit_move_insn (largetoc_reg, hi); - hi = largetoc_reg; - } - return gen_rtx_LO_SUM (Pmode, hi, copy_rtx (tocrel)); + emit_move_insn (largetoc_reg, hi); + hi = largetoc_reg; } - else - return gen_rtx_PLUS (Pmode, tocreg, tocrel); + return gen_rtx_LO_SUM (Pmode, hi, tocrel); } /* Issue assembly directives that create a reference to the given DWARF Index: gcc/config/rs6000/predicates.md =================================================================== --- gcc/config/rs6000/predicates.md (revision 187010) +++ gcc/config/rs6000/predicates.md (working copy) @@ -824,8 +824,8 @@ ;; Return 1 if this operand is a valid input for a move insn. (define_predicate "input_operand" - (match_code "label_ref,symbol_ref,const,high,reg,subreg,mem, - const_double,const_vector,const_int,plus") + (match_code "symbol_ref,const,reg,subreg,mem, + const_double,const_vector,const_int") { /* Memory is always valid. */ if (memory_operand (op, mode)) @@ -833,7 +833,6 @@ /* For floating-point, easy constants are valid. */ if (SCALAR_FLOAT_MODE_P (mode) - && CONSTANT_P (op) && easy_fp_constant (op, mode)) return 1; @@ -866,14 +865,6 @@ if (register_operand (op, mode)) return 1; - /* A SYMBOL_REF referring to the TOC is valid. */ - if (legitimate_constant_pool_address_p (op, mode, false)) - return 1; - - /* A constant pool expression (relative to the TOC) is valid */ - if (toc_relative_expr_p (op)) - return 1; - /* V.4 allows SYMBOL_REFs and CONSTs that are in the small data region to be valid. */ if (DEFAULT_ABI == ABI_V4 @@ -886,8 +877,8 @@ ;; Return 1 if this operand is a valid input for a vsx_splat insn. (define_predicate "splat_input_operand" - (match_code "label_ref,symbol_ref,const,high,reg,subreg,mem, - const_double,const_vector,const_int,plus") + (match_code "symbol_ref,const,reg,subreg,mem, + const_double,const_vector,const_int") { if (MEM_P (op)) { @@ -1461,3 +1452,14 @@ && GET_MODE (XEXP (XVECEXP (op, 0, 0), 0)) == BLKmode && XEXP (XVECEXP (op, 0, 0), 1) == const0_rtx); }) + +;; Match a small code model toc reference (or medium and large +;; model toc references before reload). +(define_predicate "small_toc_ref" + (match_code "unspec,plus") +{ + if (GET_CODE (op) == PLUS && CONST_INT_P (XEXP (op, 1))) + op = XEXP (op, 0); + + return GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_TOCREL; +}) Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 187010) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -9261,8 +9261,8 @@ (set_attr "length" "4")]) (define_insn "*movsi_internal1" - [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h") - (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,r,0"))] + [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,*q,*c*l,*h,*h") + (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,*h,r,r,r,0"))] "!TARGET_SINGLE_FPU && (gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode))" "@ @@ -9273,18 +9273,17 @@ {lil|li} %0,%1 {liu|lis} %0,%v1 # - {cal|la} %0,%a1 mf%1 %0 mt%0 %1 mt%0 %1 mt%0 %1 {cror 0,0,0|nop}" - [(set_attr "type" "*,*,load,store,*,*,*,*,mfjmpr,*,mtjmpr,*,*") - (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4")]) + [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,*,mtjmpr,*,*") + (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4")]) (define_insn "*movsi_internal1_single" - [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h,m,*f") - (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,r,0,f,m"))] + [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,*q,*c*l,*h,*h,m,*f") + (match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,*h,r,r,r,0,f,m"))] "TARGET_SINGLE_FPU && (gpc_reg_operand (operands[0], SImode) || gpc_reg_operand (operands[1], SImode))" "@ @@ -9295,7 +9294,6 @@ {lil|li} %0,%1 {liu|lis} %0,%v1 # - {cal|la} %0,%a1 mf%1 %0 mt%0 %1 mt%0 %1 @@ -9303,8 +9301,8 @@ {cror 0,0,0|nop} stfs%U0%X0 %1, %0 lfs%U1%X1 %0, %1" - [(set_attr "type" "*,*,load,store,*,*,*,*,mfjmpr,*,mtjmpr,*,*,*,*") - (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4,4,4")]) + [(set_attr "type" "*,*,load,store,*,*,*,mfjmpr,*,mtjmpr,*,*,*,*") + (set_attr "length" "4,4,4,4,4,4,8,4,4,4,4,4,4,4")]) ;; Split a load of a large constant into the appropriate two-insn ;; sequence. @@ -9499,8 +9497,8 @@ (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,8")]) (define_insn "*movsf_softfloat" - [(set (match_operand:SF 0 "nonimmediate_operand" "=r,cl,q,r,r,m,r,r,r,r,r,*h") - (match_operand:SF 1 "input_operand" "r,r,r,h,m,r,I,L,R,G,Fn,0"))] + [(set (match_operand:SF 0 "nonimmediate_operand" "=r,cl,q,r,r,m,r,r,r,r,*h") + (match_operand:SF 1 "input_operand" "r,r,r,h,m,r,I,L,G,Fn,0"))] "(gpc_reg_operand (operands[0], SFmode) || gpc_reg_operand (operands[1], SFmode)) && (TARGET_SOFT_FLOAT || !TARGET_FPRS)" @@ -9513,12 +9511,11 @@ {st%U0%X0|stw%U0%X0} %1,%0 {lil|li} %0,%1 {liu|lis} %0,%v1 - {cal|la} %0,%a1 # # {cror 0,0,0|nop}" - [(set_attr "type" "*,mtjmpr,*,mfjmpr,load,store,*,*,*,*,*,*") - (set_attr "length" "4,4,4,4,4,4,4,4,4,4,8,4")]) + [(set_attr "type" "*,mtjmpr,*,mfjmpr,load,store,*,*,*,*,*") + (set_attr "length" "4,4,4,4,4,4,4,4,4,8,4")]) (define_expand "movdf" @@ -10146,8 +10143,8 @@ { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }) (define_insn "*movdi_mfpgpr" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*d,*d,m,r,*h,*h,r,*d") - (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,d,m,d,*h,r,0,*d,r"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,*d,*d,m,r,*h,*h,r,*d") + (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,d,m,d,*h,r,0,*d,r"))] "TARGET_POWERPC64 && TARGET_MFPGPR && TARGET_HARD_FLOAT && TARGET_FPRS && (gpc_reg_operand (operands[0], DImode) || gpc_reg_operand (operands[1], DImode))" @@ -10158,7 +10155,6 @@ li %0,%1 lis %0,%v1 # - la %0,%a1 fmr %0,%1 lfd%U1%X1 %0,%1 stfd%U0%X0 %1,%0 @@ -10167,12 +10163,12 @@ {cror 0,0,0|nop} mftgpr %0,%1 mffgpr %0,%1" - [(set_attr "type" "*,load,store,*,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*,mftgpr,mffgpr") - (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4,4")]) + [(set_attr "type" "*,load,store,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*,mftgpr,mffgpr") + (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4")]) (define_insn "*movdi_internal64" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*d,*d,m,r,*h,*h,?wa") - (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,d,m,d,*h,r,0,O"))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,*d,*d,m,r,*h,*h,?wa") + (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,d,m,d,*h,r,0,O"))] "TARGET_POWERPC64 && (!TARGET_MFPGPR || !TARGET_HARD_FLOAT || !TARGET_FPRS) && (gpc_reg_operand (operands[0], DImode) || gpc_reg_operand (operands[1], DImode))" @@ -10183,7 +10179,6 @@ li %0,%1 lis %0,%v1 # - la %0,%a1 fmr %0,%1 lfd%U1%X1 %0,%1 stfd%U0%X0 %1,%0 @@ -10191,8 +10186,8 @@ mt%0 %1 {cror 0,0,0|nop} xxlxor %x0,%x0,%x0" - [(set_attr "type" "*,load,store,*,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*,vecsimple") - (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4,4")]) + [(set_attr "type" "*,load,store,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*,vecsimple") + (set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4")]) ;; immediate value valid for a single instruction hiding in a const_double (define_insn "" @@ -11548,10 +11543,8 @@ "addi %0,%1,%2@got@tlsgd" "&& TARGET_CMODEL != CMODEL_SMALL" [(set (match_dup 3) - (const:TLSmode - (plus:TLSmode (match_dup 1) - (high:TLSmode - (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD))))) + (high:TLSmode + (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGD))) (set (match_dup 0) (lo_sum:TLSmode (match_dup 3) (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGD)))] @@ -11566,11 +11559,10 @@ (define_insn "*tls_gd_high<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") - (const:TLSmode - (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b") - (high:TLSmode - (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] - UNSPEC_TLSGD)))))] + (high:TLSmode + (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b") + (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] + UNSPEC_TLSGD)))] "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL" "addis %0,%1,%2@got@tlsgd@ha" [(set_attr "length" "4")]) @@ -11685,10 +11677,8 @@ "addi %0,%1,%&@got@tlsld" "&& TARGET_CMODEL != CMODEL_SMALL" [(set (match_dup 2) - (const:TLSmode - (plus:TLSmode (match_dup 1) - (high:TLSmode - (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD))))) + (high:TLSmode + (unspec:TLSmode [(const_int 0) (match_dup 1)] UNSPEC_TLSLD))) (set (match_dup 0) (lo_sum:TLSmode (match_dup 2) (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))] @@ -11703,10 +11693,10 @@ (define_insn "*tls_ld_high<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") - (const:TLSmode - (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b") - (high:TLSmode - (unspec:TLSmode [(const_int 0)] UNSPEC_TLSLD)))))] + (high:TLSmode + (unspec:TLSmode [(const_int 0) + (match_operand:TLSmode 1 "gpc_reg_operand" "b")] + UNSPEC_TLSLD)))] "HAVE_AS_TLS && TARGET_TLS_MARKERS && TARGET_CMODEL != CMODEL_SMALL" "addis %0,%1,%&@got@tlsld@ha" [(set_attr "length" "4")]) @@ -11782,10 +11772,8 @@ "l<TLSmode:tls_insn_suffix> %0,%2@got@dtprel(%1)" "&& TARGET_CMODEL != CMODEL_SMALL" [(set (match_dup 3) - (const:TLSmode - (plus:TLSmode (match_dup 1) - (high:TLSmode - (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL))))) + (high:TLSmode + (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTDTPREL))) (set (match_dup 0) (lo_sum:TLSmode (match_dup 3) (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTDTPREL)))] @@ -11800,11 +11788,10 @@ (define_insn "*tls_got_dtprel_high<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") - (const:TLSmode - (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b") - (high:TLSmode - (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] - UNSPEC_TLSGOTDTPREL)))))] + (high:TLSmode + (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b") + (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] + UNSPEC_TLSGOTDTPREL)))] "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL" "addis %0,%1,%2@got@dtprel@ha" [(set_attr "length" "4")]) @@ -11854,10 +11841,8 @@ "l<TLSmode:tls_insn_suffix> %0,%2@got@tprel(%1)" "&& TARGET_CMODEL != CMODEL_SMALL" [(set (match_dup 3) - (const:TLSmode - (plus:TLSmode (match_dup 1) - (high:TLSmode - (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL))))) + (high:TLSmode + (unspec:TLSmode [(match_dup 1) (match_dup 2)] UNSPEC_TLSGOTTPREL))) (set (match_dup 0) (lo_sum:TLSmode (match_dup 3) (unspec:TLSmode [(match_dup 2)] UNSPEC_TLSGOTTPREL)))] @@ -11872,11 +11857,10 @@ (define_insn "*tls_got_tprel_high<TLSmode:tls_abi_suffix>" [(set (match_operand:TLSmode 0 "gpc_reg_operand" "=b") - (const:TLSmode - (plus:TLSmode (match_operand:TLSmode 1 "gpc_reg_operand" "b") - (high:TLSmode - (unspec:TLSmode [(match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] - UNSPEC_TLSGOTTPREL)))))] + (high:TLSmode + (unspec:TLSmode [(match_operand:TLSmode 1 "gpc_reg_operand" "b") + (match_operand:TLSmode 2 "rs6000_tls_symbol_ref" "")] + UNSPEC_TLSGOTTPREL)))] "HAVE_AS_TLS && TARGET_CMODEL != CMODEL_SMALL" "addis %0,%1,%2@got@tprel@ha" [(set_attr "length" "4")]) @@ -12233,6 +12217,45 @@ DONE; }") +;; Largetoc support +(define_insn "*largetoc_high" + [(set (match_operand:DI 0 "gpc_reg_operand" "=b*r") + (high:DI + (unspec [(match_operand:DI 1 "" "") + (match_operand:DI 2 "gpc_reg_operand" "b")] + UNSPEC_TOCREL)))] + "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL" + "{cau|addis} %0,%2,%1@toc@ha") + +(define_insn "*largetoc_high_plus" + [(set (match_operand:DI 0 "gpc_reg_operand" "=b*r") + (high:DI + (plus:DI + (unspec [(match_operand:DI 1 "" "") + (match_operand:DI 2 "gpc_reg_operand" "b")] + UNSPEC_TOCREL) + (match_operand 3 "const_int_operand" "n"))))] + "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL" + "{cau|addis} %0,%2,%1+%3@toc@ha") + +(define_insn "*largetoc_low" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r") + (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,!*r") + (match_operand:DI 2 "" "")))] + "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL" + "@ + {cal %0,%2@l(%1)|addi %0,%1,%2@l} + {ai|addic} %0,%1,%2@l") + +(define_insn_and_split "*tocref<mode>" + [(set (match_operand:P 0 "gpc_reg_operand" "=b*r") + (match_operand:P 1 "small_toc_ref" "R"))] + "TARGET_TOC" + "{cal|la} %0,%a1" + "&& TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL && reload_completed" + [(set (match_dup 0) (high:P (match_dup 1))) + (set (match_dup 0) (lo_sum:P (match_dup 0) (match_dup 1)))]) + ;; Elf specific ways of loading addresses for non-PIC code. ;; The output of this could be r0, but we make a very strong ;; preference for a base register because it will usually @@ -12251,22 +12274,6 @@ "@ {cal|la} %0,%2@l(%1) {ai|addic} %0,%1,%K2") - -;; Largetoc support -(define_insn "largetoc_high" - [(set (match_operand:DI 0 "gpc_reg_operand" "=b") - (const:DI - (plus:DI (match_operand:DI 1 "gpc_reg_operand" "b") - (high:DI (match_operand:DI 2 "" "")))))] - "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL" - "{cau|addis} %0,%1,%2@ha") - -(define_insn "largetoc_low" - [(set (match_operand:DI 0 "gpc_reg_operand" "=r") - (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b") - (match_operand:DI 2 "" "")))] - "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL" - "{cal %0,%2@l(%1)|addi %0,%1,%2@l}") ;; Call and call_value insns (define_expand "call" Index: gcc/config/rs6000/rs6000-protos.h =================================================================== --- gcc/config/rs6000/rs6000-protos.h (revision 187010) +++ gcc/config/rs6000/rs6000-protos.h (working copy) @@ -38,7 +38,7 @@ extern bool macho_lo_sum_memory_operand (rtx, enum extern int num_insns_constant (rtx, enum machine_mode); extern int num_insns_constant_wide (HOST_WIDE_INT); extern int small_data_operand (rtx, enum machine_mode); -extern bool toc_relative_expr_p (rtx); +extern bool toc_relative_expr_p (const_rtx, bool); extern bool invalid_e500_subreg (rtx, enum machine_mode); extern void validate_condition_mode (enum rtx_code, enum machine_mode); extern bool legitimate_constant_pool_address_p (const_rtx, enum machine_mode, -- Alan Modra Australia Development Lab, IBM