Revised patch with testcase. This one also fixes a small problem with reg_or_add_cint_operand in that any 32-bit value is valid for SImode. Compare with reg_or_sub_cint_operand.
Bootstrapped and regression tested powerpc64-linux. OK to apply? gcc/ * config/rs6000/predicates.md (add_cint_operand): New. (reg_or_add_cint_operand): Use add_cint_operand. * config/rs6000/rs6000.md (largetoc_high_plus): Restrict offset using add_cint_operand. (largetoc_high_plus_aix, small_toc_ref): Likewise. gcc/testsuite/ * gcc.target/powerpc/medium_offset.c: New. Index: gcc/config/rs6000/predicates.md =================================================================== --- gcc/config/rs6000/predicates.md (revision 202351) +++ gcc/config/rs6000/predicates.md (working copy) @@ -376,12 +376,18 @@ (ior (match_code "const_int") (match_operand 0 "gpc_reg_operand"))) +;; Return 1 if op is a constant integer valid for addition with addis, addi. +(define_predicate "add_cint_operand" + (and (match_code "const_int") + (match_test "(unsigned HOST_WIDE_INT) + (INTVAL (op) + (mode == SImode ? 0x80000000 : 0x80008000)) + < (unsigned HOST_WIDE_INT) 0x100000000ll"))) + ;; Return 1 if op is a constant integer valid for addition ;; or non-special register. (define_predicate "reg_or_add_cint_operand" (if_then_else (match_code "const_int") - (match_test "(unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80008000) - < (unsigned HOST_WIDE_INT) 0x100000000ll") + (match_operand 0 "add_cint_operand") (match_operand 0 "gpc_reg_operand"))) ;; Return 1 if op is a constant integer valid for subtraction @@ -1697,7 +1703,7 @@ (define_predicate "small_toc_ref" (match_code "unspec,plus") { - if (GET_CODE (op) == PLUS && CONST_INT_P (XEXP (op, 1))) + if (GET_CODE (op) == PLUS && add_cint_operand (XEXP (op, 1), mode)) 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 202351) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -12207,7 +12209,7 @@ (unspec [(match_operand:DI 1 "" "") (match_operand:DI 2 "gpc_reg_operand" "b")] UNSPEC_TOCREL) - (match_operand 3 "const_int_operand" "n"))))] + (match_operand:DI 3 "add_cint_operand" "n"))))] "TARGET_ELF && TARGET_CMODEL != CMODEL_SMALL" "addis %0,%2,%1+%3@toc@ha") @@ -12218,7 +12220,7 @@ (unspec [(match_operand:P 1 "" "") (match_operand:P 2 "gpc_reg_operand" "b")] UNSPEC_TOCREL) - (match_operand 3 "const_int_operand" "n"))))] + (match_operand:P 3 "add_cint_operand" "n"))))] "TARGET_XCOFF && TARGET_CMODEL != CMODEL_SMALL" "addis %0,%1+%3@u(%2)") Index: gcc/testsuite/gcc.target/powerpc/medium_offset.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/medium_offset.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/medium_offset.c (revision 0) @@ -0,0 +1,12 @@ +/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-O" } */ +/* { dg-final { scan-assembler-not "\\+4611686018427387904" } } */ + +static int x; + +unsigned long +foo (void) +{ + return ((unsigned long) &x) - 0xc000000000000000; +} -- Alan Modra Australia Development Lab, IBM