AIX has added its equivalent to PPC64 Linux Large TOC support. The appended patch implements GCC support and enables it if the AIX system tools support the new relocs. This is not the default for XLC and will not be the default for GCC.
GCC testsuite produces same results if run with -mcmodel=large. Bootstrapped on powerpc-ibm-aix7.1.0.0. I wanted to allow a chance for additional eyes before I commit it. Thanks, David * configure.ac (HAVE_LD_LARGE_TOC): Add AIX ld test. * configure: Regenerated. * config/rs6000/aix61.h (SUBTARGET_OVERRIDE_OPTIONS): Disable TARGET_NO_FP_IN_TOC and TARGET_NO_SUM_IN_TOC if not CMODEL_SMALL. CMODEL_MEDIUM means CMODEL_LARGE on AIX. (ASM_SPEC): -mvsx implies -mpwr6. Add -many. (ASM_DEFAULT_SPEC): Use -mpwr4. * config/rs6000/rs6000.md (largetoc_high_aix<mode>): New. (largetoc_high_plus_aix<mode>): New. (largetoc_low<mode>): Change to mode iterator. Test TARGET_TOC instead of TARGET_ELF. (tocref): Remove TARGET_ELF test. * config/rs6000/aix64.opt (mcmodel): New. Index: configure.ac =================================================================== --- configure.ac (revision 193425) +++ configure.ac (working copy) @@ -4496,6 +4496,35 @@ ;; esac +case "$target" in + *-*-aix*) + AC_CACHE_CHECK(linker large toc support, + gcc_cv_ld_large_toc, + [gcc_cv_ld_large_toc=no + if test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then + cat > conftest.s <<EOF + .toc + .tc a[TC],a[RW] + .extern a[RW] + .csect .text[PR] +.largetoctest: + addis 9,a@u(2) + ld 3,a@l(9) +EOF + if $gcc_cv_as -a64 -o conftest.o conftest.s > /dev/null 2>&1; then + gcc_cv_ld_large_toc=yes + fi + rm -f conftest conftest.o conftest.s + fi + ]) + if test x"$gcc_cv_ld_large_toc" = xyes; then + AC_DEFINE(HAVE_LD_LARGE_TOC, 1, + [Define if your AIX linker supports a large TOC.]) + fi + ;; +esac + AC_CACHE_CHECK(linker --build-id support, gcc_cv_ld_buildid, [gcc_cv_ld_buildid=no Index: config/rs6000/aix61.h =================================================================== --- config/rs6000/aix61.h (revision 193425) +++ config/rs6000/aix61.h (working copy) @@ -39,6 +39,15 @@ { \ error ("-maix64 required: 64-bit computation with 32-bit addressing not yet supported"); \ } \ + if (rs6000_current_cmodel != CMODEL_SMALL) \ + { \ + TARGET_NO_FP_IN_TOC = 0; \ + TARGET_NO_SUM_IN_TOC = 0; \ + } \ + if (rs6000_current_cmodel == CMODEL_MEDIUM) \ + { \ + rs6000_current_cmodel = CMODEL_LARGE; \ + } \ } while (0); #undef ASM_SPEC @@ -72,10 +81,12 @@ %{mcpu=620: -m620} \ %{mcpu=630: -m620} \ %{mcpu=970: -m970} \ -%{mcpu=G5: -m970}" +%{mcpu=G5: -m970} \ +%{mvsx: %{!mcpu*: -mpwr6}} \ +-many" #undef ASM_DEFAULT_SPEC -#define ASM_DEFAULT_SPEC "-mppc" +#define ASM_DEFAULT_SPEC "-mpwr4" #undef TARGET_OS_CPP_BUILTINS #define TARGET_OS_CPP_BUILTINS() \ Index: config/rs6000/rs6000.md =================================================================== --- config/rs6000/rs6000.md (revision 193425) +++ config/rs6000/rs6000.md (working copy) @@ -10339,6 +10339,15 @@ "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL" "addis %0,%2,%1@toc@ha") +(define_insn "*largetoc_high_aix<mode>" + [(set (match_operand:P 0 "gpc_reg_operand" "=b*r") + (high:P + (unspec [(match_operand:P 1 "" "") + (match_operand:P 2 "gpc_reg_operand" "b")] + UNSPEC_TOCREL)))] + "TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL" + "addis %0,%1@u(%2)") + (define_insn "*largetoc_high_plus" [(set (match_operand:DI 0 "gpc_reg_operand" "=b*r") (high:DI @@ -10350,11 +10359,22 @@ "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL" "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" +(define_insn "*largetoc_high_plus_aix<mode>" + [(set (match_operand:P 0 "gpc_reg_operand" "=b*r") + (high:P + (plus:P + (unspec [(match_operand:P 1 "" "") + (match_operand:P 2 "gpc_reg_operand" "b")] + UNSPEC_TOCREL) + (match_operand 3 "const_int_operand" "n"))))] + "TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL" + "addis %0,%2,%1+%3@u") + +(define_insn "*largetoc_low<mode>" + [(set (match_operand:P 0 "gpc_reg_operand" "=r,r") + (lo_sum:P (match_operand:P 1 "gpc_reg_operand" "b,!*r") + (match_operand:P 2 "" "")))] + "TARGET_TOC && TARGET_CMODEL != CMODEL_SMALL" "@ addi %0,%1,%2@l addic %0,%1,%2@l") @@ -10364,7 +10384,7 @@ (match_operand:P 1 "small_toc_ref" "R"))] "TARGET_TOC" "la %0,%a1" - "&& TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL && reload_completed" + "&& 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)))]) Index: config/rs6000/aix64.opt =================================================================== --- config/rs6000/aix64.opt (revision 193425) +++ config/rs6000/aix64.opt (working copy) @@ -27,6 +27,23 @@ Target Report RejectNegative Negative(maix64) InverseMask(64BIT) Var(rs6000_isa_flags) Compile for 32-bit pointers +mcmodel= +Target RejectNegative Joined Enum(rs6000_cmodel) Var(rs6000_current_cmodel) +Select code model + +Enum +Name(rs6000_cmodel) Type(enum rs6000_cmodel) +Known code models (for use with the -mcmodel= option): + +EnumValue +Enum(rs6000_cmodel) String(small) Value(CMODEL_SMALL) + +EnumValue +Enum(rs6000_cmodel) String(medium) Value(CMODEL_MEDIUM) + +EnumValue +Enum(rs6000_cmodel) String(large) Value(CMODEL_LARGE) + mpe Target Report RejectNegative Var(internal_nothing_1) Save Support message passing with the Parallel Environment