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-*-* } } } */
signature.asc
Description: PGP signature
