The following fixes a bug in fold-const.c which happily drops side-effects when simplifying X - X to 0. I ran into this because on match-and-simplify I cannot simplify expressions with TREE_SIDE_EFFECTS and it happens that TYPE_SIZE for VLAs has side-effects because it usually contains a SAVE_EXPR which are forced to have side-effects (even if its arg does not have side-effects). This is appearantly because you can use SAVE_EXPRs to force creation of initialized temporaries at defined place in the instruction stream. For example fold-const.c currently would miscompile
(save_expr<global> - save_expr<global>, (global = 1, save_expr<global>)) Of course all this makes my life hard on match-and-simplify branch and I wonder why we need to use SAVE_EXPRs for these cases where the initialization of a new temporary could be done explicitely (using INIT_EXPR or TARGET_EXPR). Anyway - fixing the fold-const.c bug requires fixing the bug I run into on match-and-simplify branch - here by simply "stripping" the side-effects to get to the actual difference of the two DECL_FIELD_OFFSETs (I wonder if I missed an obvious tool to do such stripping). Bootstrap & regtest running on x86_64-unknown-linux-gnu. Of course this doesn't help me on match-and-simplify branch (example testcase that ICEs there with the assert in stor-layout.c visible below is gcc.c-torture/execute/20040308-1.c). In theory it should be ok to simplify these late in GIMPLE and for the stor-layout.c case unset TREE_SIDE_EFFECTS temporarily to make generic_simplify happy ... (ugh). Thanks, Richard. 2014-10-22 Richard Biener <rguent...@suse.de> * fold-const.c (fold_binary_loc): Preserve side-effects of X - X when simplifying to 0. * stor-layout.c (finish_bitfield_representative): Strip side-effects of evaluating the difference of two DECL_FIELD_OFFSET. Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c (revision 216543) +++ gcc/fold-const.c (working copy) @@ -10749,7 +10768,7 @@ fold_binary_loc (location_t loc, if ((!FLOAT_TYPE_P (type) || !HONOR_NANS (TYPE_MODE (type))) && operand_equal_p (arg0, arg1, 0)) - return build_zero_cst (type); + return omit_one_operand_loc (loc, type, build_zero_cst (type), arg0); /* A - B -> A + (-B) if B is easily negatable. */ if (negate_expr_p (arg1) Index: gcc/stor-layout.c =================================================================== --- gcc/stor-layout.c (revision 216543) +++ gcc/stor-layout.c (working copy) @@ -1860,6 +1860,8 @@ finish_bitfield_representative (tree rep size = size_diffop (DECL_FIELD_OFFSET (field), DECL_FIELD_OFFSET (repr)); + while (TREE_CODE (size) == COMPOUND_EXPR) + size = TREE_OPERAND (size, 1); gcc_assert (tree_fits_uhwi_p (size)); bitsize = (tree_to_uhwi (size) * BITS_PER_UNIT + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field))