This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [RS6000] powerpc64 -mcmodel=medium large symbol offsets
- From: Alan Modra <amodra at gmail dot com>
- To: David Edelsohn <dje dot gcc at gmail dot com>, GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Mon, 9 Sep 2013 18:37:03 +0930
- Subject: Re: [RS6000] powerpc64 -mcmodel=medium large symbol offsets
- Authentication-results: sourceware.org; auth=none
- References: <20130906071329 dot GB3430 at bubble dot grove dot modra dot org> <CAGWvny=9tx2QX7+DCvzNWt3S=AB6HWsxbT4rTkNbO8xSq-aArg at mail dot gmail dot com> <20130906233608 dot GA2643 at bubble dot grove dot modra dot org> <20130907024438 dot GB2643 at bubble dot grove dot modra dot org>
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