https://gcc.gnu.org/g:91916b862d82d21d4271bcb191af6cfb710edbc7
commit 91916b862d82d21d4271bcb191af6cfb710edbc7 Author: Alexandre Oliva <ol...@gnu.org> Date: Thu Nov 21 22:36:38 2024 -0300 fold_truth_andor: use pattern matching Diff: --- gcc/gimple-fold.cc | 173 +++++++++-------------------------------------------- gcc/match.pd | 7 +++ 2 files changed, 36 insertions(+), 144 deletions(-) diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index cf711081387d..d55e5941c1ae 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -7387,69 +7387,10 @@ maybe_fold_comparisons_from_match_pd (tree type, enum tree_code code, return NULL_TREE; } -/* Return TRUE if expression STMT is suitable for replacement. ??? - Same as ssa_is_replaceable_p, except that we don't insist it has a - single use. */ - -static bool -ssa_is_substitutable_p (gimple *stmt) -{ -#if 0 - use_operand_p use_p; -#endif - tree def; -#if 0 - gimple *use_stmt; -#endif - - /* Only consider modify stmts. */ - if (!is_gimple_assign (stmt)) - return false; - - /* If the statement may throw an exception, it cannot be replaced. */ - if (stmt_could_throw_p (cfun, stmt)) - return false; - - /* Punt if there is more than 1 def. */ - def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF); - if (!def) - return false; - -#if 0 - /* Only consider definitions which have a single use. */ - if (!single_imm_use (def, &use_p, &use_stmt)) - return false; - - /* Used in this block, but at the TOP of the block, not the end. */ - if (gimple_code (use_stmt) == GIMPLE_PHI) - return false; -#endif - - /* There must be no VDEFs. */ - if (gimple_vdef (stmt)) - return false; - - /* Float expressions must go through memory if float-store is on. */ - if (flag_float_store - && FLOAT_TYPE_P (TREE_TYPE (def))) - return false; - - /* An assignment with a register variable on the RHS is not - replaceable. */ - if (gimple_assign_rhs_code (stmt) == VAR_DECL - && DECL_HARD_REGISTER (gimple_assign_rhs1 (stmt))) - return false; - - /* No function calls can be replaced. */ - if (is_gimple_call (stmt)) - return false; - - /* Leave any stmt with volatile operands alone as well. */ - if (gimple_has_volatile_ops (stmt)) - return false; - - return true; -} +extern bool gimple_nop_convert (tree, tree *, tree (*)(tree)); +extern bool gimple_bit_and_cst (tree, tree *, tree (*)(tree)); +extern bool gimple_bit_xor_cst (tree, tree *, tree (*)(tree)); +extern bool gimple_rshift_cst (tree, tree *, tree (*)(tree)); /* Follow substitutable SSA DEFs for *NAME, including type casts, adjusting *NAME to the single rhs or the type cast operand along @@ -7460,79 +7401,18 @@ static tree is_cast_p (tree *name) { tree type = 0; + tree res_ops[1]; - while (TREE_CODE (*name) == SSA_NAME - && !SSA_NAME_IS_DEFAULT_DEF (*name)) + while (gimple_nop_convert (*name, res_ops, follow_all_ssa_edges)) { - gimple *def = SSA_NAME_DEF_STMT (*name); - - if (!ssa_is_substitutable_p (def)) - break; - - if (gimple_num_ops (def) != 2) - break; - - if (gimple_assign_single_p (def)) - { - if (gimple_assign_load_p (def)) - break; - *name = gimple_assign_rhs1 (def); - continue; - } - - if (!gimple_assign_cast_p (def)) - break; - if (!type) type = TREE_TYPE (*name); - *name = gimple_assign_rhs1 (def); + *name = res_ops[0]; } return type; } -/* Follow substitutable SSA DEFs for *NAME. If we find it is assigned - a CODE binary expr, return the second operand, and set *NAME to the - first operand. */ - -static tree -is_binop_p (enum tree_code code, tree *name) -{ - while (TREE_CODE (*name) == SSA_NAME - && !SSA_NAME_IS_DEFAULT_DEF (*name)) - { - gimple *def = SSA_NAME_DEF_STMT (*name); - - if (!ssa_is_substitutable_p (def)) - return 0; - - switch (gimple_num_ops (def)) - { - default: - return 0; - - case 2: - if (gimple_assign_single_p (def) && !gimple_assign_load_p (def)) - { - *name = gimple_assign_rhs1 (def); - continue; - } - return 0; - - case 3: - break; - } - - if (gimple_assign_rhs_code (def) != code) - return 0; - - *name = gimple_assign_rhs1 (def); - return gimple_assign_rhs2 (def); - } - - return 0; -} - /* If *R_ARG is a constant zero, and L_ARG is a possibly masked BIT_XOR_EXPR, return 1 and set *r_arg to l_arg. Otherwise, return 0. @@ -7549,14 +7429,12 @@ prepare_xor (tree l_arg, tree *r_arg) return ret; tree exp = l_arg; + tree res_ops[2]; - if (tree and_mask = is_binop_p (BIT_AND_EXPR, &exp)) - { - if (TREE_CODE (and_mask) != INTEGER_CST) - return ret; - } + if (gimple_bit_and_cst (exp, res_ops, follow_all_ssa_edges)) + exp = res_ops[0]; - if (is_binop_p (BIT_XOR_EXPR, &exp)) + if (gimple_bit_xor_cst (exp, res_ops, follow_all_ssa_edges)) { *r_arg = l_arg; return 1; @@ -7645,29 +7523,36 @@ decode_field_reference (location_t loc, tree *exp_, HOST_WIDE_INT *pbitsize, outermost expression if it may matter below. */ outer_type = is_cast_p (&exp); - if ((and_mask = is_binop_p (BIT_AND_EXPR, &exp))) + tree res_ops[2]; + if (gimple_bit_and_cst (exp, res_ops, follow_all_ssa_edges)) { - if (TREE_CODE (and_mask) != INTEGER_CST) - return NULL_TREE; + exp = res_ops[0]; + and_mask = res_ops[1]; } if (xor_which) { - tree op2 = is_binop_p (BIT_XOR_EXPR, &exp); - gcc_checking_assert (op2); - if (xor_which > 1) - exp = op2; + if (!gimple_bit_xor_cst (exp, res_ops, follow_all_ssa_edges)) + gcc_unreachable (); + switch (xor_which) + { + case 1: + case 2: + exp = res_ops[xor_which - 1]; + break; + default: + gcc_unreachable (); + } } if (tree t = is_cast_p (&exp)) if (!outer_type) outer_type = t; - if (tree shift = is_binop_p (RSHIFT_EXPR, &exp)) + if (gimple_rshift_cst (exp, res_ops, follow_all_ssa_edges)) { - if (TREE_CODE (shift) != INTEGER_CST || !tree_fits_shwi_p (shift)) - return NULL_TREE; - shiftrt = tree_to_shwi (shift); + exp = res_ops[0]; + shiftrt = tree_to_shwi (res_ops[1]); if (shiftrt <= 0) return NULL_TREE; } diff --git a/gcc/match.pd b/gcc/match.pd index 48317dc80b63..598624086bd5 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -201,6 +201,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) (match (maybe_bit_not @0) (bit_xor_cst@0 @1 @2)) +/* These are used by ifcombine fold_truth_andor. */ +(match (bit_and_cst @0 @1) + (bit_and @0 uniform_integer_cst_p@1)) +(match (rshift_cst @0 @1) + (rshift @0 uniform_integer_cst_p@1) + (if (tree_fits_shwi_p (@1)))) + #if GIMPLE (match (maybe_truncate @0) (convert @0)