The attached change fixes the canonicalization of method and void pointers in comparisons against another method or function pointer on 32-bit hppa targets.  As far as I know, 32-bit hppa is the only architecture that requires function pointer canonicalization due to lazy binding.

Tested on hppa2.0w-hp-hpux11.11 and hppa-unknown-linux-gnu, GCC trunk and 8.  Committed to
trunk and gcc-8 branch.

Dave

--
John David Anglin  dave.ang...@bell.net

2018-09-14  John David Anglin  <dang...@gcc.gnu.org>

        PR middle-end/87188
        * dojump.c (do_compare_and_jump): Canonicalize function pointers
        when one operand is a function pointer.  Use POINTER_TYPE_P and
        FUNC_OR_METHOD_TYPE_P.
        * expr.c (do_store_flag): Use POINTER_TYPE_P and FUNC_OR_METHOD_TYPE_P.
        * fold-const.c (build_range_check): Likewise.
        * match.pd (simple_comparison): Likewise.

Index: dojump.c
===================================================================
--- dojump.c    (revision 264245)
+++ dojump.c    (working copy)
@@ -1214,15 +1214,15 @@
   code = unsignedp ? unsigned_code : signed_code;
 
   /* If function pointers need to be "canonicalized" before they can
-     be reliably compared, then canonicalize them.
-     Only do this if *both* sides of the comparison are function pointers.
-     If one side isn't, we want a noncanonicalized comparison.  See PR
-     middle-end/17564.  */
+     be reliably compared, then canonicalize them.  Canonicalize the
+     expression when one of the operands is a function pointer.  This
+     handles the case where the other operand is a void pointer.  See
+     PR middle-end/17564.  */
   if (targetm.have_canonicalize_funcptr_for_compare ()
-      && POINTER_TYPE_P (TREE_TYPE (treeop0))
-      && POINTER_TYPE_P (TREE_TYPE (treeop1))
-      && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (treeop0)))
-      && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (treeop1))))
+      && ((POINTER_TYPE_P (TREE_TYPE (treeop0))
+          && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (treeop0))))
+         || (POINTER_TYPE_P (TREE_TYPE (treeop1))
+             && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (treeop1))))))
     {
       rtx new_op0 = gen_reg_rtx (mode);
       rtx new_op1 = gen_reg_rtx (mode);
Index: expr.c
===================================================================
--- expr.c      (revision 264245)
+++ expr.c      (working copy)
@@ -11532,12 +11532,10 @@
   /* We won't bother with store-flag operations involving function pointers
      when function pointers must be canonicalized before comparisons.  */
   if (targetm.have_canonicalize_funcptr_for_compare ()
-      && ((TREE_CODE (TREE_TYPE (arg0)) == POINTER_TYPE
-          && (TREE_CODE (TREE_TYPE (TREE_TYPE (arg0)))
-              == FUNCTION_TYPE))
-         || (TREE_CODE (TREE_TYPE (arg1)) == POINTER_TYPE
-             && (TREE_CODE (TREE_TYPE (TREE_TYPE (arg1)))
-                 == FUNCTION_TYPE))))
+      && ((POINTER_TYPE_P (TREE_TYPE (arg0))
+          && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (arg0))))
+         || (POINTER_TYPE_P (TREE_TYPE (arg1))
+             && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (arg1))))))
     return 0;
 
   STRIP_NOPS (arg0);
Index: fold-const.c
===================================================================
--- fold-const.c        (revision 264245)
+++ fold-const.c        (working copy)
@@ -4922,8 +4922,8 @@
   /* Disable this optimization for function pointer expressions
      on targets that require function pointer canonicalization.  */
   if (targetm.have_canonicalize_funcptr_for_compare ()
-      && TREE_CODE (etype) == POINTER_TYPE
-      && TREE_CODE (TREE_TYPE (etype)) == FUNCTION_TYPE)
+      && POINTER_TYPE_P (etype)
+      && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (etype)))
     return NULL_TREE;
 
   if (! in_p)
Index: match.pd
===================================================================
--- match.pd    (revision 264245)
+++ match.pd    (working copy)
@@ -3462,8 +3462,8 @@
        /* Disable this optimization if we're casting a function pointer
          type on targets that require function pointer canonicalization.  */
        && !(targetm.have_canonicalize_funcptr_for_compare ()
-           && TREE_CODE (TREE_TYPE (@00)) == POINTER_TYPE
-           && TREE_CODE (TREE_TYPE (TREE_TYPE (@00))) == FUNCTION_TYPE)
+           && POINTER_TYPE_P (TREE_TYPE (@00))
+           && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (TREE_TYPE (@00))))
        && single_use (@0))
    (if (TYPE_PRECISION (TREE_TYPE (@00)) == TYPE_PRECISION (TREE_TYPE (@0))
        && (TREE_CODE (@10) == INTEGER_CST

Reply via email to