Hi, The attached SH patch converts sequences such as: movt r2 movt r13 into: movt r2 mov r2,r13
This shortens the live range of the T bit register and is better for parallel execution. It doesn't happen often, but it's easy to avoid it. Unfortunately I had to do this manually because cprop_hardreg gets in the way here. If done as a peephole2, cprop_hardreg then unconditionally just converts it back, because it thinks that all reg copies are equal in some way. Tested on sh-elf with make -k check RUNTESTFLAGS="--target_board=sh-sim \{-m2/-ml,-m2/-mb,-m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}" Committed as r228386. Cheers, Oleg gcc/ChangeLog: * config/sh/sh.md: Add new unnamed split pattern to handle movt-movt sequences.
Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (revision 228331) +++ gcc/config/sh/sh.md (working copy) @@ -14860,6 +14860,46 @@ gen_rtx_REG (SImode, (REGNO (operands[1]))))); }) +;; This is not a peephole, but it's here because it's actually supposed +;; to be one. It tries to convert a sequence such as +;; movt r2 -> movt r2 +;; movt r13 mov r2,r13 +;; This gives the schduler a bit more freedom to hoist a following +;; comparison insn. Moreover, it the reg-reg mov insn is MT group which has +;; better chances for parallel execution. +;; We can do this with a peephole2 pattern, but then the cprop_hardreg +;; pass will revert the change. See also PR 64331. +;; Thus do it manually in one of the split passes after register allocation. +;; Sometimes the cprop_hardreg pass might also eliminate the reg-reg copy. +(define_split + [(set (match_operand:SI 0 "arith_reg_dest") + (match_operand:SI 1 "t_reg_operand"))] + "TARGET_SH1 && reload_completed" + [(set (match_dup 0) (match_dup 1))] +{ + rtx t_reg = get_t_reg_rtx (); + + for (rtx_insn* i = prev_nonnote_insn_bb (curr_insn); i != NULL; + i = prev_nonnote_insn_bb (i)) + { + if (!INSN_P (i) || DEBUG_INSN_P (i)) + continue; + + if (modified_in_p (t_reg, i) || BARRIER_P (i)) + FAIL; + + if (sh_is_movt_insn (i)) + { + rtx r = sh_movt_set_dest (i); + if (!modified_between_p (r, i, curr_insn)) + { + operands[1] = r; + break; + } + } + } +}) + (define_peephole [(set (match_operand:SI 0 "register_operand" "=r") (plus:SI (match_dup 0) (match_operand:SI 1 "register_operand" "r")))