On 11/13/2010 08:40 PM, Peter Bergner wrote:
On Sat, 2010-11-13 at 11:27 +0100, Paolo Bonzini wrote:
On 11/12/2010 03:25 PM, H.J. Lu wrote:
IRA may move instructions across an unspec_volatile,

Do you have a testcase?

Are you sure it's IRA and not our old friend update_equiv_regs()
which IRA calls?  http://gcc.gnu.org/PR41171 shows an example
where update_equiv_regs() moves code around.

Peter



I'm just having a similar issue on SH4. The machine description inserts a unspec_volatile when generating a PIC access to the stack_chk_guard symbol to avoid combine them into a mem (R0,Rx) addressing mode, generating a unable to find a register to spill in class 'R0_REGS' spill failure.

The simplified RTL sequence was like, before ira:

(insn 33 32 34 5 (set (reg:SI 175)
        (plus:SI (reg/f:SI 174)
            (reg:SI 12 r12)))

(insn 34 33 35 5 (unspec_volatile [
            (const_int 0 [0])
        ] 0)

(insn 35 34 36 5 (set (reg/f:SI 173)
        (mem/u/c:SI (reg:SI 175) [0 S4 A32]))

Then during IRA :

(insn 35 56 55 5 (set (reg/f:SI 1 r1 [173])
        (mem/u/c:SI (plus:SI (reg/f:SI 1 r1 [174])
                (reg:SI 12 r12)) [0 S4 A32]))

So insn 33 has been moved across the unspec_volatile by 'update_equiv_regs'.

So, back to the original question. Is unspec_volatile expected to avoid this ?

The conservative illustrative attached patch fixed my problem, but this should clearly need to refined because it's also prevents combines of insns that are not concerned by the blockage. I also suspect that there are other places in the compiler where instructions could be combined without checking the unspec_volatile.


Index: ira.c
===================================================================
--- ira.c       (revision 166230)
+++ ira.c       (working copy)
@@ -2304,6 +2304,16 @@
             only mark all destinations as having no known equivalence.  */
          if (set == 0)
            {
+             if (GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE)
+               {
+                 int i;
+                 /* UNSPEC_VOLATILE is considered to use and clobber all hard 
+                  registers and all of memory.  This blocks insns from being
+                  combined across this point.  */
+                 for (i = FIRST_PSEUDO_REGISTER; i < reg_equiv_init_size; i++)
+                   reg_equiv[i].replace = 0;
+               }
+
              note_stores (PATTERN (insn), no_equiv, NULL);
              continue;
            }

Reply via email to