Hi Richard, As suggested in PR, I have attached WIP patch that adds two patterns to match.pd: erfc(x) --> 1 - erf(x) if canonicalize_math_p() and, 1 - erf(x) --> erfc(x) if !canonicalize_math_p().
This works to remove call to erfc for the following test: double f(double x) { double g(double, double); double t1 = __builtin_erf (x); double t2 = __builtin_erfc (x); return g(t1, t2); } with .optimized dump shows: t1_2 = __builtin_erf (x_1(D)); t2_3 = 1.0e+0 - t1_2; However, for the following test: double f(double x) { double g(double, double); double t1 = __builtin_erfc (x); return t1; } It canonicalizes erfc(x) to 1 - erf(x), but does not transform 1 - erf(x) to erfc(x) again post canonicalization. -fdump-tree-folding shows that 1 - erf(x) --> erfc(x) gets applied, but then it tries to resimplify erfc(x), which fails post canonicalization. So we end up with erfc(x) transformed to 1 - erf(x) in .optimized dump, which I suppose isn't ideal. Could you suggest how to proceed ? Thanks, Prathamesh
diff --git a/gcc/match.pd b/gcc/match.pd index a9791ceb74a..217e46ff12c 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -6147,6 +6147,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (floors tree_expr_nonnegative_p@0) (truncs @0)))) +/* Simplify, + erfc(x) -> 1 - erf(x) if canonicalize_math_p(). + 1 - erf(x) -> erfc(x) if !canonicalize_math_p(). */ + +(if (flag_unsafe_math_optimizations) + (simplify + (ERFC @0) + (if (canonicalize_math_p ()) + (minus { build_one_cst (TREE_TYPE (@0)); } (ERF @0)))) + (simplify + (minus real_onep (ERF @0)) + (if (!canonicalize_math_p ()) + (ERFC @0)))) + (match double_value_p @0 (if (TYPE_MAIN_VARIANT (TREE_TYPE (@0)) == double_type_node)))