On Thu, 2014-12-18 at 10:04 +0900, Kaz Kojima wrote: > This patch is discussed in PR55212 > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55212#c65 > > and is to make LRA's register elimination work well on SH. > The problem is SH has very limited add instructions only and expands > rA := rB + N to (set rA (const_int N)) and (set rA (plus rA rB)) > instead of (set rA (plus rB (const_int N))). It seems that the former > combination isn't good for LRA's register elimination pass. The patch > adds splitter to addsi3_compact insn so that LRA can see the latter > rtl. > > -- > * config/sh/predicates.md (arith_or_int_operand): New predicate. > * config/sh/sh.md (addsi3): Use arith_or_int_operand for operand 2. > Return fail if operands[0] and operands[1] are overlap when > operands[2] is integer constant. > (*addsi3_compact): Make it define_insn_and_split which splits > reg0 := reg1 + constant to reg0 = constant and reg0 := reg0 + reg1.
I've noticed that this change tends to produce code like ... mov #123,rA ... add rA,rB It's a bit better to do: mov rB,rA ... add #123,rA if the constant fits into #imm8. The attached patch does that. 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. CSiBE shows a couple of cases where code size decreases. Committed as r219341. Cheers, Oleg gcc/ChangeLog: PR target/55212 * config/sh/sh.md (*addsi3_compact): Emit reg-reg copy instead of constant load if constant operand fits into I08.
Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (revision 219339) +++ gcc/config/sh/sh.md (working copy) @@ -2061,8 +2061,9 @@ ;; The problem is that LRA expects something like ;; (set rA (plus rB (const_int N))) ;; to work. We can do that, but we have to split out an additional reg-reg -;; copy before the actual add insn. Use u constraint for that case to avoid -;; the invalid value in the stack pointer. +;; copy or constant load before the actual add insn. +;; Use u constraint for that case to avoid the invalid value in the stack +;; pointer. (define_insn_and_split "*addsi3_compact" [(set (match_operand:SI 0 "arith_reg_dest" "=r,&u") (plus:SI (match_operand:SI 1 "arith_operand" "%0,r") @@ -2078,7 +2079,11 @@ && ! reg_overlap_mentioned_p (operands[0], operands[1])" [(set (match_dup 0) (match_dup 2)) (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))] - "" +{ + /* Prefer 'mov r0,r1; add #imm8,r1' over 'mov #imm8,r1; add r0,r1' */ + if (satisfies_constraint_I08 (operands[2])) + std::swap (operands[1], operands[2]); +} [(set_attr "type" "arith")]) ;; -------------------------------------------------------------------------