Fix a cse problem with libcalls

Bernd Schmidt bernds_cb1@t-online.de
Sat Nov 13 17:29:00 GMT 2004


The Blackfin port that I'm working on uses an outgoing argument area; 
all calls construct their arguments in this reserved space above the 
stack pointer.  This is quite normal and done by other ports as well. 
Nested calls are handled properly in calls.c by creating a save area as 
needed and copying already constructed arguments to it when we encounter 
a second call while evaluating arguments.

The attached testcase has a nested libcall (for the division).  Initial 
RTL generation is correct:

(insn 13 12 14 (set (reg:DI 52)
         (mem:DI (plus:SI (reg/f:SI 47 virtual-outgoing-args)
                 (const_int 8 [0x8])) [0 S8 A32])) -1 (nil)
     (nil))
  - this copies the already constructed arguments to pseudo

(insn 15 14 16 (set (mem:SI (plus:SI (reg/f:SI 47 virtual-outgoing-args)
                 (const_int 12 [0xc])) [0 S4 A32])
         (reg:SI 53)) -1 (nil)
     (insn_list:REG_LIBCALL 22 (nil)))
  - this sets one of the stack args for the following libcall.

[...]
(call_insn/u 19 18 20 (set (reg:DF 0 R0)
         (call (mem:SI (symbol_ref:SI ("__divdf3") [flags 0x41]) [0 S4 A32])
             (const_int 16 [0x10]))) -1 (nil)
     (expr_list:REG_EH_REGION (const_int -1 [0xffffffff])
         (nil))
     (expr_list (use (reg:DF 2 R2))
         (expr_list (use (reg:DF 0 R0))
             (nil))))
  - the libcall

(insn 20 19 23 (set (mem:DI (plus:SI (reg/f:SI 47 virtual-outgoing-args)
                 (const_int 8 [0x8])) [0 S8 A32])
         (reg:DI 52)) -1 (nil)
     (nil))
  - restore the arguments for the outer call.

Then, it all gets completely messed up by CSE, which believes the store 
of insn 15 doesn't conflict with anything because it is in a libcall 
block.  Hence, we turn insn 20 into

(insn 20 19 23 (set (mem:DI (plus:SI (reg/f:SI 47 virtual-outgoing-args)
                 (const_int 8 [0x8])) [0 S8 A32])
         (mem:DI (plus:SI (reg/f:SI 47 virtual-outgoing-args)
                 (const_int 8 [0x8])) -1 (nil)
     (nil))

which is a no-op move that subsequently gets deleted.

I've committed the patch below, which disables this excessive attempt at 
cleverness.  Bootstrapped on i686-linux; I've also verified that for a 
fairly large number of testcases, an sh-elf compiler (which should be a 
relatively heavy user of libcalls) produces exactly the same output as 
before.  I've also committed the testcase as execute/20041113-1.c.


Bernd
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: arg3.c
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20041113/b2f27cce/attachment.c>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cse.diff
Type: text/x-patch
Size: 1999 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/gcc-patches/attachments/20041113/b2f27cce/attachment.bin>


More information about the Gcc-patches mailing list