arm.md (arm_adddi3, [...]): Merge with splitters to create define_insn_and_split...
authorRichard Earnshaw <rearnsha@arm.com>
Mon, 27 Nov 2000 16:01:29 +0000 (16:01 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Mon, 27 Nov 2000 16:01:29 +0000 (16:01 +0000)
* arm.md (arm_adddi3, adddi_sesidi_di, adddi_zesidi_di, arm_addsi3,
arm_subsi3_insn, anddi_zesidi_di, arm_andsi3_insn, anddi_notdi_di,
anddi_notzesidi_di, anddi_notsesidi_di, arm_iorsi3,
one_cmpldi2): Merge with splitters to create define_insn_and_split
patterns.  Remove redundant splits.
(peephole2 for add:SI of invalid immediate): New.
(peephole2 for minus:SI of invalid immediate): New.
(peephole2 for ior:SI of invalid immediate): New.
(peephole for merge of move and compare): Convert ot peephole2.
(addsf3, adddf3): Mark as commutative.

* arm.md (thumb peephole for merging stack adjustments): Convert to
peephole2.

From-SVN: r37796

gcc/ChangeLog
gcc/config/arm/arm.md

index 0a7aeb6b4259a19f9fc7209f8604c288c25fe641..a1970f75ea6d2b1efc7ab2340400597509286f57 100644 (file)
@@ -1,3 +1,19 @@
+2000-11-27  Richard Earnshaw  <rearnsha@arm.com>
+
+       * arm.md (arm_adddi3, adddi_sesidi_di, adddi_zesidi_di, arm_addsi3,
+       arm_subsi3_insn, anddi_zesidi_di, arm_andsi3_insn, anddi_notdi_di,
+       anddi_notzesidi_di, anddi_notsesidi_di, arm_iorsi3, 
+       one_cmpldi2): Merge with splitters to create define_insn_and_split
+       patterns.  Remove redundant splits.
+       (peephole2 for add:SI of invalid immediate): New.
+       (peephole2 for minus:SI of invalid immediate): New.
+       (peephole2 for ior:SI of invalid immediate): New.
+       (peephole for merge of move and compare): Convert ot peephole2.
+       (addsf3, adddf3): Mark as commutative.
+
+       * arm.md (thumb peephole for merging stack adjustments): Convert to
+       peephole2.
+
 2000-11-27  Bernd Schmidt  <bernds@redhat.co.uk>
 
        * haifa-sched.c (print_pattern): Prettier output for COND_EXEC.
index 793f1a47fe8130ebcce505e87e461d77f5cda6a3..ddb2640869012ca13714c11db313385400cbecb3 100644 (file)
    (LAST_ARM_REGNUM 15)
    (CC_REGNUM       24)]
 )
-\f
-;;---------------------------------------------------------------------------
+
+;; Addition insns.
 
 ;; Note: For DImode insns, there is normally no reason why operands should
 ;; not be in the same register, what we don't want is for something being
 ;; written to partially overlap something that is an input.
 
-;; Split up 64bit addition so that the component insns can schedule
-;; independently.
-(define_split
-  [(set (match_operand:DI          0 "s_register_operand" "")
-       (plus:DI (match_operand:DI 1 "s_register_operand" "")
-                (match_operand:DI 2 "s_register_operand" "")))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_ARM && reload_completed
-  "
-  [(parallel [(set (reg:CC_C CC_REGNUM)
-                  (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
-                                (match_dup 1)))
-             (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
-   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
-                              (plus:SI (match_dup 4) (match_dup 5))))]
-  "
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-    operands[5] = gen_highpart (SImode, operands[2]);
-    operands[2] = gen_lowpart (SImode, operands[2]);
-  }"
-)
-
-;; The first insn created by this splitter must set the low part of
-;; operand0 as well as the carry bit in the CC register.  The second
-;; insn must compute the sum of the carry bit, the sign extension of
-;; operand 2 from 32 to 64 bits and the high part of operand 1.
-(define_split
-  [(set (match_operand:DI 0 "s_register_operand" "")
-       (plus:DI (sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
-                (match_operand:DI 1 "s_register_operand" "")))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_ARM && reload_completed
-  "
-  [(parallel [(set (reg:CC_C CC_REGNUM)
-                  (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
-                                (match_dup 1)))
-             (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
-   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
-                              (plus:SI (ashiftrt:SI (match_dup 2)
-                                                    (const_int 31))
-                                       (match_dup 4))))]
-  "
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-    operands[2] = gen_lowpart (SImode, operands[2]);
-  }"
-)
-
-; The first insn created by this splitter must set the low part of
-; operand0 as well as the carry bit in the CC register.  The second
-; insn must compute the sum of the carry bit and the high bits from
-; operand 1
-(define_split
-  [(set (match_operand:DI 0 "s_register_operand" "")
-       (plus:DI (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
-                (match_operand:DI 1 "s_register_operand" "")))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_ARM && reload_completed
-  "
-  [(parallel [(set (reg:CC_C CC_REGNUM)
-                  (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
-                                (match_dup 1)))
-             (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
-   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
-                              (plus:SI (match_dup 4) (const_int 0))))]
-  "
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-    operands[2] = gen_lowpart (SImode, operands[2]);
-  }"
-)
-
-;; Addition insns.
-
 (define_expand "adddi3"
  [(parallel
    [(set (match_operand:DI           0 "s_register_operand" "")
   [(set_attr "length" "4")]
 )
 
-(define_insn "*arm_adddi3"
+(define_insn_and_split "*arm_adddi3"
   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
        (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
                 (match_operand:DI 2 "s_register_operand" "r,  0")))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_ARM
-  "
+  "TARGET_ARM"
   "#"
+  "TARGET_ARM && reload_completed"
+  [(parallel [(set (reg:CC_C CC_REGNUM)
+                  (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
+                                (match_dup 1)))
+             (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
+   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
+                              (plus:SI (match_dup 4) (match_dup 5))))]
+  "
+  {
+    operands[3] = gen_highpart (SImode, operands[0]);
+    operands[0] = gen_lowpart (SImode, operands[0]);
+    operands[4] = gen_highpart (SImode, operands[1]);
+    operands[1] = gen_lowpart (SImode, operands[1]);
+    operands[5] = gen_highpart (SImode, operands[2]);
+    operands[2] = gen_lowpart (SImode, operands[2]);
+  }"
   [(set_attr "conds" "clob")
    (set_attr "length" "8")]
 )
 
-(define_insn "*adddi_sesidi_di"
+(define_insn_and_split "*adddi_sesidi_di"
   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
        (plus:DI (sign_extend:DI
                  (match_operand:SI 2 "s_register_operand" "r,r"))
                 (match_operand:DI 1 "s_register_operand" "r,0")))
    (clobber (reg:CC CC_REGNUM))]
-  "TARGET_ARM
-  "
+  "TARGET_ARM"
   "#"
+  "TARGET_ARM && reload_completed"
+  [(parallel [(set (reg:CC_C CC_REGNUM)
+                  (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
+                                (match_dup 1)))
+             (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
+   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
+                              (plus:SI (ashiftrt:SI (match_dup 2)
+                                                    (const_int 31))
+                                       (match_dup 4))))]
+  "
+  {
+    operands[3] = gen_highpart (SImode, operands[0]);
+    operands[0] = gen_lowpart (SImode, operands[0]);
+    operands[4] = gen_highpart (SImode, operands[1]);
+    operands[1] = gen_lowpart (SImode, operands[1]);
+    operands[2] = gen_lowpart (SImode, operands[2]);
+  }"
   [(set_attr "conds" "clob")
    (set_attr "length" "8")]
 )
 
-(define_insn "*adddi_zesidi_di"
+(define_insn_and_split "*adddi_zesidi_di"
   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
        (plus:DI (zero_extend:DI
                  (match_operand:SI 2 "s_register_operand" "r,r"))
                 (match_operand:DI 1 "s_register_operand" "r,0")))
-   (clobber (reg:CC CC_REGNUM))
-  ]
-  "TARGET_ARM
-  "
+   (clobber (reg:CC CC_REGNUM))]
+  "TARGET_ARM"
   "#"
+  "TARGET_ARM && reload_completed"
+  [(parallel [(set (reg:CC_C CC_REGNUM)
+                  (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
+                                (match_dup 1)))
+             (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
+   (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
+                              (plus:SI (match_dup 4) (const_int 0))))]
+  "
+  {
+    operands[3] = gen_highpart (SImode, operands[0]);
+    operands[0] = gen_lowpart (SImode, operands[0]);
+    operands[4] = gen_highpart (SImode, operands[1]);
+    operands[1] = gen_lowpart (SImode, operands[1]);
+    operands[2] = gen_lowpart (SImode, operands[2]);
+  }"
   [(set_attr "conds" "clob")
    (set_attr "length" "8")]
 )
   "
 )
 
-(define_split
-  [(set (match_operand:SI          0 "s_register_operand" "")
+; If there is a scratch available, this will be faster than synthesising the
+; addition.
+(define_peephole2
+  [(match_scratch:SI 3 "r")
+   (set (match_operand:SI          0 "s_register_operand" "")
        (plus:SI (match_operand:SI 1 "s_register_operand" "")
                 (match_operand:SI 2 "const_int_operand"  "")))]
   "TARGET_ARM &&
-  (!(const_ok_for_arm (INTVAL (operands[2]))
-   || const_ok_for_arm (-INTVAL (operands[2]))))"
-  [(clobber (const_int 0))]
-  "
-  arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
-                     operands[1], 0);
-  DONE;
-")
+   !(const_ok_for_arm (INTVAL (operands[2]))
+     || const_ok_for_arm (-INTVAL (operands[2])))
+    && const_ok_for_arm (~INTVAL (operands[2]))"
+  [(set (match_dup 3) (match_dup 2))
+   (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
+  ""
+)
 
-(define_insn "*arm_addsi3"
+(define_insn_and_split "*arm_addsi3"
   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
-       (plus:SI (match_operand:SI 1 "s_register_operand" "r, r,r")
+       (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
                 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
   "TARGET_ARM"
   "@
    add%?\\t%0, %1, %2
    sub%?\\t%0, %1, #%n2
    #"
+  "TARGET_ARM &&
+   GET_CODE (operands[2]) == CONST_INT
+   && !(const_ok_for_arm (INTVAL (operands[2]))
+        || const_ok_for_arm (-INTVAL (operands[2])))"
+  [(clobber (const_int 0))]
+  "
+  arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
+                     operands[1], 0);
+  DONE;
+  "
   [(set_attr "length" "4,4,16")
    (set_attr "predicable" "yes")]
 )
 
 ;; Reloading and elimination of the frame pointer can
 ;; sometimes cause this optimization to be missed.
-(define_peephole
+(define_peephole2
   [(set (match_operand:SI 0 "register_operand" "=l")
        (match_operand:SI 1 "const_int_operand" "M"))
    (set (match_dup 0)
    && REGNO (operands[2]) == STACK_POINTER_REGNUM 
    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
    && (INTVAL (operands[1]) & 3) == 0"
-  "add\\t%0, %2, %1"
-  [(set_attr "length" "2")]
+  [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
+  ""
 )
 
 (define_insn "*addsi3_compare0"
    (set_attr "length" "4,8")]
 )
 
-; If a constant is too big to fit in a single instruction then the constant
-; will be pre-loaded into a register taking at least two insns, we might be
-; able to merge it with an add, but it depends on the exact value.
-
-(define_split
-  [(set (match_operand:SI          0 "s_register_operand" "=r")
-       (plus:SI (match_operand:SI 1 "s_register_operand"  "r")
-                (match_operand:SI 2 "const_int_operand"   "n")))]
-  "TARGET_ARM
-    && (!(const_ok_for_arm (INTVAL (operands[2]))
-          || const_ok_for_arm (-INTVAL (operands[2]))))"
-  [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
-   (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
-  "
-  {
-    unsigned int val = (unsigned) INTVAL (operands[2]);
-    int i;
-    unsigned int temp;
-
-    /* This code is similar to the approach followed in movsi,
-       but it must generate exactly two insns.  */
-
-    for (i = 30; i >= 0; i -= 2)
-      {
-       if (val & (3 << i))
-         {
-           i -= 6;
-           if (i < 0)
-             i = 0;
-
-           if (const_ok_for_arm (temp = (val & ~(255 << i))))
-             {
-               val &= 255 << i;
-               break;
-             }
-
-           /* We might be able to do this as (larger number - small
-               number).  */
-           temp = ((val >> i) & 255) + 1;
-           if (temp > 255 && i < 24)
-             {
-               i += 2;
-               temp = ((val >> i) & 255) + 1;
-             }
-
-           if (const_ok_for_arm ((temp << i) - val))
-             {
-               i = temp << i;
-               temp = (unsigned) - (int) (i - val);
-               val = i;
-               break;
-             }
-
-           FAIL;
-         }
-      }
-
-    /* If we got here, we have found a way of doing it in two
-       instructions.  the two constants are in val and temp.  */
-    operands[2] = GEN_INT ((int) val);
-    operands[3] = GEN_INT ((int) temp);
-  }"
-)
-
 (define_insn "addsf3"
   [(set (match_operand:SF          0 "s_register_operand" "=f,f")
-       (plus:SF (match_operand:SF 1 "s_register_operand"  "f,f")
+       (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
                 (match_operand:SF 2 "fpu_add_operand"    "fG,H")))]
   "TARGET_ARM && TARGET_HARD_FLOAT"
   "@
 
 (define_insn "adddf3"
   [(set (match_operand:DF          0 "s_register_operand" "=f,f")
-       (plus:DF (match_operand:DF 1 "s_register_operand"  "f,f")
+       (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
                 (match_operand:DF 2 "fpu_add_operand"    "fG,H")))]
   "TARGET_ARM && TARGET_HARD_FLOAT"
   "@
   [(set_attr "length" "2")]
 )
 
-(define_insn "*arm_subsi3_insn"
+(define_insn_and_split "*arm_subsi3_insn"
   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
        (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
                  (match_operand:SI 2 "s_register_operand" "r,r")))]
   "@
    rsb%?\\t%0, %2, %1
    #"
-  [(set_attr "length" "4,16")
-   (set_attr "predicable" "yes")]
-)
-
-(define_split
-  [(set (match_operand:SI           0 "s_register_operand" "")
-       (minus:SI (match_operand:SI 1 "const_int_operand" "")
-                 (match_operand:SI 2 "s_register_operand" "")))]
-  "TARGET_ARM && (!const_ok_for_arm (INTVAL (operands[1])))"
+  "TARGET_ARM
+   && GET_CODE (operands[1]) == CONST_INT
+   && !const_ok_for_arm (INTVAL (operands[1]))"
   [(clobber (const_int 0))]
   "
   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
                      operands[2], 0);
   DONE;
   "
+  [(set_attr "length" "4,16")
+   (set_attr "predicable" "yes")]
+)
+
+(define_peephole2
+  [(match_scratch:SI 3 "r")
+   (set (match_operand:SI           0 "s_register_operand" "")
+       (minus:SI (match_operand:SI 1 "const_int_operand" "")
+                 (match_operand:SI 2 "s_register_operand" "")))]
+  "TARGET_ARM
+   && !const_ok_for_arm (INTVAL (operands[1]))
+   && const_ok_for_arm (~INTVAL (operands[1]))"
+  [(set (match_dup 3) (match_dup 1))
+   (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
+  ""
 )
 
 (define_insn "*subsi3_compare0"
   }"
 )
 
-(define_split
-  [(set (match_operand:DI 0 "s_register_operand" "")
-       (not:DI (match_operand:DI 1 "s_register_operand" "")))]
-  "TARGET_ARM && reload_completed"
-  [(set (match_dup 0) (not:SI (match_dup 1)))
-   (set (match_dup 2) (not:SI (match_dup 3)))]
-  "
-  {
-    operands[2] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[3] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-  }"
-)
-
-(define_split
-  [(set (match_operand:DI 0 "s_register_operand" "")
-       (and:DI
-         (not:DI (match_operand:DI 1 "s_register_operand" ""))
-         (match_operand:DI 2 "s_register_operand" "")))]
-  "TARGET_ARM && reload_completed"
-  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
-   (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
-  "
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-    operands[5] = gen_highpart (SImode, operands[2]);
-    operands[2] = gen_lowpart (SImode, operands[2]);
-  }"
-)
-
 (define_split
   [(set (match_operand:DI 0 "s_register_operand" "")
        (match_operator:DI 6 "logical_binary_operator"
   }"
 )
 
-(define_split
-  [(set (match_operand:DI 0 "s_register_operand" "")
-       (and:DI (not:DI (sign_extend:DI
-                       (match_operand:SI 2 "s_register_operand" "")))
-               (match_operand:DI 1 "s_register_operand" "")))]
-  "TARGET_ARM && reload_completed"
-  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
-   (set (match_dup 3) (and:SI (not:SI
-                               (ashiftrt:SI (match_dup 2) (const_int 31)))
-                              (match_dup 4)))]
-  "
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-    operands[2] = gen_lowpart (SImode, operands[2]);
-  }"
-)
-
-;; The zero extend of operand 2 clears the high word of the output
-;; operand.
-(define_split
-  [(set (match_operand:DI 0 "s_register_operand" "")
-       (and:DI
-         (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
-         (match_operand:DI 1 "s_register_operand" "")))]
-  "TARGET_ARM && reload_completed"
-  [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
-   (set (match_dup 3) (const_int 0))]
-  "
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-  }"
-)
-
 ;; The zero extend of operand 2 means we can just copy the high part of
 ;; operand1 into operand0.
 (define_split
   }"
 )
 
-;; (not (zero_extend ...)) allows us to just copy the high word from
-;; operand1 to operand0.
-(define_split
-  [(set (match_operand:DI 0 "s_register_operand" "")
-       (and:DI (not:DI (zero_extend:DI
-                       (match_operand:SI 2 "s_register_operand" "")))
-               (match_operand:DI 1 "s_register_operand" "")))]
-  "TARGET_ARM && operands[0] != operands[1] && reload_completed"
-  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
-   (set (match_dup 3) (match_dup 4))]
-  "
-  {
-    operands[3] = gen_highpart (SImode, operands[0]);
-    operands[0] = gen_lowpart (SImode, operands[0]);
-    operands[4] = gen_highpart (SImode, operands[1]);
-    operands[1] = gen_lowpart (SImode, operands[1]);
-    operands[2] = gen_lowpart (SImode, operands[2]);
-  }"
-)
-
 (define_insn "anddi3"
   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
        (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
   [(set_attr "length" "8")]
 )
 
-(define_insn "*anddi_zesidi_di"
+(define_insn_and_split "*anddi_zesidi_di"
   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
        (and:DI (zero_extend:DI
                 (match_operand:SI 2 "s_register_operand" "r,r"))
                (match_operand:DI 1 "s_register_operand" "?r,0")))]
   "TARGET_ARM"
   "#"
+  "TARGET_ARM && reload_completed"
+  ; The zero extend of operand 2 clears the high word of the output
+  ; operand.
+  [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
+   (set (match_dup 3) (const_int 0))]
+  "
+  {
+    operands[3] = gen_highpart (SImode, operands[0]);
+    operands[0] = gen_lowpart (SImode, operands[0]);
+    operands[1] = gen_lowpart (SImode, operands[1]);
+  }"
   [(set_attr "length" "8")]
 )
 
   "
 )
 
-(define_insn "*arm_andsi3_insn"
+(define_insn_and_split "*arm_andsi3_insn"
   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
        (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
                (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
    and%?\\t%0, %1, %2
    bic%?\\t%0, %1, #%B2
    #"
+  "TARGET_ARM
+   && GET_CODE (operands[2]) == CONST_INT
+   && !(const_ok_for_arm (INTVAL (operands[2]))
+       || const_ok_for_arm (~INTVAL (operands[2])))"
+  [(clobber (const_int 0))]
+  "
+  arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
+                      operands[1], 0);
+  DONE;
+  "
   [(set_attr "length" "4,4,16")
    (set_attr "predicable" "yes")]
 )
   [(set_attr "length" "2")]
 )
 
-(define_split
-  [(set (match_operand:SI         0 "s_register_operand" "")
-       (and:SI (match_operand:SI 1 "s_register_operand" "")
-               (match_operand:SI 2 "const_int_operand" "")))]
-  "TARGET_ARM
-   && (!(const_ok_for_arm (INTVAL (operands[2]))
-        || const_ok_for_arm (~INTVAL (operands[2]))))"
-  [(clobber (const_int 0))]
-  "
-  arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
-                      operands[1], 0);
-  DONE;
-  "
-)
-
 (define_insn "*andsi3_compare0"
   [(set (reg:CC_NOOV CC_REGNUM)
        (compare:CC_NOOV
 )
 
 ; constants for op 2 will never be given to these patterns.
-(define_insn "*anddi_notdi_di"
+(define_insn_and_split "*anddi_notdi_di"
   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
-       (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
-               (match_operand:DI 1 "s_register_operand" "0,r")))]
+       (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
+               (match_operand:DI 2 "s_register_operand" "0,r")))]
   "TARGET_ARM"
   "#"
+  "TARGET_ARM && reload_completed"
+  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
+   (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
+  "
+  {
+    operands[3] = gen_highpart (SImode, operands[0]);
+    operands[0] = gen_lowpart (SImode, operands[0]);
+    operands[4] = gen_highpart (SImode, operands[1]);
+    operands[1] = gen_lowpart (SImode, operands[1]);
+    operands[5] = gen_highpart (SImode, operands[2]);
+    operands[2] = gen_lowpart (SImode, operands[2]);
+  }"
   [(set_attr "length" "8")
    (set_attr "predicable" "yes")]
 )
   
-(define_insn "*anddi_notzesidi_di"
+(define_insn_and_split "*anddi_notzesidi_di"
   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
        (and:DI (not:DI (zero_extend:DI
                         (match_operand:SI 2 "s_register_operand" "r,r")))
   "@
    bic%?\\t%Q0, %Q1, %2
    #"
+  ; (not (zero_extend ...)) allows us to just copy the high word from
+  ; operand1 to operand0.
+  "TARGET_ARM
+   && reload_completed
+   && operands[0] != operands[1]"
+  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
+   (set (match_dup 3) (match_dup 4))]
+  "
+  {
+    operands[3] = gen_highpart (SImode, operands[0]);
+    operands[0] = gen_lowpart (SImode, operands[0]);
+    operands[4] = gen_highpart (SImode, operands[1]);
+    operands[1] = gen_lowpart (SImode, operands[1]);
+  }"
   [(set_attr "length" "4,8")
    (set_attr "predicable" "yes")]
 )
   
-(define_insn "*anddi_notsesidi_di"
+(define_insn_and_split "*anddi_notsesidi_di"
   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
        (and:DI (not:DI (sign_extend:DI
                         (match_operand:SI 2 "s_register_operand" "r,r")))
                (match_operand:DI 1 "s_register_operand" "?r,0")))]
   "TARGET_ARM"
   "#"
+  "TARGET_ARM && reload_completed"
+  [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
+   (set (match_dup 3) (and:SI (not:SI
+                               (ashiftrt:SI (match_dup 2) (const_int 31)))
+                              (match_dup 4)))]
+  "
+  {
+    operands[3] = gen_highpart (SImode, operands[0]);
+    operands[0] = gen_lowpart (SImode, operands[0]);
+    operands[4] = gen_highpart (SImode, operands[1]);
+    operands[1] = gen_lowpart (SImode, operands[1]);
+  }"
   [(set_attr "length" "8")
    (set_attr "predicable" "yes")]
 )
   "
 )
 
-(define_insn "*arm_iorsi3"
+(define_insn_and_split "*arm_iorsi3"
   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
        (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
                (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
   "@
    orr%?\\t%0, %1, %2
    #"
+  "TARGET_ARM
+   && GET_CODE (operands[2]) == CONST_INT
+   && !const_ok_for_arm (INTVAL (operands[2]))"
+  [(clobber (const_int 0))]
+  "
+  arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
+                     operands[1], 0);
+  DONE;
+  "
   [(set_attr "length" "4,16")
    (set_attr "predicable" "yes")]
 )
   [(set_attr "length" "2")]
 )
 
-(define_split
-  [(set (match_operand:SI         0 "s_register_operand" "")
+(define_peephole2
+  [(match_scratch:SI 3 "r")
+   (set (match_operand:SI         0 "s_register_operand" "")
        (ior:SI (match_operand:SI 1 "s_register_operand" "")
                (match_operand:SI 2 "const_int_operand" "")))]
-  "TARGET_ARM && (!const_ok_for_arm (INTVAL (operands[2])))"
-  [(clobber (const_int 0))]
-  "
-  arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
-                     operands[1], 0);
-  DONE;
-  "
+  "TARGET_ARM
+   && !const_ok_for_arm (INTVAL (operands[2]))
+   && const_ok_for_arm (~INTVAL (operands[2]))"
+  [(set (match_dup 3) (match_dup 2))
+   (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
+  ""
 )
-  
+
 (define_insn "*iorsi3_compare0"
   [(set (reg:CC_NOOV CC_REGNUM)
        (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
 ;  "cos%?e\\t%0, %1"
 ;[(set_attr "type" "float_em")])
 
-(define_insn "one_cmpldi2"
+(define_insn_and_split "one_cmpldi2"
   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
        (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
   "TARGET_ARM"
   "#"
+  "TARGET_ARM && reload_completed"
+  [(set (match_dup 0) (not:SI (match_dup 1)))
+   (set (match_dup 2) (not:SI (match_dup 3)))]
+  "
+  {
+    operands[2] = gen_highpart (SImode, operands[0]);
+    operands[0] = gen_lowpart (SImode, operands[0]);
+    operands[3] = gen_highpart (SImode, operands[1]);
+    operands[1] = gen_lowpart (SImode, operands[1]);
+  }"
   [(set_attr "length" "8")
    (set_attr "predicable" "yes")]
 )
 
 ; This pattern is never tried by combine, so do it as a peephole
 
-(define_peephole
-  [(set (match_operand:SI 0 "s_register_operand" "=r")
-       (match_operand:SI 1 "s_register_operand" "r"))
+(define_peephole2
+  [(set (match_operand:SI 0 "s_register_operand" "")
+       (match_operand:SI 1 "s_register_operand" ""))
    (set (reg:CC CC_REGNUM)
        (compare:CC (match_dup 1) (const_int 0)))]
-  "TARGET_ARM
-  "
-  "sub%?s\\t%0, %1, #0"
-  [(set_attr "conds" "set")]
+  "TARGET_ARM"
+  [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
+             (set (match_dup 0) (match_dup 1))])]
+  ""
 )
 
 ; Peepholes to spot possible load- and store-multiples, if the ordering is