This fixes a ??? and handles NOP_EXPR and CONVERT_EXPR matching similar to GIMPLE by using CASE_CONVERT. This uncovers a mismatch between fold-const.c and tree-ssa-forwprop.c transforms which try to do opposite things with ((T) X) & CST vs. (T) (X & CST). I have disabled the forwprop transform on GENERIC. It also uncovers that the C++ FE uses a mix of NOP_EXPR and CONVERT_EXPR both when building expressions and when checking for them. Jason - is there any difference between NOP_EXPR and CONVERT_EXPR as far as the C++ FE is concerned? I have silenced -Wsign-compare warnings that the patch caused by making enum_cast_to_int "accept" both NOP_EXPR and CONVERT_EXPR as conversion code (ok for trunk?).
Bootstrap and testing on x86_64-unknown-linux-gnu in progress. Richard. 2014-09-26 Richard Biener <rguent...@suse.de> * genmatch.c (dt_node::gen_kids): Handle conversions in generic expressions properly. * match-bitwise.pd ((type) X & CST -> (type) (X & ((type-x) CST))): Disable on GENERIC as it conflicts with a transform in fold-const.c. cp/ * typeck.c (enum_cast_to_int): Use CONVERT_EXPR_P to check for conversions. Index: gcc/genmatch.c =================================================================== --- gcc/genmatch.c (revision 215638) +++ gcc/genmatch.c (working copy) @@ -1719,8 +1719,10 @@ dt_node::gen_kids (FILE *f, bool gimple) { expr *e = as_a <expr *>(generic_exprs[i]->op); id_base *op = e->operation; - /* ??? CONVERT */ - fprintf (f, "case %s:\n", op->id); + if (*op == CONVERT_EXPR || *op == NOP_EXPR) + fprintf (f, "CASE_CONVERT:\n"); + else + fprintf (f, "case %s:\n", op->id); fprintf (f, "{\n"); generic_exprs[i]->gen (f, gimple); fprintf (f, "break;\n" Index: gcc/match-bitwise.pd =================================================================== --- gcc/match-bitwise.pd (revision 215554) +++ gcc/match-bitwise.pd (working copy) @@ -28,7 +28,13 @@ along with GCC; see the file COPYING3. (bitop (convert @0) (convert? @1)) (if (((TREE_CODE (@1) == INTEGER_CST && INTEGRAL_TYPE_P (TREE_TYPE (@0)) - && int_fits_type_p (@1, TREE_TYPE (@0))) + && int_fits_type_p (@1, TREE_TYPE (@0)) + /* ??? This transform conflicts with fold-const.c doing + Convert (T)(x & c) into (T)x & (T)c, if c is an integer + constants (if x has signed type, the sign bit cannot be set + in c). This folds extension into the BIT_AND_EXPR. + Restrict it to GIMPLE to avoid endless recursions. */ + && (bitop != BIT_AND_EXPR || GIMPLE)) || types_compatible_p (TREE_TYPE (@0), TREE_TYPE (@1))) && (/* That's a good idea if the conversion widens the operand, thus after hoisting the conversion the operation will be narrower. */ Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (revision 215554) +++ gcc/cp/typeck.c (working copy) @@ -3858,7 +3858,7 @@ build_x_array_ref (location_t loc, tree static bool enum_cast_to_int (tree op) { - if (TREE_CODE (op) == NOP_EXPR + if (CONVERT_EXPR_P (op) && TREE_TYPE (op) == integer_type_node && TREE_CODE (TREE_TYPE (TREE_OPERAND (op, 0))) == ENUMERAL_TYPE && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 0))))