This patch allows the user to specify -mfp-in-toc/-msum-in-toc options without being overridden when -fsection-anchors or -mcmodel != small is in effect. I also change the default to -mno-fp-in-toc for -mcmodel=medium, because -mcmodel=medium ought to be able to address constants anywhere from the toc pointer, and putting them in their usual constant sections (.rodata.cst4 and .rodata.cst8) allow them to be merged at link time. For -mcmodel=large we keep the default as -mfp-in-toc because large code model requires a toc entry to address any constant outside the TOC.
The patch also allows -mcmodel=medium toc relative addressing for CONSTANT_POOL_ADDRESS_P constants (the very sort we get from force_const_mem when -mno-fp-in-toc), and allows combine to merge the low-part of the address calculation with the load/store from memory. I'm not sure now why I had this disabled, perhaps there was a problem when we split toc refs early. Bootstrapped and regression tested powerpc64-linux. OK to apply? * config/rs6000/rs6000.c (rs6000_option_override_internal): Don't override user -mfp-in-toc. (legitimate_constant_pool_address_p): Assume sufficent alignment on all CONSTANT_POOL_ADDRESS_P constants, not just those put in the TOC. (use_toc_relative_ref): Allow CONSTANT_POOL_ADDRESS_P constants for -mcmodel=medium. * config/rs6000/linux64.h (SUBSUBTARGET_OVERRIDE_OPTIONS): Don't override user -mfp-in-toc or -msum-in-toc. Default to -mno-fp-in-toc for -mcmodel=medium. Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 199646) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -3042,7 +3042,8 @@ rs6000_option_override_internal (bool global_init_ /* Place FP constants in the constant pool instead of TOC if section anchors enabled. */ - if (flag_section_anchors) + if (flag_section_anchors + && !global_options_set.x_TARGET_NO_FP_IN_TOC) TARGET_NO_FP_IN_TOC = 1; if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET) @@ -5617,7 +5618,8 @@ legitimate_constant_pool_address_p (const_rtx x, e { return (toc_relative_expr_p (x, strict) && (TARGET_CMODEL != CMODEL_MEDIUM - || constant_pool_expr_p (XVECEXP (tocrel_base, 0, 0)) + || (GET_CODE (XVECEXP (tocrel_base, 0, 0)) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (XVECEXP (tocrel_base, 0, 0))) || mode == QImode || offsettable_ok_by_alignment (XVECEXP (tocrel_base, 0, 0), INTVAL (tocrel_offset), mode))); @@ -6504,7 +6506,6 @@ use_toc_relative_ref (rtx 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))); } Index: gcc/config/rs6000/linux64.h =================================================================== --- gcc/config/rs6000/linux64.h (revision 199644) +++ gcc/config/rs6000/linux64.h (working copy) @@ -136,8 +136,11 @@ extern int dot_symbols; SET_CMODEL (CMODEL_MEDIUM); \ if (rs6000_current_cmodel != CMODEL_SMALL) \ { \ - TARGET_NO_FP_IN_TOC = 0; \ - TARGET_NO_SUM_IN_TOC = 0; \ + if (!global_options_set.x_TARGET_NO_FP_IN_TOC) \ + TARGET_NO_FP_IN_TOC \ + = rs6000_current_cmodel == CMODEL_MEDIUM; \ + if (!global_options_set.x_TARGET_NO_SUM_IN_TOC) \ + TARGET_NO_SUM_IN_TOC = 0; \ } \ } \ } \ -- Alan Modra Australia Development Lab, IBM