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")])
 
 ;; -------------------------------------------------------------------------

Reply via email to