Hello! There is off-by-one error in classify_argument, when processing integer atomic types. When bit_offset is 64, two X86_64_INTEGER CLASS registers should be used.
Attached patch fixes this off-by-one error, so we won't use size = 0 when bit_offset = 64. 2014-02-02 Uros Bizjak <ubiz...@gmail.com> PR target/60017 * config/i386/i386.c (classify_argument): Fix handling of bit_offset when calculating size of integer atomic types. testsuite/ChangeLog: 2014-02-02 Uros Bizjak <ubiz...@gmail.com> PR target/60017 * gcc.c-torture/execute/pr60017.c: New test. Tested on x86_64-linux-gnu, committed to mainline SVN. Patch will be backported to other release branches in a couple of days. Uros.
Index: config/i386/i386.c =================================================================== --- config/i386/i386.c (revision 207393) +++ config/i386/i386.c (working copy) @@ -6627,25 +6627,28 @@ classify_argument (enum machine_mode mode, const_t case CHImode: case CQImode: { - int size = (bit_offset % 64)+ (int) GET_MODE_BITSIZE (mode); + int size = bit_offset + (int) GET_MODE_BITSIZE (mode); - if (size <= 32) + /* Analyze last 128 bits only. */ + size = (size - 1) & 0x7f; + + if (size < 32) { classes[0] = X86_64_INTEGERSI_CLASS; return 1; } - else if (size <= 64) + else if (size < 64) { classes[0] = X86_64_INTEGER_CLASS; return 1; } - else if (size <= 64+32) + else if (size < 64+32) { classes[0] = X86_64_INTEGER_CLASS; classes[1] = X86_64_INTEGERSI_CLASS; return 2; } - else if (size <= 64+64) + else if (size < 64+64) { classes[0] = classes[1] = X86_64_INTEGER_CLASS; return 2; Index: testsuite/gcc.c-torture/execute/pr60017.c =================================================================== --- testsuite/gcc.c-torture/execute/pr60017.c (revision 0) +++ testsuite/gcc.c-torture/execute/pr60017.c (working copy) @@ -0,0 +1,33 @@ +/* PR target/60017 */ + +extern void abort (void); + +struct S0 +{ + short m0; + short m1; +}; + +struct S1 +{ + unsigned m0:1; + char m1[2][2]; + struct S0 m2[2]; +}; + +struct S1 x = { 1, {{2, 3}, {4, 5}}, {{6, 7}, {8, 9}} }; + +struct S1 func (void) +{ + return x; +} + +int main (void) +{ + struct S1 ret = func (); + + if (ret.m2[1].m1 != 9) + abort (); + + return 0; +}