Richard Biener <[email protected]> writes:

> The following exposes function pointer canonicalization for
> comparisons early by lowering to an internal function call
> during gimplification.  This allows us to make conversions
> to function pointers useless, restoring symmetry and
> avoiding issues like PR127263.
>
> I have not removed gates on few optimizations.
>
> Function pointer canonicalizations for comparisons are only
> required for 32bit hppa.  I built a cc1 cross and verified
> this works for gcc.dg/tree-ssa/pr22051-1.c but I have no
> further means (or intent ...) of testing.  Jeff, I suppose
> you have some way of testing 32bit hppa for regressions?

I can test if you can be patient (few days).

Also, cc'd dave.

>
> Is this otherwise sound?
>
> Bootstrap/regtest running on x86_64-unknown-linux-gnu (2/2
> separately succeeded in that)
>
> Thanks,
> Richard.
>
>       * internal-fn.def (CANONICALIZE_FUNCPTR_FOR_COMPARE): New
>       internal fn.
>       * internal-fn.h (expand_CANONICALIZE_FUNCPTR_FOR_COMPARE):
>       Declare.
>       * internal-fn.cc (expand_CANONICALIZE_FUNCPTR_FOR_COMPARE): New.
>       * gimplify.cc (gimplify_expr): Insert function pointer
>       canonicalization for compares.
>       * dojump.cc (do_compare_and_jump): Remove function pointer
>       canonicalization.
>
>       * gcc.dg/tree-ssa/pr22051-1.c: Adjust.
> ---
>  gcc/dojump.cc                             | 21 ---------------------
>  gcc/gimplify.cc                           | 21 ++++++++++++++++++++-
>  gcc/internal-fn.cc                        | 12 ++++++++++++
>  gcc/internal-fn.def                       |  3 +++
>  gcc/internal-fn.h                         |  1 +
>  gcc/testsuite/gcc.dg/tree-ssa/pr22051-1.c |  8 ++------
>  6 files changed, 38 insertions(+), 28 deletions(-)
>
> diff --git a/gcc/dojump.cc b/gcc/dojump.cc
> index 1ed22116a27..298fe7bd903 100644
> --- a/gcc/dojump.cc
> +++ b/gcc/dojump.cc
> @@ -1305,27 +1305,6 @@ do_compare_and_jump (tree treeop0, tree treeop1, enum 
> rtx_code signed_code,
>    unsignedp = TYPE_UNSIGNED (type);
>    code = unsignedp ? unsigned_code : signed_code;
>  
> -  /* If function pointers need to be "canonicalized" before they can
> -     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))
> -        && 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);
> -
> -      emit_insn (targetm.gen_canonicalize_funcptr_for_compare (new_op0, 
> op0));
> -      op0 = new_op0;
> -
> -      emit_insn (targetm.gen_canonicalize_funcptr_for_compare (new_op1, 
> op1));
> -      op1 = new_op1;
> -    }
> -
>    do_compare_rtx_and_jump (op0, op1, code, unsignedp, treeop0, mode,
>                          ((mode == BLKmode)
>                           ? expr_size (treeop0) : NULL_RTX),
> diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
> index 0f8bf533ba7..b72195efaf1 100644
> --- a/gcc/gimplify.cc
> +++ b/gcc/gimplify.cc
> @@ -21317,7 +21317,26 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, 
> gimple_seq *post_p,
>                         ret = GS_OK;
>                       }
>                     else
> -                     goto expr_2;
> +                     {
> +                       if (POINTER_TYPE_P (type)
> +                           && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (type))
> +                           && targetm.have_canonicalize_funcptr_for_compare 
> ())
> +                         {
> +                           if (!integer_zerop (TREE_OPERAND (*expr_p, 0)))
> +                             TREE_OPERAND (*expr_p, 0)
> +                               = build_call_expr_internal_loc
> +                                   (UNKNOWN_LOCATION,
> +                                    IFN_CANONICALIZE_FUNCPTR_FOR_COMPARE,
> +                                    type, 1, TREE_OPERAND (*expr_p, 0));
> +                           if (!integer_zerop (TREE_OPERAND (*expr_p, 1)))
> +                             TREE_OPERAND (*expr_p, 1)
> +                               = build_call_expr_internal_loc
> +                                   (UNKNOWN_LOCATION,
> +                                    IFN_CANONICALIZE_FUNCPTR_FOR_COMPARE,
> +                                    type, 1, TREE_OPERAND (*expr_p, 1));
> +                         }
> +                       goto expr_2;
> +                     }
>                   }
>                 else if (SCALAR_INT_MODE_P (TYPE_MODE (type)))
>                   ret = gimplify_scalar_mode_aggregate_compare (expr_p);
> diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc
> index c57b594ac59..5fd6cc19515 100644
> --- a/gcc/internal-fn.cc
> +++ b/gcc/internal-fn.cc
> @@ -5902,3 +5902,15 @@ expand_BITREVERSE (internal_fn fn, gcall *stmt)
>    if (expand_bitquery (fn, stmt))
>      expand_unary_optab_fn (fn, stmt, bitreverse_optab);
>  }
> +
> +void
> +expand_CANONICALIZE_FUNCPTR_FOR_COMPARE (internal_fn, gcall *stmt)
> +{
> +  tree lhs = gimple_call_lhs (stmt);
> +  tree rhs = gimple_call_arg (stmt, 0);
> +  rtx plhs = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
> +  rtx prhs = expand_normal (rhs);
> +  rtx new_rhs = gen_reg_rtx (Pmode);
> +  emit_insn (targetm.gen_canonicalize_funcptr_for_compare (new_rhs, prhs));
> +  emit_move_insn (plhs, new_rhs);
> +}
> diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
> index af9f92950c7..e6619f53171 100644
> --- a/gcc/internal-fn.def
> +++ b/gcc/internal-fn.def
> @@ -636,6 +636,9 @@ DEF_INTERNAL_FN (SPACESHIP, ECF_CONST | ECF_LEAF | 
> ECF_NOTHROW, NULL)
>  DEF_INTERNAL_FN (ASSUME, ECF_CONST | ECF_LEAF | ECF_NOTHROW
>                        | ECF_LOOPING_CONST_OR_PURE, NULL)
>  
> +DEF_INTERNAL_FN (CANONICALIZE_FUNCPTR_FOR_COMPARE, ECF_CONST | ECF_LEAF
> +              | ECF_NOTHROW, NULL)
> +
>  /* For if-conversion of inbranch SIMD clones.  */
>  DEF_INTERNAL_FN (MASK_CALL, ECF_NOVOPS, NULL)
>  
> diff --git a/gcc/internal-fn.h b/gcc/internal-fn.h
> index 30930f388b0..23e62c03183 100644
> --- a/gcc/internal-fn.h
> +++ b/gcc/internal-fn.h
> @@ -288,6 +288,7 @@ extern void expand_PARITY (internal_fn, gcall *);
>  extern void expand_POPCOUNT (internal_fn, gcall *);
>  extern void expand_BSWAP (internal_fn, gcall *);
>  extern void expand_BITREVERSE (internal_fn, gcall *);
> +extern void expand_CANONICALIZE_FUNCPTR_FOR_COMPARE (internal_fn, gcall *);
>  
>  extern bool vectorized_internal_fn_supported_p (internal_fn, tree);
>  
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr22051-1.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/pr22051-1.c
> index e01f39216c4..fc21b4ebb77 100644
> --- a/gcc/testsuite/gcc.dg/tree-ssa/pr22051-1.c
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr22051-1.c
> @@ -14,9 +14,5 @@ foo()
>      return 2;
>  }
>  
> -/* The cast to a function pointer type must remain after all optimizations
> -   are complete so that function pointer canonicalization works on those
> -   targets which require it.  */
> -/* { dg-final { scan-tree-dump-times "= \\(void \\(\\*<.*>\\) \\(void\\)\\) 
> p_" 1 "optimized" } } */
> -
> -
> +/* A function pointer must be canonicalized on hppa.  */
> +/* { dg-final { scan-tree-dump-times " = .CANONICALIZE_FUNCPTR_FOR_COMPARE 
> \\(p_" 1 "optimized" { target hppa-*-* } } } */

Attachment: signature.asc
Description: PGP signature

Reply via email to