https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88904
Bug ID: 88904 Summary: Basic block incorrectly skipped in jump threading. Product: gcc Version: 9.0 Status: UNCONFIRMED Severity: major Priority: P3 Component: rtl-optimization Assignee: unassigned at gcc dot gnu.org Reporter: matmal01 at gcc dot gnu.org Target Milestone: --- When compiling the attached code, with an arm-none-eabi cross compiler from trunk, arm-none-eabi-gcc -march=armv6-m -S test.c -o test.s -Os incorrect assembly is generated, which leads to the second assert always being triggered. This happens since revision r266734 which introduced a new pass running jump-threading just after reload. For the attached testcase this triggers a latent bug in the `thread_jump` function. The combine pass can modify a jump_insn so that its pattern is of the form (parallel [ (set (pc) ...) (clobber (scratch))]) which after reload can end up in the form (parallel [ (set (pc) (if_then_else (<something including (reg N)) ...)) (clobber (reg N))]) where 'N' is the same register. The `thread_jump` function does not account for this possibility occurring at the last insn of a basic block. When checking to see what modifications the basic block makes to registers (using `mark_effect`), it records that the block doesn't overall set (reg N) since it is clobbered in the last insn. It then incorrectly deduces from this fact that the jump condition using (reg N) is not affected by the execution of the basic block and can hence be skipped (using `mentions_nonequal_regs`). I am currently working on a patch, but reporting upstream so it's on peoples radar. n.b. I am currently looking into how `onlyjump_p` is used elsewhere to see whether it should account for the possibility of a CLOBBER in a PARALLEL pattern or whether the fix should be constrained to how the `thread_jump` function calculates what registers are used in the final jump condition.