[ARC] Add/update combiner patterns.

Message ID 20180307115903.12916-1-claziss@gmail.com
State New
Headers show
Series
  • [ARC] Add/update combiner patterns.
Related show

Commit Message

Claudiu Zissulescu March 7, 2018, 11:59 a.m.
From: claziss <claziss@synopsys.com>


Hi Andrew,

Please find the following patch which improves generating more instructions with .f flag (i.e., compare with zero).

Ok to apply?
Claudiu

gcc/
2018-01-26  Claudiu Zissulescu  <claziss@synopsys.com>

	* config/arc/arc.md (add_shift): New pattern.
	(add_shift2): Likewise.
	(sub_shift): Likewise.
	(sub_shift_cmp0_noout): Likewise.
	(compare_si_ashiftsi): Likewise.
	(xbfu_cmp0_noout): New combine pattern.
	(xbfu_cmp0"): Likewise.
	(movsi_set_cc_insn): Place the predicable variant first.
	(commutative_binary_cmp0_noout): Remove clobber.
	(commutative_binary_cmp0): New pattern.
	(noncommutative_binary_cmp0): Likewise.
	(noncommutative_binary_cmp0_noout): Likewise.
	(noncommutative_binary_comparison_result_used): Removed.
	(rsub_cmp0): New pattern.
	(rsub_cmp0_noout): Likewise.
	(extzvsi): Changed, keep only meaningful variants.
	(SQH, SEZ): New iterators.
	(SQH_postfix): New mode attribute.
	(SEZ_prefix): New code attribute.
	(<SEZ_prefix>xt<SQH_postfix>_cmp0_noout): New instruction pattern.
	(<SEZ_prefix>xt<SQH_postfix>_cmp0): Likewise.
	* config/arc/predicates.md (cc_set_register): Use CC_REG instead
	of numerical value.
	(noncommutative_operator): Check the availability of barrel
	shifter option.
---
 gcc/config/arc/arc.md        | 274 ++++++++++++++++++++++++++++++++++++-------
 gcc/config/arc/predicates.md |   6 +-
 2 files changed, 233 insertions(+), 47 deletions(-)

-- 
2.14.3

Comments

Andrew Burgess April 7, 2018, 9:07 a.m. | #1
* Claudiu Zissulescu <claziss@gmail.com> [2018-03-07 13:59:03 +0200]:

> From: claziss <claziss@synopsys.com>

> 

> Hi Andrew,

> 

> Please find the following patch which improves generating more instructions with .f flag (i.e., compare with zero).

> 

> Ok to apply?


Looks good.

Thanks.
Andrew


> Claudiu

> 

> gcc/

> 2018-01-26  Claudiu Zissulescu  <claziss@synopsys.com>

> 

> 	* config/arc/arc.md (add_shift): New pattern.

> 	(add_shift2): Likewise.

> 	(sub_shift): Likewise.

> 	(sub_shift_cmp0_noout): Likewise.

> 	(compare_si_ashiftsi): Likewise.

> 	(xbfu_cmp0_noout): New combine pattern.

> 	(xbfu_cmp0"): Likewise.

> 	(movsi_set_cc_insn): Place the predicable variant first.

> 	(commutative_binary_cmp0_noout): Remove clobber.

> 	(commutative_binary_cmp0): New pattern.

> 	(noncommutative_binary_cmp0): Likewise.

> 	(noncommutative_binary_cmp0_noout): Likewise.

> 	(noncommutative_binary_comparison_result_used): Removed.

> 	(rsub_cmp0): New pattern.

> 	(rsub_cmp0_noout): Likewise.

> 	(extzvsi): Changed, keep only meaningful variants.

> 	(SQH, SEZ): New iterators.

> 	(SQH_postfix): New mode attribute.

> 	(SEZ_prefix): New code attribute.

> 	(<SEZ_prefix>xt<SQH_postfix>_cmp0_noout): New instruction pattern.

> 	(<SEZ_prefix>xt<SQH_postfix>_cmp0): Likewise.

> 	* config/arc/predicates.md (cc_set_register): Use CC_REG instead

> 	of numerical value.

> 	(noncommutative_operator): Check the availability of barrel

> 	shifter option.

> ---

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

>  gcc/config/arc/predicates.md |   6 +-

>  2 files changed, 233 insertions(+), 47 deletions(-)

> 

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

> index 7633d36b5a6..fb3432964ac 100644

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

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

> @@ -810,20 +810,90 @@ archs4x, archs4xd, archs4xd_slow"

>    "st%U0 %1,%0\;st%U0.di %1,%0"

>    [(set_attr "type" "store")])

>  

> +;; Combiner patterns for compare with zero

> +(define_mode_iterator SQH [QI HI])

> +(define_mode_attr SQH_postfix [(QI "b") (HI "%_")])

> +

> +(define_code_iterator SEZ [sign_extend zero_extend])

> +(define_code_attr SEZ_prefix [(sign_extend "sex") (zero_extend "ext")])

> +

> +(define_insn "*<SEZ_prefix>xt<SQH_postfix>_cmp0_noout"

> +  [(set (match_operand 0 "cc_set_register" "")

> +	(compare:CC_ZN (SEZ:SI (match_operand:SQH 1 "register_operand" "r"))

> +		       (const_int 0)))]

> +  ""

> +  "<SEZ_prefix><SQH_postfix>.f\\t0,%1"

> +  [(set_attr "type" "compare")

> +   (set_attr "cond" "set_zn")])

> +

> +(define_insn "*<SEZ_prefix>xt<SQH_postfix>_cmp0"

> +  [(set (match_operand 0 "cc_set_register" "")

> +	(compare:CC_ZN (SEZ:SI (match_operand:SQH 1 "register_operand" "r"))

> +		       (const_int 0)))

> +   (set (match_operand:SI 2 "register_operand" "=r")

> +	(SEZ:SI (match_dup 1)))]

> +  ""

> +  "<SEZ_prefix><SQH_postfix>.f\\t%2,%1"

> +  [(set_attr "type" "compare")

> +   (set_attr "cond" "set_zn")])

> +

> +(define_insn "*xbfu_cmp0_noout"

> +  [(set (match_operand 0 "cc_set_register" "")

> +	(compare:CC_Z

> +	 (zero_extract:SI

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

> +	  (match_operand:SI 2 "const_int_operand" "C3p,n")

> +	  (match_operand:SI 3 "const_int_operand" "  n,n"))

> +	 (const_int 0)))]

> +  "TARGET_HS && TARGET_BARREL_SHIFTER"

> +  {

> +   int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL (operands[3]) & 0x1f);

> +   operands[2] = GEN_INT (assemble_op2);

> +   return "xbfu%?.f\\t0,%1,%2";

> +  }

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

> +   (set_attr "iscompact"  "false")

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

> +   (set_attr "predicable" "no")

> +   (set_attr "cond"       "set_zn")])

> +

> +(define_insn "*xbfu_cmp0"

> +  [(set (match_operand 4 "cc_set_register" "")

> +	(compare:CC_Z

> +	 (zero_extract:SI

> +	  (match_operand:SI 1 "register_operand"  "0  ,r,0")

> +	  (match_operand:SI 2 "const_int_operand" "C3p,n,n")

> +	  (match_operand:SI 3 "const_int_operand" "n  ,n,n"))

> +	 (const_int 0)))

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

> +	(zero_extract:SI (match_dup 1) (match_dup 2) (match_dup 3)))]

> +  "TARGET_HS && TARGET_BARREL_SHIFTER"

> +  {

> +   int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL (operands[3]) & 0x1f);

> +   operands[2] = GEN_INT (assemble_op2);

> +   return "xbfu%?.f\\t%0,%1,%2";

> +  }

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

> +   (set_attr "iscompact"  "false")

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

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

> +   (set_attr "cond"       "set_zn")])

> +

> +; splitting to 'tst' allows short insns and combination into brcc.

>  (define_insn_and_split "*movsi_set_cc_insn"

> -  [(set (match_operand:CC_ZN 2 "cc_set_register" "")

> -	(match_operator:CC_ZN 3 "zn_compare_operator"

> -	  [(match_operand:SI 1 "nonmemory_operand" "cI,cL,Cal") (const_int 0)]))

> -   (set (match_operand:SI 0 "register_operand" "=w,w,w")

> +  [(set (match_operand 2 "cc_set_register" "")

> +	(match_operator 3 "zn_compare_operator"

> +			[(match_operand:SI 1 "nonmemory_operand" "rL,rI,Cal")

> +			 (const_int 0)]))

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

>  	(match_dup 1))]

>    ""

> -  "mov%?.f %0,%1"

> -  ; splitting to 'tst' allows short insns and combination into brcc.

> +  "mov%?.f\\t%0,%1"

>    "reload_completed && operands_match_p (operands[0], operands[1])"

>    [(set (match_dup 2) (match_dup 3))]

>    ""

>    [(set_attr "type" "compare")

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

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

>     (set_attr "cond" "set_zn")

>     (set_attr "length" "4,4,8")])

>  

> @@ -973,19 +1043,35 @@ archs4x, archs4xd, archs4xd_slow"

>     (set_attr "cond" "set_zn")

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

>  

> -(define_insn "*commutative_binary_comparison"

> -  [(set (match_operand:CC_ZN 0 "cc_set_register" "")

> -	(match_operator:CC_ZN 5 "zn_compare_operator"

> +;; The next two patterns are for plos, ior, xor, and, and mult.

> +(define_insn "*commutative_binary_cmp0_noout"

> +  [(set (match_operand 0 "cc_set_register" "")

> +	(match_operator 4 "zn_compare_operator"

> +	  [(match_operator:SI 3 "commutative_operator"

> +	     [(match_operand:SI 1 "register_operand" "%r,r")

> +	      (match_operand:SI 2 "nonmemory_operand" "rL,Cal")])

> +	   (const_int 0)]))]

> +  ""

> +  "%O3.f\\t0,%1,%2"

> +  [(set_attr "type" "compare")

> +   (set_attr "cond" "set_zn")

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

> +

> +(define_insn "*commutative_binary_cmp0"

> +  [(set (match_operand 3 "cc_set_register" "")

> +	(match_operator 5 "zn_compare_operator"

>  	  [(match_operator:SI 4 "commutative_operator"

> -	     [(match_operand:SI 1 "register_operand" "%c,c")

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

> +	     [(match_operand:SI 1 "register_operand"  "%0, 0,r,r")

> +	      (match_operand:SI 2 "nonmemory_operand" "rL,rI,r,Cal")])

>  	   (const_int 0)]))

> -   (clobber (match_scratch:SI 3 "=X,X"))]

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

> +	(match_dup 4))]

>    ""

> -  "%O4.f 0,%1,%2"

> +  "%O4.f\\t%0,%1,%2"

>    [(set_attr "type" "compare")

>     (set_attr "cond" "set_zn")

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

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

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

>  

>  ; for flag setting 'add' instructions like if (a+b) { ...}

>  ; the combiner needs this pattern

> @@ -1059,32 +1145,60 @@ archs4x, archs4xd, archs4xd_slow"

>     (set_attr "cond" "set_zn,set_zn,set_zn")

>     (set_attr "length" "4,4,8")])

>  

> -; this pattern is needed by combiner for cases like if (c=a<<b) { ... }

> -(define_insn "*noncommutative_binary_comparison_result_used"

> -  [(set (match_operand 3 "cc_register" "")

> +(define_insn "*noncommutative_binary_cmp0"

> +  [(set (match_operand 3 "cc_set_register" "")

>  	(match_operator 5 "zn_compare_operator"

>  	  [(match_operator:SI 4 "noncommutative_operator"

> -	     [(match_operand:SI 1 "register_operand" "c,0,c")

> -	      (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])

> -	       (const_int 0)]))

> -   (set (match_operand:SI 0 "register_operand" "=w,w,w")

> -	(match_dup 4 ))]

> -  "TARGET_BARREL_SHIFTER || GET_CODE (operands[4]) == MINUS"

> -  "%O4.f %0,%1,%2"

> -  [(set_attr "type" "compare,compare,compare")

> -   (set_attr "cond" "set_zn,set_zn,set_zn")

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

> +	     [(match_operand:SI 1 "register_operand"   "0,r,0,  0,r")

> +	      (match_operand:SI 2 "nonmemory_operand" "rL,r,I,Cal,Cal")])

> +	   (const_int 0)]))

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

> +	(match_dup 4))]

> +  ""

> +  "%O4%?.f\\t%0,%1,%2"

> +  [(set_attr "type" "compare")

> +   (set_attr "cond" "set_zn")

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

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

>  

> -(define_insn "*noncommutative_binary_comparison"

> -  [(set (match_operand:CC_ZN 0 "cc_set_register" "")

> -	(match_operator:CC_ZN 5 "zn_compare_operator"

> +(define_insn "*noncommutative_binary_cmp0_noout"

> +  [(set (match_operand 0 "cc_set_register" "")

> +	(match_operator 3 "zn_compare_operator"

>  	  [(match_operator:SI 4 "noncommutative_operator"

> -	     [(match_operand:SI 1 "register_operand" "c,c")

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

> +	     [(match_operand:SI 1 "register_operand"   "r,r")

> +	      (match_operand:SI 2 "nonmemory_operand" "rL,Cal")])

> +	   (const_int 0)]))]

> +  ""

> +  "%O4.f\\t0,%1,%2"

> +  [(set_attr "type" "compare")

> +   (set_attr "cond" "set_zn")

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

> +

> +;;rsub variants

> +(define_insn "*rsub_cmp0"

> +  [(set (match_operand 4 "cc_set_register" "")

> +	(match_operator 3 "zn_compare_operator"

> +	  [(minus:SI

> +	    (match_operand:SI 1 "nonmemory_operand" "rL,Cal")

> +	    (match_operand:SI 2 "register_operand"   "r,r"))

>  	   (const_int 0)]))

> -   (clobber (match_scratch:SI 3 "=X,X"))]

> -  "TARGET_BARREL_SHIFTER || GET_CODE (operands[4]) == MINUS"

> -  "%O4.f 0,%1,%2"

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

> +	(minus:SI (match_dup 1) (match_dup 2)))]

> +  ""

> +  "rsub.f\\t%0,%2,%1"

> +  [(set_attr "type" "compare")

> +   (set_attr "cond" "set_zn")

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

> +

> +(define_insn "*rsub_cmp0_noout"

> +  [(set (match_operand 0 "cc_set_register" "")

> +	(match_operator 3 "zn_compare_operator"

> +	  [(minus:SI

> +	    (match_operand:SI 1 "nonmemory_operand" "rL,Cal")

> +	    (match_operand:SI 2 "register_operand"   "r,r"))

> +	   (const_int 0)]))]

> +  ""

> +  "rsub.f\\t0,%2,%1"

>    [(set_attr "type" "compare")

>     (set_attr "cond" "set_zn")

>     (set_attr "length" "4,8")])

> @@ -5624,23 +5738,22 @@ archs4x, archs4xd, archs4xd_slow"

>   DONE;

>  })

>  

> -

>  (define_insn "extzvsi"

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

> -	(zero_extract:SI (match_operand:SI 1 "register_operand"  "0  , r  , 0, 0, r")

> -			 (match_operand:SI 2 "const_int_operand" "C3p, C3p, i, i, i")

> -			 (match_operand:SI 3 "const_int_operand" "i  , i  , i, i, i")))]

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

> +	(zero_extract:SI (match_operand:SI 1 "register_operand"  "0  ,  r,r,0")

> +			 (match_operand:SI 2 "const_int_operand" "C3p,C3p,n,n")

> +			 (match_operand:SI 3 "const_int_operand" "n  ,  n,n,n")))]

>    "TARGET_HS && TARGET_BARREL_SHIFTER"

>    {

>     int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL (operands[3]) & 0x1f);

>     operands[2] = GEN_INT (assemble_op2);

> -   return "xbfu%? %0,%1,%2";

> +   return "xbfu%?\\t%0,%1,%2";

>    }

>    [(set_attr "type"       "shift")

>     (set_attr "iscompact"  "false")

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

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

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

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

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

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

>  

>  (define_insn "kflag"

>    [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "rL,I,Cal")]

> @@ -6439,6 +6552,77 @@ archs4x, archs4xd, archs4xd_slow"

>     (set_attr "type" "block")]

>    )

>  

> +(define_insn "*add_shift"

> +  [(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")))]

> +  ""

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

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

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

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

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

> +

> +(define_insn "*add_shift2"

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

> +	(plus:SI (match_operand:SI 1 "nonmemory_operand"  "0,r,Cal")

> +		 (ashift:SI (match_operand:SI 2 "register_operand" "q,r,r")

> +			    (match_operand:SI 3 "_1_2_3_operand" ""))))]

> +  ""

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

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

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

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

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

> +

> +(define_insn "*sub_shift"

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

> +	 (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal")

> +		   (ashift:SI (match_operand:SI 2 "register_operand" "r,r,r")

> +			      (match_operand:SI 3 "_1_2_3_operand" ""))))]

> +  ""

> +  "sub%3\\t%0,%1,%2"

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

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

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

> +

> +(define_insn "*sub_shift_cmp0_noout"

> +  [(set (match_operand 0 "cc_set_register" "")

> +	(compare:CC

> +	 (minus:SI (match_operand:SI 1 "register_operand" "r")

> +		   (ashift:SI (match_operand:SI 2 "register_operand" "r")

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

> +	 (const_int 0)))]

> +  ""

> +  "sub%3.f\\t0,%1,%2"

> +  [(set_attr "length" "4")])

> +

> +(define_insn "*compare_si_ashiftsi"

> +  [(set (match_operand 0 "cc_set_register" "")

> +	(compare:CC (match_operand:SI 1 "register_operand" "r")

> +		    (ashift:SI (match_operand:SI 2 "register_operand" "r")

> +			       (match_operand:SI 3 "_1_2_3_operand" ""))))]

> +  ""

> +  "sub%3.f\\t0,%1,%2"

> +  [(set_attr "length" "4")])

> +

> +;; Convert the sequence

> +;;  asl rd,rn,_1_2_3

> +;;  cmp ra,rd

> +;; into

> +;;  sub{123}.f 0,ra,rn

> +(define_peephole2

> +  [(set (match_operand:SI 0 "register_operand" "")

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

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

> +   (set (reg:CC CC_REG)

> +	(compare:CC (match_operand:SI 3 "register_operand" "")

> +		    (match_dup 0)))]

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

> +  [(set (reg:CC CC_REG) (compare:CC (match_dup 3)

> +				    (ashift:SI (match_dup 1) (match_dup 2))))])

> +

>  ;; include the arc-FPX instructions

>  (include "fpx.md")

>  

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

> index 38651f79bf4..0abfc839b07 100644

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

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

> @@ -522,7 +522,7 @@

>  	return FALSE;

>      }

>  

> -  if (REGNO (op) != 61)

> +  if (REGNO (op) != CC_REG)

>      return FALSE;

>    if (mode == rmode

>        || (mode == CC_ZNmode && rmode == CC_Zmode)

> @@ -609,7 +609,9 @@

>  )

>  

>  (define_predicate "noncommutative_operator"

> -  (ior (match_code "minus,ashift,ashiftrt,lshiftrt,rotatert")

> +  (ior (and (match_code "ashift,ashiftrt,lshiftrt,rotatert")

> +	    (match_test "TARGET_BARREL_SHIFTER"))

> +       (match_code "minus")

>         (and (match_code "ss_minus")

>  	    (match_test "TARGET_ARC700 || TARGET_EA_SET")))

>  )

> -- 

> 2.14.3

>
Claudiu Zissulescu April 9, 2018, 3:05 p.m. | #2
Committed. Thank you for your review,
Claudiu

> -----Original Message-----

> From: Andrew Burgess [mailto:andrew.burgess@embecosm.com]

> Sent: Saturday, April 07, 2018 11:07 AM

> To: Claudiu Zissulescu <claziss@gmail.com>

> Cc: gcc-patches@gcc.gnu.org; Claudiu.Zissulescu@synopsys.com;

> Francois.Bedard@synopsys.com

> Subject: Re: [PATCH] [ARC] Add/update combiner patterns.

> 

> * Claudiu Zissulescu <claziss@gmail.com> [2018-03-07 13:59:03 +0200]:

> 

> > From: claziss <claziss@synopsys.com>

> >

> > Hi Andrew,

> >

> > Please find the following patch which improves generating more

> instructions with .f flag (i.e., compare with zero).

> >

> > Ok to apply?

> 

> Looks good.

> 

> Thanks.

> Andrew

> 

> 

> > Claudiu

> >

> > gcc/

> > 2018-01-26  Claudiu Zissulescu  <claziss@synopsys.com>

> >

> > 	* config/arc/arc.md (add_shift): New pattern.

> > 	(add_shift2): Likewise.

> > 	(sub_shift): Likewise.

> > 	(sub_shift_cmp0_noout): Likewise.

> > 	(compare_si_ashiftsi): Likewise.

> > 	(xbfu_cmp0_noout): New combine pattern.

> > 	(xbfu_cmp0"): Likewise.

> > 	(movsi_set_cc_insn): Place the predicable variant first.

> > 	(commutative_binary_cmp0_noout): Remove clobber.

> > 	(commutative_binary_cmp0): New pattern.

> > 	(noncommutative_binary_cmp0): Likewise.

> > 	(noncommutative_binary_cmp0_noout): Likewise.

> > 	(noncommutative_binary_comparison_result_used): Removed.

> > 	(rsub_cmp0): New pattern.

> > 	(rsub_cmp0_noout): Likewise.

> > 	(extzvsi): Changed, keep only meaningful variants.

> > 	(SQH, SEZ): New iterators.

> > 	(SQH_postfix): New mode attribute.

> > 	(SEZ_prefix): New code attribute.

> > 	(<SEZ_prefix>xt<SQH_postfix>_cmp0_noout): New instruction

> pattern.

> > 	(<SEZ_prefix>xt<SQH_postfix>_cmp0): Likewise.

> > 	* config/arc/predicates.md (cc_set_register): Use CC_REG instead

> > 	of numerical value.

> > 	(noncommutative_operator): Check the availability of barrel

> > 	shifter option.

> > ---

> >  gcc/config/arc/arc.md        | 274

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

> >  gcc/config/arc/predicates.md |   6 +-

> >  2 files changed, 233 insertions(+), 47 deletions(-)

> >

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

> > index 7633d36b5a6..fb3432964ac 100644

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

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

> > @@ -810,20 +810,90 @@ archs4x, archs4xd, archs4xd_slow"

> >    "st%U0 %1,%0\;st%U0.di %1,%0"

> >    [(set_attr "type" "store")])

> >

> > +;; Combiner patterns for compare with zero

> > +(define_mode_iterator SQH [QI HI])

> > +(define_mode_attr SQH_postfix [(QI "b") (HI "%_")])

> > +

> > +(define_code_iterator SEZ [sign_extend zero_extend])

> > +(define_code_attr SEZ_prefix [(sign_extend "sex") (zero_extend "ext")])

> > +

> > +(define_insn "*<SEZ_prefix>xt<SQH_postfix>_cmp0_noout"

> > +  [(set (match_operand 0 "cc_set_register" "")

> > +	(compare:CC_ZN (SEZ:SI (match_operand:SQH 1 "register_operand"

> "r"))

> > +		       (const_int 0)))]

> > +  ""

> > +  "<SEZ_prefix><SQH_postfix>.f\\t0,%1"

> > +  [(set_attr "type" "compare")

> > +   (set_attr "cond" "set_zn")])

> > +

> > +(define_insn "*<SEZ_prefix>xt<SQH_postfix>_cmp0"

> > +  [(set (match_operand 0 "cc_set_register" "")

> > +	(compare:CC_ZN (SEZ:SI (match_operand:SQH 1 "register_operand"

> "r"))

> > +		       (const_int 0)))

> > +   (set (match_operand:SI 2 "register_operand" "=r")

> > +	(SEZ:SI (match_dup 1)))]

> > +  ""

> > +  "<SEZ_prefix><SQH_postfix>.f\\t%2,%1"

> > +  [(set_attr "type" "compare")

> > +   (set_attr "cond" "set_zn")])

> > +

> > +(define_insn "*xbfu_cmp0_noout"

> > +  [(set (match_operand 0 "cc_set_register" "")

> > +	(compare:CC_Z

> > +	 (zero_extract:SI

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

> > +	  (match_operand:SI 2 "const_int_operand" "C3p,n")

> > +	  (match_operand:SI 3 "const_int_operand" "  n,n"))

> > +	 (const_int 0)))]

> > +  "TARGET_HS && TARGET_BARREL_SHIFTER"

> > +  {

> > +   int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL

> (operands[3]) & 0x1f);

> > +   operands[2] = GEN_INT (assemble_op2);

> > +   return "xbfu%?.f\\t0,%1,%2";

> > +  }

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

> > +   (set_attr "iscompact"  "false")

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

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

> > +   (set_attr "cond"       "set_zn")])

> > +

> > +(define_insn "*xbfu_cmp0"

> > +  [(set (match_operand 4 "cc_set_register" "")

> > +	(compare:CC_Z

> > +	 (zero_extract:SI

> > +	  (match_operand:SI 1 "register_operand"  "0  ,r,0")

> > +	  (match_operand:SI 2 "const_int_operand" "C3p,n,n")

> > +	  (match_operand:SI 3 "const_int_operand" "n  ,n,n"))

> > +	 (const_int 0)))

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

> > +	(zero_extract:SI (match_dup 1) (match_dup 2) (match_dup 3)))]

> > +  "TARGET_HS && TARGET_BARREL_SHIFTER"

> > +  {

> > +   int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL

> (operands[3]) & 0x1f);

> > +   operands[2] = GEN_INT (assemble_op2);

> > +   return "xbfu%?.f\\t%0,%1,%2";

> > +  }

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

> > +   (set_attr "iscompact"  "false")

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

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

> > +   (set_attr "cond"       "set_zn")])

> > +

> > +; splitting to 'tst' allows short insns and combination into brcc.

> >  (define_insn_and_split "*movsi_set_cc_insn"

> > -  [(set (match_operand:CC_ZN 2 "cc_set_register" "")

> > -	(match_operator:CC_ZN 3 "zn_compare_operator"

> > -	  [(match_operand:SI 1 "nonmemory_operand" "cI,cL,Cal")

> (const_int 0)]))

> > -   (set (match_operand:SI 0 "register_operand" "=w,w,w")

> > +  [(set (match_operand 2 "cc_set_register" "")

> > +	(match_operator 3 "zn_compare_operator"

> > +			[(match_operand:SI 1 "nonmemory_operand"

> "rL,rI,Cal")

> > +			 (const_int 0)]))

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

> >  	(match_dup 1))]

> >    ""

> > -  "mov%?.f %0,%1"

> > -  ; splitting to 'tst' allows short insns and combination into brcc.

> > +  "mov%?.f\\t%0,%1"

> >    "reload_completed && operands_match_p (operands[0], operands[1])"

> >    [(set (match_dup 2) (match_dup 3))]

> >    ""

> >    [(set_attr "type" "compare")

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

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

> >     (set_attr "cond" "set_zn")

> >     (set_attr "length" "4,4,8")])

> >

> > @@ -973,19 +1043,35 @@ archs4x, archs4xd, archs4xd_slow"

> >     (set_attr "cond" "set_zn")

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

> >

> > -(define_insn "*commutative_binary_comparison"

> > -  [(set (match_operand:CC_ZN 0 "cc_set_register" "")

> > -	(match_operator:CC_ZN 5 "zn_compare_operator"

> > +;; The next two patterns are for plos, ior, xor, and, and mult.

> > +(define_insn "*commutative_binary_cmp0_noout"

> > +  [(set (match_operand 0 "cc_set_register" "")

> > +	(match_operator 4 "zn_compare_operator"

> > +	  [(match_operator:SI 3 "commutative_operator"

> > +	     [(match_operand:SI 1 "register_operand" "%r,r")

> > +	      (match_operand:SI 2 "nonmemory_operand" "rL,Cal")])

> > +	   (const_int 0)]))]

> > +  ""

> > +  "%O3.f\\t0,%1,%2"

> > +  [(set_attr "type" "compare")

> > +   (set_attr "cond" "set_zn")

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

> > +

> > +(define_insn "*commutative_binary_cmp0"

> > +  [(set (match_operand 3 "cc_set_register" "")

> > +	(match_operator 5 "zn_compare_operator"

> >  	  [(match_operator:SI 4 "commutative_operator"

> > -	     [(match_operand:SI 1 "register_operand" "%c,c")

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

> > +	     [(match_operand:SI 1 "register_operand"  "%0, 0,r,r")

> > +	      (match_operand:SI 2 "nonmemory_operand" "rL,rI,r,Cal")])

> >  	   (const_int 0)]))

> > -   (clobber (match_scratch:SI 3 "=X,X"))]

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

> > +	(match_dup 4))]

> >    ""

> > -  "%O4.f 0,%1,%2"

> > +  "%O4.f\\t%0,%1,%2"

> >    [(set_attr "type" "compare")

> >     (set_attr "cond" "set_zn")

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

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

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

> >

> >  ; for flag setting 'add' instructions like if (a+b) { ...}

> >  ; the combiner needs this pattern

> > @@ -1059,32 +1145,60 @@ archs4x, archs4xd, archs4xd_slow"

> >     (set_attr "cond" "set_zn,set_zn,set_zn")

> >     (set_attr "length" "4,4,8")])

> >

> > -; this pattern is needed by combiner for cases like if (c=a<<b) { ... }

> > -(define_insn "*noncommutative_binary_comparison_result_used"

> > -  [(set (match_operand 3 "cc_register" "")

> > +(define_insn "*noncommutative_binary_cmp0"

> > +  [(set (match_operand 3 "cc_set_register" "")

> >  	(match_operator 5 "zn_compare_operator"

> >  	  [(match_operator:SI 4 "noncommutative_operator"

> > -	     [(match_operand:SI 1 "register_operand" "c,0,c")

> > -	      (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])

> > -	       (const_int 0)]))

> > -   (set (match_operand:SI 0 "register_operand" "=w,w,w")

> > -	(match_dup 4 ))]

> > -  "TARGET_BARREL_SHIFTER || GET_CODE (operands[4]) == MINUS"

> > -  "%O4.f %0,%1,%2"

> > -  [(set_attr "type" "compare,compare,compare")

> > -   (set_attr "cond" "set_zn,set_zn,set_zn")

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

> > +	     [(match_operand:SI 1 "register_operand"   "0,r,0,  0,r")

> > +	      (match_operand:SI 2 "nonmemory_operand" "rL,r,I,Cal,Cal")])

> > +	   (const_int 0)]))

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

> > +	(match_dup 4))]

> > +  ""

> > +  "%O4%?.f\\t%0,%1,%2"

> > +  [(set_attr "type" "compare")

> > +   (set_attr "cond" "set_zn")

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

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

> >

> > -(define_insn "*noncommutative_binary_comparison"

> > -  [(set (match_operand:CC_ZN 0 "cc_set_register" "")

> > -	(match_operator:CC_ZN 5 "zn_compare_operator"

> > +(define_insn "*noncommutative_binary_cmp0_noout"

> > +  [(set (match_operand 0 "cc_set_register" "")

> > +	(match_operator 3 "zn_compare_operator"

> >  	  [(match_operator:SI 4 "noncommutative_operator"

> > -	     [(match_operand:SI 1 "register_operand" "c,c")

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

> > +	     [(match_operand:SI 1 "register_operand"   "r,r")

> > +	      (match_operand:SI 2 "nonmemory_operand" "rL,Cal")])

> > +	   (const_int 0)]))]

> > +  ""

> > +  "%O4.f\\t0,%1,%2"

> > +  [(set_attr "type" "compare")

> > +   (set_attr "cond" "set_zn")

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

> > +

> > +;;rsub variants

> > +(define_insn "*rsub_cmp0"

> > +  [(set (match_operand 4 "cc_set_register" "")

> > +	(match_operator 3 "zn_compare_operator"

> > +	  [(minus:SI

> > +	    (match_operand:SI 1 "nonmemory_operand" "rL,Cal")

> > +	    (match_operand:SI 2 "register_operand"   "r,r"))

> >  	   (const_int 0)]))

> > -   (clobber (match_scratch:SI 3 "=X,X"))]

> > -  "TARGET_BARREL_SHIFTER || GET_CODE (operands[4]) == MINUS"

> > -  "%O4.f 0,%1,%2"

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

> > +	(minus:SI (match_dup 1) (match_dup 2)))]

> > +  ""

> > +  "rsub.f\\t%0,%2,%1"

> > +  [(set_attr "type" "compare")

> > +   (set_attr "cond" "set_zn")

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

> > +

> > +(define_insn "*rsub_cmp0_noout"

> > +  [(set (match_operand 0 "cc_set_register" "")

> > +	(match_operator 3 "zn_compare_operator"

> > +	  [(minus:SI

> > +	    (match_operand:SI 1 "nonmemory_operand" "rL,Cal")

> > +	    (match_operand:SI 2 "register_operand"   "r,r"))

> > +	   (const_int 0)]))]

> > +  ""

> > +  "rsub.f\\t0,%2,%1"

> >    [(set_attr "type" "compare")

> >     (set_attr "cond" "set_zn")

> >     (set_attr "length" "4,8")])

> > @@ -5624,23 +5738,22 @@ archs4x, archs4xd, archs4xd_slow"

> >   DONE;

> >  })

> >

> > -

> >  (define_insn "extzvsi"

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

> > -	(zero_extract:SI (match_operand:SI 1 "register_operand"  "0  , r  , 0,

> 0, r")

> > -			 (match_operand:SI 2 "const_int_operand" "C3p,

> C3p, i, i, i")

> > -			 (match_operand:SI 3 "const_int_operand" "i  , i  , i, i,

> i")))]

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

> > +	(zero_extract:SI (match_operand:SI 1 "register_operand"  "0  ,  r,r,0")

> > +			 (match_operand:SI 2 "const_int_operand"

> "C3p,C3p,n,n")

> > +			 (match_operand:SI 3 "const_int_operand" "n  ,

> n,n,n")))]

> >    "TARGET_HS && TARGET_BARREL_SHIFTER"

> >    {

> >     int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL

> (operands[3]) & 0x1f);

> >     operands[2] = GEN_INT (assemble_op2);

> > -   return "xbfu%? %0,%1,%2";

> > +   return "xbfu%?\\t%0,%1,%2";

> >    }

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

> >     (set_attr "iscompact"  "false")

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

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

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

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

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

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

> >

> >  (define_insn "kflag"

> >    [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand"

> "rL,I,Cal")]

> > @@ -6439,6 +6552,77 @@ archs4x, archs4xd, archs4xd_slow"

> >     (set_attr "type" "block")]

> >    )

> >

> > +(define_insn "*add_shift"

> > +  [(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")))]

> > +  ""

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

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

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

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

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

> > +

> > +(define_insn "*add_shift2"

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

> > +	(plus:SI (match_operand:SI 1 "nonmemory_operand"  "0,r,Cal")

> > +		 (ashift:SI (match_operand:SI 2 "register_operand" "q,r,r")

> > +			    (match_operand:SI 3 "_1_2_3_operand" ""))))]

> > +  ""

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

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

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

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

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

> > +

> > +(define_insn "*sub_shift"

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

> > +	 (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal")

> > +		   (ashift:SI (match_operand:SI 2 "register_operand" "r,r,r")

> > +			      (match_operand:SI 3 "_1_2_3_operand" ""))))]

> > +  ""

> > +  "sub%3\\t%0,%1,%2"

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

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

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

> > +

> > +(define_insn "*sub_shift_cmp0_noout"

> > +  [(set (match_operand 0 "cc_set_register" "")

> > +	(compare:CC

> > +	 (minus:SI (match_operand:SI 1 "register_operand" "r")

> > +		   (ashift:SI (match_operand:SI 2 "register_operand" "r")

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

> > +	 (const_int 0)))]

> > +  ""

> > +  "sub%3.f\\t0,%1,%2"

> > +  [(set_attr "length" "4")])

> > +

> > +(define_insn "*compare_si_ashiftsi"

> > +  [(set (match_operand 0 "cc_set_register" "")

> > +	(compare:CC (match_operand:SI 1 "register_operand" "r")

> > +		    (ashift:SI (match_operand:SI 2 "register_operand" "r")

> > +			       (match_operand:SI 3 "_1_2_3_operand" ""))))]

> > +  ""

> > +  "sub%3.f\\t0,%1,%2"

> > +  [(set_attr "length" "4")])

> > +

> > +;; Convert the sequence

> > +;;  asl rd,rn,_1_2_3

> > +;;  cmp ra,rd

> > +;; into

> > +;;  sub{123}.f 0,ra,rn

> > +(define_peephole2

> > +  [(set (match_operand:SI 0 "register_operand" "")

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

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

> > +   (set (reg:CC CC_REG)

> > +	(compare:CC (match_operand:SI 3 "register_operand" "")

> > +		    (match_dup 0)))]

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

> > +  [(set (reg:CC CC_REG) (compare:CC (match_dup 3)

> > +				    (ashift:SI (match_dup 1) (match_dup 2))))])

> > +

> >  ;; include the arc-FPX instructions

> >  (include "fpx.md")

> >

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

> > index 38651f79bf4..0abfc839b07 100644

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

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

> > @@ -522,7 +522,7 @@

> >  	return FALSE;

> >      }

> >

> > -  if (REGNO (op) != 61)

> > +  if (REGNO (op) != CC_REG)

> >      return FALSE;

> >    if (mode == rmode

> >        || (mode == CC_ZNmode && rmode == CC_Zmode)

> > @@ -609,7 +609,9 @@

> >  )

> >

> >  (define_predicate "noncommutative_operator"

> > -  (ior (match_code "minus,ashift,ashiftrt,lshiftrt,rotatert")

> > +  (ior (and (match_code "ashift,ashiftrt,lshiftrt,rotatert")

> > +	    (match_test "TARGET_BARREL_SHIFTER"))

> > +       (match_code "minus")

> >         (and (match_code "ss_minus")

> >  	    (match_test "TARGET_ARC700 || TARGET_EA_SET")))

> >  )

> > --

> > 2.14.3

> >

Patch

diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index 7633d36b5a6..fb3432964ac 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -810,20 +810,90 @@  archs4x, archs4xd, archs4xd_slow"
   "st%U0 %1,%0\;st%U0.di %1,%0"
   [(set_attr "type" "store")])
 
+;; Combiner patterns for compare with zero
+(define_mode_iterator SQH [QI HI])
+(define_mode_attr SQH_postfix [(QI "b") (HI "%_")])
+
+(define_code_iterator SEZ [sign_extend zero_extend])
+(define_code_attr SEZ_prefix [(sign_extend "sex") (zero_extend "ext")])
+
+(define_insn "*<SEZ_prefix>xt<SQH_postfix>_cmp0_noout"
+  [(set (match_operand 0 "cc_set_register" "")
+	(compare:CC_ZN (SEZ:SI (match_operand:SQH 1 "register_operand" "r"))
+		       (const_int 0)))]
+  ""
+  "<SEZ_prefix><SQH_postfix>.f\\t0,%1"
+  [(set_attr "type" "compare")
+   (set_attr "cond" "set_zn")])
+
+(define_insn "*<SEZ_prefix>xt<SQH_postfix>_cmp0"
+  [(set (match_operand 0 "cc_set_register" "")
+	(compare:CC_ZN (SEZ:SI (match_operand:SQH 1 "register_operand" "r"))
+		       (const_int 0)))
+   (set (match_operand:SI 2 "register_operand" "=r")
+	(SEZ:SI (match_dup 1)))]
+  ""
+  "<SEZ_prefix><SQH_postfix>.f\\t%2,%1"
+  [(set_attr "type" "compare")
+   (set_attr "cond" "set_zn")])
+
+(define_insn "*xbfu_cmp0_noout"
+  [(set (match_operand 0 "cc_set_register" "")
+	(compare:CC_Z
+	 (zero_extract:SI
+	  (match_operand:SI 1 "register_operand"  "  r,r")
+	  (match_operand:SI 2 "const_int_operand" "C3p,n")
+	  (match_operand:SI 3 "const_int_operand" "  n,n"))
+	 (const_int 0)))]
+  "TARGET_HS && TARGET_BARREL_SHIFTER"
+  {
+   int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL (operands[3]) & 0x1f);
+   operands[2] = GEN_INT (assemble_op2);
+   return "xbfu%?.f\\t0,%1,%2";
+  }
+  [(set_attr "type"       "shift")
+   (set_attr "iscompact"  "false")
+   (set_attr "length"     "4,8")
+   (set_attr "predicable" "no")
+   (set_attr "cond"       "set_zn")])
+
+(define_insn "*xbfu_cmp0"
+  [(set (match_operand 4 "cc_set_register" "")
+	(compare:CC_Z
+	 (zero_extract:SI
+	  (match_operand:SI 1 "register_operand"  "0  ,r,0")
+	  (match_operand:SI 2 "const_int_operand" "C3p,n,n")
+	  (match_operand:SI 3 "const_int_operand" "n  ,n,n"))
+	 (const_int 0)))
+   (set (match_operand:SI 0 "register_operand"  "=r,r,r")
+	(zero_extract:SI (match_dup 1) (match_dup 2) (match_dup 3)))]
+  "TARGET_HS && TARGET_BARREL_SHIFTER"
+  {
+   int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL (operands[3]) & 0x1f);
+   operands[2] = GEN_INT (assemble_op2);
+   return "xbfu%?.f\\t%0,%1,%2";
+  }
+  [(set_attr "type"       "shift")
+   (set_attr "iscompact"  "false")
+   (set_attr "length"     "4,8,8")
+   (set_attr "predicable" "yes,no,yes")
+   (set_attr "cond"       "set_zn")])
+
+; splitting to 'tst' allows short insns and combination into brcc.
 (define_insn_and_split "*movsi_set_cc_insn"
-  [(set (match_operand:CC_ZN 2 "cc_set_register" "")
-	(match_operator:CC_ZN 3 "zn_compare_operator"
-	  [(match_operand:SI 1 "nonmemory_operand" "cI,cL,Cal") (const_int 0)]))
-   (set (match_operand:SI 0 "register_operand" "=w,w,w")
+  [(set (match_operand 2 "cc_set_register" "")
+	(match_operator 3 "zn_compare_operator"
+			[(match_operand:SI 1 "nonmemory_operand" "rL,rI,Cal")
+			 (const_int 0)]))
+   (set (match_operand:SI 0 "register_operand" "=r,r,r")
 	(match_dup 1))]
   ""
-  "mov%?.f %0,%1"
-  ; splitting to 'tst' allows short insns and combination into brcc.
+  "mov%?.f\\t%0,%1"
   "reload_completed && operands_match_p (operands[0], operands[1])"
   [(set (match_dup 2) (match_dup 3))]
   ""
   [(set_attr "type" "compare")
-   (set_attr "predicable" "no,yes,yes")
+   (set_attr "predicable" "yes,no,yes")
    (set_attr "cond" "set_zn")
    (set_attr "length" "4,4,8")])
 
@@ -973,19 +1043,35 @@  archs4x, archs4xd, archs4xd_slow"
    (set_attr "cond" "set_zn")
    (set_attr "length" "*,4,4,4,8")])
 
-(define_insn "*commutative_binary_comparison"
-  [(set (match_operand:CC_ZN 0 "cc_set_register" "")
-	(match_operator:CC_ZN 5 "zn_compare_operator"
+;; The next two patterns are for plos, ior, xor, and, and mult.
+(define_insn "*commutative_binary_cmp0_noout"
+  [(set (match_operand 0 "cc_set_register" "")
+	(match_operator 4 "zn_compare_operator"
+	  [(match_operator:SI 3 "commutative_operator"
+	     [(match_operand:SI 1 "register_operand" "%r,r")
+	      (match_operand:SI 2 "nonmemory_operand" "rL,Cal")])
+	   (const_int 0)]))]
+  ""
+  "%O3.f\\t0,%1,%2"
+  [(set_attr "type" "compare")
+   (set_attr "cond" "set_zn")
+   (set_attr "length" "4,8")])
+
+(define_insn "*commutative_binary_cmp0"
+  [(set (match_operand 3 "cc_set_register" "")
+	(match_operator 5 "zn_compare_operator"
 	  [(match_operator:SI 4 "commutative_operator"
-	     [(match_operand:SI 1 "register_operand" "%c,c")
-	      (match_operand:SI 2 "nonmemory_operand" "cL,Cal")])
+	     [(match_operand:SI 1 "register_operand"  "%0, 0,r,r")
+	      (match_operand:SI 2 "nonmemory_operand" "rL,rI,r,Cal")])
 	   (const_int 0)]))
-   (clobber (match_scratch:SI 3 "=X,X"))]
+   (set (match_operand:SI 0 "register_operand" "=r,r,r,r")
+	(match_dup 4))]
   ""
-  "%O4.f 0,%1,%2"
+  "%O4.f\\t%0,%1,%2"
   [(set_attr "type" "compare")
    (set_attr "cond" "set_zn")
-   (set_attr "length" "4,8")])
+   (set_attr "predicable" "yes,yes,no,no")
+   (set_attr "length" "4,4,4,8")])
 
 ; for flag setting 'add' instructions like if (a+b) { ...}
 ; the combiner needs this pattern
@@ -1059,32 +1145,60 @@  archs4x, archs4xd, archs4xd_slow"
    (set_attr "cond" "set_zn,set_zn,set_zn")
    (set_attr "length" "4,4,8")])
 
-; this pattern is needed by combiner for cases like if (c=a<<b) { ... }
-(define_insn "*noncommutative_binary_comparison_result_used"
-  [(set (match_operand 3 "cc_register" "")
+(define_insn "*noncommutative_binary_cmp0"
+  [(set (match_operand 3 "cc_set_register" "")
 	(match_operator 5 "zn_compare_operator"
 	  [(match_operator:SI 4 "noncommutative_operator"
-	     [(match_operand:SI 1 "register_operand" "c,0,c")
-	      (match_operand:SI 2 "nonmemory_operand" "cL,I,?Cal")])
-	       (const_int 0)]))
-   (set (match_operand:SI 0 "register_operand" "=w,w,w")
-	(match_dup 4 ))]
-  "TARGET_BARREL_SHIFTER || GET_CODE (operands[4]) == MINUS"
-  "%O4.f %0,%1,%2"
-  [(set_attr "type" "compare,compare,compare")
-   (set_attr "cond" "set_zn,set_zn,set_zn")
-   (set_attr "length" "4,4,8")])
+	     [(match_operand:SI 1 "register_operand"   "0,r,0,  0,r")
+	      (match_operand:SI 2 "nonmemory_operand" "rL,r,I,Cal,Cal")])
+	   (const_int 0)]))
+   (set (match_operand:SI 0 "register_operand" "=r,r,r,r,r")
+	(match_dup 4))]
+  ""
+  "%O4%?.f\\t%0,%1,%2"
+  [(set_attr "type" "compare")
+   (set_attr "cond" "set_zn")
+   (set_attr "predicable" "yes,no,no,yes,no")
+   (set_attr "length" "4,4,4,8,8")])
 
-(define_insn "*noncommutative_binary_comparison"
-  [(set (match_operand:CC_ZN 0 "cc_set_register" "")
-	(match_operator:CC_ZN 5 "zn_compare_operator"
+(define_insn "*noncommutative_binary_cmp0_noout"
+  [(set (match_operand 0 "cc_set_register" "")
+	(match_operator 3 "zn_compare_operator"
 	  [(match_operator:SI 4 "noncommutative_operator"
-	     [(match_operand:SI 1 "register_operand" "c,c")
-	      (match_operand:SI 2 "nonmemory_operand" "cL,Cal")])
+	     [(match_operand:SI 1 "register_operand"   "r,r")
+	      (match_operand:SI 2 "nonmemory_operand" "rL,Cal")])
+	   (const_int 0)]))]
+  ""
+  "%O4.f\\t0,%1,%2"
+  [(set_attr "type" "compare")
+   (set_attr "cond" "set_zn")
+   (set_attr "length" "4,8")])
+
+;;rsub variants
+(define_insn "*rsub_cmp0"
+  [(set (match_operand 4 "cc_set_register" "")
+	(match_operator 3 "zn_compare_operator"
+	  [(minus:SI
+	    (match_operand:SI 1 "nonmemory_operand" "rL,Cal")
+	    (match_operand:SI 2 "register_operand"   "r,r"))
 	   (const_int 0)]))
-   (clobber (match_scratch:SI 3 "=X,X"))]
-  "TARGET_BARREL_SHIFTER || GET_CODE (operands[4]) == MINUS"
-  "%O4.f 0,%1,%2"
+   (set (match_operand:SI 0 "register_operand" "=r,r")
+	(minus:SI (match_dup 1) (match_dup 2)))]
+  ""
+  "rsub.f\\t%0,%2,%1"
+  [(set_attr "type" "compare")
+   (set_attr "cond" "set_zn")
+   (set_attr "length" "4,8")])
+
+(define_insn "*rsub_cmp0_noout"
+  [(set (match_operand 0 "cc_set_register" "")
+	(match_operator 3 "zn_compare_operator"
+	  [(minus:SI
+	    (match_operand:SI 1 "nonmemory_operand" "rL,Cal")
+	    (match_operand:SI 2 "register_operand"   "r,r"))
+	   (const_int 0)]))]
+  ""
+  "rsub.f\\t0,%2,%1"
   [(set_attr "type" "compare")
    (set_attr "cond" "set_zn")
    (set_attr "length" "4,8")])
@@ -5624,23 +5738,22 @@  archs4x, archs4xd, archs4xd_slow"
  DONE;
 })
 
-
 (define_insn "extzvsi"
-  [(set (match_operand:SI 0 "register_operand"                  "=r  , r  , r, r, r")
-	(zero_extract:SI (match_operand:SI 1 "register_operand"  "0  , r  , 0, 0, r")
-			 (match_operand:SI 2 "const_int_operand" "C3p, C3p, i, i, i")
-			 (match_operand:SI 3 "const_int_operand" "i  , i  , i, i, i")))]
+  [(set (match_operand:SI 0 "register_operand"                  "=r  ,  r,r,r")
+	(zero_extract:SI (match_operand:SI 1 "register_operand"  "0  ,  r,r,0")
+			 (match_operand:SI 2 "const_int_operand" "C3p,C3p,n,n")
+			 (match_operand:SI 3 "const_int_operand" "n  ,  n,n,n")))]
   "TARGET_HS && TARGET_BARREL_SHIFTER"
   {
    int assemble_op2 = (((INTVAL (operands[2]) - 1) & 0x1f) << 5) | (INTVAL (operands[3]) & 0x1f);
    operands[2] = GEN_INT (assemble_op2);
-   return "xbfu%? %0,%1,%2";
+   return "xbfu%?\\t%0,%1,%2";
   }
   [(set_attr "type"       "shift")
    (set_attr "iscompact"  "false")
-   (set_attr "length"     "4,4,4,8,8")
-   (set_attr "predicable" "yes,no,no,yes,no")
-   (set_attr "cond"       "canuse,nocond,nocond,canuse,nocond")])
+   (set_attr "length"     "4,4,8,8")
+   (set_attr "predicable" "yes,no,no,yes")
+   (set_attr "cond"       "canuse,nocond,nocond,canuse_limm")])
 
 (define_insn "kflag"
   [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand" "rL,I,Cal")]
@@ -6439,6 +6552,77 @@  archs4x, archs4xd, archs4xd_slow"
    (set_attr "type" "block")]
   )
 
+(define_insn "*add_shift"
+  [(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")))]
+  ""
+  "add%2%?\\t%0,%3,%1"
+  [(set_attr "length" "*,4,8")
+   (set_attr "predicable" "yes,no,no")
+   (set_attr "iscompact" "maybe,false,false")
+   (set_attr "cond" "canuse,nocond,nocond")])
+
+(define_insn "*add_shift2"
+  [(set (match_operand:SI 0 "register_operand" "=q,r,r")
+	(plus:SI (match_operand:SI 1 "nonmemory_operand"  "0,r,Cal")
+		 (ashift:SI (match_operand:SI 2 "register_operand" "q,r,r")
+			    (match_operand:SI 3 "_1_2_3_operand" ""))))]
+  ""
+  "add%3%?\\t%0,%1,%2"
+  [(set_attr "length" "*,4,8")
+   (set_attr "predicable" "yes,no,no")
+   (set_attr "iscompact" "maybe,false,false")
+   (set_attr "cond" "canuse,nocond,nocond")])
+
+(define_insn "*sub_shift"
+  [(set (match_operand:SI 0"register_operand" "=r,r,r")
+	 (minus:SI (match_operand:SI 1 "nonmemory_operand" "0,r,Cal")
+		   (ashift:SI (match_operand:SI 2 "register_operand" "r,r,r")
+			      (match_operand:SI 3 "_1_2_3_operand" ""))))]
+  ""
+  "sub%3\\t%0,%1,%2"
+  [(set_attr "length" "4,4,8")
+   (set_attr "cond" "canuse,nocond,nocond")
+   (set_attr "predicable" "yes,no,no")])
+
+(define_insn "*sub_shift_cmp0_noout"
+  [(set (match_operand 0 "cc_set_register" "")
+	(compare:CC
+	 (minus:SI (match_operand:SI 1 "register_operand" "r")
+		   (ashift:SI (match_operand:SI 2 "register_operand" "r")
+			      (match_operand:SI 3 "_1_2_3_operand" "")))
+	 (const_int 0)))]
+  ""
+  "sub%3.f\\t0,%1,%2"
+  [(set_attr "length" "4")])
+
+(define_insn "*compare_si_ashiftsi"
+  [(set (match_operand 0 "cc_set_register" "")
+	(compare:CC (match_operand:SI 1 "register_operand" "r")
+		    (ashift:SI (match_operand:SI 2 "register_operand" "r")
+			       (match_operand:SI 3 "_1_2_3_operand" ""))))]
+  ""
+  "sub%3.f\\t0,%1,%2"
+  [(set_attr "length" "4")])
+
+;; Convert the sequence
+;;  asl rd,rn,_1_2_3
+;;  cmp ra,rd
+;; into
+;;  sub{123}.f 0,ra,rn
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(ashift:SI (match_operand:SI 1 "register_operand" "")
+		   (match_operand:SI 2 "_1_2_3_operand" "")))
+   (set (reg:CC CC_REG)
+	(compare:CC (match_operand:SI 3 "register_operand" "")
+		    (match_dup 0)))]
+  "peep2_reg_dead_p (2, operands[0])"
+  [(set (reg:CC CC_REG) (compare:CC (match_dup 3)
+				    (ashift:SI (match_dup 1) (match_dup 2))))])
+
 ;; include the arc-FPX instructions
 (include "fpx.md")
 
diff --git a/gcc/config/arc/predicates.md b/gcc/config/arc/predicates.md
index 38651f79bf4..0abfc839b07 100644
--- a/gcc/config/arc/predicates.md
+++ b/gcc/config/arc/predicates.md
@@ -522,7 +522,7 @@ 
 	return FALSE;
     }
 
-  if (REGNO (op) != 61)
+  if (REGNO (op) != CC_REG)
     return FALSE;
   if (mode == rmode
       || (mode == CC_ZNmode && rmode == CC_Zmode)
@@ -609,7 +609,9 @@ 
 )
 
 (define_predicate "noncommutative_operator"
-  (ior (match_code "minus,ashift,ashiftrt,lshiftrt,rotatert")
+  (ior (and (match_code "ashift,ashiftrt,lshiftrt,rotatert")
+	    (match_test "TARGET_BARREL_SHIFTER"))
+       (match_code "minus")
        (and (match_code "ss_minus")
 	    (match_test "TARGET_ARC700 || TARGET_EA_SET")))
 )