The following fixes a bug in genmatch exposed by adding :s flags to the (X & C2) >> C1 into (X >> C1) & (C2 >> C1) transform which hurts PR66948. We were not properly handling captures of captures resulting from (convert?:s (bit_and:s ...)) when the convert is dropped.
This also causes quite some bugs in generic-match.c code generation with respect to required TREE_SIDE_EFFECTS checks and omit-one-operand calls. Thus I am also backporting this to the 4.5 branch (a single patter is affected there). Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk and branch. Richard. 2015-07-21 Richard Biener <rguent...@suse.de> PR tree-optimization/66948 * genmatch.c (capture_info::walk_match): Also recurse to captures. Properly compute expr state from captures of captures. * match.pd: Add single-use guards to (X & C2) >> C1 into (X >> C1) & (C2 >> C1) transform. Index: gcc/genmatch.c =================================================================== *** gcc/genmatch.c (revision 226028) --- gcc/genmatch.c (working copy) *************** capture_info::walk_match (operand *o, un *** 1622,1638 **** { if (capture *c = dyn_cast <capture *> (o)) { ! info[c->where].toplevel_msk |= 1 << toplevel_arg; ! info[c->where].force_no_side_effects_p |= conditional_p; ! info[c->where].cond_expr_cond_p |= cond_expr_cond_p; ! /* Mark expr (non-leaf) captures and recurse. */ expr *e; if (c->what && (e = dyn_cast <expr *> (c->what))) { ! info[c->where].expr_p = true; ! info[c->where].force_single_use |= e->force_single_use; ! walk_match (c->what, toplevel_arg, conditional_p, false); } } else if (expr *e = dyn_cast <expr *> (o)) --- 1622,1649 ---- { if (capture *c = dyn_cast <capture *> (o)) { ! unsigned where = c->where; ! info[where].toplevel_msk |= 1 << toplevel_arg; ! info[where].force_no_side_effects_p |= conditional_p; ! info[where].cond_expr_cond_p |= cond_expr_cond_p; ! if (!c->what) ! return; ! /* Recurse to exprs and captures. */ ! if (is_a <capture *> (c->what) ! || is_a <expr *> (c->what)) ! walk_match (c->what, toplevel_arg, conditional_p, false); ! /* We need to look past multiple captures to find a captured ! expression as with conditional converts two captures ! can be collapsed onto the same expression. */ ! while (c->what && is_a <capture *> (c->what)) ! c = as_a <capture *> (c->what); ! /* Mark expr (non-leaf) captures and forced single-use exprs. */ expr *e; if (c->what && (e = dyn_cast <expr *> (c->what))) { ! info[where].expr_p = true; ! info[where].force_single_use |= e->force_single_use; } } else if (expr *e = dyn_cast <expr *> (o)) Index: gcc/match.pd =================================================================== *** gcc/match.pd (revision 226028) --- gcc/match.pd (working copy) *************** (define_operator_list CBRT BUILT_IN_CBRT *** 1052,1058 **** (X & C2) >> C1 into (X >> C1) & (C2 >> C1). */ (for shift (lshift rshift) (simplify ! (shift (convert? (bit_and @0 INTEGER_CST@2)) INTEGER_CST@1) (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) (with { tree mask = int_const_binop (shift, fold_convert (type, @2), @1); } (bit_and (shift (convert @0) @1) { mask; }))))) --- 1052,1058 ---- (X & C2) >> C1 into (X >> C1) & (C2 >> C1). */ (for shift (lshift rshift) (simplify ! (shift (convert?:s (bit_and:s @0 INTEGER_CST@2)) INTEGER_CST@1) (if (tree_nop_conversion_p (type, TREE_TYPE (@0))) (with { tree mask = int_const_binop (shift, fold_convert (type, @2), @1); } (bit_and (shift (convert @0) @1) { mask; })))))