This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][match-and-simplify] Allow zero-operand operators as predicates


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  <rguenther@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)))


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]