gccgo fails to compile tomb.go on arm64

Bug #1263806 reported by Michael Hudson-Doyle
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
gcc
Fix Released
Medium
gcc-4.8 (Ubuntu)
Fix Released
Undecided
Unassigned

Bug Description

Hi, on am2:

ubuntu@arm64:~/gopath/src/launchpad.net/tomb$ gccgo -g -c -o tomb.o tomb.go
tomb.go: In function 'tomb.Wait.pN12_go.tomb.Tomb':
tomb.go:108:1: error: total size of local objects too large
 func (t *Tomb) Wait() error {
 ^
tomb.go: In function 'tomb.Kill.pN12_go.tomb.Tomb':
tomb.go:134:1: error: total size of local objects too large
 func (t *Tomb) Kill(reason error) {
 ^

This is the first error line: http://bazaar.launchpad.net/~niemeyer/tomb/trunk/view/head:/tomb.go#L108 which seems pretty innocuous.

Will dig (and probably kick upstream) in January.

Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

This is the traceback:

(gdb) bt
#0 0x0000000000b6cf58 in error_at(unsigned int, char const*, ...) ()
#1 0x00000000006d995c in frame_offset_overflow(long, tree_node*) ()
#2 0x00000000006d9b90 in assign_stack_local_1(machine_mode, long, int, int) ()
#3 0x00000000006dcc98 in assign_parms(tree_node*) ()
#4 0x00000000006de6e8 in expand_function_start(tree_node*) ()
#5 0x0000000000600048 in gimple_expand_cfg() ()
#6 0x00000000007b1edc in execute_one_pass(opt_pass*) ()
#7 0x00000000007b225c in execute_pass_list(opt_pass*) ()
#8 0x000000000061b498 in expand_function(cgraph_node*) ()
#9 0x000000000061cbc8 in compile() ()
#10 0x000000000061ceac in finalize_compilation_unit() ()
#11 0x000000000056093c in Gogo::write_globals() ()
#12 0x000000000083f110 in compile_file() ()
#13 0x0000000000840c6c in toplev_main(int, char**) ()

(looks like I need to build a gcc with debugging info though?)

Revision history for this message
In , Michael Hudson-Doyle (mwhudson) wrote :

Hi,

This slightly strangely written program (it's distilled down from frame_offset_overflow in the gcc source itself) should print "bigger" if the first argument is bigger than 10 (or negative, but let's ignore that please):

#include <stdlib.h>
#include <stdio.h>

int a[2] = { 10, 20 };

int
is_bigger (long offset, int index)
{
  unsigned long size = -offset;

  if (size > a[index])
    {
      printf("bigger\n");
      return 1;
    }

  return 0;
}

int
main (int argc, char** argv)
{
  long v;
  v = atol(argv[1]);
  is_bigger(-v, 0);
  return 0;
}

When compiled at -O1 or above (and with inlining disabled at -O2 and above), though, it bungles the 0 case:

(t-doko)mwhudson@arm64:~$ gcc-4.9 -O3 test.c -o test -fno-inline -Wall
(t-doko)mwhudson@arm64:~$ ./test 1
(t-doko)mwhudson@arm64:~$ ./test 11
bigger
(t-doko)mwhudson@arm64:~$ ./test 0
bigger
(t-doko)mwhudson@arm64:~$ gcc-4.9 -O0 test.c -o test -Wall
(t-doko)mwhudson@arm64:~$ ./test 1
(t-doko)mwhudson@arm64:~$ ./test 11
bigger
(t-doko)mwhudson@arm64:~$ ./test 0
(t-doko)mwhudson@arm64:~$

What's going on? Here's the disassembly of is_bigger (at O3):

0000000000400608 <is_bigger>:
  400608: b0000082 adrp x2, 411000 <_GLOBAL_OFFSET_TABLE_+0x28>
  40060c: 91010042 add x2, x2, #0x40
  400610: a9bf7bfd stp x29, x30, [sp,#-16]!
  400614: 52800003 mov w3, #0x0 // #0
  400618: 910003fd mov x29, sp
  40061c: b8a1d841 ldrsw x1, [x2,w1,sxtw #2]
  400620: ab00003f cmn x1, x0
  400624: 540000a2 b.cs 400638 <is_bigger+0x30>
  400628: 90000000 adrp x0, 400000 <_init-0x3f8>
  40062c: 911b6000 add x0, x0, #0x6d8
  400630: 97ffff90 bl 400470 <puts@plt>
  400634: 52800023 mov w3, #0x1 // #1
  400638: 2a0303e0 mov w0, w3
  40063c: a8c17bfd ldp x29, x30, [sp],#16
  400640: d65f03c0 ret

Basically it seems that the condition "-offset > val" is being compiled as "val + offset does not overflow", which is not valid for offset == 0.

Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

After some considerable prodding and poking, this seems to be a gcc bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59744

Revision history for this message
In , Pinskia (pinskia) wrote :

(insn 14 13 15 2 (set (reg:CC_SWP 66 cc)
        (compare:CC_SWP (neg:DI (reg:DI 0 x0 [ offset ]))
            (reg:DI 1 x1 [orig:85 D.3895 ] [85]))) t7.c:11 114 {*compare_negdi}
     (expr_list:REG_DEAD (reg:DI 1 x1 [orig:85 D.3895 ] [85])
        (expr_list:REG_DEAD (reg:DI 0 x0 [ offset ])
            (nil))))

--- CUT ---
Here is a testcase that fails at -O1 and above without any arguments.

int a[2] = { 10, 20 };

int
is_bigger (long, int) __attribute__((noinline,noclone));

int
is_bigger (long offset, int index)
{
  unsigned long size = -offset;

  if (size > a[index])
   return 1;

  return 0;
}

int
main (int argc, char** argv)
{
  long v;
  if (is_bigger(0, 0))
    __builtin_abort ();
  if (!is_bigger(1, 0))
    __builtin_abort ();
  if (is_bigger(-10, 0))
    __builtin_abort ();
  if (!is_bigger(10, 0))
    __builtin_abort ();
  return 0;
}

Revision history for this message
In , Rearnsha (rearnsha) wrote :

Author: rearnsha
Date: Fri Jan 10 15:21:21 2014
New Revision: 206530

URL: http://gcc.gnu.org/viewcvs?rev=206530&root=gcc&view=rev
Log:
PR target/59744
Fix ChangeLog typos in previous commit (r206529).

Modified:
    trunk/gcc/ChangeLog

Revision history for this message
In , Rearnsha (rearnsha) wrote :

Fixed on trunk

Revision history for this message
In , Michael Hudson-Doyle (mwhudson) wrote :

Hi, thanks for the super fast fix. Could it be backported to 4.8? git cherry-pick gives a conflict in aarch64.md which is probably easy to fix if you know how this code works:

(define_insn "*compare_neg<mode>"
<<<<<<< HEAD
  [(set (reg:CC CC_REGNUM)
 (compare:CC
  (match_operand:GPI 0 "register_operand" "r")
  (neg:GPI (match_operand:GPI 1 "register_operand" "r"))))]
||||||| parent of 46b590a... PR target/9744
  [(set (reg:CC_SWP CC_REGNUM)
 (compare:CC_SWP
  (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
  (match_operand:GPI 1 "register_operand" "r")))]
=======
  [(set (reg:CC_Z CC_REGNUM)
 (compare:CC_Z
  (neg:GPI (match_operand:GPI 0 "register_operand" "r"))
  (match_operand:GPI 1 "register_operand" "r")))]
>>>>>>> 46b590a... PR target/9744
  ""
  "cmn\\t%<w>0, %<w>1"
  [(set_attr "v8type" "alus")
   (set_attr "mode" "<MODE>")]
)

Revision history for this message
In , Rearnsha (rearnsha) wrote :

I don't expect that pattern to match on 4.8 (the pattern is not canonical form), which is why this wasn't seen before.

If you can find a test-case that triggers on that branch, I'll do a back-port; otherwise, there's no point.

Revision history for this message
In , Ktkachov (ktkachov) wrote :

I couldn't reproduce the failure using 4.8.

Revision history for this message
In , Michael Hudson-Doyle (mwhudson) wrote :

I saw the problem with Linaro GCC 4.8, but haven't tried the vanilla 4.8 branch. If the committed test case doesn't fail, I'll believe that it is not a problem. Sorry for the noise.

Revision history for this message
Matthias Klose (doko) wrote :

fixed in trusty

Changed in gcc-4.8 (Ubuntu):
status: New → Fix Released
Revision history for this message
In , Yroux (yroux) wrote :

Author: yroux
Date: Mon Aug 11 22:08:03 2014
New Revision: 213842

URL: https://gcc.gnu.org/viewcvs?rev=213842&root=gcc&view=rev
Log:
gcc/
2014-08-11 Michael Collison <email address hidden>

 Backport from trunk r206529, r206530
 2014-01-10 Richard Earnshaw <email address hidden>

 PR target/59744
 * aarch64-modes.def (CC_Zmode): New flags mode.
 * aarch64.c (aarch64_select_cc_mode): Only allow NEG when the condition
 represents an equality.
 (aarch64_get_condition_code): Handle CC_Zmode.
 * aarch64.md (compare_neg<mode>): Restrict to equality operations.

gcc/testsuite/
2014-08-11 Michael Collison <email address hidden>

 Backport from trunk r206529
 2014-01-10 Richard Earnshaw <email address hidden>

 PR target/59744
 * gcc.target/aarch64/cmn-neg.c: Use equality comparisons.
 * gcc.target/aarch64/cmn-neg2.c: New test.

Added:
    branches/linaro/gcc-4_8-branch/gcc/testsuite/gcc.target/aarch64/cmn-neg2.c
Modified:
    branches/linaro/gcc-4_8-branch/gcc/ChangeLog.linaro
    branches/linaro/gcc-4_8-branch/gcc/config/aarch64/aarch64-modes.def
    branches/linaro/gcc-4_8-branch/gcc/config/aarch64/aarch64.c
    branches/linaro/gcc-4_8-branch/gcc/config/aarch64/aarch64.md
    branches/linaro/gcc-4_8-branch/gcc/testsuite/ChangeLog.linaro
    branches/linaro/gcc-4_8-branch/gcc/testsuite/gcc.target/aarch64/cmn-neg.c

Changed in gcc:
importance: Unknown → Medium
status: Unknown → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.