On Thu, Dec 01, 2016 at 01:19:16PM +0100, Bernd Schmidt wrote: > On 11/30/2016 11:11 PM, Jakub Jelinek wrote: > >I run into the problem that while simplify_replace_rtx if it actually does > >copy_rtx (for y) or if it simplifies something through > >simplify_gen_{unary,binary,relational,ternary}, the used bits on the newly > >created rtxes are cleared, when we fall through into the fallback > >simplify_replace_fn_rtx handling, it calls shallow_copy_rtx which copies the > >set used bit and thus copy_rtx_if_shared copies it again. > > Shouldn't the bit be cleared in shallow_copy_rtx then?
Not very easily. The problem is that the used bit means lots of things for various rtls: /* At the end of RTL generation, 1 if this rtx is used. This is used for copying shared structure. See `unshare_all_rtl'. In a REG, this is not needed for that purpose, and used instead in `leaf_renumber_regs_insn'. 1 in a SYMBOL_REF, means that emit_library_call has used it as the function. 1 in a CONCAT is VAL_HOLDS_TRACK_EXPR in var-tracking.c. 1 in a VALUE or DEBUG_EXPR is VALUE_RECURSED_INTO in var-tracking.c. */ unsigned int used : 1; so we'd need to slow shallow_copy_rtx down by adding switch (code) in there or something similar. The callers of it have the advantage that they know they call shallow_copy_rtx already on something that shouldn't be shared, and many of them take care of the used bit already (some clear it, other callers set it). So clearing it in shallow_copy_rtx for the callers that set it would be just waste of time. But if you strongly prefer that I can try to implement it. That said, I found a bug in my patch, ADDR_DIFF_VEC has "eEee0" format, thus if simplify_replace_fn_rtx replaces anything in the first operand, then either it wouldn't properly duplicate the vector operand if no changes are needed there, or it would ICE with the previous version of the patch. So here is an updated patch that fixes this. 2016-12-01 Jakub Jelinek <ja...@redhat.com> PR target/78614 * simplify-rtx.c (simplify_replace_fn_rtx): When copying rtx with 'E' in format, copy all vectors. Clear used flag after shallow_copy_rtx. --- gcc/simplify-rtx.c.jj 2016-12-01 08:53:37.134284466 +0100 +++ gcc/simplify-rtx.c 2016-12-01 23:32:45.074152770 +0100 @@ -547,13 +547,20 @@ simplify_replace_fn_rtx (rtx x, const_rt old_rtx, fn, data); if (op != RTVEC_ELT (vec, j)) { - if (newvec == vec) + if (x == newx) { - newvec = shallow_copy_rtvec (vec); - if (x == newx) - newx = shallow_copy_rtx (x); - XVEC (newx, i) = newvec; + newx = shallow_copy_rtx (x); + RTX_FLAG (newx, used) = 0; + /* If we copy X, we need to copy also all + vectors in it, rather than copy only + a subset of them and share the rest. */ + for (int k = 0; fmt[k]; k++) + if (fmt[k] == 'E') + XVEC (newx, k) = shallow_copy_rtvec (XVEC (x, k)); + newvec = XVEC (newx, i); } + else + gcc_checking_assert (vec != newvec); RTVEC_ELT (newvec, j) = op; } } @@ -566,7 +573,16 @@ simplify_replace_fn_rtx (rtx x, const_rt if (op != XEXP (x, i)) { if (x == newx) - newx = shallow_copy_rtx (x); + { + newx = shallow_copy_rtx (x); + RTX_FLAG (newx, used) = 0; + /* If we copy X, we need to copy also all + vectors in it, rather than copy only + a subset of them and share the rest. */ + for (int k = 0; fmt[k]; k++) + if (fmt[k] == 'E') + XVEC (newx, k) = shallow_copy_rtvec (XVEC (x, k)); + } XEXP (newx, i) = op; } } Jakub