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