On Wed, 8 Jul 2015, Richard Biener wrote: > > This introduces a :s flag to match expressions which enforces > the expression to have a single-use if(!) the simplified > expression is larger than one statement. > > Thus with that we for example allow > > tem = a + 1; > x = tem - 3; > foo (tem); > > to simplify to > > tem = a + 1; > x = a - 2; > foo (tem); > > and more importantly not require "hacks" like > > /* Associate (p +p off1) +p off2 as (p +p (off1 + off2)). */ > (simplify > ! (pointer_plus (pointer_plus@2 @0 @1) @3) > ! (if (single_use (@2) > ! || (TREE_CODE (@1) == INTEGER_CST && TREE_CODE (@3) == > INTEGER_CST)) > ! (pointer_plus @0 (plus @1 @3)))) > > to allow the simplification if (plus @1 @3) will simplify further. > > The trick is that generated code is changed like > > tree captures[4] ATTRIBUTE_UNUSED = {}; > captures[0] = op0; > captures[1] = o20; > captures[2] = o21; > captures[3] = op1; > -/* #line 659 "/space/rguenther/tramp3d/trunk/gcc/match.pd" */ > -if (single_use (captures[0]) || (TREE_CODE (captures[2]) == INTEGER_CST > && TREE > _CODE (captures[3]) == INTEGER_CST)) > -{ > +gimple_seq *lseq = seq; > +if (!single_use (captures[0])) lseq = NULL; > ... > > so in particular it disables all single-use restrictions if seq is NULL > anyway (that is enough of a restriction already). > > Bootstrap / regtest running on x86_64-unknown-linux-gnu.
The following is what I will apply soon. I have changed code-generation to use gimple_seq *lseq = seq; if (lseq && (!single_use (captures[0]) || !single_use (captures[2]))) lseq = NULL; to short-cut the single_use checks completely if they would have no effect. I've also cleaned up genmatch by adding a kind-of copy-constructor to expr (verified that doesn't change generated code). I've also changed all but one pattern to the new style. The single non-changed one is /* Transform comparisons of the form X - Y CMP 0 to X CMP Y. ... (for cmp (eq ne) (simplify (cmp (minus@2 @0 @1) integer_zerop) (if (single_use (@2)) (cmp @0 @1)))) which is the one regressing DOM. The issue with conditionals if not appearing as the RHS of an assignment is that their value is not available, so it isn't just a no-op change regarding to surrounding code. I've once attempted to "fix" that by forcing predicate computation out of GIMPLE_CONDs but never finished that (doing this for [VEC_]COND_EXPRs on RHS of assignments is still on my list of things to do though). Richard. 2015-07-09 Richard Biener <rguent...@suse.de> * genmatch.c (struct expr): Add force_single_use flag. (expr::expr): Add copy constructor. (capture_info::walk_match): Gather force_single_use captures. (expr::gen_transform): Use possibly NULLified sequence. (dt_simplify::gen): Apply single-use restrictions by NULLifying seq if any constrained expr is not single-use. (parser::parse_expr): Refactor to allow multiple flags. Handle 's' flag to force an expression have a single-use if the pattern simplifies to more than one statement. * match.pd: Convert most single_use conditionals to :s flags. Index: gcc/genmatch.c =================================================================== *** gcc/genmatch.c (revision 225600) --- gcc/genmatch.c (working copy) *************** struct expr : public operand *** 491,497 **** expr (id_base *operation_, bool is_commutative_ = false) : operand (OP_EXPR), operation (operation_), ops (vNULL), expr_type (NULL), is_commutative (is_commutative_), ! is_generic (false) {} void append_op (operand *op) { ops.safe_push (op); } /* The operator and its operands. */ id_base *operation; --- 491,501 ---- expr (id_base *operation_, bool is_commutative_ = false) : operand (OP_EXPR), operation (operation_), ops (vNULL), expr_type (NULL), is_commutative (is_commutative_), ! is_generic (false), force_single_use (false) {} ! expr (expr *e) ! : operand (OP_EXPR), operation (e->operation), ! ops (vNULL), expr_type (e->expr_type), is_commutative (e->is_commutative), ! is_generic (e->is_generic), force_single_use (e->force_single_use) {} void append_op (operand *op) { ops.safe_push (op); } /* The operator and its operands. */ id_base *operation; *************** struct expr : public operand *** 503,508 **** --- 507,515 ---- bool is_commutative; /* Whether the expression is expected to be in GENERIC form. */ bool is_generic; + /* Whether pushing any stmt to the sequence should be conditional + on this expression having a single-use. */ + bool force_single_use; virtual void gen_transform (FILE *f, const char *, bool, int, const char *, capture_info *, dt_operand ** = 0, bool = true); *************** commutate (operand *op) *** 747,753 **** for (unsigned i = 0; i < result.length (); ++i) { ! expr *ne = new expr (e->operation); for (unsigned j = 0; j < result[i].length (); ++j) ne->append_op (result[i][j]); ret.safe_push (ne); --- 754,761 ---- for (unsigned i = 0; i < result.length (); ++i) { ! expr *ne = new expr (e); ! ne->is_commutative = false; for (unsigned j = 0; j < result[i].length (); ++j) ne->append_op (result[i][j]); ret.safe_push (ne); *************** commutate (operand *op) *** 758,764 **** for (unsigned i = 0; i < result.length (); ++i) { ! expr *ne = new expr (e->operation); // result[i].length () is 2 since e->operation is binary for (unsigned j = result[i].length (); j; --j) ne->append_op (result[i][j-1]); --- 766,773 ---- for (unsigned i = 0; i < result.length (); ++i) { ! expr *ne = new expr (e); ! ne->is_commutative = false; // result[i].length () is 2 since e->operation is binary for (unsigned j = result[i].length (); j; --j) ne->append_op (result[i][j-1]); *************** lower_opt_convert (operand *o, enum tree *** 809,822 **** if (strip) return lower_opt_convert (e->ops[0], oper, to_oper, strip); ! expr *ne = new expr (to_oper == CONVERT_EXPR ! ? get_operator ("CONVERT_EXPR") ! : get_operator ("VIEW_CONVERT_EXPR")); ne->append_op (lower_opt_convert (e->ops[0], oper, to_oper, strip)); return ne; } ! expr *ne = new expr (e->operation, e->is_commutative); for (unsigned i = 0; i < e->ops.length (); ++i) ne->append_op (lower_opt_convert (e->ops[i], oper, to_oper, strip)); --- 818,832 ---- if (strip) return lower_opt_convert (e->ops[0], oper, to_oper, strip); ! expr *ne = new expr (e); ! ne->operation = (to_oper == CONVERT_EXPR ! ? get_operator ("CONVERT_EXPR") ! : get_operator ("VIEW_CONVERT_EXPR")); ne->append_op (lower_opt_convert (e->ops[0], oper, to_oper, strip)); return ne; } ! expr *ne = new expr (e); for (unsigned i = 0; i < e->ops.length (); ++i) ne->append_op (lower_opt_convert (e->ops[i], oper, to_oper, strip)); *************** lower_cond (operand *o) *** 951,957 **** for (unsigned i = 0; i < result.length (); ++i) { ! expr *ne = new expr (e->operation); for (unsigned j = 0; j < result[i].length (); ++j) ne->append_op (result[i][j]); ro.safe_push (ne); --- 961,967 ---- for (unsigned i = 0; i < result.length (); ++i) { ! expr *ne = new expr (e); for (unsigned j = 0; j < result[i].length (); ++j) ne->append_op (result[i][j]); ro.safe_push (ne); *************** lower_cond (operand *o) *** 968,980 **** || (is_a <expr *> (e->ops[0]) && as_a <expr *> (e->ops[0])->ops.length () == 2))) { ! expr *ne = new expr (e->operation); for (unsigned j = 0; j < result[i].length (); ++j) ne->append_op (result[i][j]); if (capture *c = dyn_cast <capture *> (ne->ops[0])) { expr *ocmp = as_a <expr *> (c->what); ! expr *cmp = new expr (ocmp->operation); for (unsigned j = 0; j < ocmp->ops.length (); ++j) cmp->append_op (ocmp->ops[j]); cmp->is_generic = true; --- 978,990 ---- || (is_a <expr *> (e->ops[0]) && as_a <expr *> (e->ops[0])->ops.length () == 2))) { ! expr *ne = new expr (e); for (unsigned j = 0; j < result[i].length (); ++j) ne->append_op (result[i][j]); if (capture *c = dyn_cast <capture *> (ne->ops[0])) { expr *ocmp = as_a <expr *> (c->what); ! expr *cmp = new expr (ocmp); for (unsigned j = 0; j < ocmp->ops.length (); ++j) cmp->append_op (ocmp->ops[j]); cmp->is_generic = true; *************** lower_cond (operand *o) *** 983,989 **** else { expr *ocmp = as_a <expr *> (ne->ops[0]); ! expr *cmp = new expr (ocmp->operation); for (unsigned j = 0; j < ocmp->ops.length (); ++j) cmp->append_op (ocmp->ops[j]); cmp->is_generic = true; --- 993,999 ---- else { expr *ocmp = as_a <expr *> (ne->ops[0]); ! expr *cmp = new expr (ocmp); for (unsigned j = 0; j < ocmp->ops.length (); ++j) cmp->append_op (ocmp->ops[j]); cmp->is_generic = true; *************** replace_id (operand *o, user_id *id, id_ *** 1027,1035 **** } else if (expr *e = dyn_cast<expr *> (o)) { ! expr *ne = new expr (e->operation == id ? with : e->operation, ! e->is_commutative); ! ne->expr_type = e->expr_type; for (unsigned i = 0; i < e->ops.length (); ++i) ne->append_op (replace_id (e->ops[i], id, with)); return ne; --- 1037,1045 ---- } else if (expr *e = dyn_cast<expr *> (o)) { ! expr *ne = new expr (e); ! if (e->operation == id) ! ne->operation = with; for (unsigned i = 0; i < e->ops.length (); ++i) ne->append_op (replace_id (e->ops[i], id, with)); return ne; *************** struct capture_info *** 1513,1518 **** --- 1523,1529 ---- bool expr_p; bool cse_p; bool force_no_side_effects_p; + bool force_single_use; bool cond_expr_cond_p; unsigned long toplevel_msk; int result_use_count; *************** capture_info::walk_match (operand *o, un *** 1566,1575 **** 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. */ if (c->what ! && is_a <expr *> (c->what)) { info[c->where].expr_p = true; walk_match (c->what, toplevel_arg, conditional_p, false); } } --- 1577,1588 ---- 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); } } *************** expr::gen_transform (FILE *f, const char *** 1808,1816 **** for (unsigned i = 0; i < ops.length (); ++i) fprintf (f, "ops%d[%u]%s", depth, i, i == ops.length () - 1 ? " };\n" : ", "); ! fprintf (f, " gimple_resimplify%d (seq, &tem_code, %s, tem_ops, valueize);\n", ops.length (), type); ! fprintf (f, " res = maybe_push_res_to_seq (tem_code, %s, tem_ops, seq);\n" " if (!res) return false;\n", type); if (*operation == CONVERT_EXPR) fprintf (f, " }\n" --- 1821,1829 ---- for (unsigned i = 0; i < ops.length (); ++i) fprintf (f, "ops%d[%u]%s", depth, i, i == ops.length () - 1 ? " };\n" : ", "); ! fprintf (f, " gimple_resimplify%d (lseq, &tem_code, %s, tem_ops, valueize);\n", ops.length (), type); ! fprintf (f, " res = maybe_push_res_to_seq (tem_code, %s, tem_ops, lseq);\n" " if (!res) return false;\n", type); if (*operation == CONVERT_EXPR) fprintf (f, " }\n" *************** dt_simplify::gen (FILE *f, bool gimple) *** 2449,2475 **** that cover cases we cannot handle. */ capture_info cinfo (s); expr *e; ! if (!gimple ! && s->result && !((e = dyn_cast <expr *> (s->result)) && is_a <predicate_id *> (e->operation))) { ! for (unsigned i = 0; i < as_a <expr *> (s->match)->ops.length (); ++i) ! if (cinfo.force_no_side_effects & (1 << i)) ! fprintf (f, "if (TREE_SIDE_EFFECTS (op%d)) return NULL_TREE;\n", i); ! for (int i = 0; i <= s->capture_max; ++i) ! if (cinfo.info[i].cse_p) ! ; ! else if (cinfo.info[i].force_no_side_effects_p ! && (cinfo.info[i].toplevel_msk ! & cinfo.force_no_side_effects) == 0) ! fprintf (f, "if (TREE_SIDE_EFFECTS (captures[%d])) " ! "return NULL_TREE;\n", i); ! else if ((cinfo.info[i].toplevel_msk ! & cinfo.force_no_side_effects) != 0) ! /* Mark capture as having no side-effects if we had to verify ! that via forced toplevel operand checks. */ ! cinfo.info[i].force_no_side_effects_p = true; } fprintf (f, "if (dump_file && (dump_flags & TDF_DETAILS)) " --- 2462,2513 ---- that cover cases we cannot handle. */ capture_info cinfo (s); expr *e; ! if (s->result && !((e = dyn_cast <expr *> (s->result)) && is_a <predicate_id *> (e->operation))) { ! if (!gimple) ! { ! for (unsigned i = 0; i < as_a <expr *> (s->match)->ops.length (); ++i) ! if (cinfo.force_no_side_effects & (1 << i)) ! fprintf (f, "if (TREE_SIDE_EFFECTS (op%d)) return NULL_TREE;\n", i); ! for (int i = 0; i <= s->capture_max; ++i) ! if (cinfo.info[i].cse_p) ! ; ! else if (cinfo.info[i].force_no_side_effects_p ! && (cinfo.info[i].toplevel_msk ! & cinfo.force_no_side_effects) == 0) ! fprintf (f, "if (TREE_SIDE_EFFECTS (captures[%d])) " ! "return NULL_TREE;\n", i); ! else if ((cinfo.info[i].toplevel_msk ! & cinfo.force_no_side_effects) != 0) ! /* Mark capture as having no side-effects if we had to verify ! that via forced toplevel operand checks. */ ! cinfo.info[i].force_no_side_effects_p = true; ! } ! if (gimple) ! { ! /* Force single-use restriction by only allowing simple ! results via setting seq to NULL. */ ! fprintf (f, "gimple_seq *lseq = seq;\n"); ! bool first_p = true; ! for (int i = 0; i <= s->capture_max; ++i) ! if (cinfo.info[i].force_single_use) ! { ! if (first_p) ! { ! fprintf (f, "if (lseq\n" ! "&& ("); ! first_p = false; ! } ! else ! fprintf (f, "\n|| "); ! fprintf (f, "!single_use (captures[%d])", i); ! } ! if (!first_p) ! fprintf (f, "))\n" ! "lseq = NULL;\n"); ! } } fprintf (f, "if (dump_file && (dump_flags & TDF_DETAILS)) " *************** dt_simplify::gen (FILE *f, bool gimple) *** 2524,2530 **** /* Re-fold the toplevel result. It's basically an embedded gimple_build w/o actually building the stmt. */ if (!is_predicate) ! fprintf (f, "gimple_resimplify%d (seq, res_code, type, " "res_ops, valueize);\n", e->ops.length ()); } else if (result->type == operand::OP_CAPTURE --- 2562,2568 ---- /* Re-fold the toplevel result. It's basically an embedded gimple_build w/o actually building the stmt. */ if (!is_predicate) ! fprintf (f, "gimple_resimplify%d (lseq, res_code, type, " "res_ops, valueize);\n", e->ops.length ()); } else if (result->type == operand::OP_CAPTURE *************** parser::parse_expr () *** 3051,3056 **** --- 3089,3095 ---- const cpp_token *token = peek (); operand *op; bool is_commutative = false; + bool force_capture = false; const char *expr_type = NULL; if (token->type == CPP_COLON *************** parser::parse_expr () *** 3062,3083 **** && !(token->flags & PREV_WHITE)) { const char *s = get_ident (); ! if (s[0] == 'c' && !s[1]) { ! if (!parsing_match_operand) ! fatal_at (token, ! "flag 'c' can only be used in match expression"); ! is_commutative = true; ! } ! else if (s[1] != '\0') ! { ! if (parsing_match_operand) ! fatal_at (token, "type can only be used in result expression"); ! expr_type = s; } - else - fatal_at (token, "flag %s not recognized", s); - token = peek (); } else --- 3101,3125 ---- && !(token->flags & PREV_WHITE)) { const char *s = get_ident (); ! if (!parsing_match_operand) ! expr_type = s; ! else { ! const char *sp = s; ! while (*sp) ! { ! if (*sp == 'c') ! is_commutative = true; ! else if (*sp == 's') ! { ! e->force_single_use = true; ! force_capture = true; ! } ! else ! fatal_at (token, "flag %c not recognized", *sp); ! sp++; ! } } token = peek (); } else *************** parser::parse_expr () *** 3087,3092 **** --- 3129,3145 ---- if (token->type == CPP_ATSIGN && !(token->flags & PREV_WHITE)) op = parse_capture (e); + else if (force_capture) + { + unsigned num = capture_ids->elements (); + char id[8]; + bool existed; + sprintf (id, "__%u", num); + capture_ids->get_or_insert (xstrdup (id), &existed); + if (existed) + fatal_at (token, "reserved capture id '%s' already used", id); + op = new capture (num, e); + } else op = e; do Index: gcc/match.pd =================================================================== *** gcc/match.pd (revision 225600) --- gcc/match.pd (working copy) *************** (define_operator_list CBRT BUILT_IN_CBRT *** 334,350 **** /* x + (x & 1) -> (x + 1) & ~1 */ (simplify ! (plus:c @0 (bit_and@2 @0 integer_onep@1)) ! (if (single_use (@2)) ! (bit_and (plus @0 @1) (bit_not @1)))) /* x & ~(x & y) -> x & ~y */ /* x | ~(x | y) -> x | ~y */ (for bitop (bit_and bit_ior) (simplify ! (bitop:c @0 (bit_not (bitop:c@2 @0 @1))) ! (if (single_use (@2)) ! (bitop @0 (bit_not @1))))) /* (x | y) & ~x -> y & ~x */ /* (x & y) | ~x -> y | ~x */ --- 334,348 ---- /* x + (x & 1) -> (x + 1) & ~1 */ (simplify ! (plus:c @0 (bit_and:s @0 integer_onep@1)) ! (bit_and (plus @0 @1) (bit_not @1))) /* x & ~(x & y) -> x & ~y */ /* x | ~(x | y) -> x | ~y */ (for bitop (bit_and bit_ior) (simplify ! (bitop:c @0 (bit_not (bitop:cs @0 @1))) ! (bitop @0 (bit_not @1)))) /* (x | y) & ~x -> y & ~x */ /* (x & y) | ~x -> y | ~x */ *************** (define_operator_list CBRT BUILT_IN_CBRT *** 633,649 **** /* (x & ~m) | (y & m) -> ((x ^ y) & m) ^ x */ (simplify ! (bit_ior:c (bit_and:c@3 @0 (bit_not @2)) (bit_and:c@4 @1 @2)) ! (if (single_use (@3) && single_use (@4)) ! (bit_xor (bit_and (bit_xor @0 @1) @2) @0))) /* Associate (p +p off1) +p off2 as (p +p (off1 + off2)). */ (simplify ! (pointer_plus (pointer_plus@2 @0 @1) @3) ! (if (single_use (@2) ! || (TREE_CODE (@1) == INTEGER_CST && TREE_CODE (@3) == INTEGER_CST)) ! (pointer_plus @0 (plus @1 @3)))) /* Pattern match tem1 = (long) ptr1; --- 631,644 ---- /* (x & ~m) | (y & m) -> ((x ^ y) & m) ^ x */ (simplify ! (bit_ior:c (bit_and:cs @0 (bit_not @2)) (bit_and:cs @1 @2)) ! (bit_xor (bit_and (bit_xor @0 @1) @2) @0)) /* Associate (p +p off1) +p off2 as (p +p (off1 + off2)). */ (simplify ! (pointer_plus (pointer_plus:s@2 @0 @1) @3) ! (pointer_plus @0 (plus @1 @3))) /* Pattern match tem1 = (long) ptr1; *************** (define_operator_list CBRT BUILT_IN_CBRT *** 913,919 **** if the new mask might be further optimized. */ (for shift (lshift rshift) (simplify ! (bit_and (convert?@4 (shift@5 (convert1?@3 @0) INTEGER_CST@1)) INTEGER_CST@2) (if (tree_nop_conversion_p (TREE_TYPE (@4), TREE_TYPE (@5)) && TYPE_PRECISION (type) <= HOST_BITS_PER_WIDE_INT && tree_fits_uhwi_p (@1) --- 908,915 ---- if the new mask might be further optimized. */ (for shift (lshift rshift) (simplify ! (bit_and (convert?:s@4 (shift:s@5 (convert1?@3 @0) INTEGER_CST@1)) ! INTEGER_CST@2) (if (tree_nop_conversion_p (TREE_TYPE (@4), TREE_TYPE (@5)) && TYPE_PRECISION (type) <= HOST_BITS_PER_WIDE_INT && tree_fits_uhwi_p (@1) *************** (define_operator_list CBRT BUILT_IN_CBRT *** 993,1000 **** (with { tree newmaskt = build_int_cst_type (TREE_TYPE (@2), newmask); } (if (!tree_int_cst_equal (newmaskt, @2)) ! (if (shift_type != TREE_TYPE (@3) ! && single_use (@4) && single_use (@5)) (bit_and (convert (shift:shift_type (convert @3) @1)) { newmaskt; })) (if (shift_type == TREE_TYPE (@3)) (bit_and @4 { newmaskt; })))))))))))) --- 989,995 ---- (with { tree newmaskt = build_int_cst_type (TREE_TYPE (@2), newmask); } (if (!tree_int_cst_equal (newmaskt, @2)) ! (if (shift_type != TREE_TYPE (@3)) (bit_and (convert (shift:shift_type (convert @3) @1)) { newmaskt; })) (if (shift_type == TREE_TYPE (@3)) (bit_and @4 { newmaskt; })))))))))))) *************** (define_operator_list CBRT BUILT_IN_CBRT *** 1733,1739 **** operation and convert the result to the desired type. */ (for op (plus minus) (simplify ! (convert (op@4 (convert@2 @0) (convert@3 @1))) (if (INTEGRAL_TYPE_P (type) /* We check for type compatibility between @0 and @1 below, so there's no need to check that @1/@3 are integral types. */ --- 1728,1734 ---- operation and convert the result to the desired type. */ (for op (plus minus) (simplify ! (convert (op:s (convert@2 @0) (convert@3 @1))) (if (INTEGRAL_TYPE_P (type) /* We check for type compatibility between @0 and @1 below, so there's no need to check that @1/@3 are integral types. */ *************** (define_operator_list CBRT BUILT_IN_CBRT *** 1750,1757 **** /* The inner conversion must be a widening conversion. */ && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0)) && types_match (@0, @1) ! && types_match (@0, type) ! && single_use (@4)) (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))) (convert (op @0 @1))) (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); } --- 1745,1751 ---- /* The inner conversion must be a widening conversion. */ && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0)) && types_match (@0, @1) ! && types_match (@0, type)) (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))) (convert (op @0 @1))) (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); } *************** (define_operator_list CBRT BUILT_IN_CBRT *** 1764,1770 **** arithmetic operation. */ (for op (minus plus) (simplify ! (bit_and (op@5 (convert@2 @0) (convert@3 @1)) INTEGER_CST@4) (if (INTEGRAL_TYPE_P (type) /* We check for type compatibility between @0 and @1 below, so there's no need to check that @1/@3 are integral types. */ --- 1758,1764 ---- arithmetic operation. */ (for op (minus plus) (simplify ! (bit_and (op:s (convert@2 @0) (convert@3 @1)) INTEGER_CST@4) (if (INTEGRAL_TYPE_P (type) /* We check for type compatibility between @0 and @1 below, so there's no need to check that @1/@3 are integral types. */ *************** (define_operator_list CBRT BUILT_IN_CBRT *** 1784,1791 **** && (tree_int_cst_min_precision (@4, TYPE_SIGN (TREE_TYPE (@0))) <= TYPE_PRECISION (TREE_TYPE (@0))) && (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)) ! || tree_int_cst_sgn (@4) >= 0) ! && single_use (@5)) (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))) (with { tree ntype = TREE_TYPE (@0); } (convert (bit_and (op @0 @1) (convert:ntype @4))))) --- 1778,1784 ---- && (tree_int_cst_min_precision (@4, TYPE_SIGN (TREE_TYPE (@0))) <= TYPE_PRECISION (TREE_TYPE (@0))) && (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)) ! || tree_int_cst_sgn (@4) >= 0)) (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0))) (with { tree ntype = TREE_TYPE (@0); } (convert (bit_and (op @0 @1) (convert:ntype @4)))))