https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91987
--- Comment #3 from rguenther at suse dot de <rguenther at suse dot de> --- On Fri, 4 Oct 2019, jakub at gcc dot gnu.org wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91987 > > --- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> --- > So for the shifts we'd need additionally: > --- gcc/fold-const.c.jj 2019-09-02 15:29:34.548515139 +0200 > +++ gcc/fold-const.c 2019-10-04 10:44:23.319883187 +0200 > @@ -9447,16 +9447,23 @@ fold_binary_loc (location_t loc, enum tr > if (TREE_CODE (arg0) == COMPOUND_EXPR) > { > tem = fold_build2_loc (loc, code, type, > - fold_convert_loc (loc, TREE_TYPE (op0), > - TREE_OPERAND (arg0, 1)), op1); > + fold_convert_loc (loc, TREE_TYPE (op0), > + TREE_OPERAND (arg0, 1)), > + op1); > return build2_loc (loc, COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0), > tem); > } > - if (TREE_CODE (arg1) == COMPOUND_EXPR) > + if (TREE_CODE (arg1) == COMPOUND_EXPR > + && (flag_strong_eval_order != 2 > + /* C++17 disallows this canonicalization for shifts. */ > + || (code != LSHIFT_EXPR > + && code != RSHIFT_EXPR > + && code != LROTATE_EXPR > + && code != RROTATE_EXPR))) > { > tem = fold_build2_loc (loc, code, type, op0, > - fold_convert_loc (loc, TREE_TYPE (op1), > - TREE_OPERAND (arg1, 1))); > + fold_convert_loc (loc, TREE_TYPE (op1), > + TREE_OPERAND (arg1, 1))); > return build2_loc (loc, COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0), > tem); > } Ick. I'd say we should unconditionally guard the transform with the appropriate TREE_SIDE_EFFECTS check? > One thing I'm worried about are the special cases where we enforce some > argument order, evaluate one argument before the other or vice versa. > For is_gimple_reg_type args it can be just a matter of forcing it into an > SSA_NAME or a new VAR_DECL, but if a function argument is a structure, > struct S { int a, b; } c = { 1, 2 }; > fun (c, (c.b = 3, 5); > and fun is one of the magic one that enforce operand ordering and the first > argument needs to be sequenced before the second, what can we do? You need to emit an aggregate copy, don't you? Consider int i; void fun (int i, int j) { assert (i == 0 && j == 1); } and i = 0; fun (i, (i = 1, 5)); so you cannot gimplify to the post-call sequence. For the aggregate case it might be fun (S &a, S &b) so handling of fun (c, c = {}) needs a temporary anyways?