Hello, This fixes a bug on the 4.8 branch which was initially described in PR 51244 comment 59 and also reported as a separate PR 59343. Tested with make -k check RUNTESTFLAGS="--target_board=sh-sim \{-m2/-ml,-m2/-mb,-m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}"
and no new failures. OK for 4.8? Cheers, Oleg gcc/ChangeLog: PR target/51244 PR target/59343 * config/sh/sh.md (*cbranch_t): Check that there are no labels between the s1 insn and the testing insn. Remove REG_DEAD note from s1 insn. testsuite/ChangeLog: PR target/51244 PR target/59343 * gcc.target/sh/pr51244-19.c: Adjust test case.
Index: gcc/testsuite/gcc.target/sh/pr51244-19.c =================================================================== --- gcc/testsuite/gcc.target/sh/pr51244-19.c (revision 205675) +++ gcc/testsuite/gcc.target/sh/pr51244-19.c (working copy) @@ -22,11 +22,16 @@ unwanted sequences. Thus, if we see any movt insns, something is not working as expected. This test requires -O2 because the T bit stores in question will be eliminated in additional insn split passes after - reload. */ + reload. + + Notice: When this test case was initially added, the T bit optimization + was buggy and this test case resulted in wrong code. The movt + instructions actually have to be present in this case to get + correct code. */ /* { dg-do compile { target "sh*-*-*" } } */ /* { dg-options "-O2" } */ /* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */ -/* { dg-final { scan-assembler-not "movt" } } */ +/* { dg-final { scan-assembler "movt" } } */ struct request { Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (revision 205675) +++ gcc/config/sh/sh.md (working copy) @@ -8427,11 +8427,9 @@ while (true) { - /* It's not safe to go beyond the current basic block after reload. */ set_of_reg s1 = sh_find_set_of_reg (tested_reg, s0.insn, - reload_completed - ? prev_nonnote_insn_bb - : prev_nonnote_insn); + prev_nonnote_insn); + if (s1.set_src == NULL_RTX) break; @@ -8449,15 +8447,25 @@ continue; } - /* It's only safe to remove the testing insn if the T bit is not - modified between the testing insn and the insn that stores the - T bit. Notice that some T bit stores such as negc also modify - the T bit. */ - if (modified_between_p (get_t_reg_rtx (), s1.insn, testing_insn) - || modified_in_p (get_t_reg_rtx (), s1.insn)) - operands[2] = NULL_RTX; + /* It's only safe to remove the testing insn if the T bit is not + modified between the testing insn and the insn that stores the + T bit. Notice that some T bit stores such as negc also modify + the T bit. */ + if (modified_between_p (get_t_reg_rtx (), s1.insn, testing_insn) + || modified_in_p (get_t_reg_rtx (), s1.insn) + || !no_labels_between_p (s1.insn, testing_insn)) + operands[2] = NULL_RTX; + else + { + /* If the insn that sets the tested reg has a REG_DEAD note on + the T bit remove that note since we're extending the usage + of the T bit. */ + rtx n = find_regno_note (s1.insn, REG_DEAD, T_REG); + if (n != NULL_RTX) + remove_note (s1.insn, n); + } - break; + break; } if (operands[2] == NULL_RTX)