Here is the completed patch.  Bootstrapped and regression tested
powerpc64-linux.  Is this OK to apply?  If not now, then when gcc is
in stage1 again?

gcc/
        PR target/64703
        * target.def (has_function_descriptors): New hook.
        * doc/tm.texi.in: Add TARGET_HAS_FUNCTION_DESCRIPTORS.
        * doc/tc.texi: Regenerate.
        * tree-ssa-alias.c (pt_solution_includes_base): New function,
        extracted from..
        (ref_maybe_used_by_call_p_1): ..here.  Handle potential memory
        reference by indirect calls on targets using function descriptors.
        * config/rs6000/rs6000.c (TARGET_HAS_FUNCTION_DESCRIPTORS): Define.
        (rs6000_has_function_descriptors): New function.
gcc/testsuite/
        * gcc.target/powerpc/pr64703.c: New.

Index: gcc/target.def
===================================================================
--- gcc/target.def      (revision 220025)
+++ gcc/target.def      (working copy)
@@ -2821,6 +2821,15 @@ The default value of this hook is based on target'
  bool, (void),
  default_has_ifunc_p)
 
+/* True if target defines the address of a function as that of a
+   function descriptor.  */
+DEFHOOK
+(has_function_descriptors,
+ "True if target has function descriptors and defines the address\n\
+of a function as that of a function descriptor.",
+ bool, (void),
+ hook_bool_void_false)
+
 /* True if it is OK to do sibling call optimization for the specified
    call expression EXP.  DECL will be the called function, or NULL if
    this is an indirect call.  */
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in  (revision 220025)
+++ gcc/doc/tm.texi.in  (working copy)
@@ -8175,6 +8175,8 @@ and the associated definitions of those functions.
 
 @hook TARGET_HAS_IFUNC_P
 
+@hook TARGET_HAS_FUNCTION_DESCRIPTORS
+
 @hook TARGET_ATOMIC_ALIGN_FOR_MODE
 
 @hook TARGET_ATOMIC_ASSIGN_EXPAND_FENV
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi     (revision 220025)
+++ gcc/doc/tm.texi     (working copy)
@@ -11510,6 +11510,11 @@ The support includes the assembler, linker and dyn
 The default value of this hook is based on target's libc.
 @end deftypefn
 
+@deftypefn {Target Hook} bool TARGET_HAS_FUNCTION_DESCRIPTORS (void)
+True if target has function descriptors and defines the address
+of a function as that of a function descriptor.
+@end deftypefn
+
 @deftypefn {Target Hook} {unsigned int} TARGET_ATOMIC_ALIGN_FOR_MODE 
(machine_mode @var{mode})
 If defined, this function returns an appropriate alignment in bits for an 
atomic object of machine_mode @var{mode}.  If 0 is returned then the default 
alignment for the specified mode is used. 
 @end deftypefn
Index: gcc/tree-ssa-alias.c
===================================================================
--- gcc/tree-ssa-alias.c        (revision 220025)
+++ gcc/tree-ssa-alias.c        (working copy)
@@ -1532,6 +1532,25 @@ refs_output_dependent_p (tree store1, tree store2)
   return refs_may_alias_p_1 (&r1, &r2, false);
 }
 
+/* Return true if the points-to solution *PT includes the object BASE.  */
+
+static bool
+pt_solution_includes_base (struct pt_solution *pt, tree base)
+{
+  if (DECL_P (base))
+    return pt_solution_includes (pt, base);
+
+  if ((TREE_CODE (base) == MEM_REF
+       || TREE_CODE (base) == TARGET_MEM_REF)
+      && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
+    {
+      struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
+      if (pi)
+       return pt_solutions_intersect (pt, &pi->pt);
+    }
+  return true;
+}
+
 /* If the call CALL may use the memory reference REF return true,
    otherwise return false.  */
 
@@ -1542,6 +1561,22 @@ ref_maybe_used_by_call_p_1 (gcall *call, ao_ref *r
   unsigned i;
   int flags = gimple_call_flags (call);
 
+  callee = gimple_call_fn (call);
+  if (callee && TREE_CODE (callee) == SSA_NAME
+      && targetm.has_function_descriptors ())
+    {
+      /* Handle indirect call.  When a target defines the address of a
+        function as that of a function descriptor, then dereferencing
+        a function pointer implicitly references memory.  */
+      struct ptr_info_def *pi = SSA_NAME_PTR_INFO (callee);
+      if (pi)
+       {
+         base = ao_ref_base (ref);
+         if (pt_solution_includes_base (&pi->pt, base))
+           return true;
+       }
+    }
+
   /* Const functions without a static chain do not implicitly use memory.  */
   if (!gimple_call_chain (call)
       && (flags & (ECF_CONST|ECF_NOVOPS)))
@@ -1564,7 +1599,7 @@ ref_maybe_used_by_call_p_1 (gcall *call, ao_ref *r
       && !is_global_var (base))
     goto process_args;
 
-  callee = gimple_call_fndecl (call);
+  callee = gimple_call_addr_fndecl (callee);
 
   /* Handle those builtin functions explicitly that do not act as
      escape points.  See tree-ssa-structalias.c:find_func_aliases
@@ -1803,23 +1838,7 @@ ref_maybe_used_by_call_p_1 (gcall *call, ao_ref *r
     }
 
   /* Check if the base variable is call-used.  */
-  if (DECL_P (base))
-    {
-      if (pt_solution_includes (gimple_call_use_set (call), base))
-       return true;
-    }
-  else if ((TREE_CODE (base) == MEM_REF
-           || TREE_CODE (base) == TARGET_MEM_REF)
-          && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
-    {
-      struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
-      if (!pi)
-       return true;
-
-      if (pt_solutions_intersect (gimple_call_use_set (call), &pi->pt))
-       return true;
-    }
-  else
+  if (pt_solution_includes_base (gimple_call_use_set (call), base))
     return true;
 
   /* Inspect call arguments for passed-by-value aliases.  */
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 220025)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -1490,6 +1490,9 @@ static const struct attribute_spec rs6000_attribut
 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK 
hook_bool_const_tree_hwi_hwi_const_tree_true
 
+#undef TARGET_HAS_FUNCTION_DESCRIPTORS
+#define TARGET_HAS_FUNCTION_DESCRIPTORS rs6000_has_function_descriptors
+
 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
 #define TARGET_FUNCTION_OK_FOR_SIBCALL rs6000_function_ok_for_sibcall
 
@@ -22099,6 +22102,14 @@ rs6000_return_addr (int count, rtx frame)
   return get_hard_reg_initial_val (Pmode, LR_REGNO);
 }
 
+/* Return true if we use function descriptors.  */
+
+static bool
+rs6000_has_function_descriptors (void)
+{
+  return DEFAULT_ABI == ABI_AIX;
+}
+
 /* Say whether a function is a candidate for sibcall handling or not.  */
 
 static bool
Index: gcc/testsuite/gcc.target/powerpc/pr64703.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr64703.c  (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr64703.c  (working copy)
@@ -0,0 +1,36 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-options "-O2 -mabi=elfv1" } */
+/* { dg-final { scan-assembler "std .\*,112\\(1\\)" } } */
+/* { dg-final { scan-assembler "std .\*,120\\(1\\)" } } */
+/* { dg-final { scan-assembler "std .\*,128\\(1\\)" } } */
+/* { dg-final { scan-assembler "addi .\*,1,112" } } */
+
+/* Testcase taken from glibc, powerpc64 dl-machine.h.  */
+
+typedef struct {
+  unsigned long fd_func;
+  unsigned long fd_toc;
+  unsigned long fd_aux;
+} Elf64_FuncDesc;
+
+extern unsigned long dl_hwcap;
+
+unsigned long
+resolve_ifunc (unsigned long value, unsigned long adjust)
+{
+  Elf64_FuncDesc opd;
+
+  if (adjust)
+    {
+      Elf64_FuncDesc *func = (Elf64_FuncDesc *) value;
+      opd.fd_func = func->fd_func + adjust;
+      opd.fd_toc = func->fd_toc + adjust;
+      opd.fd_aux = func->fd_aux;
+      value = (unsigned long) &opd;
+    }
+#if 0
+  __asm__ ("#%0" : : "r" (value));
+#endif
+  return ((unsigned long (*) (unsigned long)) value) (dl_hwcap);
+}

-- 
Alan Modra
Australia Development Lab, IBM

Reply via email to