[committed] hppa: Fix canonicalize of method and void pointers in comparison operations

Message ID d6955728-244a-0a5c-b6c1-e4bf569c8f04@bell.net
State New
Headers show
Series
  • [committed] hppa: Fix canonicalize of method and void pointers in comparison operations
Related show

Commit Message

John David Anglin Sept. 14, 2018, 11:44 p.m.
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.anglin@bell.net
2018-09-14  John David Anglin  <danglin@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.

Comments

Jeff Law Sept. 17, 2018, 3:02 p.m. | #1
On 9/14/18 5:44 PM, John David Anglin wrote:
> 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.

My recollection is HP's engineers were really concerned about the cost
of indirect calls and wanted to drop all the $$dyncall and associated
canonicalization of function pointers as they went to the 64 bit ABI.

This was made easier by no longer having to support MPE.  So they could
rely on more standard mechanisms to handle function pointers.

Jeff
John David Anglin Sept. 17, 2018, 4:29 p.m. | #2
On 2018-09-17 11:02 AM, Jeff Law wrote:
> On 9/14/18 5:44 PM, John David Anglin wrote:

>> 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.

> My recollection is HP's engineers were really concerned about the cost

> of indirect calls and wanted to drop all the $$dyncall and associated

> canonicalization of function pointers as they went to the 64 bit ABI.

As things stand, the linker and glibc would have to change to use OPDs.  
I doubt very much
much that this can be done without breaking compatibility with existing 
applications.  In linux,
there is a problem with the trampoline design used for lazy binding.  Of 
course, the code to
canonicalize function pointers is pretty horrible and fragile.

Helge has been pushing to get the 64-bit ABI working on linux.  I tend 
to think it would be easier
to get a 64-bit glibc working than solve the above.  Helge has the 
kernel interface more or less
done.

Dave

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

Patch

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