https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94119
Bug ID: 94119 Summary: MIPS: Invalid use of branch delay slots leading to corrupt jump Product: gcc Version: 8.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: d.dorau at avm dot de Target Milestone: --- Created attachment 48007 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=48007&action=edit Example code + Makefile to reproduce issue We found an issue with gcc 8.3 issuing wrong instructions in MIPS branch delay slots. The issue is that in a chain of bne instructions an instruction is put repeatedly into the delay slots of the bne instructions that should be issued only once. This leads to an invalid calculation of a subsequent jalr address which then leads to a crash. By using git bisect we found commit cd36a4518d14aae18ac89a6232e009ee2bcb6008 to be the commit that introduced this behaviour (first appeared in gcc 7.1) although that commit is not directly related to MIPS. So it maybe just triggering a MIPS specific bug elsewhere. The issue is still present in the gcc 10 branch. Reverting this commit "fixes" the issue. The commit mentioned fixes PR71785. Steps to reproduce: Compile the provided sample .c file with CFLAGS := -mno-abicalls \ -mno-branch-likely \ -ffreestanding \ -O2 \ -fno-reorder-blocks \ -mlong-calls \ -static \ -g \ -save-temps The bad branch delay slots are in the expansion of the #define BUFFER_IS_FF(_a) \ ((_a)[0] == 0xff && \ (_a)[1] == 0xff && \ (_a)[2] == 0xff && \ (_a)[3] == 0xff && \ (_a)[4] == 0xff && \ (_a)[5] == 0xff) macro: The addiu s0,s0,0 instruction must only be issued once but instead is in several places. This leads to an invalid call at 9c. if((subtype == 8) && !BUFFER_IS_FF(data->addr1)) 30: 14c20016 bne a2,v0,8c <foo+0x8c> 34: a7a00018 sh zero,24(sp) 38: 90a20000 lbu v0,0(a1) 3c: 240300ff li v1,255 40: 14430010 bne v0,v1,84 <foo+0x84> 44: 3c100000 lui s0,0x0 44: R_MIPS_HI16 memcmp_ 48: 90a30001 lbu v1,1(a1) 4c: 14620015 bne v1,v0,a4 <foo+0xa4> 50: 26100000 addiu s0,s0,0 50: R_MIPS_LO16 memcmp_ 54: 90a20002 lbu v0,2(a1) 58: 14430012 bne v0,v1,a4 <foo+0xa4> 5c: 26100000 addiu s0,s0,0 5c: R_MIPS_LO16 memcmp_ 60: 90a30003 lbu v1,3(a1) 64: 1462000f bne v1,v0,a4 <foo+0xa4> 68: 26100000 addiu s0,s0,0 68: R_MIPS_LO16 memcmp_ 6c: 90a20004 lbu v0,4(a1) 70: 14430004 bne v0,v1,84 <foo+0x84> 74: 00000000 nop 78: 90a30005 lbu v1,5(a1) 7c: 10620003 beq v1,v0,8c <foo+0x8c> 80: 00000000 nop 84: 10000007 b a4 <foo+0xa4> 88: 26100000 addiu s0,s0,0 88: R_MIPS_LO16 memcmp_ if(!memcmp_(data->addr2, nullbuf, BUF_LEN)) 8c: 3c100000 lui s0,0x0 8c: R_MIPS_HI16 memcmp_ 90: 24060006 li a2,6 94: 27a50014 addiu a1,sp,20 98: 26100000 addiu s0,s0,0 98: R_MIPS_LO16 memcmp_ 9c: 0200f809 jalr s0 The provided example code + Makefile will reprocude the crash.