Re: [PATCH v2 1/3] match: allow c variable for the code/operation of the result [PR126912]
Richard Biener <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <CAFiYyc2r8N10fbSvaonfR_LYvjhK=p8Ui4wgKXK+EF3-frpp6g@mail.gmail.com> |
On Thu, Aug 20, 2026 at 5:54 AM Andrea Pinski <[email protected]> wrote: > > On Wed, Aug 19, 2026 at 1:56 AM Richard Biener > <[email protected]> wrote: > > > > On Wed, Aug 19, 2026 at 2:34 AM Andrea Pinski > > <[email protected]> wrote: > > > > > > This allows a C variable for the code of the result > > > to reduce how many for loops are needed and reduces the code size of > > > the generated files by a factor of 6 (in some cases). > > > This should allow for arm to build again at -O0. > > > > > > Currently this only allows if the variable contains `code` in it. > > > If the identifier has cmp in it; genmatch assumes it will be a > > > tcc_comparison for type resultion. > > > > > > I can add support for combined_fn and internal_fn later if needed. > > > From looking into the match patterns right now; there is a few but none > > > use a for loop for cases but rather just a few (3/4) if statements. So it > > > was not high on my list of things to support currently. > > > > I do not like the automagic ID recognition too much. Esp. automatically > > treating anything with 'cmp' as tcc_comparison might lead to wrong code. > > If we stick with that can you please code-generate runtime checking at least? > > There might be more problematic cases for type-inference(?) and most > > definitely for "escape" handling - capture_info::walk_result checks > > for COND_EXPR and TRUTH_{AND,OR}IF_EXPR but you do not touch > > this. Runtime checking could be done for those as well. > > > > But I wonder whether sth like > > > > (simplify (...) > > (with { tree_code code = ...; } > > (code<tcc_comparison> ...))) > > > > would be better overall, that is, require the set of possible operators to > > be specified as declared operator list. So it would be a user-id > > declaration at result parsing time. > > > > I thought of > > > > (tcc_comparsion code @0 @1) > > > > but this doesn't seem lispy syntax. Alternatively do "toplevel" > > > > (simplify (...) > > (with { tree_code = ...; } > > (with_code code (tcc_comparison) > > (code @0 @1))) > > > > so similar to (for ..) syntax, have a declare syntax. Allow > > > > (with_code code (tcc_comparison) > > code2 (plus minus) > > > > as well. I think I prefer (with_code ...)? > > What about this: > (simplify > (bit_xor (cmp @@0 @@1) integer_truep) > (with_code > rescode tcc_comparison > resbincode 2 > resunarycode 1 > restrianycode 3 > (with { rescode = invert_tree_comparison (cmp, HONOR_NANS (@0)); } > (if (TREE_CODE_CLASS (rescode) == tcc_comparison) > (rescode @0 @1))))) > > with_code can only contain a `(with` expression too. So how about extending (with ..) directly then? (simplify (bit_xor (cmp @@0 @@1) integer_truep) (with rescode (tcc_comparison) resunarycode (tcc_unary) { tree_code rescode = invert_tree_comparison (cmp, HONOR_NANS (@0)); } (if (TREE_CODE_CLASS (rescode) == tcc_comparison) (rescode @0 @1)))) I don't like 'resbincode 2', it should be very easy to enumerate allowed codes (and we could code generate checking in checking mode if we want). I'd also like to re-use the (for ..) operator list syntax, so a paren around (tcc_comparison), that can also easily re-use parsing for that plus the representation of the set itself. It makes sense to combine with (with ...) since there has to be a with that actually declares the variable. Not sure if we should be able to elide the declaration of the variables in the {}, we could possibly inject code_helper <identifier>; declarations. I could see use for builtins/ifns when doing target dependent selection, so it should in princinple be extensible to the function designator case without syntactic changes (so temporarily only injecting tree_code <identifier>; would work for me if code_helper doesn't work downstream w/o big changes) So to summarize, I now prefer extending (with ...), use the (for ..) operator list syntax, inject declarations to the start of the with c_expr block. The last bit is least important, but changing it later would affect compatibility. > 3 can't be COND_EXPR/VEC_COND_EXPR. (I can't see where that would > happen anyways) > 2 can't be either TRUTH_ANDIF_EXPR/TRUTH_ORIF_EXPR either. > 1 can be VCE/REAL_PART_EXPR/IMAG_PART_EXPR; otherwise it is tcc_unary. > 2 can't be tcc_comparison. > > Note I can't see any use right now outside of comparison or internal/builtins. > The MIN/MAX results from minmax_from_comparison is the only other > place which we could use it though currently an if happens so it could > simplify the generation code slightly. > > Anyways I will try to come up with a patch later this week. Thanks. Richard. > > > > > > > > Richard. > > > > > Bootstrapped and tested on x86_64-linux-gnu. > > > > > > PR middle-end/126912 > > > gcc/ChangeLog: > > > > > > * doc/match-and-simplify.texi: Document new syntax. > > > * genmatch.cc (class c_code_id): New class. > > > (c_code_id::get_c_code_id): New method. > > > (c_ids): New hashtable. > > > (test): Handle C_CODE_ID. > > > (lower_for): Handle c_code_id. > > > (get_operand_type): Check cmp of c_code_id. > > > (expr::gen_transform): Likewise. > > > (dt_simplify::gen_1): Handle C_CODE_ID like CODE. > > > (parser::parse_operation): Add bool res argument. For unknown id > > > see if this can be a c code id for res. > > > (parser::parse_expr): Add bool res argument. Pass down to parse_op > > > and parse_operation. > > > (parser::parse_op): Add bool res argument. > > > Pass down to parse_expr and parse_op. > > > (parser::parse_result): Pass true to parse_op and parse_expr. > > > (parser::parse_simplify): Pass false to parse_op. > > > (main): Allocate and free c_ids. > > > * match.pd (`(a CMP1 b) bitop (a CMP2 b)`): Remove rcmp > > > loop and update for the new syntax. > > > (other comparison loops): Update for the new syntax. > > > > > > Signed-off-by: Andrea Pinski <[email protected]> > > > --- > > > gcc/doc/match-and-simplify.texi | 13 ++++ > > > gcc/genmatch.cc | 114 ++++++++++++++++++++++++-------- > > > gcc/match.pd | 77 +++++++++------------ > > > 3 files changed, 129 insertions(+), 75 deletions(-) > > > > > > diff --git a/gcc/doc/match-and-simplify.texi b/gcc/doc/match-and-simplify.texi > > > index b187dd27561..4f171a36f69 100644 > > > --- a/gcc/doc/match-and-simplify.texi > > > +++ b/gcc/doc/match-and-simplify.texi > > > @@ -361,6 +361,19 @@ Usually the types of the generated result expressions are > > > determined from the context, but sometimes like in the above case > > > it is required that you specify them explicitly. > > > > > > +In the result of a simplify, a variable defined in @code{with} can be > > > +use as the resulting tree code if it contains @code{code} in the name. > > > +Comparisons results need to have cmp in its name to get the correct type for it. > > > + > > > +@smallexample > > > + (simplify > > > + (bit_xor (cmp @@0 @@1) integer_truep) > > > + (with @{ enum tree_code rescmpcode = invert_tree_comparison > > > + (cmp, HONOR_NANS (@@0)); @} > > > + (if (TREE_CODE_CLASS (rescmpcode) == tcc_comparison) > > > + (rescmpcode @@0 @@1)))) > > > +@end smallexample > > > + > > > Another modifier for generated expressions is @code{^} which > > > tells the machinery to try more matches for some special cases. > > > For example, normally the @code{cond} only allows the gimple > > > diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc > > > index 920cf27877d..44da9fa3970 100644 > > > --- a/gcc/genmatch.cc > > > +++ b/gcc/genmatch.cc > > > @@ -1121,7 +1121,7 @@ comparison_code_p (enum tree_code code) > > > class id_base : public nofree_ptr_hash<id_base> > > > { > > > public: > > > - enum id_kind { CODE, FN, PREDICATE, USER, NULL_ID } kind; > > > + enum id_kind { CODE, FN, PREDICATE, USER, C_CODE_ID, NULL_ID } kind; > > > > > > id_base (id_kind, const char *, int = -1); > > > > > > @@ -1199,6 +1199,37 @@ public: > > > vec<simplify *> matchers; > > > }; > > > > > > +// Identifier that maps to a operator defined by a 'C' identifier. > > > +// Contains code in the id, also if contains cmp then it is a compare. > > > + > > > +class c_code_id : public id_base > > > +{ > > > +public: > > > + c_code_id (const char *id_) > > > + : id_base (id_base::C_CODE_ID, xstrdup (id_)), > > > + cmp (strstr (id_, "cmp")) {} > > > + static id_base *get_c_code_id (const char *); > > > + ~c_code_id() { delete const_cast<char*>(id); } > > > + bool cmp; > > > +}; > > > + > > > +static hash_table<id_base> *c_ids; > > > + > > > +id_base * > > > +c_code_id::get_c_code_id (const char *id) > > > +{ > > > + if (!strstr (id, "code")) > > > + return nullptr; > > > + id_base tem (id_base::C_CODE_ID, id); > > > + > > > + id_base **op = c_ids->find_slot_with_hash (&tem, tem.hashval, INSERT); > > > + if (!*op) > > > + *op = new c_code_id (id); > > > + > > > + return *op; > > > +} > > > + > > > + > > > /* Identifier that maps to a operator defined by a 'for' directive. */ > > > > > > class user_id : public id_base > > > @@ -1244,6 +1275,14 @@ is_a_helper <user_id *>::test (id_base *id) > > > return id->kind == id_base::USER; > > > } > > > > > > +template<> > > > +template<> > > > +inline bool > > > +is_a_helper <c_code_id *>::test (id_base *id) > > > +{ > > > + return id->kind == id_base::C_CODE_ID; > > > +} > > > + > > > /* If ID has a pair of consecutive, commutative operands, return the > > > index of the first, otherwise return -1. */ > > > > > > @@ -2301,6 +2340,8 @@ lower_for (simplify *sin, vec<simplify *>& simplifiers) > > > } > > > else if (is_a <fn_id *> (ids[i]->substitutes[j])) > > > ; > > > + else if (is_a <c_code_id *> (ids[i]->substitutes[j])) > > > + ; > > > else > > > can_delay_subst = false; > > > } > > > @@ -3222,8 +3263,10 @@ get_operand_type (id_base *op, unsigned pos, > > > else if (*op == REALPART_EXPR > > > || *op == IMAGPART_EXPR) > > > return other_oprnd_type; > > > - else if (is_a <operator_id *> (op) > > > - && strcmp (as_a <operator_id *> (op)->tcc, "tcc_comparison") == 0) > > > + else if ((is_a <operator_id *> (op) > > > + && strcmp (as_a <operator_id *> (op)->tcc, "tcc_comparison") == 0) > > > + || (is_a <c_code_id *> (op) > > > + && as_a <c_code_id *>(op)->cmp)) > > > return other_oprnd_type; > > > else if (*op == COND_EXPR > > > && pos == 0) > > > @@ -3285,8 +3328,10 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple, > > > depth); > > > type = optype; > > > } > > > - else if (is_a <operator_id *> (opr) > > > - && !strcmp (as_a <operator_id *> (opr)->tcc, "tcc_comparison")) > > > + else if ((is_a <operator_id *> (opr) > > > + && !strcmp (as_a <operator_id *> (opr)->tcc, "tcc_comparison")) > > > + || (is_a <c_code_id *> (opr) > > > + && as_a <c_code_id *> (opr)->cmp)) > > > { > > > /* comparisons use boolean_type_node (or what gets in), but > > > their operands need to figure out the types themselves. */ > > > @@ -3451,7 +3496,7 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple, > > > fprintf_indent (f, indent + 2, "{\n"); > > > indent += 4; > > > } > > > - if (opr->kind == id_base::CODE) > > > + if (opr->kind == id_base::CODE || opr->kind == id_base::C_CODE_ID) > > > fprintf_indent (f, indent, "_r%d = fold_build%d_loc (loc, %s, %s", > > > depth, ops.length(), opr_name, type); > > > else > > > @@ -3460,7 +3505,7 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple, > > > for (unsigned i = 0; i < ops.length (); ++i) > > > fprintf (f, ", _o%d[%u]", depth, i); > > > fprintf (f, ");\n"); > > > - if (opr->kind != id_base::CODE) > > > + if (opr->kind != id_base::CODE && opr->kind != id_base::C_CODE_ID) > > > { > > > fprintf_indent (f, indent, "if (!_r%d)\n", depth); > > > fprintf_indent (f, indent, " goto %s;\n", fail_label); > > > @@ -4630,7 +4675,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result) > > > "_r = non_lvalue_loc (loc, res_op0);\n"); > > > else > > > { > > > - if (is_a <operator_id *> (opr)) > > > + if (is_a <operator_id *> (opr) || is_a <c_code_id *> (opr)) > > > fprintf_indent (f, indent, > > > "_r = fold_build%d_loc (loc, %s, type", > > > e->ops.length (), > > > @@ -4644,7 +4689,7 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result) > > > for (unsigned j = 0; j < e->ops.length (); ++j) > > > fprintf (f, ", res_op%d", j); > > > fprintf (f, ");\n"); > > > - if (!is_a <operator_id *> (opr)) > > > + if (!is_a <operator_id *> (opr) && !is_a<c_code_id *> (opr)) > > > { > > > fprintf_indent (f, indent, "if (!_r)\n"); > > > fprintf_indent (f, indent, " goto %s;\n", fail_label); > > > @@ -5146,11 +5191,11 @@ private: > > > > > > unsigned get_internal_capture_id (); > > > > > > - id_base *parse_operation (unsigned char &); > > > + id_base *parse_operation (unsigned char &, bool); > > > operand *parse_capture (operand *, bool); > > > - operand *parse_expr (); > > > + operand *parse_expr (bool = false); > > > c_expr *parse_c_expr (cpp_ttype); > > > - operand *parse_op (); > > > + operand *parse_op (bool); > > > > > > void record_operlist (location_t, user_id *); > > > > > > @@ -5338,7 +5383,7 @@ parser::record_operlist (location_t loc, user_id *p) > > > convert2? */ > > > > > > id_base * > > > -parser::parse_operation (unsigned char &opt_grp) > > > +parser::parse_operation (unsigned char &opt_grp, bool res) > > > { > > > const cpp_token *id_tok = peek (); > > > char *alt_id = NULL; > > > @@ -5365,7 +5410,18 @@ parser::parse_operation (unsigned char &opt_grp) > > > } > > > id_base *op = get_operator (alt_id ? alt_id : id); > > > if (!op) > > > - fatal_at (id_tok, "unknown operator %s", alt_id ? alt_id : id); > > > + { > > > + // An unknown id that contains code in it is considered a C code identifier > > > + if (res) > > > + { > > > + if (id_base *op = c_code_id::get_c_code_id (id)) > > > + { > > > + free (alt_id); > > > + return op; > > > + } > > > + } > > > + fatal_at (id_tok, "unknown operator %s", alt_id ? alt_id : id); > > > + } > > > if (alt_id) > > > free (alt_id); > > > user_id *p = dyn_cast<user_id *> (op); > > > @@ -5420,11 +5476,11 @@ parser::parse_capture (operand *op, bool require_existing) > > > expr = '(' <operation>[capture][flag][type] <operand>... ')' */ > > > > > > class operand * > > > -parser::parse_expr () > > > +parser::parse_expr (bool res) > > > { > > > const cpp_token *token = peek (); > > > unsigned char opt_grp; > > > - expr *e = new expr (parse_operation (opt_grp), token->src_loc); > > > + expr *e = new expr (parse_operation (opt_grp, res), token->src_loc); > > > token = peek (); > > > operand *op; > > > bool is_commutative = false; > > > @@ -5537,7 +5593,7 @@ parser::parse_expr () > > > else if (!(token->flags & PREV_WHITE)) > > > fatal_at (token, "expected expression operand"); > > > > > > - e->append_op (parse_op ()); > > > + e->append_op (parse_op (res)); > > > } > > > while (1); > > > } > > > @@ -5602,14 +5658,14 @@ parser::parse_c_expr (cpp_ttype start) > > > op = predicate | expr | c_expr | capture */ > > > > > > class operand * > > > -parser::parse_op () > > > +parser::parse_op (bool res) > > > { > > > const cpp_token *token = peek (); > > > class operand *op = NULL; > > > if (token->type == CPP_OPEN_PAREN) > > > { > > > eat_token (CPP_OPEN_PAREN); > > > - op = parse_expr (); > > > + op = parse_expr (res); > > > eat_token (CPP_CLOSE_PAREN); > > > } > > > else if (token->type == CPP_OPEN_BRACE) > > > @@ -5695,7 +5751,7 @@ parser::parse_result (operand *result, predicate_id *matcher) > > > { > > > const cpp_token *token = peek (); > > > if (token->type != CPP_OPEN_PAREN) > > > - return parse_op (); > > > + return parse_op (true); > > > > > > eat_token (CPP_OPEN_PAREN); > > > if (peek_ident ("if")) > > > @@ -5709,15 +5765,15 @@ parser::parse_result (operand *result, predicate_id *matcher) > > > if (peek ()->type == CPP_OPEN_PAREN) > > > ife->falseexpr = parse_result (result, matcher); > > > else if (peek ()->type != CPP_CLOSE_PAREN) > > > - ife->falseexpr = parse_op (); > > > + ife->falseexpr = parse_op (true); > > > } > > > else if (peek ()->type != CPP_CLOSE_PAREN) > > > { > > > - ife->trueexpr = parse_op (); > > > + ife->trueexpr = parse_op (true); > > > if (peek ()->type == CPP_OPEN_PAREN) > > > ife->falseexpr = parse_result (result, matcher); > > > else if (peek ()->type != CPP_CLOSE_PAREN) > > > - ife->falseexpr = parse_op (); > > > + ife->falseexpr = parse_op (true); > > > } > > > /* If this if is immediately closed then it contains a > > > manual matcher or is part of a predicate definition. */ > > > @@ -5752,7 +5808,7 @@ parser::parse_result (operand *result, predicate_id *matcher) > > > if (peek ()->type == CPP_OPEN_PAREN) > > > ife->trueexpr = parse_result (result, matcher); > > > else > > > - ife->trueexpr = parse_op (); > > > + ife->trueexpr = parse_op (true); > > > eat_token (CPP_CLOSE_PAREN); > > > if (peek ()->type != CPP_OPEN_PAREN > > > || !peek_ident ("if", 2)) > > > @@ -5771,7 +5827,7 @@ parser::parse_result (operand *result, predicate_id *matcher) > > > if (peek ()->type == CPP_OPEN_PAREN) > > > ife->trueexpr = parse_result (result, matcher); > > > else > > > - ife->trueexpr = parse_op (); > > > + ife->trueexpr = parse_op (true); > > > if (peek ()->type == CPP_OPEN_PAREN) > > > fatal_at (peek(), "if inside switch cannot have an else"); > > > eat_token (CPP_CLOSE_PAREN); > > > @@ -5787,7 +5843,7 @@ parser::parse_result (operand *result, predicate_id *matcher) > > > else > > > { > > > /* switch default clause */ > > > - ife->falseexpr = parse_op (); > > > + ife->falseexpr = parse_op (true); > > > eat_token (CPP_CLOSE_PAREN); > > > return res; > > > } > > > @@ -5799,7 +5855,7 @@ parser::parse_result (operand *result, predicate_id *matcher) > > > { > > > operand *op = result; > > > if (!matcher) > > > - op = parse_expr (); > > > + op = parse_expr (true); > > > eat_token (CPP_CLOSE_PAREN); > > > return op; > > > } > > > @@ -5826,7 +5882,7 @@ parser::parse_simplify (simplify::simplify_kind kind, > > > > > > const cpp_token *loc = peek (); > > > parsing_match_operand = true; > > > - class operand *match = parse_op (); > > > + class operand *match = parse_op (false); > > > finish_match_operand (match); > > > parsing_match_operand = false; > > > if (match->type == operand::OP_CAPTURE && !matcher) > > > @@ -6366,6 +6422,7 @@ main (int argc, char **argv) > > > > > > /* Pre-seed operators. */ > > > operators = new hash_table<id_base> (1024); > > > + c_ids = new hash_table<id_base> (4); > > > #define DEFTREECODE(SYM, STRING, TYPE, NARGS) \ > > > add_operator (SYM, # SYM, # TYPE, NARGS); > > > #define END_OF_BASE_TREE_CODES > > > @@ -6471,6 +6528,7 @@ main (int argc, char **argv) > > > cpp_destroy (r); > > > > > > delete operators; > > > + delete c_ids; > > > > > > return 0; > > > } > > > diff --git a/gcc/match.pd b/gcc/match.pd > > > index eae8717bcfe..d255795c8dd 100644 > > > --- a/gcc/match.pd > > > +++ b/gcc/match.pd > > > @@ -4006,20 +4006,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > > > (for bitop (bit_and bit_ior) > > > (for cmp1 (tcc_comparison) > > > (for cmp2 (tcc_comparison) > > > - (for rcmp (tcc_comparison) > > > - (simplify > > > - (bitop (cmp1 @0 @1) (cmp2 @0 @1)) > > > - (with { > > > - tree_code rescode; > > > - tree res; > > > - bool honor_nans = HONOR_NANS (@0); > > > - rescode = combine_comparisons (bitop, cmp1, cmp2, > > > - type, honor_nans, &res); > > > - } > > > - (if (rescode == INTEGER_CST) > > > - { res; } > > > - (if (rescode == rcmp) > > > - (rcmp @0 @1))))))))) > > > + (simplify > > > + (bitop (cmp1 @0 @1) (cmp2 @0 @1)) > > > + (with { > > > + tree_code rescmpcode; > > > + tree res; > > > + bool honor_nans = HONOR_NANS (@0); > > > + rescmpcode = combine_comparisons (bitop, cmp1, cmp2, > > > + type, honor_nans, &res); > > > + } > > > + (if (rescmpcode == INTEGER_CST) > > > + { res; } > > > + (if (TREE_CODE_CLASS (rescmpcode) == tcc_comparison) > > > + (rescmpcode @0 @1)))))))) > > > > > > /* (type)([0,1]@a != 0) -> (type)a > > > (type)([0,1]@a == 1) -> (type)a > > > @@ -7781,8 +7780,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > > > operator using invert_tree_comparison we have to simulate > > > that with expression code iteration. */ > > > (for cmp (tcc_comparison) > > > - icmp (inverted_tcc_comparison) > > > - ncmp (inverted_tcc_comparison_with_nans) > > > /* Ideally we'd like to combine the following two patterns > > > and handle some more cases by using > > > (logical_inverted_value (cmp @0 @1)) > > > @@ -7793,39 +7790,29 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > > > (if (VECTOR_TYPE_P (type) > > > || (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1)) > > > /* Comparison inversion may be impossible for trapping math, > > > - invert_tree_comparison will tell us. But we can't use > > > - a computed operator in the replacement tree thus we have > > > - to play the trick below. */ > > > - (with { enum tree_code ic = invert_tree_comparison > > > + invert_tree_comparison will tell us. */ > > > + (with { enum tree_code rescmpcode = invert_tree_comparison > > > (cmp, HONOR_NANS (@0)); } > > > - (if (ic == icmp) > > > - (icmp @0 @1) > > > - (if (ic == ncmp) > > > - (ncmp @0 @1)))))) > > > + (if (TREE_CODE_CLASS (rescmpcode) == tcc_comparison) > > > + (rescmpcode @0 @1))))) > > > (simplify > > > (bit_xor (cmp @0 @1) integer_truep) > > > - (with { enum tree_code ic = invert_tree_comparison > > > + (with { enum tree_code rescmpcode = invert_tree_comparison > > > (cmp, HONOR_NANS (@0)); } > > > - (if (ic == icmp) > > > - (icmp @0 @1) > > > - (if (ic == ncmp) > > > - (ncmp @0 @1))))) > > > + (if (TREE_CODE_CLASS (rescmpcode) == tcc_comparison) > > > + (rescmpcode @0 @1)))) > > > /* ((cast)cmp) - 1 -> -(cast)icmp . */ > > > (simplify > > > (plus (convert? (cmp@2 @0 @1)) integer_minus_onep) > > > (if (TYPE_PRECISION (type) > 1 > > > && INTEGRAL_TYPE_P (TREE_TYPE (@2)) && TYPE_PRECISION (TREE_TYPE (@2)) == 1) > > > /* Comparison inversion may be impossible for trapping math, > > > - invert_tree_comparison will tell us. But we can't use > > > - a computed operator in the replacement tree thus we have > > > - to play the trick below. */ > > > - (with { enum tree_code ic = invert_tree_comparison > > > + invert_tree_comparison will tell us. */ > > > + (with { enum tree_code rescmpcode = invert_tree_comparison > > > (cmp, HONOR_NANS (@0)); > > > tree cmptype = TREE_TYPE (@2); } > > > - (if (ic == icmp) > > > - (negate (convert (icmp:cmptype @0 @1))) > > > - (if (ic == ncmp) > > > - (negate (convert (ncmp:cmptype @0 @1)))))))) > > > + (if (TREE_CODE_CLASS (rescmpcode) == tcc_comparison) > > > + (negate (convert (rescmpcode:cmptype @0 @1))))))) > > > /* The following bits are handled by fold_binary_op_with_conditional_arg. */ > > > (simplify > > > (ne (cmp@2 @0 @1) integer_zerop) > > > @@ -7838,21 +7825,17 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) > > > (simplify > > > (ne (cmp@2 @0 @1) integer_truep) > > > (if (types_match (type, TREE_TYPE (@2))) > > > - (with { enum tree_code ic = invert_tree_comparison > > > + (with { enum tree_code rescmpcode = invert_tree_comparison > > > (cmp, HONOR_NANS (@0)); } > > > - (if (ic == icmp) > > > - (icmp @0 @1) > > > - (if (ic == ncmp) > > > - (ncmp @0 @1)))))) > > > + (if (TREE_CODE_CLASS (rescmpcode) == tcc_comparison) > > > + (rescmpcode @0 @1))))) > > > (simplify > > > (eq (cmp@2 @0 @1) integer_zerop) > > > (if (types_match (type, TREE_TYPE (@2))) > > > - (with { enum tree_code ic = invert_tree_comparison > > > + (with { enum tree_code rescmpcode = invert_tree_comparison > > > (cmp, HONOR_NANS (@0)); } > > > - (if (ic == icmp) > > > - (icmp @0 @1) > > > - (if (ic == ncmp) > > > - (ncmp @0 @1))))))) > > > + (if (TREE_CODE_CLASS (rescmpcode) == tcc_comparison) > > > + (rescmpcode @0 @1)))))) > > > > > > /* Transform comparisons of the form X - Y CMP 0 to X CMP Y. > > > ??? The transformation is valid for the other operators if overflow > > > -- > > > 2.43.0 > > >