This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Reload pass clobbers cc0


[Originally posted to gcc-help, but http://gcc.gnu.org/lists.html
suggests that this was the wrong list.]

I'm hacking around on the Linux/VAX port of GCC (not yet part of
the official sources).  To get a feel for how the machine.md stuff
works, I'm trying to add native support for udivsi3 and umodsi3
(rather than relying on libgcc.a to provide them).

However, I've run up against a problem that I can't understand yet.
Based on gcc 2.95.2.

Take this define_expand:

   (define_expand "udivsi3"
     [(set (match_operand:SI 0 "general_operand" "=g")
           (udiv:SI (match_operand:SI 1 "general_operand" "g")
                    (match_operand:SI 2 "general_operand" "g")))]
     ""
     "
   {
     emit_insn(gen_cmpsi(operands[1], operands[2]));
     emit_insn(gen_sgeu(operands[0]));
     DONE;
   }
   ")

(Never mind the fact that it'll produce the wrong answer.  I'm
convinced that it's producing the wrong code...)

Now take this fragment:

   extern void xx(unsigned int x);

   unsigned int f(unsigned int a, unsigned int b)
   {
      xx(a/0x80000001);
   }

If I compile without optimization, everything works as expected.
Correct asm code is generated for the emit_insn()s above.

If I compile with -O, here's what we get at the various stages:

File u.c.lreg:

   (insn 9 8 10 (set (cc0)
           (compare (mem/f:SI (plus:SI (reg:SI 12 ap)
                       (const_int 4 [0x4])) 0)
               (const_int -2147483647 [0x80000001]))) 5 {cmpsi} (nil)
       (nil))

   (note 10 9 11 "" NOTE_INSN_DELETED)

   (insn 11 10 12 (set (mem:SI (pre_dec:SI (reg:SI 14 sp)) 0)
           (geu:SI (cc0)
               (const_int 0 [0x0]))) 14 {sgeu} (nil)
       (nil))

Insn 9 is the comparison and insn 11 is the sgeu.  So far, so good.
Then, from u.c.greg

   (insn 9 8 10 (set (cc0)
           (compare (mem/f:SI (plus:SI (reg:SI 12 ap)
                       (const_int 4 [0x4])) 0)
               (const_int -2147483647 [0x80000001]))) 5 {cmpsi} (nil)
       (nil))

   (note 10 9 21 "" NOTE_INSN_DELETED)

   (insn 21 10 23 (set (reg:SI 14 sp)
           (plus:SI (reg:SI 14 sp)
               (const_int -4 [0xfffffffc]))) 50 {addsi3} (nil)
       (nil))

   (insn 23 21 11 (set (reg:SI 0 r0)
           (reg:SI 14 sp)) 18 {movsi} (nil)
       (nil))

   (insn 11 23 12 (set (mem:SI (reg:SI 0 r0) 0)
           (geu:SI (cc0)
               (const_int 0 [0x0]))) 14 {sgeu} (nil)
       (nil))

What happens here is that the pattern for our sgeu specifies
a "=ro" constraint which prohibits pre-decrement (because sgeu
is implemented with two instructions, and substitutin a 
pre-decrement would end up decrementing twice).  So the reload
pass generates insns that decrement the stack pointer, move this
new address to R0 and store the sgeu result in the location
pointed to by R0.

However, the subsequent data flow analysis seems to spot that 
the addsi3 in insn 21 will clobber cc0, therefore insn 9 is
a no-op and gets removed.  From u.c.flow2:

   (note 9 19 10 "" NOTE_INSN_DELETED)

   (note 10 9 21 "" NOTE_INSN_DELETED)

   (insn 21 10 23 (set (reg:SI 14 sp)
           (plus:SI (reg:SI 14 sp)
               (const_int -4 [0xfffffffc]))) 50 {addsi3} (nil)
       (nil))

   (insn 23 21 11 (set (reg:SI 0 r0)
           (reg:SI 14 sp)) 18 {movsi} (nil)
       (nil))

   (insn 11 23 12 (set (mem:SI (reg:SI 0 r0) 0)
           (geu:SI (cc0)
               (const_int 0 [0x0]))) 14 {sgeu} (insn_list 23 (nil))
       (expr_list:REG_DEAD (reg:SI 0 r0)
           (nil)))

So, what's the best way to tackle this:

1  Add sgeu and sltu constraint alternatives that can deal with 
   a pre-decrement operand?

2  Fix the reload pass to somehow generate insns to replace the
   pre-decrement with code that doesn't clobber cc0?

3  Fix reload to generate the reload code for output operands
   _after_ the operation, so that it doesn't affect inputs?

(I'm not too keen on actually doing options 2 or 3 myself, as
I don't understand the reload code at all yet. :-)

Is this a bug in the reload code or a shortcoming in our machine
description?

Thanks for reading this far!

Later,
Kenn


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]