[2/2,ARC] Avoid specific constants to end in limm field.

Message ID 20180917125027.10946-3-claziss@gmail.com
State New
Headers show
Series
  • Bug fix, improve size figures.
Related show

Commit Message

Claudiu Zissulescu Sept. 17, 2018, 12:50 p.m.
The 3-operand instructions accepts to place an immediate into the
second operand. However, this immediate will end up in the long
immediate field. This patch avoids constants to end up in the limm
field for particular instructions when compiling for size.

gcc/
xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>

	* config/arc/arc.md (*add_n): Clean up pattern, update instruction
	constraints.
	(ashlsi3_insn): Update instruction constraints.
	(ashrsi3_insn): Likewise.
	(rotrsi3): Likewise.
	(add_shift): Likewise.
	* config/arc/constraints.md (Csz): New 32 bit constraint. It
	avoids placing in the limm field small constants which, otherwise,
	could end into a small instruction.
---
 gcc/config/arc/arc.md                   | 51 +++++++++---------------
 gcc/config/arc/constraints.md           |  6 +++
 gcc/testsuite/gcc.target/arc/tph_addx.c | 53 +++++++++++++++++++++++++
 3 files changed, 78 insertions(+), 32 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/arc/tph_addx.c

-- 
2.17.1

Comments

Andrew Burgess Sept. 20, 2018, 9:12 p.m. | #1
* Claudiu Zissulescu <claziss@gmail.com> [2018-09-17 15:50:27 +0300]:

> The 3-operand instructions accepts to place an immediate into the

> second operand. However, this immediate will end up in the long

> immediate field. This patch avoids constants to end up in the limm

> field for particular instructions when compiling for size.

> 

> gcc/

> xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>

> 

> 	* config/arc/arc.md (*add_n): Clean up pattern, update instruction

> 	constraints.

> 	(ashlsi3_insn): Update instruction constraints.

> 	(ashrsi3_insn): Likewise.

> 	(rotrsi3): Likewise.

> 	(add_shift): Likewise.

> 	* config/arc/constraints.md (Csz): New 32 bit constraint. It

> 	avoids placing in the limm field small constants which, otherwise,

> 	could end into a small instruction.

> ---

>  gcc/config/arc/arc.md                   | 51 +++++++++---------------

>  gcc/config/arc/constraints.md           |  6 +++

>  gcc/testsuite/gcc.target/arc/tph_addx.c | 53 +++++++++++++++++++++++++

>  3 files changed, 78 insertions(+), 32 deletions(-)

>  create mode 100644 gcc/testsuite/gcc.target/arc/tph_addx.c


Looks good.

Thanks,
Andrew


> 

> diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md

> index 2d108ef166d..c28a87cd3b0 100644

> --- a/gcc/config/arc/arc.md

> +++ b/gcc/config/arc/arc.md

> @@ -3056,30 +3056,17 @@ core_3, archs4x, archs4xd, archs4xd_slow"

>     (set (match_dup 3) (match_dup 4))])

>  

>  (define_insn "*add_n"

> -  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,W,W,w,w")

> -	(plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "Rcqq,c,c,c,c,c")

> -	                    (match_operand:SI 2 "_1_2_3_operand" ""))

> -		 (match_operand:SI 3 "nonmemory_operand" "0,0,c,?Cal,?c,??Cal")))]

> +  [(set (match_operand:SI 0 "dest_reg_operand" "=q,r,r")

> +	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "q,r,r")

> +			  (match_operand:SI 2 "_2_4_8_operand" ""))

> +		 (match_operand:SI 3 "nonmemory_operand" "0,r,Csz")))]

>    ""

> -  "add%c2%? %0,%3,%1%&"

> +  "add%z2%?\\t%0,%3,%1%&"

>    [(set_attr "type" "shift")

> -   (set_attr "length" "*,4,4,8,4,8")

> -   (set_attr "predicable" "yes,yes,no,no,no,no")

> -   (set_attr "cond" "canuse,canuse,nocond,nocond,nocond,nocond")

> -   (set_attr "iscompact" "maybe,false,false,false,false,false")])

> -

> -(define_insn "*add_n"

> -  [(set (match_operand:SI 0 "dest_reg_operand"                  "=Rcqq,Rcw,W,  W,w,w")

> -	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "Rcqq,  c,c,  c,c,c")

> -			  (match_operand:SI 2 "_2_4_8_operand"   ""))

> -		 (match_operand:SI 3 "nonmemory_operand"            "0,  0,c,Cal,c,Cal")))]

> -  ""

> -  "add%z2%? %0,%3,%1%&"

> -  [(set_attr "type" "shift")

> -   (set_attr "length" "*,4,4,8,4,8")

> -   (set_attr "predicable" "yes,yes,no,no,no,no")

> -   (set_attr "cond" "canuse,canuse,nocond,nocond,nocond,nocond")

> -   (set_attr "iscompact" "maybe,false,false,false,false,false")])

> +   (set_attr "length" "*,4,8")

> +   (set_attr "predicable" "yes,no,no")

> +   (set_attr "cond" "canuse,nocond,nocond")

> +   (set_attr "iscompact" "maybe,false,false")])

>  

>  ;; N.B. sub[123] has the operands of the MINUS in the opposite order from

>  ;; what synth_mult likes.

> @@ -3496,7 +3483,7 @@ core_3, archs4x, archs4xd, archs4xd_slow"

>  ; provide one alternatice for this, without condexec support.

>  (define_insn "*ashlsi3_insn"

>    [(set (match_operand:SI 0 "dest_reg_operand"           "=Rcq,Rcqq,Rcqq,Rcw, w,   w")

> -	(ashift:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq,   0,  0, c,cCal")

> +	(ashift:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq,   0,  0, c,cCsz")

>  		   (match_operand:SI 2 "nonmemory_operand"  "K,  K,RcqqM, cL,cL,cCal")))]

>    "TARGET_BARREL_SHIFTER

>     && (register_operand (operands[1], SImode)

> @@ -3509,7 +3496,7 @@ core_3, archs4x, archs4xd, archs4xd_slow"

>  

>  (define_insn "*ashrsi3_insn"

>    [(set (match_operand:SI 0 "dest_reg_operand"             "=Rcq,Rcqq,Rcqq,Rcw, w,   w")

> -	(ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq,   0,  0, c,cCal")

> +	(ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq,   0,  0, c,cCsz")

>  		     (match_operand:SI 2 "nonmemory_operand"  "K,  K,RcqqM, cL,cL,cCal")))]

>    "TARGET_BARREL_SHIFTER

>     && (register_operand (operands[1], SImode)

> @@ -3536,7 +3523,7 @@ core_3, archs4x, archs4xd, archs4xd_slow"

>  

>  (define_insn "rotrsi3"

>    [(set (match_operand:SI 0 "dest_reg_operand"             "=Rcw, w,   w")

> -	(rotatert:SI (match_operand:SI 1 "register_operand"  " 0,cL,cCal")

> +	(rotatert:SI (match_operand:SI 1 "register_operand"  " 0,cL,cCsz")

>  		     (match_operand:SI 2 "nonmemory_operand" "cL,cL,cCal")))]

>    "TARGET_BARREL_SHIFTER"

>    "ror%? %0,%1,%2"

> @@ -4284,16 +4271,16 @@ core_3, archs4x, archs4xd, archs4xd_slow"

>  (define_peephole2

>    [(set (match_operand:SI 0 "dest_reg_operand" "")

>  	(ashift:SI (match_operand:SI 1 "register_operand" "")

> -		   (match_operand:SI 2 "const_int_operand" "")))

> +		   (match_operand:SI 2 "_1_2_3_operand" "")))

>    (set (match_operand:SI 3 "dest_reg_operand" "")

>         (plus:SI (match_operand:SI 4 "nonmemory_operand" "")

>  		(match_operand:SI 5 "nonmemory_operand" "")))]

> -  "(INTVAL (operands[2]) == 1

> -    || INTVAL (operands[2]) == 2

> -    || INTVAL (operands[2]) == 3)

> -   && (true_regnum (operands[4]) == true_regnum (operands[0])

> +  "(true_regnum (operands[4]) == true_regnum (operands[0])

>         || true_regnum (operands[5]) == true_regnum (operands[0]))

> -   && (peep2_reg_dead_p (2, operands[0]) || (true_regnum (operands[3]) == true_regnum (operands[0])))"

> +   && (peep2_reg_dead_p (2, operands[0])

> +       || (true_regnum (operands[3]) == true_regnum (operands[0])))

> +   && !(optimize_size && satisfies_constraint_I (operands[4]))

> +   && !(optimize_size && satisfies_constraint_I (operands[5]))"

>   ;; the preparation statements take care to put proper operand in operands[4]

>   ;; operands[4] will always contain the correct operand. This is added to satisfy commutativity

>    [(set (match_dup 3)

> @@ -6329,7 +6316,7 @@ core_3, archs4x, archs4xd, archs4xd_slow"

>    [(set (match_operand:SI 0 "register_operand" "=q,r,r")

>  	(plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "q,r,r")

>  			    (match_operand:SI 2 "_1_2_3_operand" ""))

> -		 (match_operand:SI 3 "nonmemory_operand"  "0,r,Cal")))]

> +		 (match_operand:SI 3 "nonmemory_operand"  "0,r,Csz")))]

>    ""

>    "add%2%?\\t%0,%3,%1"

>    [(set_attr "length" "*,4,8")

> diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md

> index f9ef3f94dfe..abfeedffe9a 100644

> --- a/gcc/config/arc/constraints.md

> +++ b/gcc/config/arc/constraints.md

> @@ -428,6 +428,12 @@

>  	       && !arc_legitimate_pic_addr_p (op)

>  	       && !satisfies_constraint_I (op)"))

>  

> +(define_constraint "Csz"

> +  "a 32 bit constant avoided when compiling for size."

> +  (match_test "immediate_operand (op, VOIDmode)

> +	       && !arc_legitimate_pic_addr_p (op)

> +	       && !(satisfies_constraint_I (op) && optimize_size)"))

> +

>  ; Note that the 'cryptic' register constraints will not make reload use the

>  ; associated class to reload into, but this will not penalize reloading of any

>  ; other operands, or using an alternate part of the same alternative.

> diff --git a/gcc/testsuite/gcc.target/arc/tph_addx.c b/gcc/testsuite/gcc.target/arc/tph_addx.c

> new file mode 100644

> index 00000000000..f942ab19eb1

> --- /dev/null

> +++ b/gcc/testsuite/gcc.target/arc/tph_addx.c

> @@ -0,0 +1,53 @@

> +/* { dg-do compile } */

> +/* { dg-options "-Os" } */

> +

> +/* when compiling for size avoid the following peephole

> +-------------------------------------------------------------

> +Pattern 1 : r0 = r1 << {i}

> +            r3 = r4/INT + r0     ;;and commutative

> +                ||

> +                \/

> +            add{i} r3,r4/INT,r1

> +-------------------------------------------------------------

> +*/

> +

> +typedef int a;

> +typedef int b                                                    ;

> +struct c

> +{

> +  b d;

> +};

> +

> +struct e

> +{

> +  a f;

> +};

> +

> +int g(int family)

> +{

> +  switch (family)

> +  case 2:

> +    return sizeof(struct e);

> +  return 0;

> +}

> +

> +int h(int family)

> +{

> +  return 1 + g(family) - 1 ;

> +}

> +

> +extern void m (void);

> +

> +int i(int j)

> +{

> +  struct c *hdr;

> +  int k;

> +  int l;

> +  k = h(j);

> +  l = sizeof(struct c) +   k * 2;

> +  hdr->d = l ;

> +  if (j)

> +    m();

> +}

> +

> +/* { dg-final { scan-assembler-not "add\d" } } */

> -- 

> 2.17.1

>
Claudiu Zissulescu Oct. 1, 2018, 9:38 a.m. | #2
Pushed. Thank you for your review,
Claudiu
On Fri, Sep 21, 2018 at 12:12 AM Andrew Burgess
<andrew.burgess@embecosm.com> wrote:
>

> * Claudiu Zissulescu <claziss@gmail.com> [2018-09-17 15:50:27 +0300]:

>

> > The 3-operand instructions accepts to place an immediate into the

> > second operand. However, this immediate will end up in the long

> > immediate field. This patch avoids constants to end up in the limm

> > field for particular instructions when compiling for size.

> >

> > gcc/

> > xxxx-xx-xx  Claudiu Zissulescu  <claziss@synopsys.com>

> >

> >       * config/arc/arc.md (*add_n): Clean up pattern, update instruction

> >       constraints.

> >       (ashlsi3_insn): Update instruction constraints.

> >       (ashrsi3_insn): Likewise.

> >       (rotrsi3): Likewise.

> >       (add_shift): Likewise.

> >       * config/arc/constraints.md (Csz): New 32 bit constraint. It

> >       avoids placing in the limm field small constants which, otherwise,

> >       could end into a small instruction.

> > ---

> >  gcc/config/arc/arc.md                   | 51 +++++++++---------------

> >  gcc/config/arc/constraints.md           |  6 +++

> >  gcc/testsuite/gcc.target/arc/tph_addx.c | 53 +++++++++++++++++++++++++

> >  3 files changed, 78 insertions(+), 32 deletions(-)

> >  create mode 100644 gcc/testsuite/gcc.target/arc/tph_addx.c

>

> Looks good.

>

> Thanks,

> Andrew

>

>

> >

> > diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md

> > index 2d108ef166d..c28a87cd3b0 100644

> > --- a/gcc/config/arc/arc.md

> > +++ b/gcc/config/arc/arc.md

> > @@ -3056,30 +3056,17 @@ core_3, archs4x, archs4xd, archs4xd_slow"

> >     (set (match_dup 3) (match_dup 4))])

> >

> >  (define_insn "*add_n"

> > -  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,W,W,w,w")

> > -     (plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "Rcqq,c,c,c,c,c")

> > -                         (match_operand:SI 2 "_1_2_3_operand" ""))

> > -              (match_operand:SI 3 "nonmemory_operand" "0,0,c,?Cal,?c,??Cal")))]

> > +  [(set (match_operand:SI 0 "dest_reg_operand" "=q,r,r")

> > +     (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "q,r,r")

> > +                       (match_operand:SI 2 "_2_4_8_operand" ""))

> > +              (match_operand:SI 3 "nonmemory_operand" "0,r,Csz")))]

> >    ""

> > -  "add%c2%? %0,%3,%1%&"

> > +  "add%z2%?\\t%0,%3,%1%&"

> >    [(set_attr "type" "shift")

> > -   (set_attr "length" "*,4,4,8,4,8")

> > -   (set_attr "predicable" "yes,yes,no,no,no,no")

> > -   (set_attr "cond" "canuse,canuse,nocond,nocond,nocond,nocond")

> > -   (set_attr "iscompact" "maybe,false,false,false,false,false")])

> > -

> > -(define_insn "*add_n"

> > -  [(set (match_operand:SI 0 "dest_reg_operand"                  "=Rcqq,Rcw,W,  W,w,w")

> > -     (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "Rcqq,  c,c,  c,c,c")

> > -                       (match_operand:SI 2 "_2_4_8_operand"   ""))

> > -              (match_operand:SI 3 "nonmemory_operand"            "0,  0,c,Cal,c,Cal")))]

> > -  ""

> > -  "add%z2%? %0,%3,%1%&"

> > -  [(set_attr "type" "shift")

> > -   (set_attr "length" "*,4,4,8,4,8")

> > -   (set_attr "predicable" "yes,yes,no,no,no,no")

> > -   (set_attr "cond" "canuse,canuse,nocond,nocond,nocond,nocond")

> > -   (set_attr "iscompact" "maybe,false,false,false,false,false")])

> > +   (set_attr "length" "*,4,8")

> > +   (set_attr "predicable" "yes,no,no")

> > +   (set_attr "cond" "canuse,nocond,nocond")

> > +   (set_attr "iscompact" "maybe,false,false")])

> >

> >  ;; N.B. sub[123] has the operands of the MINUS in the opposite order from

> >  ;; what synth_mult likes.

> > @@ -3496,7 +3483,7 @@ core_3, archs4x, archs4xd, archs4xd_slow"

> >  ; provide one alternatice for this, without condexec support.

> >  (define_insn "*ashlsi3_insn"

> >    [(set (match_operand:SI 0 "dest_reg_operand"           "=Rcq,Rcqq,Rcqq,Rcw, w,   w")

> > -     (ashift:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq,   0,  0, c,cCal")

> > +     (ashift:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq,   0,  0, c,cCsz")

> >                  (match_operand:SI 2 "nonmemory_operand"  "K,  K,RcqqM, cL,cL,cCal")))]

> >    "TARGET_BARREL_SHIFTER

> >     && (register_operand (operands[1], SImode)

> > @@ -3509,7 +3496,7 @@ core_3, archs4x, archs4xd, archs4xd_slow"

> >

> >  (define_insn "*ashrsi3_insn"

> >    [(set (match_operand:SI 0 "dest_reg_operand"             "=Rcq,Rcqq,Rcqq,Rcw, w,   w")

> > -     (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq,   0,  0, c,cCal")

> > +     (ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq,   0,  0, c,cCsz")

> >                    (match_operand:SI 2 "nonmemory_operand"  "K,  K,RcqqM, cL,cL,cCal")))]

> >    "TARGET_BARREL_SHIFTER

> >     && (register_operand (operands[1], SImode)

> > @@ -3536,7 +3523,7 @@ core_3, archs4x, archs4xd, archs4xd_slow"

> >

> >  (define_insn "rotrsi3"

> >    [(set (match_operand:SI 0 "dest_reg_operand"             "=Rcw, w,   w")

> > -     (rotatert:SI (match_operand:SI 1 "register_operand"  " 0,cL,cCal")

> > +     (rotatert:SI (match_operand:SI 1 "register_operand"  " 0,cL,cCsz")

> >                    (match_operand:SI 2 "nonmemory_operand" "cL,cL,cCal")))]

> >    "TARGET_BARREL_SHIFTER"

> >    "ror%? %0,%1,%2"

> > @@ -4284,16 +4271,16 @@ core_3, archs4x, archs4xd, archs4xd_slow"

> >  (define_peephole2

> >    [(set (match_operand:SI 0 "dest_reg_operand" "")

> >       (ashift:SI (match_operand:SI 1 "register_operand" "")

> > -                (match_operand:SI 2 "const_int_operand" "")))

> > +                (match_operand:SI 2 "_1_2_3_operand" "")))

> >    (set (match_operand:SI 3 "dest_reg_operand" "")

> >         (plus:SI (match_operand:SI 4 "nonmemory_operand" "")

> >               (match_operand:SI 5 "nonmemory_operand" "")))]

> > -  "(INTVAL (operands[2]) == 1

> > -    || INTVAL (operands[2]) == 2

> > -    || INTVAL (operands[2]) == 3)

> > -   && (true_regnum (operands[4]) == true_regnum (operands[0])

> > +  "(true_regnum (operands[4]) == true_regnum (operands[0])

> >         || true_regnum (operands[5]) == true_regnum (operands[0]))

> > -   && (peep2_reg_dead_p (2, operands[0]) || (true_regnum (operands[3]) == true_regnum (operands[0])))"

> > +   && (peep2_reg_dead_p (2, operands[0])

> > +       || (true_regnum (operands[3]) == true_regnum (operands[0])))

> > +   && !(optimize_size && satisfies_constraint_I (operands[4]))

> > +   && !(optimize_size && satisfies_constraint_I (operands[5]))"

> >   ;; the preparation statements take care to put proper operand in operands[4]

> >   ;; operands[4] will always contain the correct operand. This is added to satisfy commutativity

> >    [(set (match_dup 3)

> > @@ -6329,7 +6316,7 @@ core_3, archs4x, archs4xd, archs4xd_slow"

> >    [(set (match_operand:SI 0 "register_operand" "=q,r,r")

> >       (plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "q,r,r")

> >                           (match_operand:SI 2 "_1_2_3_operand" ""))

> > -              (match_operand:SI 3 "nonmemory_operand"  "0,r,Cal")))]

> > +              (match_operand:SI 3 "nonmemory_operand"  "0,r,Csz")))]

> >    ""

> >    "add%2%?\\t%0,%3,%1"

> >    [(set_attr "length" "*,4,8")

> > diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md

> > index f9ef3f94dfe..abfeedffe9a 100644

> > --- a/gcc/config/arc/constraints.md

> > +++ b/gcc/config/arc/constraints.md

> > @@ -428,6 +428,12 @@

> >              && !arc_legitimate_pic_addr_p (op)

> >              && !satisfies_constraint_I (op)"))

> >

> > +(define_constraint "Csz"

> > +  "a 32 bit constant avoided when compiling for size."

> > +  (match_test "immediate_operand (op, VOIDmode)

> > +            && !arc_legitimate_pic_addr_p (op)

> > +            && !(satisfies_constraint_I (op) && optimize_size)"))

> > +

> >  ; Note that the 'cryptic' register constraints will not make reload use the

> >  ; associated class to reload into, but this will not penalize reloading of any

> >  ; other operands, or using an alternate part of the same alternative.

> > diff --git a/gcc/testsuite/gcc.target/arc/tph_addx.c b/gcc/testsuite/gcc.target/arc/tph_addx.c

> > new file mode 100644

> > index 00000000000..f942ab19eb1

> > --- /dev/null

> > +++ b/gcc/testsuite/gcc.target/arc/tph_addx.c

> > @@ -0,0 +1,53 @@

> > +/* { dg-do compile } */

> > +/* { dg-options "-Os" } */

> > +

> > +/* when compiling for size avoid the following peephole

> > +-------------------------------------------------------------

> > +Pattern 1 : r0 = r1 << {i}

> > +            r3 = r4/INT + r0     ;;and commutative

> > +                ||

> > +                \/

> > +            add{i} r3,r4/INT,r1

> > +-------------------------------------------------------------

> > +*/

> > +

> > +typedef int a;

> > +typedef int b                                                    ;

> > +struct c

> > +{

> > +  b d;

> > +};

> > +

> > +struct e

> > +{

> > +  a f;

> > +};

> > +

> > +int g(int family)

> > +{

> > +  switch (family)

> > +  case 2:

> > +    return sizeof(struct e);

> > +  return 0;

> > +}

> > +

> > +int h(int family)

> > +{

> > +  return 1 + g(family) - 1 ;

> > +}

> > +

> > +extern void m (void);

> > +

> > +int i(int j)

> > +{

> > +  struct c *hdr;

> > +  int k;

> > +  int l;

> > +  k = h(j);

> > +  l = sizeof(struct c) +   k * 2;

> > +  hdr->d = l ;

> > +  if (j)

> > +    m();

> > +}

> > +

> > +/* { dg-final { scan-assembler-not "add\d" } } */

> > --

> > 2.17.1

> >

Patch

diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 2d108ef166d..c28a87cd3b0 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -3056,30 +3056,17 @@  core_3, archs4x, archs4xd, archs4xd_slow"
    (set (match_dup 3) (match_dup 4))])
 
 (define_insn "*add_n"
-  [(set (match_operand:SI 0 "dest_reg_operand" "=Rcqq,Rcw,W,W,w,w")
-	(plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "Rcqq,c,c,c,c,c")
-	                    (match_operand:SI 2 "_1_2_3_operand" ""))
-		 (match_operand:SI 3 "nonmemory_operand" "0,0,c,?Cal,?c,??Cal")))]
+  [(set (match_operand:SI 0 "dest_reg_operand" "=q,r,r")
+	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "q,r,r")
+			  (match_operand:SI 2 "_2_4_8_operand" ""))
+		 (match_operand:SI 3 "nonmemory_operand" "0,r,Csz")))]
   ""
-  "add%c2%? %0,%3,%1%&"
+  "add%z2%?\\t%0,%3,%1%&"
   [(set_attr "type" "shift")
-   (set_attr "length" "*,4,4,8,4,8")
-   (set_attr "predicable" "yes,yes,no,no,no,no")
-   (set_attr "cond" "canuse,canuse,nocond,nocond,nocond,nocond")
-   (set_attr "iscompact" "maybe,false,false,false,false,false")])
-
-(define_insn "*add_n"
-  [(set (match_operand:SI 0 "dest_reg_operand"                  "=Rcqq,Rcw,W,  W,w,w")
-	(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "Rcqq,  c,c,  c,c,c")
-			  (match_operand:SI 2 "_2_4_8_operand"   ""))
-		 (match_operand:SI 3 "nonmemory_operand"            "0,  0,c,Cal,c,Cal")))]
-  ""
-  "add%z2%? %0,%3,%1%&"
-  [(set_attr "type" "shift")
-   (set_attr "length" "*,4,4,8,4,8")
-   (set_attr "predicable" "yes,yes,no,no,no,no")
-   (set_attr "cond" "canuse,canuse,nocond,nocond,nocond,nocond")
-   (set_attr "iscompact" "maybe,false,false,false,false,false")])
+   (set_attr "length" "*,4,8")
+   (set_attr "predicable" "yes,no,no")
+   (set_attr "cond" "canuse,nocond,nocond")
+   (set_attr "iscompact" "maybe,false,false")])
 
 ;; N.B. sub[123] has the operands of the MINUS in the opposite order from
 ;; what synth_mult likes.
@@ -3496,7 +3483,7 @@  core_3, archs4x, archs4xd, archs4xd_slow"
 ; provide one alternatice for this, without condexec support.
 (define_insn "*ashlsi3_insn"
   [(set (match_operand:SI 0 "dest_reg_operand"           "=Rcq,Rcqq,Rcqq,Rcw, w,   w")
-	(ashift:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq,   0,  0, c,cCal")
+	(ashift:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq,   0,  0, c,cCsz")
 		   (match_operand:SI 2 "nonmemory_operand"  "K,  K,RcqqM, cL,cL,cCal")))]
   "TARGET_BARREL_SHIFTER
    && (register_operand (operands[1], SImode)
@@ -3509,7 +3496,7 @@  core_3, archs4x, archs4xd, archs4xd_slow"
 
 (define_insn "*ashrsi3_insn"
   [(set (match_operand:SI 0 "dest_reg_operand"             "=Rcq,Rcqq,Rcqq,Rcw, w,   w")
-	(ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq,   0,  0, c,cCal")
+	(ashiftrt:SI (match_operand:SI 1 "nonmemory_operand" "!0,Rcqq,   0,  0, c,cCsz")
 		     (match_operand:SI 2 "nonmemory_operand"  "K,  K,RcqqM, cL,cL,cCal")))]
   "TARGET_BARREL_SHIFTER
    && (register_operand (operands[1], SImode)
@@ -3536,7 +3523,7 @@  core_3, archs4x, archs4xd, archs4xd_slow"
 
 (define_insn "rotrsi3"
   [(set (match_operand:SI 0 "dest_reg_operand"             "=Rcw, w,   w")
-	(rotatert:SI (match_operand:SI 1 "register_operand"  " 0,cL,cCal")
+	(rotatert:SI (match_operand:SI 1 "register_operand"  " 0,cL,cCsz")
 		     (match_operand:SI 2 "nonmemory_operand" "cL,cL,cCal")))]
   "TARGET_BARREL_SHIFTER"
   "ror%? %0,%1,%2"
@@ -4284,16 +4271,16 @@  core_3, archs4x, archs4xd, archs4xd_slow"
 (define_peephole2
   [(set (match_operand:SI 0 "dest_reg_operand" "")
 	(ashift:SI (match_operand:SI 1 "register_operand" "")
-		   (match_operand:SI 2 "const_int_operand" "")))
+		   (match_operand:SI 2 "_1_2_3_operand" "")))
   (set (match_operand:SI 3 "dest_reg_operand" "")
        (plus:SI (match_operand:SI 4 "nonmemory_operand" "")
 		(match_operand:SI 5 "nonmemory_operand" "")))]
-  "(INTVAL (operands[2]) == 1
-    || INTVAL (operands[2]) == 2
-    || INTVAL (operands[2]) == 3)
-   && (true_regnum (operands[4]) == true_regnum (operands[0])
+  "(true_regnum (operands[4]) == true_regnum (operands[0])
        || true_regnum (operands[5]) == true_regnum (operands[0]))
-   && (peep2_reg_dead_p (2, operands[0]) || (true_regnum (operands[3]) == true_regnum (operands[0])))"
+   && (peep2_reg_dead_p (2, operands[0])
+       || (true_regnum (operands[3]) == true_regnum (operands[0])))
+   && !(optimize_size && satisfies_constraint_I (operands[4]))
+   && !(optimize_size && satisfies_constraint_I (operands[5]))"
  ;; the preparation statements take care to put proper operand in operands[4]
  ;; operands[4] will always contain the correct operand. This is added to satisfy commutativity
   [(set (match_dup 3)
@@ -6329,7 +6316,7 @@  core_3, archs4x, archs4xd, archs4xd_slow"
   [(set (match_operand:SI 0 "register_operand" "=q,r,r")
 	(plus:SI (ashift:SI (match_operand:SI 1 "register_operand" "q,r,r")
 			    (match_operand:SI 2 "_1_2_3_operand" ""))
-		 (match_operand:SI 3 "nonmemory_operand"  "0,r,Cal")))]
+		 (match_operand:SI 3 "nonmemory_operand"  "0,r,Csz")))]
   ""
   "add%2%?\\t%0,%3,%1"
   [(set_attr "length" "*,4,8")
diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
index f9ef3f94dfe..abfeedffe9a 100644
--- a/gcc/config/arc/constraints.md
+++ b/gcc/config/arc/constraints.md
@@ -428,6 +428,12 @@ 
 	       && !arc_legitimate_pic_addr_p (op)
 	       && !satisfies_constraint_I (op)"))
 
+(define_constraint "Csz"
+  "a 32 bit constant avoided when compiling for size."
+  (match_test "immediate_operand (op, VOIDmode)
+	       && !arc_legitimate_pic_addr_p (op)
+	       && !(satisfies_constraint_I (op) && optimize_size)"))
+
 ; Note that the 'cryptic' register constraints will not make reload use the
 ; associated class to reload into, but this will not penalize reloading of any
 ; other operands, or using an alternate part of the same alternative.
diff --git a/gcc/testsuite/gcc.target/arc/tph_addx.c b/gcc/testsuite/gcc.target/arc/tph_addx.c
new file mode 100644
index 00000000000..f942ab19eb1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arc/tph_addx.c
@@ -0,0 +1,53 @@ 
+/* { dg-do compile } */
+/* { dg-options "-Os" } */
+
+/* when compiling for size avoid the following peephole
+-------------------------------------------------------------
+Pattern 1 : r0 = r1 << {i}
+            r3 = r4/INT + r0     ;;and commutative
+                ||
+                \/
+            add{i} r3,r4/INT,r1
+-------------------------------------------------------------
+*/
+
+typedef int a;
+typedef int b                                                    ;
+struct c
+{
+  b d;
+};
+
+struct e
+{
+  a f;
+};
+
+int g(int family)
+{
+  switch (family)
+  case 2:
+    return sizeof(struct e);
+  return 0;
+}
+
+int h(int family)
+{
+  return 1 + g(family) - 1 ;
+}
+
+extern void m (void);
+
+int i(int j)
+{
+  struct c *hdr;
+  int k;
+  int l;
+  k = h(j);
+  l = sizeof(struct c) +   k * 2;
+  hdr->d = l ;
+  if (j)
+    m();
+}
+
+/* { dg-final { scan-assembler-not "add\d" } } */