Hello, > >>> (parallel [ > >>> (set (pc) > >>> (if_then_else (lt:SI (reg:SI 45) <--- > >>> (reg:SI 26)) > >>> (label_ref:HI 129) > >>> (pc))) > >>> (clobber (reg:SI 45)) <-- must be the > >>> same > >>> (clobber (scratch:BI)) > >>> ]) > > >actually, I probably misunderstood what you meant. The problem is that > >invariant motion rewrites just part of the considered insn, changing > >reg:45 to another register in if_then_else, but leaving it the same in > >the clobber? > > Correct. I originally had a patch like this > > Index: gcc/loop-invariant.c > =================================================================== > --- gcc/loop-invariant.c (revision 125308) > +++ gcc/loop-invariant.c (working copy) > @@ -1212,7 +1212,14 @@ move_invariant_reg (struct loop *loop, u > if (inv->def) > { > for (use = inv->def->uses; use; use = use->next) > - *use->pos = reg; > + { > + rtx orig = *use->pos; > + > + /* Use replace_rtx() in case there are other references to > + ORIG inside the insn which are not recorded in the USE > + list. eg references inside CLOBBERs. */ > + replace_rtx (use->insn, orig, reg); > + } > } > > return true; > > which I thought would solve the problem, but I found that it introduced > regressions into the gcc testsuite for an x86_64-linux-gnulibc > toolchain, so I abandoned it. (I did not investigate why it caused > regressions, I just assumed that my approach was wrong).
It will break in situations like loop { insn 1: (set reg:1 something_invariant) insn 2: (set reg:1 (plus reg:1 something_else)) } When we move the insn 1 out of the loop, we want this to be rewritten as insn 1: (set reg:3 something_invariant) loop { insn 2: (set reg:1 (plus reg:3 something_else)) } While your patch would rewrite insn 2 to set reg:3. What could work would be going through the it might be more efficient to go through defs recorded by df, and rewriting those with DF_REF_MUST_CLOBBER flag. Zdenek