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

Reply via email to