From: Sergei Trofimovich <siarh...@google.com>

Tested on the following example:

    void * a[77] __attribute((visibility("hidden")));
    void f(long o, void * v) { a[0x6ffffeff - o + 66] = v; }

Before the patch generated code uses .GOT entry:

        addl r14 = @ltoffx(a#), r1
        ld8.mov r14 = [r14], a#

After the patch generated code uses static gprel relocation:

        movl r14 = @gprel(a#)
        add r14 = r1, r14

That way gcc will be able to compile glibc's ld: PR/60465

Bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60465
Signed-off-by: Sergei Trofimovich <siarh...@google.com>
---
 gcc/config/ia64/ia64.c        |  2 ++
 gcc/config/ia64/predicates.md | 26 ++++++++++++++++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index f48cebc..6ea5072 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -1105,6 +1105,8 @@ ia64_expand_load_address (rtx dest, rtx src)
     emit_insn (gen_load_fptr (dest, src));
   else if (sdata_symbolic_operand (src, VOIDmode))
     emit_insn (gen_load_gprel (dest, src));
+  else if (local_symbolic_operand64 (src, VOIDmode))
+    emit_insn (gen_load_gprel64 (dest, src));
   else
     {
       HOST_WIDE_INT addend = 0;
diff --git a/gcc/config/ia64/predicates.md b/gcc/config/ia64/predicates.md
index 2aa7a78..9c6951d 100644
--- a/gcc/config/ia64/predicates.md
+++ b/gcc/config/ia64/predicates.md
@@ -97,6 +97,32 @@
     }
 })
 
+;; True if OP refers to a local symbol +any large offset).
+;; To be encoded as:
+;;   movl % = @gprel(symbol+offset)
+;;   add  % = %, gp
+(define_predicate "local_symbolic_operand64" 
+  (match_code "symbol_ref,const")
+{
+  switch (GET_CODE (op))
+    {
+    case CONST:
+      op = XEXP (op, 0);
+      if (GET_CODE (op) != PLUS
+         || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+         || GET_CODE (XEXP (op, 1)) != CONST_INT)
+       return false;
+      op = XEXP (op, 0);
+      /* FALLTHRU */
+
+    case SYMBOL_REF:
+       return SYMBOL_REF_LOCAL_P (op);
+
+    default:
+       gcc_unreachable ();
+    }
+})
+
 ;; True if OP refers to a symbol in the small address area.
 (define_predicate "small_addr_symbolic_operand" 
   (match_code "symbol_ref,const")
-- 
2.6.4

Reply via email to