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]
Other format: [Raw text]

set_mem_attributes_minus_bitpos vs. size


Hello Richard,

after updating to the latest tree I'm seeing failures of
struct-cpy-1.c on s390.  This appears to be caused by
movstr being called with a destination MEM with incorrect
size attibute.

What happens is that when using these structures:

  struct termios
  {
    unsigned int a;
    unsigned int b;
    unsigned int c;
    unsigned int d;
    unsigned char pad[28];
  };

  struct tty_driver
  {
    unsigned char pad1[38];
    struct termios t __attribute__ ((aligned (8)));
  };

  static struct termios zero_t;
  static struct tty_driver pty;

the assignment

  pty.t = zero_t;

gets translated to

(insn 10 9 12 (nil) (parallel [
            (set (mem/s:BLK (plus:SI (reg/f:SI 40)
                        (const_int 40 [0x28])) [5 pty.t+0 S4 A64])
                (mem/s:BLK (reg/f:SI 41) [5 zero_t+0 S44 A32]))
            (use (const_int 43 [0x2b]))
            (clobber (scratch:SI))
        ]) -1 (nil)
    (nil))

Note the dest size of 4 instead of 44.  This incorrect size
leads to incorrect scheduling decisions later.

The reason for the incorrect size appears to be an unfortunate
interaction between set_mem_attributes_minus_bitpos_size as
called from expand_assignment and adjust_address as called from
store_field.

In expand_assignment, we start out with
   (mem/s:BLK (reg/f:SI 40) [3 pty+0 S88 A64])
describing the whole pty struct.

expand_assignment then calls set_mem_attributes_minus_bitpos_size,
which adjusts this target MEM to
   (mem/s:BLK (reg/f:SI 40) [5 pty.t+-40 S44 A64])
which has the size already reduced to the size of a struct termios.

This MEM is now passed to store_field together with a corresponding
bitpos of 320 (40 bytes).  store_field now calls adjust_address
to add the bitpos to the starting offset.  This results in
  (mem/s:BLK (plus:SI (reg/f:SI 40)
         (const_int 40 [0x28])) [5 pty.t+0 S4 A64])
which now has the correct address, but an incorrect size.

This is because adjust_address thinks it is accessing a memory
block of size 44 starting at offset 40 *within this block*,
so the remaining size is just 4 ...

I'm not sure how this is to be fixed; either
set_mem_attributes_minus_bitpos_size increments the size accordingly,
or else adjust_address should recognize this case somehow.

What do you think?


Mit freundlichen Gruessen / Best Regards

Ulrich Weigand

--
  Dr. Ulrich Weigand
  Linux for S/390 Design & Development
  IBM Deutschland Entwicklung GmbH, Schoenaicher Str. 220, 71032 Boeblingen
  Phone: +49-7031/16-3727   ---   Email: Ulrich.Weigand@de.ibm.com


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