https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84790
Bug ID: 84790
Summary: Miscompilation for MIPS16 with -fpic and -Os or -O2
Product: gcc
Version: 7.3.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: mschif...@universe-factory.net
Target Milestone: ---
Created attachment 43609
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=43609&action=edit
Reproducer C code
Compiling the following piece of C code:
void ext(void);
struct A {
unsigned v;
};
__attribute__((noinline))
void foo(void) {
ext();
}
__attribute__((noinline))
static void bar(struct A *a) {
if (a)
a->v--;
}
__attribute__((noinline))
static void baz(struct A *a) {
bar(a);
}
void test(struct A *a) {
baz(a);
foo();
baz(a);
}
using the command
mips-openwrt-linux-musl-gcc -Os -mips32r2 -mtune=24kc -mips16 -fpic -Wall
-Wextra -c -o reproducer.o reproducer.c
(current OpenWrt toolchain) generates the following code:
:
0: 2403beqza0,8
2: 9c40lw v0,0(a0)
4: 4affaddiu v0,-1
6: dc40sw v0,0(a0)
8: e8a0jrc ra
a: 6500nop
000c :
c: f000 6a00 li v0,0
c: R_MIPS16_HI16_gp_disp
10: f000 0b00 la v1,10
10: R_MIPS16_LO16 _gp_disp
14: f400 3240 sll v0,16
18: e269adduv0,v1
1a: 64c4save32,ra
1c: 659amovegp,v0
1e: d204sw v0,16(sp)
20: 675cmovev0,gp
22: f000 9a40 lw v0,0(v0)
22: R_MIPS16_GOT16 bar
26: f000 4a00 addiu v0,0
26: R_MIPS16_LO16 bar
2a: ea40jalrv0
2c: 653amovet9,v0
2e: 6444restore 32,ra
30: e8a0jrc ra
32: 6500nop
0034 :
34: f000 6a00 li v0,0
34: R_MIPS16_HI16 _gp_disp
38: f000 0b00 la v1,38
38: R_MIPS16_LO16 _gp_disp
3c: f400 3240 sll v0,16
40: e269adduv0,v1
42: 64c4save32,ra
44: 659amovegp,v0
46: d204sw v0,16(sp)
48: 675cmovev0,gp
4a: f000 9a40 lw v0,0(v0)
4a: R_MIPS16_CALL16 ext
4e: ea40jalrv0
50: 653amovet9,v0
52: 6444restore 32,ra
54: e8a0jrc ra
56: 6500nop
0058 :
58: f000 6a00 li v0,0
58: R_MIPS16_HI16 _gp_disp
5c: f000 0b00 la v1,5c
5c: R_MIPS16_LO16 _gp_disp
60: f400 3240 sll v0,16
64: e269adduv0,v1
66: 659amovegp,v0
68: 677cmovev1,gp
6a: 64f5save40,ra,s0-s1
6c: f000 9b00 lw s0,0(v1)
6c: R_MIPS16_GOT16 baz
70: d204sw v0,16(sp)
72: f000 4800 addiu s0,0
72: R_MIPS16_LO16 baz
76: 6538movet9,s0
78: e840jalrs0
7a: 6724moves1,a0
7c: 9604lw a2,16(sp)
7e: f000 9b60 lw v1,0(v1)
7e: R_MIPS16_CALL16 foo
82: 659emovegp,a2
84: eb40jalrv1
86: 653bmovet9,v1
88: 6791movea0,s1
8a: e840jalrs0
8c: 6538movet9,s0
8e: 6475restore 40,ra,s0-s1
90: e8a0jrc ra
92: 6500nop
94: 6500nop
96: 6500nop
98: 6500nop
9a: 6500nop
9c: 6500nop
9e: 6500nop
This is incorrect: The GOT lookup for foo at 7e assumes that v1 still contains
the gp value set at 68, even though it is not valid anymore after the baz call
at 78.
We noticed this issue as it started to affect real software with GCC 7, but for
this reproducer code, GCC 5.4 and 5.5 produce identical code, so it is not a
regression per se.
Version: mips-openwrt-linux-musl-gcc -v
Reading specs from
/home/neoraider/Devel/OpenWrt/openwrt/staging_dir/toolchain-mips_24kc_gcc-7.3.0_musl/lib/gcc/mips-openwrt-linux-musl/7.3.0/specs
COLLECT_GCC=/home/neoraider/Devel/OpenWrt/openwrt/staging_dir/toolchain-mips_24kc_gcc-7.3.0_musl/bin/mips-openwrt-linux-musl-gcc
COLLECT_LTO_WRAPPER=/home/neoraider/Devel/OpenWrt/openwrt/staging_dir/toolchain-mip