https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68273

            Bug ID: 68273
           Summary: Wrong code on mips/mipsel with -fno-ipa-sra
           Product: gcc
           Version: 5.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: ipa
          Assignee: unassigned at gcc dot gnu.org
          Reporter: aurelien at aurel32 dot net
  Target Milestone: ---
              Host: mipsel-linux-gnu
            Target: mipsel-linux-gnu
             Build: mipsel-linux-gnu

Created attachment 36676
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=36676&action=edit
preprocessed source

gsoap version 2.8.22 does not compile correctly on mips and mipsel with GCC
5.2.1 or trunk, while it compiles correctly on GCC 4.9. The resulting binary
segfaults.

A bit of analysis shows this is due to wrong code optimization at -O2 level,
and more specifically with the  -fipa-sra option, which calls functions with
arguments in the wrong register.

I have not been able to get a simple testcase yet, but it is possible to
reproduce the issue with the attached preprocessed code. The problem occurs in
this function:

  case 34:
# 436 "soapcpp2_yacc.y"
    { if ((yyvsp[-1].rec).sto & Stypedef)
     { sprintf(errbuf, "invalid typedef qualifier for '%s'",
(yyvsp[0].sym)->name);
    semwarn(errbuf);
     }
     printf("%p\n", (yyvsp[0].sym));
     p = enter(sp->table, (yyvsp[0].sym));
     p->info.typ = (yyvsp[-1].rec).typ;
     p->info.sto = (yyvsp[-1].rec).sto;
     p->info.hasval = False;
     p->info.offset = sp->offset;
     if (sp->grow)
    sp->offset += p->info.typ->width;
     else if (p->info.typ->width > sp->offset)
    sp->offset = p->info.typ->width;
     sp->entry = p;
   }
# 2290 "soapcpp2_yacc.c"
    break;

When compiled with -O2, GCC outputs the following corresponding code:

$L380:  
        lw      $25,%call16(__printf_chk)($28)
        lw      $21,%got(sp)($28)
        lui     $5,%hi($LC37)
        move    $6,$7
        addiu   $5,$5,%lo($LC37)
        sw      $7,13452($sp)
        .reloc  1f,R_MIPS_JALR,__printf_chk
1:      jalr    $25
        li      $4,1                    # 0x1

        lw      $28,88($sp)
        lw      $2,0($21)
        lw      $7,13452($sp)
        lw      $4,0($2)
        lw      $25,%call16(enter)($28)
        nop
        .reloc  1f,R_MIPS_JALR,enter
1:      jalr    $25
        move    $6,$7

Note how the second argument is loaded in $6 (ie a2) instead of $5 (ie a1) when
calling enter.

When compiled with -O2 -fno-ipa-sra the correct register is used:

-O2 -fno-ipa-sra

$L387:  
        lw      $25,%call16(__printf_chk)($28)
        lw      $21,%got(sp)($28)
        lui     $5,%hi($LC37)
        move    $6,$7
        sw      $7,13500($sp)
        addiu   $5,$5,%lo($LC37)
        .reloc  1f,R_MIPS_JALR,__printf_chk
1:      jalr    $25
        li      $4,1                    # 0x1

        lw      $28,136($sp)
        lw      $2,0($21)
        lw      $7,13500($sp)
        lw      $4,0($2)
        lw      $25,%call16(enter)($28)
        nop
        .reloc  1f,R_MIPS_JALR,enter
1:      jalr    $25
        move    $5,$7

However it is first loaded to $7 for no obvious reason, especially this is not
a saved register, so its value is lost after the call. I am note sure it is
something related, but loading the value through this intermediate register is
due to the use of -O2, this is not the case -O1:

$L370:  
        lw      $2,0($16)
        nop
        sw      $2,13476($sp)
        move    $6,$2
        lui     $5,%hi($LC37)
        addiu   $5,$5,%lo($LC37)
        li      $4,1                    # 0x1
        lw      $25,%call16(__printf_chk)($28)
        nop
        .reloc  1f,R_MIPS_JALR,__printf_chk
1:      jalr    $25
        nop

        lw      $28,136($sp)
        nop
        lw      $17,%got(sp)($28)
        nop
        lw      $2,0($17)
        lw      $5,13476($sp)
        lw      $4,0($2)
        lw      $25,%call16(enter)($28)
        nop
        .reloc  1f,R_MIPS_JALR,enter
1:      jalr    $25
        nop

Reply via email to