This adds the capability to specify a type to be used when building
an expression.

Committed.

2014-09-09  Richard Biener  <rguent...@suse.de>

        * genmatch.c (struct expr): Add expr_type member.
        (expr::gen_transform): Honor explicitely specified type.
        (parse_expr): Parse ':<ident>' on the operator as identifier
        specifying the type to use when building the expression.
        * match-conversions.pd ((T1)(X * Y) -> (T1)X * (T1)Y):
        Complete.

Index: gcc/genmatch.c
===================================================================
*** gcc/genmatch.c      (revision 215011)
--- gcc/genmatch.c      (working copy)
*************** struct e_operation {
*** 259,268 ****
  struct expr : public operand
  {
    expr (e_operation *operation_)
!     : operand (OP_EXPR), operation (operation_), ops (vNULL) {}
    void append_op (operand *op) { ops.safe_push (op); }
    e_operation *operation;
    vec<operand *> ops;
    virtual void gen_transform (FILE *f, const char *, bool, int, const char *);
  };
  
--- 259,270 ----
  struct expr : public operand
  {
    expr (e_operation *operation_)
!     : operand (OP_EXPR), operation (operation_),
!       ops (vNULL), expr_type (NULL) {}
    void append_op (operand *op) { ops.safe_push (op); }
    e_operation *operation;
    vec<operand *> ops;
+   const char *expr_type;
    virtual void gen_transform (FILE *f, const char *, bool, int, const char *);
  };
  
*************** expr::gen_transform (FILE *f, const char
*** 883,892 ****
                     const char *in_type)
  {
    bool conversion_p = is_conversion (operation->op);
! 
!   const char *type;
    char optype[20];
!   if (conversion_p)
      /* For conversions we need to build the expression using the
         outer type passed in.  */
      type = in_type;
--- 885,896 ----
                     const char *in_type)
  {
    bool conversion_p = is_conversion (operation->op);
!   const char *type = expr_type;
    char optype[20];
!   if (type)
!     /* If there was a type specification in the pattern use it.  */
!     ;
!   else if (conversion_p)
      /* For conversions we need to build the expression using the
         outer type passed in.  */
      type = in_type;
*************** parse_expr (cpp_reader *r)
*** 2146,2151 ****
--- 2150,2156 ----
    const cpp_token *token = peek (r);
    operand *op;
    bool is_commutative = false;
+   const char *expr_type = NULL;
  
    if (token->type == CPP_COLON
        && !(token->flags & PREV_WHITE))
*************** parse_expr (cpp_reader *r)
*** 2158,2169 ****
          const char *s = get_ident (r);
          if (s[0] == 'c' && !s[1])
            is_commutative = true;
          else
!           fatal_at (token, "predicates or flag %s not recognized", s);
          token = peek (r);
        }
        else
!       fatal_at (token, "expected flag or predicate");
      }
  
    if (token->type == CPP_ATSIGN
--- 2163,2176 ----
          const char *s = get_ident (r);
          if (s[0] == 'c' && !s[1])
            is_commutative = true;
+         else if (s[1] != '\0')
+           expr_type = s;
          else
!           fatal_at (token, "flag %s not recognized", s);
          token = peek (r);
        }
        else
!       fatal_at (token, "expected flag or type specifying identifier");
      }
  
    if (token->type == CPP_ATSIGN
*************** parse_expr (cpp_reader *r)
*** 2184,2189 ****
--- 2191,2197 ----
              else
                fatal_at (token, "only binary operators or function with two 
arguments can be marked commutative");
            }
+         e->expr_type = expr_type;
          return op;
        }
        e->append_op (parse_op (r));
Index: gcc/match-conversions.pd
===================================================================
*** gcc/match-conversions.pd    (revision 215010)
--- gcc/match-conversions.pd    (working copy)
***************
*** 58,71 ****
        && INTEGRAL_TYPE_P (TREE_TYPE (@0))
        && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (@0)))
    (if (TYPE_OVERFLOW_WRAPS (type))
!    (mult (convert @0) (convert @1)))))
! #if 0
!   /* 1) We can't handle the two-conversions-in-a-row below.
!      2) We can't properly specify the type for the inner conversion
!         (unsigned_type_for).  Suggested syntax below.  */
    (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
!    (convert (mult (convert:utype @0) (convert:utype @1))))
! #endif
  
  
  /* For integral conversions with the same precision or pointer
--- 58,66 ----
        && INTEGRAL_TYPE_P (TREE_TYPE (@0))
        && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (@0)))
    (if (TYPE_OVERFLOW_WRAPS (type))
!    (mult (convert @0) (convert @1)))
    (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
!    (convert (mult (convert:utype @0) (convert:utype @1))))))
  
  
  /* For integral conversions with the same precision or pointer

Reply via email to