Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
19 years ago

Compiler Bug: Wrong code generation

Hi there,

Recently I've ported a program from NIOS I to NIOS II. When debugging the ported program I noticed a strange problem in the code generated.

Basically, the compiler generated a wrong code for a nested switch statement. The problem arises if the code for the switch is bigger than a certain size.

The C code that shows the problem is as follows:

#include <stdio.h>
void Func1() {
    int j = 0;
    for(int i=0; i<10; i++)
       j += i;
}
void Func2() {
    int j = 0;
    for(int i=0; i<10; i++)
       j -= i;
}
void Func3() {
    int j = 0;
    for(int i=0; i<10; i++)
       j += 2 * i;
}
# define SOME_CODE()                            
    asm(".rept 71\n"                            
        " nop\n"                                
        ".endr\n")
void BugSample(int var1, int var2)
{# define HANDLE_CASE(__tag)                     
    case __tag:                                 
       printf(#__tag "\n");                     
       SOME_CODE();                             
       printf(#__tag "\n");                     
       break;
    switch(var1)
    {
       HANDLE_CASE(0)
       HANDLE_CASE(1)
       HANDLE_CASE(2)
       HANDLE_CASE(3)
       HANDLE_CASE(4)
       HANDLE_CASE(5)
       HANDLE_CASE(6)
       HANDLE_CASE(7)
       HANDLE_CASE(8)
       HANDLE_CASE(9)
       HANDLE_CASE(10)
       HANDLE_CASE(11)
       HANDLE_CASE(12)
       HANDLE_CASE(13)
       HANDLE_CASE(14)
       HANDLE_CASE(15)
       HANDLE_CASE(16)
       HANDLE_CASE(17)
       HANDLE_CASE(18)
       HANDLE_CASE(19)
       HANDLE_CASE(20)
       HANDLE_CASE(21)
       HANDLE_CASE(22)
       HANDLE_CASE(23)
       HANDLE_CASE(24)
       HANDLE_CASE(25)
       HANDLE_CASE(26)
       HANDLE_CASE(27)
       HANDLE_CASE(28)
       HANDLE_CASE(29)
       HANDLE_CASE(30)
       HANDLE_CASE(31)
       HANDLE_CASE(32)
       HANDLE_CASE(33)
       HANDLE_CASE(34)
       HANDLE_CASE(35)
       HANDLE_CASE(36)
       HANDLE_CASE(37)
       HANDLE_CASE(38)
       HANDLE_CASE(39)
       HANDLE_CASE(40)
       HANDLE_CASE(41)
       HANDLE_CASE(42)
       HANDLE_CASE(43)
       HANDLE_CASE(44)
       HANDLE_CASE(45)
       HANDLE_CASE(46)
       HANDLE_CASE(47)
       HANDLE_CASE(48)
       HANDLE_CASE(49)
       HANDLE_CASE(50)
       HANDLE_CASE(51)
       HANDLE_CASE(52)
       HANDLE_CASE(53)
       HANDLE_CASE(54)
       HANDLE_CASE(55)
       HANDLE_CASE(56)
       HANDLE_CASE(57)
       HANDLE_CASE(58)
       HANDLE_CASE(59)
       HANDLE_CASE(60)
       HANDLE_CASE(61)
       HANDLE_CASE(62)
       HANDLE_CASE(63)
       HANDLE_CASE(64)
       HANDLE_CASE(65)
       HANDLE_CASE(66)
       HANDLE_CASE(67)
       HANDLE_CASE(68)
       HANDLE_CASE(69)
       HANDLE_CASE(70)
       HANDLE_CASE(71)
       HANDLE_CASE(72)
       HANDLE_CASE(73)
       HANDLE_CASE(74)
       HANDLE_CASE(75)
       HANDLE_CASE(76)
       HANDLE_CASE(77)
       HANDLE_CASE(78)
       HANDLE_CASE(79)
       HANDLE_CASE(80)
       HANDLE_CASE(81)
       HANDLE_CASE(82)
       HANDLE_CASE(83)
       HANDLE_CASE(84)
       HANDLE_CASE(85)
       HANDLE_CASE(86)
       HANDLE_CASE(87)
       HANDLE_CASE(88)
       HANDLE_CASE(89)
       HANDLE_CASE(90)
       HANDLE_CASE(91)
       HANDLE_CASE(92)
       HANDLE_CASE(93)
       HANDLE_CASE(94)
       HANDLE_CASE(95)
       HANDLE_CASE(96)
       HANDLE_CASE(97)
       HANDLE_CASE(98)
       HANDLE_CASE(99)
       case 100:
         {
            Func1();
            printf("Func1 called");
            switch(var2)
            {
               case 2:
               case 3:
                 {
                    Func2();
                    printf("Func2 called");
                    break;
                 }
               case 4:
               case 5:
                 {
                    Func3();
                    printf("Func3 called");
                    break;
                 }
               default: break;
            }
            break;
         }
    }
}

In the above program we can see that the handling for the cases ranging from 0 to 99 simply call printf and insert a lot of NOPs. In the handling for the value 100, we have another switch and that is where the problem happens. If var2 equals 3 the function func3() gets called !!!

I&#39;m compiling the program under Eclipse using the Release configuration. The compiler flags are: -DALT_RELEASE -O2 -g -Wall

The version of GCC is 3.4.1 (Altera Nios II 5.1 b93)

Note 1: The real program where I found the bug uses no inline assembly.

Note 2: If I change to optimization level 1 (-O1) the code generated is correct.

The disassembly of the function BugSample() for the case of wrong code generation (with comments added):

 010001e8 <_Z9BugSampleii>:
 10001e8:    defffe04  addi    sp,sp,-8
 10001ec:    00801904  movi    r2,100
 10001f0:    dc000015  stw    r16,0(sp)
 10001f4:    dfc00115  stw    ra,4(sp)
 10001f8:    2821883a  mov    r16,r5
 10001fc:    11000636  bltu    r2,r4,1000218 <_Z9BugSampleii+0x30>
 1000200:    200490ba  slli    r2,r4,2
 1000204:    00c04074  movhi    r3,257
 1000208:    18caa704  addi    r3,r3,10908
 100020c:    10c5883a  add    r2,r2,r3
 1000210:    11000017  ldw    r4,0(r2)
 1000214:    2000683a  jmp    r4
;;; <Return>:
;;;
 1000218:    dfc00117  ldw    ra,4(sp)
 100021c:    dc000017  ldw    r16,0(sp)
 1000220:    dec00204  addi    sp,sp,8
 1000224:    f800283a  ret
;;; Handling of case 100:
;;;
 1000228:    10001ac0  call    10001ac <_Z5Func1v>
 100022c:    01004074  movhi    r4,257
 1000230:    210a3704  addi    r4,r4,10460
 1000234:    10082c40  call    10082c4 <printf>
 1000238:    00c00084  movi    r3,2
 100023c:    80fff616  blt    r16,r3,1000218 <_Z9BugSampleii+0x30> ;   -> goto <Return>
 1000240:    008000c4  movi    r2,3
 1000244:    8080030e  bge    r16,r2,1000254 <_Z9BugSampleii+0x6c> ;  -> goto <label1>  (WRONG: should be bg, not bge)
 1000248:    00404034  movhi    at,256
 100024c:    0860a814  ori    at,at,33440
 1000250:    0800683a  jmp    at            (address: 0x10082A0)   ; goto case 2/3
;;; <label1>:
 1000254:    00800144  movi    r2,5
 1000258:    143fef16  blt    r2,r16,1000218 <_Z9BugSampleii+0x30>
 100025c:    10001d40  call    10001d4 <_Z5Func3v>
 1000260:    01004074  movhi    r4,257
 1000264:    210a3b04  addi    r4,r4,10476
 1000268:    02004074  movhi    r8,257
 100026c:    4220b104  addi    r8,r8,-32060
 1000270:    dfc00117  ldw    ra,4(sp)
 1000274:    dc000017  ldw    r16,0(sp)
 1000278:    dec00204  addi    sp,sp,8
 100027c:    4000683a  jmp    r8
 1000280:    01004074  movhi    r4,257
 1000284:    210a3f04  addi    r4,r4,10492
 1000288:    100837c0  call    100837c <puts>
 100028c:    0001883a  nop
 1000290:    0001883a  nop
...
;;; Code generated for:
;;;
;;; switch(var2)
;;;    case 2:
;;;    case 3:
;;;      {
;;;         Func2();
;;;         printf("Func2 called");
;;;         break;
;;;      }
 10082a0:    10001c00  call    10001c0 <_Z5Func2v>
 10082a4:    01004074  movhi    r4,257
 10082a8:    210aa304  addi    r4,r4,10892
 10082ac:    02004074  movhi    r8,257
 10082b0:    4220b104  addi    r8,r8,-32060
 10082b4:    dfc00117  ldw    ra,4(sp)
 10082b8:    dc000017  ldw    r16,0(sp)
 10082bc:    dec00204  addi    sp,sp,8
 10082c0:    4000683a  jmp    r8

As a workaround, I&#39;ll use optmization level 1 to generate my real program.

Anyway, I believe that this subject deserves some investigation.

Regards,

mrwar

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    No one any comment on this? It seems to be importand enough to know if it&#39;s a mistake from mrwar, or a real bug!

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    originally posted by svhb@Sep 21 2006, 04:11 PM

    no one any comment on this? it seems to be importand enough to know if it&#39;s a mistake from mrwar, or a real bug!

    <div align='right'><{post_snapback}> (index.php?act=findpost&pid=18394)

    --- quote end ---

    --- Quote End ---

    Yes, I can reproduce this on our NIOS2 board using the nios2-elf-g++ version 3.4.1 under Linux.

    I&#39;ve crosschecked this with a i686-pc-linux-gnu-g++ 3.4.1. With this one, the generated code runs correctly and also a fast search in the gcc bugzilla didn&#39;t come up with a matching bugreport, so it seems like this is a nios2-port specific bug.

    @mrwar: Did you already forward this to Altera support?

    Regards,

    Andreas
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks Andreas for confirming the bug.

    It seems that the bug is related to the size of a relative jump, which I believe is handled in a platform dependent way in GCC.

    Today, I sent a bug report to Altera. When I get any answers, I&#39;ll send to the Forum.

    Regards,

    mrwar