This makes us accept (plus @0 INTEGER_CST)
and parse it as (plus @0 (INTEGER_CST)), that is, handle operator names in predicate position as expression with zero operands. This makes those leafs better integrate with the decision tree and also removes the need to define all those INTEGER_CST_P predicates. For now gobble in all tcc_constant tree codes for this as well. Note that doing (for x in INTEGER_CST VECTOR_CST (simplify (plus @1 x) ... does not (yet) work ('x' parses as predicate here). Tested on x86_64-unknown-linux-gnu, applied. Richard. 2014-08-19 Richard Biener <rguent...@suse.de> * genmatch.c (is_a_helper): Provide specializations for fn_id and operator_id. (add_operator): Collect tcc_constant codes. (commutate): Special-case zero-operand expressions. (dt_node::get_expr_code): Likewise. (parse_op): When parsing an id allow zero-operand operators as predicates, parsing as expression, and disallow any other operator names. * gimple-match-head.c (INTEGER_CST_P): Remove. (REAL_CST_P): Likewise. * match-bitwise.pd: Use INTEGER_CST instead of INTEGER_CST_P and REAL_CST instead of REAL_CST_P. * match-builtin.pd: Likewise. * match-plusminus.pd: Likewise. * match-rotate.pd: Likewise. * match.pd: Likewise. * match-comparison: Likewise. Index: gcc/genmatch.c =================================================================== *** gcc/genmatch.c.orig 2014-08-19 14:11:18.791879827 +0200 --- gcc/genmatch.c 2014-08-19 14:27:52.127811437 +0200 *************** struct fn_id : public id_base *** 174,179 **** --- 174,194 ---- enum built_in_function fn; }; + template<> + template<> + inline bool + is_a_helper <fn_id *>::test (id_base *id) + { + return id->kind == id_base::FN; + } + + template<> + template<> + inline bool + is_a_helper <operator_id *>::test (id_base *id) + { + return id->kind == id_base::CODE; + } static void add_operator (enum tree_code code, const char *id, *************** add_operator (enum tree_code code, const *** 184,190 **** && strcmp (tcc, "tcc_comparison") != 0 && strcmp (tcc, "tcc_expression") != 0 /* For {REAL,IMAG}PART_EXPR and VIEW_CONVERT_EXPR. */ ! && strcmp (tcc, "tcc_reference") != 0) return; operator_id *op = new operator_id (code, id, nargs); id_base **slot = operators->find_slot_with_hash (op, op->hashval, INSERT); --- 199,207 ---- && strcmp (tcc, "tcc_comparison") != 0 && strcmp (tcc, "tcc_expression") != 0 /* For {REAL,IMAG}PART_EXPR and VIEW_CONVERT_EXPR. */ ! && strcmp (tcc, "tcc_reference") != 0 ! /* To have INTEGER_CST and friends as "predicate operators". */ ! && strcmp (tcc, "tcc_constant") != 0) return; operator_id *op = new operator_id (code, id, nargs); id_base **slot = operators->find_slot_with_hash (op, op->hashval, INSERT); *************** commutate (operand *op) *** 580,585 **** --- 597,607 ---- } expr *e = static_cast<expr *> (op); + if (e->ops.length () == 0) + { + ret.safe_push (e); + return ret; + } vec< vec<operand *> > ops_vector = vNULL; for (unsigned i = 0; i < e->ops.length (); ++i) *************** dt_node::get_expr_code (enum tree_code& *** 1391,1396 **** --- 1413,1421 ---- return false; operator_id *opr = static_cast<operator_id *> (e->operation->op); + if (opr->nargs == 0) + return false; + code = opr->code; return true; } *************** parse_op (cpp_reader *r) *** 2272,2278 **** /* Remaining ops are either empty or predicates */ if (token->type == CPP_NAME) { ! op = new predicate (get_ident (r)); token = peek (r); if (token->flags & PREV_WHITE) return op; --- 2297,2320 ---- /* Remaining ops are either empty or predicates */ if (token->type == CPP_NAME) { ! const char *id = get_ident (r); ! /* We support zero-operand operator names as predicates. */ ! id_base *opr = get_operator (id); ! if (opr) ! { ! if (operator_id *code = dyn_cast <operator_id *> (opr)) ! { ! if (code->nargs != 0) ! fatal_at (token, "using an operator with operands as predicate"); ! /* Parse the zero-operand operator "predicates" as ! expression. */ ! op = new expr (new e_operation (id)); ! } ! else ! fatal_at (token, "using an unsupported operator as predicate"); ! } ! else ! op = new predicate (id); token = peek (r); if (token->flags & PREV_WHITE) return op; Index: gcc/match-bitwise.pd =================================================================== *** gcc/match-bitwise.pd.orig 2014-08-19 14:08:08.825892906 +0200 --- gcc/match-bitwise.pd 2014-08-19 14:15:29.640862557 +0200 *************** along with GCC; see the file COPYING3. *** 63,69 **** /* (x | CST1) & CST2 -> (x & CST2) | (CST1 & CST2) */ (simplify ! (bit_and (bit_ior integral_op_p@0 INTEGER_CST_P@1) INTEGER_CST_P@2) (bit_ior (bit_and @0 @2) (bit_and @1 @2))) /* x ^ ~0 -> ~x */ --- 63,69 ---- /* (x | CST1) & CST2 -> (x & CST2) | (CST1 & CST2) */ (simplify ! (bit_and (bit_ior integral_op_p@0 INTEGER_CST@1) INTEGER_CST@2) (bit_ior (bit_and @0 @2) (bit_and @1 @2))) /* x ^ ~0 -> ~x */ Index: gcc/match-builtin.pd =================================================================== *** gcc/match-builtin.pd.orig 2014-08-19 14:08:08.825892906 +0200 --- gcc/match-builtin.pd 2014-08-19 14:15:29.640862557 +0200 *************** along with GCC; see the file COPYING3. *** 35,41 **** (mult:c (BUILT_IN_POW @0 @1) @0) (BUILT_IN_POW @0 (PLUS_EXPR @1 { build_one_cst (TREE_TYPE (@1)); }))) (simplify ! (BUILT_IN_POW @0 REAL_CST_P@1) /* This needs to be conditionalized on flag_unsafe_math_optimizations, but we keep it for now to exercise function re-optimization. It makes gcc.dg/pr43419.c FAIL execution though. */ --- 35,41 ---- (mult:c (BUILT_IN_POW @0 @1) @0) (BUILT_IN_POW @0 (PLUS_EXPR @1 { build_one_cst (TREE_TYPE (@1)); }))) (simplify ! (BUILT_IN_POW @0 REAL_CST@1) /* This needs to be conditionalized on flag_unsafe_math_optimizations, but we keep it for now to exercise function re-optimization. It makes gcc.dg/pr43419.c FAIL execution though. */ Index: gcc/match-plusminus.pd =================================================================== *** gcc/match-plusminus.pd.orig 2014-08-19 14:08:08.825892906 +0200 --- gcc/match-plusminus.pd 2014-08-19 14:15:29.640862557 +0200 *************** along with GCC; see the file COPYING3. *** 61,74 **** Watch out for operand order and constant canonicalization we do! A - CST -> A + -CST, CST + A -> A + CST. */ (simplify ! (plus (plus @0 INTEGER_CST_P@1) INTEGER_CST_P@2) /* If the constant operation overflows we cannot do the transform as we would introduce undefined overflow, for example with (a - 1) + INT_MIN. */ (if (!TREE_OVERFLOW (@1 = int_const_binop (PLUS_EXPR, @1, @2)))) (plus @0 @1)) (simplify ! (plus (minus INTEGER_CST_P@0 @1) INTEGER_CST_P@2) (minus (plus @0 @2) @1)) /* TODO: (A +- CST) +- CST -> A +- CST --- 61,74 ---- Watch out for operand order and constant canonicalization we do! A - CST -> A + -CST, CST + A -> A + CST. */ (simplify ! (plus (plus @0 INTEGER_CST@1) INTEGER_CST@2) /* If the constant operation overflows we cannot do the transform as we would introduce undefined overflow, for example with (a - 1) + INT_MIN. */ (if (!TREE_OVERFLOW (@1 = int_const_binop (PLUS_EXPR, @1, @2)))) (plus @0 @1)) (simplify ! (plus (minus INTEGER_CST@0 @1) INTEGER_CST@2) (minus (plus @0 @2) @1)) /* TODO: (A +- CST) +- CST -> A +- CST Index: gcc/match-rotate.pd =================================================================== *** gcc/match-rotate.pd.orig 2014-08-19 14:08:08.825892906 +0200 --- gcc/match-rotate.pd 2014-08-19 14:15:29.640862557 +0200 *************** along with GCC; see the file COPYING3. *** 21,27 **** /* (x << CNT1) OP (x >> CNT2) -> x r<< CNT1 OP being +, |, ^ */ (for op in plus bit_ior bit_xor (simplify ! (op:c (lshift @0 INTEGER_CST_P@1) (rshift @0 INTEGER_CST_P@2)) (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) && TYPE_PRECISION (type) == GET_MODE_PRECISION (TYPE_MODE (type)) && tree_fits_uhwi_p (@1) && tree_fits_uhwi_p (@2) --- 21,27 ---- /* (x << CNT1) OP (x >> CNT2) -> x r<< CNT1 OP being +, |, ^ */ (for op in plus bit_ior bit_xor (simplify ! (op:c (lshift @0 INTEGER_CST@1) (rshift @0 INTEGER_CST@2)) (if (INTEGRAL_TYPE_P (type) && TYPE_UNSIGNED (type) && TYPE_PRECISION (type) == GET_MODE_PRECISION (TYPE_MODE (type)) && tree_fits_uhwi_p (@1) && tree_fits_uhwi_p (@2) Index: gcc/match.pd =================================================================== *** gcc/match.pd.orig 2014-08-19 14:08:51.451889972 +0200 --- gcc/match.pd 2014-08-19 14:15:29.653862556 +0200 *************** along with GCC; see the file COPYING3. *** 40,46 **** an ADDR_EXPR in return. */ #if GIMPLE (simplify ! (pointer_plus (addr@2 @0) INTEGER_CST_P@1) (if (is_gimple_min_invariant (@2))) { HOST_WIDE_INT off; --- 40,46 ---- an ADDR_EXPR in return. */ #if GIMPLE (simplify ! (pointer_plus (addr@2 @0) INTEGER_CST@1) (if (is_gimple_min_invariant (@2))) { HOST_WIDE_INT off; *************** along with GCC; see the file COPYING3. *** 65,71 **** (X >> C1) & C2 into (X >> C1) & (C2 | ~((type) -1 >> C1)) if the new mask might be further optimized. */ (simplify ! (bit_and (rshift@0 @1 INTEGER_CST_P@2) integer_onep) (if (compare_tree_int (@2, TYPE_PRECISION (TREE_TYPE (@1)) - 1) == 0)) @0) --- 65,71 ---- (X >> C1) & C2 into (X >> C1) & (C2 | ~((type) -1 >> C1)) if the new mask might be further optimized. */ (simplify ! (bit_and (rshift@0 @1 INTEGER_CST@2) integer_onep) (if (compare_tree_int (@2, TYPE_PRECISION (TREE_TYPE (@1)) - 1) == 0)) @0) *************** along with GCC; see the file COPYING3. *** 98,104 **** /* match-and-simplify handles constant folding so we can just do the decomposition here. */ (simplify ! (fma INTEGER_CST_P@0 INTEGER_CST_P@1 @3) (plus (mult @0 @1) @3)) /* abs (abs (x)) -> abs (x) */ --- 98,104 ---- /* match-and-simplify handles constant folding so we can just do the decomposition here. */ (simplify ! (fma INTEGER_CST@0 INTEGER_CST@1 @3) (plus (mult @0 @1) @3)) /* abs (abs (x)) -> abs (x) */ Index: gcc/gimple-match-head.c =================================================================== *** gcc/gimple-match-head.c.orig 2014-08-19 14:09:16.746888230 +0200 --- gcc/gimple-match-head.c 2014-08-19 14:15:29.653862556 +0200 *************** along with GCC; see the file COPYING3. *** 40,48 **** #include "builtins.h" #include "gimple-match.h" - #define INTEGER_CST_P(node) (TREE_CODE(node) == INTEGER_CST) #define integral_op_p(node) INTEGRAL_TYPE_P(TREE_TYPE(node)) - #define REAL_CST_P(node) (TREE_CODE(node) == REAL_CST) /* Forward declarations of the private auto-generated matchers. --- 40,46 ---- Index: gcc/match-comparison.pd =================================================================== *** gcc/match-comparison.pd.orig 2014-08-19 14:08:21.604892027 +0200 --- gcc/match-comparison.pd 2014-08-19 14:15:57.506860638 +0200 *************** *** 1,17 **** (for op in eq ne /* Simplify X * C1 CMP 0 to X CMP 0 if C1 is not zero. */ (simplify ! (op (mult @0 INTEGER_CST_P@1) integer_zerop@2) /* In fold-const.c we have this and the following patterns combined because there we can "compute" the operator to use by using swap_tree_comparison. */ (if (tree_int_cst_sgn (@1) > 0)) (op @0 @2)) (simplify ! (op (mult @0 INTEGER_CST_P@1) integer_zerop@2) (if (tree_int_cst_sgn (@1) < 0 && op == EQ_EXPR)) (ne @0 @2)) (simplify ! (op (mult @0 INTEGER_CST_P@1) integer_zerop@2) (if (tree_int_cst_sgn (@1) < 0 && op == NE_EXPR)) (eq @0 @2))) --- 1,17 ---- (for op in eq ne /* Simplify X * C1 CMP 0 to X CMP 0 if C1 is not zero. */ (simplify ! (op (mult @0 INTEGER_CST@1) integer_zerop@2) /* In fold-const.c we have this and the following patterns combined because there we can "compute" the operator to use by using swap_tree_comparison. */ (if (tree_int_cst_sgn (@1) > 0)) (op @0 @2)) (simplify ! (op (mult @0 INTEGER_CST@1) integer_zerop@2) (if (tree_int_cst_sgn (@1) < 0 && op == EQ_EXPR)) (ne @0 @2)) (simplify ! (op (mult @0 INTEGER_CST@1) integer_zerop@2) (if (tree_int_cst_sgn (@1) < 0 && op == NE_EXPR)) (eq @0 @2)))