predicates.md (shiftable_operator_strict_it): New predicate.
authorKyrylo Tkachov <kyrylo.tkachov@arm.com>
Mon, 22 Jul 2013 10:47:26 +0000 (10:47 +0000)
committerKyrylo Tkachov <ktkachov@gcc.gnu.org>
Mon, 22 Jul 2013 10:47:26 +0000 (10:47 +0000)
2013-07-22  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

* config/arm/predicates.md (shiftable_operator_strict_it):
New predicate.
* config/arm/thumb2.md (thumb_andsi_not_shiftsi_si):
Disable cond_exec version for arm_restrict_it.
(thumb2_smaxsi3): Convert to generate cond_exec.
(thumb2_sminsi3): Likewise.
(thumb32_umaxsi3): Likewise.
(thumb2_uminsi3): Likewise.
(thumb2_abssi2): Adjust constraints for arm_restrict_it.
(thumb2_neg_abssi2): Likewise.
(thumb2_mov_scc): Add alternative for 16-bit encoding.
(thumb2_movsicc_insn): Adjust alternatives.
(thumb2_mov_negscc): Disable for arm_restrict_it.
(thumb2_mov_negscc_strict_it): New pattern.
(thumb2_mov_notscc_strict_it): New pattern.
(thumb2_mov_notscc): Disable for arm_restrict_it.
(thumb2_ior_scc): Likewise.
(thumb2_ior_scc_strict_it): New pattern.
(thumb2_cond_move): Adjust for arm_restrict_it.
(thumb2_cond_arith): Disable for arm_restrict_it.
(thumb2_cond_arith_strict_it): New pattern.
(thumb2_cond_sub): Adjust for arm_restrict_it.
(thumb2_movcond): Likewise.
(thumb2_extendqisi_v6): Disable cond_exec variant for arm_restrict_it.
(thumb2_zero_extendhisi2_v6): Likewise.
(thumb2_zero_extendqisi2_v6): Likewise.
(orsi_notsi_si): Likewise.
(orsi_not_shiftsi_si): Likewise.

From-SVN: r201122

gcc/ChangeLog
gcc/config/arm/predicates.md
gcc/config/arm/thumb2.md

index 98cc565..b07b09a 100644 (file)
@@ -1,3 +1,34 @@
+2013-07-22  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
+
+       * config/arm/predicates.md (shiftable_operator_strict_it):
+       New predicate.
+       * config/arm/thumb2.md (thumb_andsi_not_shiftsi_si):
+       Disable cond_exec version for arm_restrict_it.
+       (thumb2_smaxsi3): Convert to generate cond_exec.
+       (thumb2_sminsi3): Likewise.
+       (thumb32_umaxsi3): Likewise.
+       (thumb2_uminsi3): Likewise.
+       (thumb2_abssi2): Adjust constraints for arm_restrict_it.
+       (thumb2_neg_abssi2): Likewise.
+       (thumb2_mov_scc): Add alternative for 16-bit encoding.
+       (thumb2_movsicc_insn): Adjust alternatives.
+       (thumb2_mov_negscc): Disable for arm_restrict_it.
+       (thumb2_mov_negscc_strict_it): New pattern.
+       (thumb2_mov_notscc_strict_it): New pattern.
+       (thumb2_mov_notscc): Disable for arm_restrict_it.
+       (thumb2_ior_scc): Likewise.
+       (thumb2_ior_scc_strict_it): New pattern.
+       (thumb2_cond_move): Adjust for arm_restrict_it.
+       (thumb2_cond_arith): Disable for arm_restrict_it.
+       (thumb2_cond_arith_strict_it): New pattern.
+       (thumb2_cond_sub): Adjust for arm_restrict_it.
+       (thumb2_movcond): Likewise.
+       (thumb2_extendqisi_v6): Disable cond_exec variant for arm_restrict_it.
+       (thumb2_zero_extendhisi2_v6): Likewise.
+       (thumb2_zero_extendqisi2_v6): Likewise.
+       (orsi_notsi_si): Likewise.
+       (orsi_not_shiftsi_si): Likewise.
+
 2013-07-22  Georg-Johann Lay  <avr@gjlay.de>
 
        * config/avr/avr.c (avr_out_xload): No SBIS around LPM so that
index f4a4515..29e1e5c 100644 (file)
   (and (match_code "plus,minus,ior,xor,and")
        (match_test "mode == GET_MODE (op)")))
 
+(define_special_predicate "shiftable_operator_strict_it"
+  (and (match_code "plus,and")
+       (match_test "mode == GET_MODE (op)")))
+
 ;; True for logical binary operators.
 (define_special_predicate "logical_binary_operator"
   (and (match_code "ior,xor,and")
index e36b436..8b184a8 100644 (file)
   "TARGET_THUMB2"
   "bic%?\\t%0, %1, %2%S4"
   [(set_attr "predicable" "yes")
+   (set_attr "predicable_short_it" "no")
    (set_attr "shift" "2")
    (set_attr "type" "arlo_shift")]
 )
 
+;; We use the '0' constraint for operand 1 because reload should
+;; be smart enough to generate an appropriate move for the r/r/r case.
 (define_insn_and_split "*thumb2_smaxsi3"
-  [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
-       (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
-                (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
+  [(set (match_operand:SI          0 "s_register_operand" "=r,l,r")
+       (smax:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
+                (match_operand:SI 2 "arm_rhs_operand"    "r,Py,I")))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_THUMB2"
-  "#"
-  ; cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %2
-  ; cmp\\t%1, %2\;it\\tge\;movge\\t%0, %1
-  ; cmp\\t%1, %2\;ite\\tge\;movge\\t%0, %1\;movlt\\t%0, %2
-  "TARGET_THUMB2"
+   "TARGET_THUMB2"
+   "#"
+   ; cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %2
+  "TARGET_THUMB2 && reload_completed"
   [(set (reg:CC CC_REGNUM)
         (compare:CC (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-        (if_then_else:SI (ge:SI (reg:CC CC_REGNUM) (const_int 0))
-                         (match_dup 1)
-                         (match_dup 2)))]
+   (cond_exec (lt:SI (reg:CC CC_REGNUM) (const_int 0))
+              (set (match_dup 0)
+                   (match_dup 2)))]
   ""
   [(set_attr "conds" "clob")
-   (set_attr "length" "10,10,14")]
+   (set_attr "enabled_for_depr_it" "yes,yes,no")
+   (set_attr "length" "6,6,10")]
 )
 
 (define_insn_and_split "*thumb2_sminsi3"
-  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
-       (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
-                (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
+  [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
+       (smin:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
+                (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_THUMB2"
   "#"
-   ; cmp\\t%1, %2\;it\\tge\;movge\\t%0, %2
-   ; cmp\\t%1, %2\;it\\tlt\;movlt\\t%0, %1
-   ; cmp\\t%1, %2\;ite\\tlt\;movlt\\t%0, %1\;movge\\t%0, %2"
-  "TARGET_THUMB2"
+  ; cmp\\t%1, %2\;it\\tge\;movge\\t%0, %2
+  "TARGET_THUMB2 && reload_completed"
   [(set (reg:CC CC_REGNUM)
         (compare:CC (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-        (if_then_else:SI (lt:SI (reg:CC CC_REGNUM) (const_int 0))
-                         (match_dup 1)
-                         (match_dup 2)))]
+   (cond_exec (ge:SI (reg:CC CC_REGNUM) (const_int 0))
+              (set (match_dup 0)
+                   (match_dup 2)))]
   ""
   [(set_attr "conds" "clob")
-   (set_attr "length" "10,10,14")]
+   (set_attr "enabled_for_depr_it" "yes,yes,no")
+   (set_attr "length" "6,6,10")]
 )
 
 (define_insn_and_split "*thumb32_umaxsi3"
-  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
-       (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
-                (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
-   (clobber (reg:CC CC_REGNUM))]
+  [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
+       (umax:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
+                (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
+  (clobber (reg:CC CC_REGNUM))]
   "TARGET_THUMB2"
   "#"
-   ; cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %2
-   ; cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %1
-   ; cmp\\t%1, %2\;ite\\tcs\;movcs\\t%0, %1\;movcc\\t%0, %2"
-  "TARGET_THUMB2"
+  ; cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %2
+  "TARGET_THUMB2 && reload_completed"
   [(set (reg:CC CC_REGNUM)
         (compare:CC (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-        (if_then_else:SI (geu:SI (reg:CC CC_REGNUM) (const_int 0))
-                         (match_dup 1)
-                         (match_dup 2)))]
+   (cond_exec (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
+              (set (match_dup 0)
+                   (match_dup 2)))]
   ""
   [(set_attr "conds" "clob")
-   (set_attr "length" "10,10,14")]
+   (set_attr "length" "6,6,10")
+   (set_attr "enabled_for_depr_it" "yes,yes,no")]
 )
 
 (define_insn_and_split "*thumb2_uminsi3"
-  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
-       (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
-                (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
+  [(set (match_operand:SI 0 "s_register_operand" "=r,l,r")
+       (umin:SI (match_operand:SI 1 "s_register_operand" "%0,0,0")
+                (match_operand:SI 2 "arm_rhs_operand" "r,Py,I")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_THUMB2"
   "#"
-   ; cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %2
-   ; cmp\\t%1, %2\;it\\tcc\;movcc\\t%0, %1
-   ; cmp\\t%1, %2\;ite\\tcc\;movcc\\t%0, %1\;movcs\\t%0, %2"
-  "TARGET_THUMB2"
+  ; cmp\\t%1, %2\;it\\tcs\;movcs\\t%0, %2
+  "TARGET_THUMB2 && reload_completed"
   [(set (reg:CC CC_REGNUM)
         (compare:CC (match_dup 1) (match_dup 2)))
-   (set (match_dup 0)
-        (if_then_else:SI (ltu:SI (reg:CC CC_REGNUM) (const_int 0))
-                         (match_dup 1)
-                         (match_dup 2)))]
+   (cond_exec (geu:SI (reg:CC CC_REGNUM) (const_int 0))
+              (set (match_dup 0)
+                   (match_dup 2)))]
   ""
   [(set_attr "conds" "clob")
-   (set_attr "length" "10,10,14")]
+   (set_attr "length" "6,6,10")
+   (set_attr "enabled_for_depr_it" "yes,yes,no")]
 )
 
 ;; Thumb-2 does not have rsc, so use a clever trick with shifter operands.
 )
 
 (define_insn_and_split "*thumb2_abssi2"
-  [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
-       (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
+  [(set (match_operand:SI         0 "s_register_operand" "=&r,l,r")
+       (abs:SI (match_operand:SI 1 "s_register_operand" "r,0,0")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_THUMB2"
   "#"
-   ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
    ; eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31
+   ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
+   ; cmp\\t%0, #0\;it\tlt\;rsblt\\t%0, %0, #0
   "&& reload_completed"
   [(const_int 0)]
   {
-    /* if (which_alternative == 0) */
     if (REGNO(operands[0]) == REGNO(operands[1]))
       {
        rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
       }
     DONE;
   }
-  [(set_attr "conds" "clob,*")
+  [(set_attr "conds" "*,clob,clob")
    (set_attr "shift" "1")
-   (set_attr "predicable" "no, yes")
+   (set_attr "predicable" "yes,no,no")
+   (set_attr "predicable_short_it" "no")
+   (set_attr "enabled_for_depr_it" "yes,yes,no")
    (set_attr "ce_count" "2")
-   (set_attr "length" "10,8")]
+   (set_attr "length" "8,6,10")]
 )
 
 (define_insn_and_split "*thumb2_neg_abssi2"
-  [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
-       (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
+  [(set (match_operand:SI 0 "s_register_operand" "=&r,l,r")
+       (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "r,0,0"))))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_THUMB2"
   "#"
+   ; eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31
+   ; cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0
    ; cmp\\t%0, #0\;it\\tgt\;rsbgt\\t%0, %0, #0
-   ; eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
   "&& reload_completed"
   [(const_int 0)]
   {
-    /* if (which_alternative == 0) */
     if (REGNO(operands[0]) == REGNO(operands[1]))
       {
        rtx cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);
       }
     DONE;
   }
-  [(set_attr "conds" "clob,*")
+  [(set_attr "conds" "*,clob,clob")
    (set_attr "shift" "1")
-   (set_attr "predicable" "no, yes")
+   (set_attr "predicable" "yes,no,no")
+   (set_attr "enabled_for_depr_it" "yes,yes,no")
+   (set_attr "predicable_short_it" "no")
    (set_attr "ce_count" "2")
-   (set_attr "length" "10,8")]
+   (set_attr "length" "8,6,10")]
 )
 
 ;; We have two alternatives here for memory loads (and similarly for stores)
 )
 
 (define_insn_and_split "*thumb2_mov_scc"
-  [(set (match_operand:SI 0 "s_register_operand" "=r")
+  [(set (match_operand:SI 0 "s_register_operand" "=l,r")
        (match_operator:SI 1 "arm_comparison_operator"
         [(match_operand 2 "cc_register" "") (const_int 0)]))]
   "TARGET_THUMB2"
                          (const_int 0)))]
   ""
   [(set_attr "conds" "use")
-   (set_attr "length" "10")]
+   (set_attr "enabled_for_depr_it" "yes,no")
+   (set_attr "length" "8,10")]
 )
 
 (define_insn_and_split "*thumb2_mov_negscc"
   [(set (match_operand:SI 0 "s_register_operand" "=r")
        (neg:SI (match_operator:SI 1 "arm_comparison_operator"
                 [(match_operand 2 "cc_register" "") (const_int 0)])))]
-  "TARGET_THUMB2"
+  "TARGET_THUMB2 && !arm_restrict_it"
   "#"   ; "ite\\t%D1\;mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
   "TARGET_THUMB2"
   [(set (match_dup 0)
    (set_attr "length" "10")]
 )
 
+(define_insn_and_split "*thumb2_mov_negscc_strict_it"
+  [(set (match_operand:SI 0 "low_register_operand" "=l")
+       (neg:SI (match_operator:SI 1 "arm_comparison_operator"
+                [(match_operand 2 "cc_register" "") (const_int 0)])))]
+  "TARGET_THUMB2 && arm_restrict_it"
+  "#"   ; ";mvn\\t%0, #0 ;it\\t%D1\;mov%D1\\t%0, #0\"
+  "&& reload_completed"
+  [(set (match_dup 0)
+        (match_dup 3))
+   (cond_exec (match_dup 4)
+              (set (match_dup 0)
+                   (const_int 0)))]
+  {
+    operands[3] = GEN_INT (~0);
+    enum machine_mode mode = GET_MODE (operands[2]);
+    enum rtx_code rc = GET_CODE (operands[1]);
+
+    if (mode == CCFPmode || mode == CCFPEmode)
+      rc = reverse_condition_maybe_unordered (rc);
+    else
+      rc = reverse_condition (rc);
+    operands[4] = gen_rtx_fmt_ee (rc, VOIDmode, operands[2], const0_rtx);
+
+  }
+  [(set_attr "conds" "use")
+   (set_attr "length" "8")]
+)
+
 (define_insn_and_split "*thumb2_mov_notscc"
   [(set (match_operand:SI 0 "s_register_operand" "=r")
        (not:SI (match_operator:SI 1 "arm_comparison_operator"
                 [(match_operand 2 "cc_register" "") (const_int 0)])))]
-  "TARGET_THUMB2"
+  "TARGET_THUMB2 && !arm_restrict_it"
   "#"   ; "ite\\t%D1\;mvn%D1\\t%0, #0\;mvn%d1\\t%0, #1"
   "TARGET_THUMB2"
   [(set (match_dup 0)
    (set_attr "length" "10")]
 )
 
+(define_insn_and_split "*thumb2_mov_notscc_strict_it"
+  [(set (match_operand:SI 0 "low_register_operand" "=l")
+        (not:SI (match_operator:SI 1 "arm_comparison_operator"
+                 [(match_operand 2 "cc_register" "") (const_int 0)])))]
+  "TARGET_THUMB2 && arm_restrict_it"
+  "#"   ; "mvn %0, #0 ; it%d1 ; lsl%d1 %0, %0, #1"
+  "&& reload_completed"
+  [(set (match_dup 0)
+        (match_dup 3))
+   (cond_exec (match_dup 4)
+              (set (match_dup 0)
+                   (ashift:SI (match_dup 0)
+                              (const_int 1))))]
+  {
+    operands[3] = GEN_INT (~0);
+    operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
+                                  VOIDmode, operands[2], const0_rtx);
+  }
+  [(set_attr "conds" "use")
+   (set_attr "length" "8")]
+)
+
 (define_insn_and_split "*thumb2_movsicc_insn"
-  [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r,r,r,r,r,r,r,r,l")
+  [(set (match_operand:SI 0 "s_register_operand" "=l,l,r,r,r,r,r,r,r,r,r")
        (if_then_else:SI
         (match_operator 3 "arm_comparison_operator"
          [(match_operand 4 "cc_register" "") (const_int 0)])
-        (match_operand:SI 1 "arm_not_operand" "0 ,Py,0 ,0,rI,K,rI,rI,K ,K,r,lPy")
-        (match_operand:SI 2 "arm_not_operand" "Py,0 ,rI,K,0 ,0,rI,K ,rI,K,r,lPy")))]
+        (match_operand:SI 1 "arm_not_operand" "0 ,lPy,0 ,0,rI,K,rI,rI,K ,K,r")
+        (match_operand:SI 2 "arm_not_operand" "lPy,0 ,rI,K,0 ,0,rI,K ,rI,K,r")))]
   "TARGET_THUMB2"
   "@
    it\\t%D3\;mov%D3\\t%0, %2
    #
    #
    #
-   #
    #"
    ; alt 6: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
    ; alt 7: ite\\t%d3\;mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
    ; alt 8: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
    ; alt 9: ite\\t%d3\;mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2
    ; alt 10: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2
-   ; alt 11: ite\\t%d3\;mov%d3\\t%0, %1\;mov%D3\\t%0, %2"
   "&& reload_completed"
   [(const_int 0)]
   {
                                                operands[2])));
     DONE;
   }
-  [(set_attr "length" "4,4,6,6,6,6,10,10,10,10,6,6")
-   (set_attr "enabled_for_depr_it" "yes,yes,no,no,no,no,no,no,no,no,yes,yes")
+  [(set_attr "length" "4,4,6,6,6,6,10,10,10,10,6")
+   (set_attr "enabled_for_depr_it" "yes,yes,no,no,no,no,no,no,no,no,yes")
    (set_attr "conds" "use")]
 )
 
        (ior:SI (match_operator:SI 1 "arm_comparison_operator"
                 [(match_operand 2 "cc_register" "") (const_int 0)])
                (match_operand:SI 3 "s_register_operand" "0,?r")))]
-  "TARGET_THUMB2"
+  "TARGET_THUMB2 && !arm_restrict_it"
   "@
    it\\t%d1\;orr%d1\\t%0, %3, #1
    #"
    (set_attr "length" "6,10")]
 )
 
+(define_insn "*thumb2_ior_scc_strict_it"
+  [(set (match_operand:SI 0 "s_register_operand" "=l,l")
+       (ior:SI (match_operator:SI 2 "arm_comparison_operator"
+                [(match_operand 3 "cc_register" "") (const_int 0)])
+               (match_operand:SI 1 "s_register_operand" "0,?l")))]
+  "TARGET_THUMB2 && arm_restrict_it"
+  "@
+   it\\t%d2\;mov%d2\\t%0, #1\;it\\t%d2\;orr%d2\\t%0, %1
+   mov\\t%0, #1\;orr\\t%0, %1\;it\\t%D2\;mov%D2\\t%0, %1"
+  [(set_attr "conds" "use")
+   (set_attr "length" "8")]
+)
+
 (define_insn "*thumb2_cond_move"
   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
        (if_then_else:SI (match_operator 3 "equality_operator"
        output_asm_insn (\"it\\t%D4\", operands);
        break;
       case 2:
-       output_asm_insn (\"ite\\t%D4\", operands);
+       if (arm_restrict_it)
+         output_asm_insn (\"it\\t%D4\", operands);
+       else
+         output_asm_insn (\"ite\\t%D4\", operands);
        break;
       default:
        abort();
       }
     if (which_alternative != 0)
-      output_asm_insn (\"mov%D4\\t%0, %1\", operands);
+      {
+        output_asm_insn (\"mov%D4\\t%0, %1\", operands);
+        if (arm_restrict_it && which_alternative == 2)
+          output_asm_insn (\"it\\t%d4\", operands);
+      }
     if (which_alternative != 1)
       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
     return \"\";
            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
           (match_operand:SI 1 "s_register_operand" "0,?r")]))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_THUMB2"
+  "TARGET_THUMB2 && !arm_restrict_it"
   "*
     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
       return \"%i5\\t%0, %1, %2, lsr #31\";
    (set_attr "length" "14")]
 )
 
+(define_insn_and_split "*thumb2_cond_arith_strict_it"
+  [(set (match_operand:SI 0 "s_register_operand" "=l")
+        (match_operator:SI 5 "shiftable_operator_strict_it"
+        [(match_operator:SI 4 "arm_comparison_operator"
+           [(match_operand:SI 2 "s_register_operand" "r")
+           (match_operand:SI 3 "arm_rhs_operand" "rI")])
+          (match_operand:SI 1 "s_register_operand" "0")]))
+   (clobber (reg:CC CC_REGNUM))]
+  "TARGET_THUMB2 && arm_restrict_it"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+  {
+    if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
+      {
+        /*  %i5 %0, %1, %2, lsr #31  */
+        rtx shifted_op = gen_rtx_LSHIFTRT (SImode, operands[2], GEN_INT (31));
+        rtx op = NULL_RTX;
+
+        switch (GET_CODE (operands[5]))
+          {
+          case AND:
+            op = gen_rtx_AND (SImode, shifted_op, operands[1]);
+            break;
+           case PLUS:
+            op = gen_rtx_PLUS (SImode, shifted_op, operands[1]);
+            break;
+          default: gcc_unreachable ();
+          }
+        emit_insn (gen_rtx_SET (VOIDmode, operands[0], op));
+        DONE;
+      }
+
+    /*  "cmp  %2, %3"  */
+    emit_insn (gen_rtx_SET (VOIDmode,
+                               gen_rtx_REG (CCmode, CC_REGNUM),
+                               gen_rtx_COMPARE (CCmode, operands[2], operands[3])));
+
+    if (GET_CODE (operands[5]) == AND)
+      {
+        /*  %i5  %0, %1, #1
+            it%D4
+            mov%D4  %0, #0  */
+        enum rtx_code rc = reverse_condition (GET_CODE (operands[4]));
+        emit_insn (gen_rtx_SET (VOIDmode, operands[0], gen_rtx_AND (SImode, operands[1], GEN_INT (1))));
+        emit_insn (gen_rtx_COND_EXEC (VOIDmode,
+                                      gen_rtx_fmt_ee (rc, VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
+                                      gen_rtx_SET (VOIDmode, operands[0], const0_rtx)));
+        DONE;
+      }
+    else
+      {
+        /*  it\\t%d4
+            %i5%d4\\t%0, %1, #1   */
+        emit_insn (gen_rtx_COND_EXEC (VOIDmode, gen_rtx_fmt_ee (GET_CODE (operands[4]),
+                                                                VOIDmode,
+                                                                gen_rtx_REG (CCmode, CC_REGNUM), const0_rtx),
+                                                gen_rtx_SET(VOIDmode, operands[0],
+                                                            gen_rtx_PLUS (SImode,
+                                                                          operands[1],
+                                                                          GEN_INT (1)))));
+        DONE;
+      }
+     FAIL;
+  }
+  [(set_attr "conds" "clob")
+   (set_attr "length" "12")]
+)
+
 (define_insn "*thumb2_cond_sub"
-  [(set (match_operand:SI 0 "s_register_operand" "=r,r")
-        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
+  [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts")
+        (minus:SI (match_operand:SI 1 "s_register_operand" "0,?Ts")
                  (match_operator:SI 4 "arm_comparison_operator"
                    [(match_operand:SI 2 "s_register_operand" "r,r")
                    (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
     output_asm_insn (\"cmp\\t%2, %3\", operands);
     if (which_alternative != 0)
       {
-       output_asm_insn (\"ite\\t%D4\", operands);
-       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
+       if (arm_restrict_it)
+         {
+           output_asm_insn (\"mov\\t%0, %1\", operands);
+           output_asm_insn (\"it\\t%d4\", operands);
+         }
+       else
+       {
+         output_asm_insn (\"ite\\t%D4\", operands);
+         output_asm_insn (\"mov%D4\\t%0, %1\", operands);
+       }
       }
     else
       output_asm_insn (\"it\\t%d4\", operands);
 )
 
 (define_insn "*thumb2_movcond"
-  [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
+  [(set (match_operand:SI 0 "s_register_operand" "=Ts,Ts,Ts")
        (if_then_else:SI
         (match_operator 5 "arm_comparison_operator"
          [(match_operand:SI 3 "s_register_operand" "r,r,r")
           (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
-        (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
-        (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
+        (match_operand:SI 1 "arm_rhs_operand" "0,TsI,?TsI")
+        (match_operand:SI 2 "arm_rhs_operand" "TsI,0,TsI")))
    (clobber (reg:CC CC_REGNUM))]
   "TARGET_THUMB2"
   "*
       output_asm_insn (\"it\\t%d5\", operands);
       break;
     case 2:
-      output_asm_insn (\"ite\\t%d5\", operands);
+      if (arm_restrict_it)
+        {
+          output_asm_insn (\"mov\\t%0, %1\", operands);
+          output_asm_insn (\"it\\t%D5\", operands);
+        }
+      else
+        output_asm_insn (\"ite\\t%d5\", operands);
       break;
     default:
       abort();
     }
-  if (which_alternative != 0)
+  if (which_alternative != 0 && !(arm_restrict_it && which_alternative == 2))
     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
   if (which_alternative != 1)
     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
    ldr%(sb%)\\t%0, %1"
   [(set_attr "type" "extend,load_byte")
    (set_attr "predicable" "yes")
+   (set_attr "predicable_short_it" "no")
    (set_attr "pool_range" "*,4094")
    (set_attr "neg_pool_range" "*,250")]
 )
    ldr%(h%)\\t%0, %1"
   [(set_attr "type" "extend,load_byte")
    (set_attr "predicable" "yes")
+   (set_attr "predicable_short_it" "no")
    (set_attr "pool_range" "*,4094")
    (set_attr "neg_pool_range" "*,250")]
 )
    ldr%(b%)\\t%0, %1\\t%@ zero_extendqisi2"
   [(set_attr "type" "extend,load_byte")
    (set_attr "predicable" "yes")
+   (set_attr "predicable_short_it" "no")
    (set_attr "pool_range" "*,4094")
    (set_attr "neg_pool_range" "*,250")]
 )
                (match_operand:SI 1 "s_register_operand" "r")))]
   "TARGET_THUMB2"
   "orn%?\\t%0, %1, %2"
-  [(set_attr "predicable" "yes")]
+  [(set_attr "predicable" "yes")
+   (set_attr "predicable_short_it" "no")]
 )
 
 (define_insn "*orsi_not_shiftsi_si"
   "TARGET_THUMB2"
   "orn%?\\t%0, %1, %2%S4"
   [(set_attr "predicable" "yes")
+   (set_attr "predicable_short_it" "no")
    (set_attr "shift" "2")
    (set_attr "type" "arlo_shift")]
 )