i386.md (cmpdi): Fix operand predicates.
authorJan Hubicka <jh@suse.cz>
Sat, 24 Mar 2001 22:18:11 +0000 (23:18 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Sat, 24 Mar 2001 22:18:11 +0000 (22:18 +0000)
* i386.md (cmpdi): Fix operand predicates.
(cmpdi_ccno_1_rex64, cmpdi_minus_1_rex64, cmpdi_1_rex64,
 cmpdi_1_insn_rex64): New patterns.
(adddi3): Turn to expander.
(adddi3_1, adddi3_carry_rex64, adddi3_cc_rex64): New patterns.
(addsi3_carry_zext): New pattern.
(adddi_?_rex64): New patterns and splitters.
(addsi_?_zext): New patterns.
(subsi3_carry_zext): New pattern.
(subdi_?_rex64): New patterns and splitters.
(iorsi_?_zext): New patterns.
(iordi_?_rex64): New patterns and splitters.
(iorsi_?_zext): New patterns.
(iorsi_?_zext_imm): New patterns.
(xorsi_?_zext): New patterns.
(xordi_?_rex64): New patterns and splitters.
(xorsi_?_zext): New patterns.
(negdi*): New patterns.
(one_cmpldi*): Likewise.
(one_cmplsi*_zext, negsi*_zext): Likewise.
(testqi_ext_3_rex64): New pattern.

From-SVN: r40819

gcc/ChangeLog
gcc/config/i386/i386.md

index 625ccfc192fd5f3672b2abb17f6a1425d9c9ca7c..db5a254c640fc76fd5b76c2529f37a40753bc3ae 100644 (file)
@@ -1,3 +1,27 @@
+Sat Mar 24 23:15:19 CET 2001  Jan Hubicka  <jh@suse.cz>
+
+       * i386.md (cmpdi): Fix operand predicates.
+       (cmpdi_ccno_1_rex64, cmpdi_minus_1_rex64, cmpdi_1_rex64,
+        cmpdi_1_insn_rex64): New patterns.
+       (adddi3): Turn to expander.
+       (adddi3_1, adddi3_carry_rex64, adddi3_cc_rex64): New patterns.
+       (addsi3_carry_zext): New pattern.
+       (adddi_?_rex64): New patterns and splitters.
+       (addsi_?_zext): New patterns.
+       (subsi3_carry_zext): New pattern.
+       (subdi_?_rex64): New patterns and splitters.
+       (iorsi_?_zext): New patterns.
+       (iordi_?_rex64): New patterns and splitters.
+       (iorsi_?_zext): New patterns.
+       (iorsi_?_zext_imm): New patterns.
+       (xorsi_?_zext): New patterns.
+       (xordi_?_rex64): New patterns and splitters.
+       (xorsi_?_zext): New patterns.
+       (negdi*): New patterns.
+       (one_cmpldi*): Likewise.
+       (one_cmplsi*_zext, negsi*_zext): Likewise.
+       (testqi_ext_3_rex64): New pattern.
+
 Sat Mar 24 21:13:28 CET 2001  Jan Hubicka  <jh@suse.cz>
 
        * i386-protos.h (ix86_split_long_move): Return void.
index 24e21b1ce241cea4f47ed40639f0e8824deafde4..0a490a61c23fac59dda52f7bc574ce0132ba1214 100644 (file)
 
 (define_expand "cmpdi"
   [(set (reg:CC 17)
-       (compare:CC (match_operand:DI 0 "general_operand" "")
-                   (match_operand:DI 1 "general_operand" "")))]
+       (compare:CC (match_operand:DI 0 "x86_64_general_operand" "")
+                   (match_operand:DI 1 "x86_64_general_operand" "")))]
   ""
   "
 {
   DONE;
 }")
 
+(define_insn "cmpdi_ccno_1_rex64"
+  [(set (reg 17)
+       (compare (match_operand:DI 0 "nonimmediate_operand" "r,?mr")
+                (match_operand:DI 1 "const0_operand" "n,n")))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
+  "@
+   test{q}\\t{%0, %0|%0, %0}
+   cmp{q}\\t{%1, %0|%0, %1}"
+  [(set_attr "type" "test,icmp")
+   (set_attr "length_immediate" "0,1")
+   (set_attr "mode" "DI")])
+
+(define_insn "*cmpdi_minus_1_rex64"
+  [(set (reg 17)
+       (compare (minus:DI (match_operand:DI 0 "nonimmediate_operand" "rm,r")
+                          (match_operand:DI 1 "x86_64_general_operand" "re,mr"))
+                (const_int 0)))]
+  "ix86_match_ccmode (insn, CCGOCmode)"
+  "cmp{q}\\t{%1, %0|%0, %1}"
+  [(set_attr "type" "icmp")
+   (set_attr "mode" "DI")])
+
+(define_expand "cmpdi_1_rex64"
+  [(set (reg:CC 17)
+       (compare:CC (match_operand:DI 0 "nonimmediate_operand" "")
+                   (match_operand:DI 1 "general_operand" "")))]
+  ""
+  "")
+
+(define_insn "cmpdi_1_insn_rex64"
+  [(set (reg 17)
+       (compare (match_operand:DI 0 "nonimmediate_operand" "mr,r")
+                (match_operand:DI 1 "x86_64_general_operand" "re,mr")))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
+  "cmp{q}\\t{%1, %0|%0, %1}"
+  [(set_attr "type" "icmp")
+   (set_attr "mode" "DI")])
+
+
 (define_insn "*cmpsi_ccno_1"
   [(set (reg 17)
        (compare (match_operand:SI 0 "nonimmediate_operand" "r,?mr")
 ;      (plus:DI (match_operand:DI 1 "general_operand" "")
 ;               (zero_extend:DI (match_operand:SI 2 "general_operand" ""))))]
 
-(define_insn "adddi3"
+(define_expand "adddi3"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+       (plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
+                (match_operand:DI 2 "x86_64_general_operand" "")))
+   (clobber (reg:CC 17))]
+  ""
+  "ix86_expand_binary_operator (PLUS, DImode, operands); DONE;")
+
+(define_insn "*adddi3_1"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
        (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
                 (match_operand:DI 2 "general_operand" "roiF,riF")))
    (clobber (reg:CC 17))]
-  ""
+  "!TARGET_64BIT"
   "#")
 
 (define_split
    split_di (operands+1, 1, operands+1, operands+4);
    split_di (operands+2, 1, operands+2, operands+5);")
 
+(define_insn "*adddi3_carry_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
+         (plus:DI (plus:DI (ltu:DI (reg:CC 17) (const_int 0))
+                           (match_operand:DI 1 "nonimmediate_operand" "%0,0"))
+                  (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
+   (clobber (reg:CC 17))]
+  "ix86_binary_operator_ok (PLUS, DImode, operands)"
+  "adc{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "pent_pair" "pu")
+   (set_attr "mode" "DI")
+   (set_attr "ppro_uops" "few")])
+
+(define_insn "*adddi3_cc_rex64"
+  [(set (reg:CC 17) (unspec:CC [(match_operand:DI 1 "nonimmediate_operand" "%0,0")
+                               (match_operand:DI 2 "x86_64_general_operand" "re,rm")] 12))
+   (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
+       (plus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
+  "add{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "DI")])
+
 (define_insn "*addsi3_carry"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
          (plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
    (set_attr "mode" "SI")
    (set_attr "ppro_uops" "few")])
 
+(define_insn "*addsi3_carry_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+         (zero_extend:DI 
+           (plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
+                             (match_operand:SI 1 "nonimmediate_operand" "%0"))
+                    (match_operand:SI 2 "general_operand" "rim"))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
+  "adc{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "pent_pair" "pu")
+   (set_attr "mode" "SI")
+   (set_attr "ppro_uops" "few")])
+
 (define_insn "*addsi3_cc"
   [(set (reg:CC 17) (unspec:CC [(match_operand:SI 1 "nonimmediate_operand" "%0,0")
                                (match_operand:SI 2 "general_operand" "ri,rm")] 12))
   [(set_attr "type" "lea")
    (set_attr "mode" "SI")])
 
-(define_insn "*addsi_1"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r")
-       (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r")
-                (match_operand:SI 2 "general_operand" "rmni,rni,rni")))
+(define_insn "*adddi_1_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r")
+       (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,r")
+                (match_operand:DI 2 "x86_64_general_operand" "rme,re,re")))
    (clobber (reg:CC 17))]
-  "ix86_binary_operator_ok (PLUS, SImode, operands)"
+  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, DImode, operands)"
   "*
 {
   switch (get_attr_type (insn))
     {
     case TYPE_LEA:
       operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
-      return \"lea{l}\\t{%a2, %0|%0, %a2}\";
+      return \"lea{q}\\t{%a2, %0|%0, %a2}\";
 
     case TYPE_INCDEC:
       if (! rtx_equal_p (operands[0], operands[1]))
        abort ();
       if (operands[2] == const1_rtx)
-        return \"inc{l}\\t%0\";
+        return \"inc{q}\\t%0\";
       else if (operands[2] == constm1_rtx)
-        return \"dec{l}\\t%0\";
+        return \"dec{q}\\t%0\";
       else
-       abort();
+       abort ();
 
     default:
       if (! rtx_equal_p (operands[0], operands[1]))
                  && INTVAL (operands[2]) != -128)))
         {
           operands[2] = GEN_INT (-INTVAL (operands[2]));
-          return \"sub{l}\\t{%2, %0|%0, %2}\";
+          return \"sub{q}\\t{%2, %0|%0, %2}\";
         }
-      return \"add{l}\\t{%2, %0|%0, %2}\";
+      return \"add{q}\\t{%2, %0|%0, %2}\";
     }
 }"
   [(set (attr "type")
              (const_string "lea")
            ; Current assemblers are broken and do not allow @GOTOFF in
            ; ought but a memory context.
-           (match_operand:SI 2 "pic_symbolic_operand" "")
+           (match_operand:DI 2 "pic_symbolic_operand" "")
              (const_string "lea")
-           (match_operand:SI 2 "incdec_operand" "")
+           (match_operand:DI 2 "incdec_operand" "")
              (const_string "incdec")
           ]
           (const_string "alu")))
-   (set_attr "mode" "SI")])
+   (set_attr "mode" "DI")])
 
 ;; Convert lea to the lea pattern to avoid flags dependency.
 (define_split
-  [(set (match_operand 0 "register_operand" "")
-       (plus (match_operand 1 "register_operand" "")
-              (match_operand 2 "nonmemory_operand" "")))
+  [(set (match_operand:DI 0 "register_operand" "")
+       (plus:DI (match_operand:DI 1 "register_operand" "")
+                (match_operand:DI 2 "x86_64_nonmemory_operand" "")))
    (clobber (reg:CC 17))]
-  "reload_completed
+  "reload_completed && TARGET_64BIT
    && true_regnum (operands[0]) != true_regnum (operands[1])"
-  [(const_int 0)]
-  "
-{
-  rtx pat;
-  /* In -fPIC mode the constructs like (const (unspec [symbol_ref]))
-     may confuse gen_lowpart.  */
-  if (GET_MODE (operands[0]) != Pmode)
-    {
-      operands[1] = gen_lowpart (Pmode, operands[1]);
-      operands[2] = gen_lowpart (Pmode, operands[2]);
-    }
-  operands[0] = gen_lowpart (SImode, operands[0]);
-  pat = gen_rtx_PLUS (Pmode, operands[1], operands[2]);
-  if (Pmode != SImode)
-    pat = gen_rtx_SUBREG (SImode, pat, 0);
-  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
-  DONE;
-}")
+  [(set (match_dup 0)
+       (plus:DI (match_dup 1)
+                (match_dup 2)))]
+  "")
 
-(define_insn "*addsi_2"
+(define_insn "*adddi_2_rex64"
   [(set (reg 17)
        (compare
-         (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
-                  (match_operand:SI 2 "general_operand" "rmni,rni"))
+         (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
+                  (match_operand:DI 2 "x86_64_general_operand" "rme,re"))
          (const_int 0)))                       
-   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
-       (plus:SI (match_dup 1) (match_dup 2)))]
-  "ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (PLUS, SImode, operands)
+   (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
+       (plus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+   && ix86_binary_operator_ok (PLUS, DImode, operands)
    /* Current assemblers are broken and do not allow @GOTOFF in
       ought but a memory context. */
    && ! pic_symbolic_operand (operands[2], VOIDmode)"
       if (! rtx_equal_p (operands[0], operands[1]))
        abort ();
       if (operands[2] == const1_rtx)
-        return \"inc{l}\\t%0\";
+        return \"inc{q}\\t%0\";
       else if (operands[2] == constm1_rtx)
-        return \"dec{l}\\t%0\";
+        return \"dec{q}\\t%0\";
       else
-       abort();
+       abort ();
 
     default:
       if (! rtx_equal_p (operands[0], operands[1]))
        abort ();
+      /* ???? We ought to handle there the 32bit case too
+        - do we need new constrant?  */
       /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
         Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
       if (GET_CODE (operands[2]) == CONST_INT
                  && INTVAL (operands[2]) != -128)))
         {
           operands[2] = GEN_INT (-INTVAL (operands[2]));
-          return \"sub{l}\\t{%2, %0|%0, %2}\";
+          return \"sub{q}\\t{%2, %0|%0, %2}\";
         }
-      return \"add{l}\\t{%2, %0|%0, %2}\";
+      return \"add{q}\\t{%2, %0|%0, %2}\";
     }
 }"
   [(set (attr "type")
-     (if_then_else (match_operand:SI 2 "incdec_operand" "")
+     (if_then_else (match_operand:DI 2 "incdec_operand" "")
        (const_string "incdec")
        (const_string "alu")))
-   (set_attr "mode" "SI")])
+   (set_attr "mode" "DI")])
 
-(define_insn "*addsi_3"
+(define_insn "*adddi_3"
   [(set (reg 17)
-       (compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
-                (match_operand:SI 1 "nonimmediate_operand" "%0")))
-   (clobber (match_scratch:SI 0 "=r"))]
+       (compare (neg:DI (match_operand:DI 2 "x86_64_general_operand" "rme"))
+                (match_operand:DI 1 "x86_64_general_operand" "%0")))
+   (clobber (match_scratch:DI 0 "=r"))]
   "ix86_match_ccmode (insn, CCZmode)
    && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
    /* Current assemblers are broken and do not allow @GOTOFF in
       if (! rtx_equal_p (operands[0], operands[1]))
        abort ();
       if (operands[2] == const1_rtx)
-        return \"inc{l}\\t%0\";
+        return \"inc{q}\\t%0\";
       else if (operands[2] == constm1_rtx)
-        return \"dec{l}\\t%0\";
+        return \"dec{q}\\t%0\";
       else
-       abort();
+       abort ();
 
     default:
       if (! rtx_equal_p (operands[0], operands[1]))
        abort ();
+      /* ???? We ought to handle there the 32bit case too
+        - do we need new constrant?  */
       /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
         Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
       if (GET_CODE (operands[2]) == CONST_INT
                  && INTVAL (operands[2]) != -128)))
         {
           operands[2] = GEN_INT (-INTVAL (operands[2]));
-          return \"sub{l}\\t{%2, %0|%0, %2}\";
+          return \"sub{q}\\t{%2, %0|%0, %2}\";
         }
-      return \"add{l}\\t{%2, %0|%0, %2}\";
+      return \"add{q}\\t{%2, %0|%0, %2}\";
     }
 }"
   [(set (attr "type")
-     (if_then_else (match_operand:SI 2 "incdec_operand" "")
+     (if_then_else (match_operand:DI 2 "incdec_operand" "")
        (const_string "incdec")
        (const_string "alu")))
-   (set_attr "mode" "SI")])
+   (set_attr "mode" "DI")])
 
-; For comparisons agains 1, -1 and 128, we may generate better code
+; For comparisons against 1, -1 and 128, we may generate better code
 ; by converting cmp to add, inc or dec as done by peephole2.  This pattern
 ; is matched then.  We can't accept general immediate, because for
 ; case of overflows,  the result is messed up.
-; This pattern also don't hold of 0x80000000, since the value overflows
+; This pattern also don't hold of 0x8000000000000000, since the value overflows
 ; when negated.
 ; Also carry flag is reversed compared to cmp, so this converison is valid
 ; only for comparisons not depending on it.
-(define_insn "*addsi_4"
+(define_insn "*adddi_4"
   [(set (reg 17)
-       (compare (match_operand:SI 1 "nonimmediate_operand" "0")
-                (match_operand:SI 2 "const_int_operand" "n")))
-   (clobber (match_scratch:SI 0 "=rm"))]
-  "ix86_match_ccmode (insn, CCGCmode)
-   && (INTVAL (operands[2]) & 0xffffffff) != 0x80000000"
+       (compare (match_operand:DI 1 "nonimmediate_operand" "0")
+                (match_operand:DI 2 "x86_64_immediate_operand" "e")))
+   (clobber (match_scratch:DI 0 "=rm"))]
+  "ix86_match_ccmode (insn, CCGCmode)"
   "*
 {
   switch (get_attr_type (insn))
     {
     case TYPE_INCDEC:
       if (operands[2] == constm1_rtx)
-        return \"inc{l}\\t%0\";
+        return \"inc{q}\\t%0\";
       else if (operands[2] == const1_rtx)
-        return \"dec{l}\\t%0\";
+        return \"dec{q}\\t%0\";
       else
        abort();
 
       if ((INTVAL (operands[2]) == -128
           || (INTVAL (operands[2]) > 0
               && INTVAL (operands[2]) != 128)))
-       return \"sub{l}\\t{%2, %0|%0, %2}\";
+       return \"sub{q}\\t{%2, %0|%0, %2}\";
       operands[2] = GEN_INT (-INTVAL (operands[2]));
-      return \"add{l}\\t{%2, %0|%0, %2}\";
+      return \"add{q}\\t{%2, %0|%0, %2}\";
     }
 }"
   [(set (attr "type")
-     (if_then_else (match_operand:SI 2 "incdec_operand" "")
+     (if_then_else (match_operand:DI 2 "incdec_operand" "")
        (const_string "incdec")
        (const_string "alu")))
-   (set_attr "mode" "SI")])
+   (set_attr "mode" "DI")])
 
-(define_insn "*addsi_5"
+(define_insn "*adddi_5"
   [(set (reg 17)
        (compare
-         (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
-                  (match_operand:SI 2 "general_operand" "rmni"))
+         (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
+                  (match_operand:DI 2 "x86_64_general_operand" "rme"))
          (const_int 0)))                       
-   (clobber (match_scratch:SI 0 "=r"))]
+   (clobber (match_scratch:DI 0 "=r"))]
   "ix86_match_ccmode (insn, CCGOCmode)
    && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
    /* Current assemblers are broken and do not allow @GOTOFF in
       if (! rtx_equal_p (operands[0], operands[1]))
        abort ();
       if (operands[2] == const1_rtx)
-        return \"inc{l}\\t%0\";
+        return \"inc{q}\\t%0\";
       else if (operands[2] == constm1_rtx)
-        return \"dec{l}\\t%0\";
+        return \"dec{q}\\t%0\";
       else
        abort();
 
                  && INTVAL (operands[2]) != -128)))
         {
           operands[2] = GEN_INT (-INTVAL (operands[2]));
-          return \"sub{l}\\t{%2, %0|%0, %2}\";
+          return \"sub{q}\\t{%2, %0|%0, %2}\";
         }
-      return \"add{l}\\t{%2, %0|%0, %2}\";
+      return \"add{q}\\t{%2, %0|%0, %2}\";
     }
 }"
   [(set (attr "type")
-     (if_then_else (match_operand:SI 2 "incdec_operand" "")
+     (if_then_else (match_operand:DI 2 "incdec_operand" "")
        (const_string "incdec")
        (const_string "alu")))
-   (set_attr "mode" "SI")])
-
-(define_expand "addhi3"
-  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
-                  (plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
-                           (match_operand:HI 2 "general_operand" "")))
-             (clobber (reg:CC 17))])]
-  "TARGET_HIMODE_MATH"
-  "ix86_expand_binary_operator (PLUS, HImode, operands); DONE;")
+   (set_attr "mode" "DI")])
 
-;; %%% After Dave's SUBREG_BYTE stuff goes in, re-enable incb %ah
-;; type optimizations enabled by define-splits.  This is not important
-;; for PII, and in fact harmful because of partial register stalls.
 
-(define_insn "*addhi_1_lea"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
-       (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r")
-                (match_operand:HI 2 "general_operand" "ri,rm,rni")))
+(define_insn "*addsi_1"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r")
+       (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r")
+                (match_operand:SI 2 "general_operand" "rmni,rni,rni")))
    (clobber (reg:CC 17))]
-  "!TARGET_PARTIAL_REG_STALL
-   && ix86_binary_operator_ok (PLUS, HImode, operands)"
+  "ix86_binary_operator_ok (PLUS, SImode, operands)"
   "*
 {
   switch (get_attr_type (insn))
     {
     case TYPE_LEA:
-      return \"#\";
+      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
+      return \"lea{l}\\t{%a2, %0|%0, %a2}\";
+
     case TYPE_INCDEC:
+      if (! rtx_equal_p (operands[0], operands[1]))
+       abort ();
       if (operands[2] == const1_rtx)
-       return \"inc{w}\\t%0\";
-      else if (operands[2] == constm1_rtx
-              || (GET_CODE (operands[2]) == CONST_INT
-                  && INTVAL (operands[2]) == 65535))
-       return \"dec{w}\\t%0\";
-      abort();
+        return \"inc{l}\\t%0\";
+      else if (operands[2] == constm1_rtx)
+        return \"dec{l}\\t%0\";
+      else
+       abort();
 
     default:
+      if (! rtx_equal_p (operands[0], operands[1]))
+       abort ();
+
       /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
         Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
       if (GET_CODE (operands[2]) == CONST_INT
           && (INTVAL (operands[2]) == 128
              || (INTVAL (operands[2]) < 0
                  && INTVAL (operands[2]) != -128)))
-       {
-         operands[2] = GEN_INT (-INTVAL (operands[2]));
-         return \"sub{w}\\t{%2, %0|%0, %2}\";
-       }
-      return \"add{w}\\t{%2, %0|%0, %2}\";
+        {
+          operands[2] = GEN_INT (-INTVAL (operands[2]));
+          return \"sub{l}\\t{%2, %0|%0, %2}\";
+        }
+      return \"add{l}\\t{%2, %0|%0, %2}\";
     }
 }"
   [(set (attr "type")
-     (if_then_else (eq_attr "alternative" "2")
-       (const_string "lea")
-       (if_then_else (match_operand:HI 2 "incdec_operand" "")
-          (const_string "incdec")
-          (const_string "alu"))))
-   (set_attr "mode" "HI,HI,SI")])
+     (cond [(eq_attr "alternative" "2")
+             (const_string "lea")
+           ; Current assemblers are broken and do not allow @GOTOFF in
+           ; ought but a memory context.
+           (match_operand:SI 2 "pic_symbolic_operand" "")
+             (const_string "lea")
+           (match_operand:SI 2 "incdec_operand" "")
+             (const_string "incdec")
+          ]
+          (const_string "alu")))
+   (set_attr "mode" "SI")])
 
-(define_insn "*addhi_1"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
-       (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
-                (match_operand:HI 2 "general_operand" "ri,rm")))
+;; Convert lea to the lea pattern to avoid flags dependency.
+(define_split
+  [(set (match_operand 0 "register_operand" "")
+       (plus (match_operand 1 "register_operand" "")
+              (match_operand 2 "nonmemory_operand" "")))
    (clobber (reg:CC 17))]
-  "TARGET_PARTIAL_REG_STALL
-   && ix86_binary_operator_ok (PLUS, HImode, operands)"
+  "reload_completed
+   && true_regnum (operands[0]) != true_regnum (operands[1])"
+  [(const_int 0)]
+  "
+{
+  rtx pat;
+  /* In -fPIC mode the constructs like (const (unspec [symbol_ref]))
+     may confuse gen_lowpart.  */
+  if (GET_MODE (operands[0]) != Pmode)
+    {
+      operands[1] = gen_lowpart (Pmode, operands[1]);
+      operands[2] = gen_lowpart (Pmode, operands[2]);
+    }
+  operands[0] = gen_lowpart (SImode, operands[0]);
+  pat = gen_rtx_PLUS (Pmode, operands[1], operands[2]);
+  if (Pmode != SImode)
+    pat = gen_rtx_SUBREG (SImode, pat, 0);
+  emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
+  DONE;
+}")
+
+;; It may seem that nonimmediate operand is proper one for operand 1.
+;; The addsi_1 pattern allows nonimmediate operand at that place and
+;; we take care in ix86_binary_operator_ok to not allow two memory
+;; operands so proper swapping will be done in reload.  This allow
+;; patterns constructed from addsi_1 to match.
+(define_insn "addsi_1_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (zero_extend:DI
+         (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r")
+                  (match_operand:SI 2 "general_operand" "rmni,rni"))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
   "*
 {
   switch (get_attr_type (insn))
     {
+    case TYPE_LEA:
+      operands[2] = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
+      return \"lea{l}\\t{%a2, %k0|%k0, %a2}\";
+
     case TYPE_INCDEC:
       if (operands[2] == const1_rtx)
-       return \"inc{w}\\t%0\";
-      else if (operands[2] == constm1_rtx
-              || (GET_CODE (operands[2]) == CONST_INT
-                  && INTVAL (operands[2]) == 65535))
-       return \"dec{w}\\t%0\";
+        return \"inc{l}\\t%k0\";
+      else if (operands[2] == constm1_rtx)
+        return \"dec{l}\\t%k0\";
+      else
+       abort();
+
+    default:
+      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
+        Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
+      if (GET_CODE (operands[2]) == CONST_INT
+          && (INTVAL (operands[2]) == 128
+             || (INTVAL (operands[2]) < 0
+                 && INTVAL (operands[2]) != -128)))
+        {
+          operands[2] = GEN_INT (-INTVAL (operands[2]));
+          return \"sub{l}\\t{%2, %k0|%k0, %2}\";
+        }
+      return \"add{l}\\t{%2, %k0|%k0, %2}\";
+    }
+}"
+  [(set (attr "type")
+     (cond [(eq_attr "alternative" "1")
+             (const_string "lea")
+           ; Current assemblers are broken and do not allow @GOTOFF in
+           ; ought but a memory context.
+           (match_operand:SI 2 "pic_symbolic_operand" "")
+             (const_string "lea")
+           (match_operand:SI 2 "incdec_operand" "")
+             (const_string "incdec")
+          ]
+          (const_string "alu")))
+   (set_attr "mode" "SI")])
+
+;; Convert lea to the lea pattern to avoid flags dependency.
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+       (zero_extend:DI
+         (plus:SI (match_operand:SI 1 "register_operand" "")
+                  (match_operand:SI 2 "nonmemory_operand" ""))))
+   (clobber (reg:CC 17))]
+  "reload_completed
+   && true_regnum (operands[0]) != true_regnum (operands[1])"
+  [(set (match_dup 0)
+       (zero_extend:DI (subreg:SI (plus:DI (match_dup 1) (match_dup 2)) 0)))]
+  "
+{
+  operands[1] = gen_lowpart (Pmode, operands[1]);
+  operands[2] = gen_lowpart (Pmode, operands[2]);
+}")
+
+(define_insn "*addsi_2"
+  [(set (reg 17)
+       (compare
+         (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
+                  (match_operand:SI 2 "general_operand" "rmni,rni"))
+         (const_int 0)))                       
+   (set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
+       (plus:SI (match_dup 1) (match_dup 2)))]
+  "ix86_match_ccmode (insn, CCGOCmode)
+   && ix86_binary_operator_ok (PLUS, SImode, operands)
+   /* Current assemblers are broken and do not allow @GOTOFF in
+      ought but a memory context. */
+   && ! pic_symbolic_operand (operands[2], VOIDmode)"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_INCDEC:
+      if (! rtx_equal_p (operands[0], operands[1]))
+       abort ();
+      if (operands[2] == const1_rtx)
+        return \"inc{l}\\t%0\";
+      else if (operands[2] == constm1_rtx)
+        return \"dec{l}\\t%0\";
+      else
+       abort();
+
+    default:
+      if (! rtx_equal_p (operands[0], operands[1]))
+       abort ();
+      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
+        Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
+      if (GET_CODE (operands[2]) == CONST_INT
+          && (INTVAL (operands[2]) == 128
+             || (INTVAL (operands[2]) < 0
+                 && INTVAL (operands[2]) != -128)))
+        {
+          operands[2] = GEN_INT (-INTVAL (operands[2]));
+          return \"sub{l}\\t{%2, %0|%0, %2}\";
+        }
+      return \"add{l}\\t{%2, %0|%0, %2}\";
+    }
+}"
+  [(set (attr "type")
+     (if_then_else (match_operand:SI 2 "incdec_operand" "")
+       (const_string "incdec")
+       (const_string "alu")))
+   (set_attr "mode" "SI")])
+
+;; See comment for addsi_1_zext why we do use nonimmediate_operand
+(define_insn "*addsi_2_zext"
+  [(set (reg 17)
+       (compare
+         (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
+                  (match_operand:SI 2 "general_operand" "rmni"))
+         (const_int 0)))                       
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+   && ix86_binary_operator_ok (PLUS, SImode, operands)
+   /* Current assemblers are broken and do not allow @GOTOFF in
+      ought but a memory context. */
+   && ! pic_symbolic_operand (operands[2], VOIDmode)"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_INCDEC:
+      if (operands[2] == const1_rtx)
+        return \"inc{l}\\t%k0\";
+      else if (operands[2] == constm1_rtx)
+        return \"dec{l}\\t%k0\";
+      else
+       abort();
+
+    default:
+      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
+        Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
+      if (GET_CODE (operands[2]) == CONST_INT
+          && (INTVAL (operands[2]) == 128
+             || (INTVAL (operands[2]) < 0
+                 && INTVAL (operands[2]) != -128)))
+        {
+          operands[2] = GEN_INT (-INTVAL (operands[2]));
+          return \"sub{l}\\t{%2, %k0|%k0, %2}\";
+        }
+      return \"add{l}\\t{%2, %k0|%k0, %2}\";
+    }
+}"
+  [(set (attr "type")
+     (if_then_else (match_operand:SI 2 "incdec_operand" "")
+       (const_string "incdec")
+       (const_string "alu")))
+   (set_attr "mode" "SI")])
+
+(define_insn "*addsi_3"
+  [(set (reg 17)
+       (compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
+                (match_operand:SI 1 "nonimmediate_operand" "%0")))
+   (clobber (match_scratch:SI 0 "=r"))]
+  "ix86_match_ccmode (insn, CCZmode)
+   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
+   /* Current assemblers are broken and do not allow @GOTOFF in
+      ought but a memory context. */
+   && ! pic_symbolic_operand (operands[2], VOIDmode)"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_INCDEC:
+      if (! rtx_equal_p (operands[0], operands[1]))
+       abort ();
+      if (operands[2] == const1_rtx)
+        return \"inc{l}\\t%0\";
+      else if (operands[2] == constm1_rtx)
+        return \"dec{l}\\t%0\";
+      else
+       abort();
+
+    default:
+      if (! rtx_equal_p (operands[0], operands[1]))
+       abort ();
+      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
+        Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
+      if (GET_CODE (operands[2]) == CONST_INT
+          && (INTVAL (operands[2]) == 128
+             || (INTVAL (operands[2]) < 0
+                 && INTVAL (operands[2]) != -128)))
+        {
+          operands[2] = GEN_INT (-INTVAL (operands[2]));
+          return \"sub{l}\\t{%2, %0|%0, %2}\";
+        }
+      return \"add{l}\\t{%2, %0|%0, %2}\";
+    }
+}"
+  [(set (attr "type")
+     (if_then_else (match_operand:SI 2 "incdec_operand" "")
+       (const_string "incdec")
+       (const_string "alu")))
+   (set_attr "mode" "SI")])
+
+;; See comment for addsi_1_zext why we do use nonimmediate_operand
+(define_insn "*addsi_3_zext"
+  [(set (reg 17)
+       (compare (neg:SI (match_operand:SI 2 "general_operand" "rmni"))
+                (match_operand:SI 1 "nonimmediate_operand" "%0")))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCZmode)
+   && ix86_binary_operator_ok (PLUS, SImode, operands)
+   /* Current assemblers are broken and do not allow @GOTOFF in
+      ought but a memory context. */
+   && ! pic_symbolic_operand (operands[2], VOIDmode)"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_INCDEC:
+      if (operands[2] == const1_rtx)
+        return \"inc{l}\\t%k0\";
+      else if (operands[2] == constm1_rtx)
+        return \"dec{l}\\t%k0\";
+      else
+       abort();
+
+    default:
+      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
+        Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
+      if (GET_CODE (operands[2]) == CONST_INT
+          && (INTVAL (operands[2]) == 128
+             || (INTVAL (operands[2]) < 0
+                 && INTVAL (operands[2]) != -128)))
+        {
+          operands[2] = GEN_INT (-INTVAL (operands[2]));
+          return \"sub{l}\\t{%2, %k0|%k0, %2}\";
+        }
+      return \"add{l}\\t{%2, %k0|%k0, %2}\";
+    }
+}"
+  [(set (attr "type")
+     (if_then_else (match_operand:SI 2 "incdec_operand" "")
+       (const_string "incdec")
+       (const_string "alu")))
+   (set_attr "mode" "SI")])
+
+; For comparisons agains 1, -1 and 128, we may generate better code
+; by converting cmp to add, inc or dec as done by peephole2.  This pattern
+; is matched then.  We can't accept general immediate, because for
+; case of overflows,  the result is messed up.
+; This pattern also don't hold of 0x80000000, since the value overflows
+; when negated.
+; Also carry flag is reversed compared to cmp, so this converison is valid
+; only for comparisons not depending on it.
+(define_insn "*addsi_4"
+  [(set (reg 17)
+       (compare (match_operand:SI 1 "nonimmediate_operand" "0")
+                (match_operand:SI 2 "const_int_operand" "n")))
+   (clobber (match_scratch:SI 0 "=rm"))]
+  "ix86_match_ccmode (insn, CCGCmode)
+   && (INTVAL (operands[2]) & 0xffffffff) != 0x80000000"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_INCDEC:
+      if (operands[2] == constm1_rtx)
+        return \"inc{l}\\t%0\";
+      else if (operands[2] == const1_rtx)
+        return \"dec{l}\\t%0\";
+      else
+       abort();
+
+    default:
+      if (! rtx_equal_p (operands[0], operands[1]))
+       abort ();
+      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
+        Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
+      if ((INTVAL (operands[2]) == -128
+          || (INTVAL (operands[2]) > 0
+              && INTVAL (operands[2]) != 128)))
+       return \"sub{l}\\t{%2, %0|%0, %2}\";
+      operands[2] = GEN_INT (-INTVAL (operands[2]));
+      return \"add{l}\\t{%2, %0|%0, %2}\";
+    }
+}"
+  [(set (attr "type")
+     (if_then_else (match_operand:SI 2 "incdec_operand" "")
+       (const_string "incdec")
+       (const_string "alu")))
+   (set_attr "mode" "SI")])
+
+(define_insn "*addsi_5"
+  [(set (reg 17)
+       (compare
+         (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
+                  (match_operand:SI 2 "general_operand" "rmni"))
+         (const_int 0)))                       
+   (clobber (match_scratch:SI 0 "=r"))]
+  "ix86_match_ccmode (insn, CCGOCmode)
+   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
+   /* Current assemblers are broken and do not allow @GOTOFF in
+      ought but a memory context. */
+   && ! pic_symbolic_operand (operands[2], VOIDmode)"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_INCDEC:
+      if (! rtx_equal_p (operands[0], operands[1]))
+       abort ();
+      if (operands[2] == const1_rtx)
+        return \"inc{l}\\t%0\";
+      else if (operands[2] == constm1_rtx)
+        return \"dec{l}\\t%0\";
+      else
+       abort();
+
+    default:
+      if (! rtx_equal_p (operands[0], operands[1]))
+       abort ();
+      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
+        Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
+      if (GET_CODE (operands[2]) == CONST_INT
+          && (INTVAL (operands[2]) == 128
+             || (INTVAL (operands[2]) < 0
+                 && INTVAL (operands[2]) != -128)))
+        {
+          operands[2] = GEN_INT (-INTVAL (operands[2]));
+          return \"sub{l}\\t{%2, %0|%0, %2}\";
+        }
+      return \"add{l}\\t{%2, %0|%0, %2}\";
+    }
+}"
+  [(set (attr "type")
+     (if_then_else (match_operand:SI 2 "incdec_operand" "")
+       (const_string "incdec")
+       (const_string "alu")))
+   (set_attr "mode" "SI")])
+
+(define_expand "addhi3"
+  [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
+                  (plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
+                           (match_operand:HI 2 "general_operand" "")))
+             (clobber (reg:CC 17))])]
+  "TARGET_HIMODE_MATH"
+  "ix86_expand_binary_operator (PLUS, HImode, operands); DONE;")
+
+;; %%% After Dave's SUBREG_BYTE stuff goes in, re-enable incb %ah
+;; type optimizations enabled by define-splits.  This is not important
+;; for PII, and in fact harmful because of partial register stalls.
+
+(define_insn "*addhi_1_lea"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
+       (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r")
+                (match_operand:HI 2 "general_operand" "ri,rm,rni")))
+   (clobber (reg:CC 17))]
+  "!TARGET_PARTIAL_REG_STALL
+   && ix86_binary_operator_ok (PLUS, HImode, operands)"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_LEA:
+      return \"#\";
+    case TYPE_INCDEC:
+      if (operands[2] == const1_rtx)
+       return \"inc{w}\\t%0\";
+      else if (operands[2] == constm1_rtx
+              || (GET_CODE (operands[2]) == CONST_INT
+                  && INTVAL (operands[2]) == 65535))
+       return \"dec{w}\\t%0\";
+      abort();
+
+    default:
+      /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
+        Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
+      if (GET_CODE (operands[2]) == CONST_INT
+          && (INTVAL (operands[2]) == 128
+             || (INTVAL (operands[2]) < 0
+                 && INTVAL (operands[2]) != -128)))
+       {
+         operands[2] = GEN_INT (-INTVAL (operands[2]));
+         return \"sub{w}\\t{%2, %0|%0, %2}\";
+       }
+      return \"add{w}\\t{%2, %0|%0, %2}\";
+    }
+}"
+  [(set (attr "type")
+     (if_then_else (eq_attr "alternative" "2")
+       (const_string "lea")
+       (if_then_else (match_operand:HI 2 "incdec_operand" "")
+          (const_string "incdec")
+          (const_string "alu"))))
+   (set_attr "mode" "HI,HI,SI")])
+
+(define_insn "*addhi_1"
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
+       (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
+                (match_operand:HI 2 "general_operand" "ri,rm")))
+   (clobber (reg:CC 17))]
+  "TARGET_PARTIAL_REG_STALL
+   && ix86_binary_operator_ok (PLUS, HImode, operands)"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_INCDEC:
+      if (operands[2] == const1_rtx)
+       return \"inc{w}\\t%0\";
+      else if (operands[2] == constm1_rtx
+              || (GET_CODE (operands[2]) == CONST_INT
+                  && INTVAL (operands[2]) == 65535))
+       return \"dec{w}\\t%0\";
       abort();
 
     default:
 \f
 ;; Subtract instructions
 
-;; %%% define_expand from the very first?
 ;; %%% splits for subsidi3
 
-(define_insn "subdi3"
+(define_expand "subdi3"
+  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
+                  (minus:DI (match_operand:DI 1 "nonimmediate_operand" "")
+                            (match_operand:DI 2 "x86_64_general_operand" "")))
+             (clobber (reg:CC 17))])]
+  ""
+  "ix86_expand_binary_operator (MINUS, DImode, operands); DONE;")
+
+(define_insn "*subdi3_1"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o")
        (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
                  (match_operand:DI 2 "general_operand" "roiF,riF")))
    (clobber (reg:CC 17))]
-  ""
+  "!TARGET_64BIT"
   "#")
 
 (define_split
    split_di (operands+1, 1, operands+1, operands+4);
    split_di (operands+2, 1, operands+2, operands+5);")
 
+(define_insn "subdi3_carry_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
+         (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
+           (plus:DI (ltu:DI (reg:CC 17) (const_int 0))
+              (match_operand:DI 2 "x86_64_general_operand" "re,rm"))))
+   (clobber (reg:CC 17))]
+  "ix86_binary_operator_ok (MINUS, DImode, operands)"
+  "sbb{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "pent_pair" "pu")
+   (set_attr "ppro_uops" "few")
+   (set_attr "mode" "DI")])
+
+(define_insn "*subdi_1_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
+       (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
+                 (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
+  "sub{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "DI")])
+
+(define_insn "*subdi_2_rex64"
+  [(set (reg 17)
+       (compare
+         (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
+                   (match_operand:DI 2 "x86_64_general_operand" "re,rm"))
+         (const_int 0)))
+   (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
+       (minus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+   && ix86_binary_operator_ok (MINUS, DImode, operands)"
+  "sub{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "DI")])
+
+(define_insn "*subdi_3_rex63"
+  [(set (reg 17)
+       (compare (match_operand:DI 1 "nonimmediate_operand" "0,0")
+                (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
+   (set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
+       (minus:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
+   && ix86_binary_operator_ok (MINUS, SImode, operands)"
+  "sub{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "DI")])
+
+
 (define_insn "subsi3_carry"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
          (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
    (set_attr "ppro_uops" "few")
    (set_attr "mode" "SI")])
 
+(define_insn "subsi3_carry_zext"
+  [(set (match_operand:DI 0 "register_operand" "=rm,r")
+         (zero_extend:DI
+           (minus:SI (match_operand:SI 1 "register_operand" "0,0")
+             (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
+                (match_operand:SI 2 "general_operand" "ri,rm")))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
+  "sbb{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "pent_pair" "pu")
+   (set_attr "ppro_uops" "few")
+   (set_attr "mode" "SI")])
+
 (define_expand "subsi3"
   [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
                   (minus:SI (match_operand:SI 1 "nonimmediate_operand" "")
   [(set_attr "type" "alu")
    (set_attr "mode" "SI")])
 
+(define_insn "*subsi_1_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+         (minus:SI (match_operand:SI 1 "register_operand" "0")
+                   (match_operand:SI 2 "general_operand" "rim"))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
+  "sub{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "SI")])
+
 (define_insn "*subsi_2"
   [(set (reg 17)
        (compare
   [(set_attr "type" "alu")
    (set_attr "mode" "SI")])
 
+(define_insn "*subsi_2_zext"
+  [(set (reg 17)
+       (compare
+         (minus:SI (match_operand:SI 1 "register_operand" "0")
+                   (match_operand:SI 2 "general_operand" "rim"))
+         (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+         (minus:SI (match_dup 1)
+                   (match_dup 2))))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+   && ix86_binary_operator_ok (MINUS, SImode, operands)"
+  "sub{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "SI")])
+
 (define_insn "*subsi_3"
   [(set (reg 17)
        (compare (match_operand:SI 1 "nonimmediate_operand" "0,0")
   [(set_attr "type" "alu")
    (set_attr "mode" "SI")])
 
+(define_insn "*subsi_3_zext"
+  [(set (reg 17)
+       (compare (match_operand:SI 1 "nonimmediate_operand" "0")
+                (match_operand:SI 2 "general_operand" "rim")))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+         (minus:SI (match_dup 1)
+                   (match_dup 2))))]
+  "ix86_match_ccmode (insn, CCmode)
+   && ix86_binary_operator_ok (MINUS, SImode, operands)"
+  "sub{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "DI")])
+
 (define_expand "subhi3"
   [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
                   (minus:HI (match_operand:HI 1 "nonimmediate_operand" "")
 \f
 ;; Multiply instructions
 
+(define_expand "muldi3"
+  [(parallel [(set (match_operand:DI 0 "register_operand" "")
+                  (mult:DI (match_operand:DI 1 "register_operand" "")
+                           (match_operand:DI 2 "x86_64_general_operand" "")))
+             (clobber (reg:CC 17))])]
+  "TARGET_64BIT"
+  "")
+
+(define_insn "*muldi3_1_rex64"
+  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
+       (mult:DI (match_operand:DI 1 "nonimmediate_operand" "%rm,0,0")
+                (match_operand:DI 2 "x86_64_general_operand" "K,e,mr")))
+   (clobber (reg:CC 17))]
+  "(GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)
+   && TARGET_64BIT"
+  "@
+   imul{q}\\t{%2, %1, %0|%0, %1, %2}
+   imul{q}\\t{%2, %1, %0|%0, %1, %2}
+   imul{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "imul")
+   (set_attr "prefix_0f" "0,0,1")
+   (set_attr "mode" "DI")])
+
 (define_expand "mulsi3"
   [(parallel [(set (match_operand:SI 0 "register_operand" "")
                   (mult:SI (match_operand:SI 1 "register_operand" "")
    (set_attr "prefix_0f" "0,0,1")
    (set_attr "mode" "SI")])
 
+(define_insn "*mulsi3_1_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r,r,r")
+       (zero_extend:DI
+         (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,0,0")
+                  (match_operand:SI 2 "general_operand" "K,i,mr"))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT
+   && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)"
+  ; For the {r,0,i} alternative (i.e., register <- register * immediate),
+  ; there are two ways of writing the exact same machine instruction
+  ; in assembly language.  One, for example, is:
+  ;
+  ;   imul $12, %eax
+  ;
+  ; while the other is:
+  ;
+  ;   imul $12, %eax, %eax
+  ;
+  ; The first is simply short-hand for the latter.  But, some assemblers,
+  ; like the SCO OSR5 COFF assembler, don't handle the first form.
+  "@
+   imul{l}\\t{%2, %1, %k0|%k0, %1, %2}
+   imul{l}\\t{%2, %1, %k0|%k0, %1, %2}
+   imul{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "imul")
+   (set_attr "prefix_0f" "0,0,1")
+   (set_attr "mode" "SI")])
+
 (define_expand "mulhi3"
   [(parallel [(set (match_operand:HI 0 "register_operand" "")
                   (mult:HI (match_operand:HI 1 "register_operand" "")
    (set_attr "length_immediate" "0")
    (set_attr "mode" "QI")])
 
-(define_insn "umulsi3"
-  [(set (match_operand:SI 0 "register_operand" "=a")
-       (mult:SI (match_operand:SI 1 "register_operand" "%0")
-                (match_operand:SI 2 "nonimmediate_operand" "rm")))
-   (clobber (match_operand:SI 3 "register_operand" "=d"))
+(define_insn "umulditi3"
+  [(set (match_operand:TI 0 "register_operand" "=A")
+       (mult:TI (zero_extend:TI (match_operand:DI 1 "register_operand" "%0"))
+                (zero_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm"))))
    (clobber (reg:CC 17))]
-  ""
-  "mul{l}\\t%2"
+  "TARGET_64BIT"
+  "mul{q}\\t%2"
   [(set_attr "type" "imul")
    (set_attr "ppro_uops" "few")
    (set_attr "length_immediate" "0")
-   (set_attr "mode" "SI")])
+   (set_attr "mode" "DI")])
 
 ;; We can't use this pattern in 64bit mode, since it results in two separate 32bit registers
 (define_insn "umulsidi3"
    (set_attr "length_immediate" "0")
    (set_attr "mode" "SI")])
 
+(define_insn "mulditi3"
+  [(set (match_operand:TI 0 "register_operand" "=A")
+       (mult:TI (sign_extend:TI (match_operand:DI 1 "register_operand" "%0"))
+                (sign_extend:TI (match_operand:DI 2 "nonimmediate_operand" "rm"))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT"
+  "imul{q}\\t%2"
+  [(set_attr "type" "imul")
+   (set_attr "length_immediate" "0")
+   (set_attr "mode" "DI")])
+
 (define_insn "mulsidi3"
   [(set (match_operand:DI 0 "register_operand" "=A")
        (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
    (set_attr "length_immediate" "0")
    (set_attr "mode" "SI")])
 
+(define_insn "*umuldi3_highpart_rex64"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+       (truncate:DI
+         (lshiftrt:TI
+           (mult:TI (zero_extend:TI
+                      (match_operand:DI 1 "register_operand" "%a"))
+                    (zero_extend:TI
+                      (match_operand:DI 2 "nonimmediate_operand" "rm")))
+           (const_int 64))))
+   (clobber (match_scratch:DI 3 "=a"))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT"
+  "mul{q}\\t%2"
+  [(set_attr "type" "imul")
+   (set_attr "ppro_uops" "few")
+   (set_attr "length_immediate" "0")
+   (set_attr "mode" "DI")])
+
 (define_insn "umulsi3_highpart"
   [(set (match_operand:SI 0 "register_operand" "=d")
        (truncate:SI
    (set_attr "length_immediate" "0")
    (set_attr "mode" "SI")])
 
+(define_insn "*smuldi3_highpart_rex64"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+       (truncate:DI
+         (lshiftrt:TI
+           (mult:TI (sign_extend:TI
+                      (match_operand:DI 1 "register_operand" "%a"))
+                    (sign_extend:TI
+                      (match_operand:DI 2 "nonimmediate_operand" "rm")))
+           (const_int 64))))
+   (clobber (match_scratch:DI 3 "=a"))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT"
+  "imul{q}\\t%2"
+  [(set_attr "type" "imul")
+   (set_attr "ppro_uops" "few")
+   (set_attr "mode" "DI")])
+
 (define_insn "smulsi3_highpart"
   [(set (match_operand:SI 0 "register_operand" "=d")
        (truncate:SI
    (set_attr "ppro_uops" "few")
    (set_attr "mode" "SI")])
 
+(define_insn "*smulsi3_highpart_zext"
+  [(set (match_operand:DI 0 "register_operand" "=d")
+       (zero_extend:DI (truncate:SI
+         (lshiftrt:DI
+           (mult:DI (sign_extend:DI
+                      (match_operand:SI 1 "register_operand" "%a"))
+                    (sign_extend:DI
+                      (match_operand:SI 2 "nonimmediate_operand" "rm")))
+           (const_int 32)))))
+   (clobber (match_scratch:SI 3 "=a"))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT"
+  "imul{l}\\t%2"
+  [(set_attr "type" "imul")
+   (set_attr "ppro_uops" "few")
+   (set_attr "mode" "SI")])
+
 ;; The patterns that match these are at the end of this file.
 
 (define_expand "mulxf3"
   "")
 \f
 ;; Remainder instructions.
+
+(define_expand "divmoddi4"
+  [(parallel [(set (match_operand:DI 0 "register_operand" "")
+                  (div:DI (match_operand:DI 1 "register_operand" "")
+                          (match_operand:DI 2 "nonimmediate_operand" "")))
+             (set (match_operand:DI 3 "register_operand" "")
+                  (mod:DI (match_dup 1) (match_dup 2)))
+             (clobber (reg:CC 17))])]
+  "TARGET_64BIT"
+  "")
+
+;; Allow to come the parameter in eax or edx to avoid extra moves.
+;; Penalize eax case sligthly because it results in worse scheduling
+;; of code.
+(define_insn "*divmoddi4_nocltd_rex64"
+  [(set (match_operand:DI 0 "register_operand" "=&a,?a")
+       (div:DI (match_operand:DI 2 "register_operand" "1,0")
+               (match_operand:DI 3 "nonimmediate_operand" "rm,rm")))
+   (set (match_operand:DI 1 "register_operand" "=&d,&d")
+       (mod:DI (match_dup 2) (match_dup 3)))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && !optimize_size && !TARGET_USE_CLTD"
+  "#"
+  [(set_attr "type" "multi")])
+
+(define_insn "*divmoddi4_cltd_rex64"
+  [(set (match_operand:DI 0 "register_operand" "=a")
+       (div:DI (match_operand:DI 2 "register_operand" "a")
+               (match_operand:DI 3 "nonimmediate_operand" "rm")))
+   (set (match_operand:DI 1 "register_operand" "=&d")
+       (mod:DI (match_dup 2) (match_dup 3)))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && (optimize_size || TARGET_USE_CLTD)"
+  "#"
+  [(set_attr "type" "multi")])
+
+(define_insn "*divmoddi_noext_rex64"
+  [(set (match_operand:DI 0 "register_operand" "=a")
+       (div:DI (match_operand:DI 1 "register_operand" "0")
+               (match_operand:DI 2 "nonimmediate_operand" "rm")))
+   (set (match_operand:DI 3 "register_operand" "=d")
+       (mod:DI (match_dup 1) (match_dup 2)))
+   (use (match_operand:DI 4 "register_operand" "3"))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT"
+  "idiv{q}\\t%2"
+  [(set_attr "type" "idiv")
+   (set_attr "mode" "DI")
+   (set_attr "ppro_uops" "few")])
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+       (div:DI (match_operand:DI 1 "register_operand" "")
+               (match_operand:DI 2 "nonimmediate_operand" "")))
+   (set (match_operand:DI 3 "register_operand" "")
+       (mod:DI (match_dup 1) (match_dup 2)))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && reload_completed"
+  [(parallel [(set (match_dup 3)
+                  (ashiftrt:DI (match_dup 4) (const_int 63)))
+             (clobber (reg:CC 17))])
+   (parallel [(set (match_dup 0)
+                  (div:DI (reg:DI 0) (match_dup 2)))
+             (set (match_dup 3)
+                  (mod:DI (reg:DI 0) (match_dup 2)))
+             (use (match_dup 3))
+             (clobber (reg:CC 17))])]
+  "
+{
+  /* Avoid use of cltd in favour of a mov+shift.  */
+  if (!TARGET_USE_CLTD && !optimize_size)
+    {
+      if (true_regnum (operands[1]))
+        emit_move_insn (operands[0], operands[1]);
+      else
+       emit_move_insn (operands[3], operands[1]);
+      operands[4] = operands[3];
+    }
+  else
+    {
+      if (true_regnum (operands[1]))
+       abort();
+      operands[4] = operands[1];
+    }
+}")
+
+
 (define_expand "divmodsi4"
   [(parallel [(set (match_operand:SI 0 "register_operand" "")
                   (div:SI (match_operand:SI 1 "register_operand" "")
   "cwtd\;idiv{w}\\t%2"
   [(set_attr "type" "multi")
    (set_attr "length_immediate" "0")
-   (set_attr "mode" "SI")])
+   (set_attr "mode" "SI")])
+
+(define_insn "udivmoddi4"
+  [(set (match_operand:DI 0 "register_operand" "=a")
+       (udiv:DI (match_operand:DI 1 "register_operand" "0")
+                (match_operand:DI 2 "nonimmediate_operand" "rm")))
+   (set (match_operand:DI 3 "register_operand" "=&d")
+       (umod:DI (match_dup 1) (match_dup 2)))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT"
+  "xor{q}\\t%3, %3\;div{q}\\t%2"
+  [(set_attr "type" "multi")
+   (set_attr "length_immediate" "0")
+   (set_attr "mode" "DI")])
+
+(define_insn "*udivmoddi4_noext"
+  [(set (match_operand:DI 0 "register_operand" "=a")
+       (udiv:DI (match_operand:DI 1 "register_operand" "0")
+                (match_operand:DI 2 "nonimmediate_operand" "rm")))
+   (set (match_operand:DI 3 "register_operand" "=d")
+       (umod:DI (match_dup 1) (match_dup 2)))
+   (use (match_dup 3))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT"
+  "div{q}\\t%2"
+  [(set_attr "type" "idiv")
+   (set_attr "ppro_uops" "few")
+   (set_attr "mode" "DI")])
+
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+       (udiv:DI (match_operand:DI 1 "register_operand" "")
+                (match_operand:DI 2 "nonimmediate_operand" "")))
+   (set (match_operand:DI 3 "register_operand" "")
+       (umod:DI (match_dup 1) (match_dup 2)))
+   (clobber (reg:CC 17))]
+  "reload_completed && TARGET_64BIT"
+  [(set (match_dup 3) (const_int 0))
+   (parallel [(set (match_dup 0)
+                  (udiv:DI (match_dup 1) (match_dup 2)))
+             (set (match_dup 3)
+                  (umod:DI (match_dup 1) (match_dup 2)))
+             (use (match_dup 3))
+             (clobber (reg:CC 17))])]
+  "")
 
 (define_insn "udivmodsi4"
   [(set (match_operand:SI 0 "register_operand" "=a")
 ;; On Pentium, "test imm, reg" is pairable only with eax, ax, and al.
 ;; Note that this excludes ah.
 
+(define_insn "*testdi_1_rex64"
+  [(set (reg 17)
+       (compare
+         (and:DI (match_operand:DI 0 "nonimmediate_operand" "%*a,r,*a,r,rm")
+                 (match_operand:DI 1 "x86_64_szext_nonmemory_operand" "Z,Z,e,e,re"))
+         (const_int 0)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
+  "@
+   test{l}\\t{%k1, %k0|%k0, %k1} 
+   test{l}\\t{%k1, %k0|%k0, %k1} 
+   test{q}\\t{%1, %0|%0, %1} 
+   test{q}\\t{%1, %0|%0, %1} 
+   test{q}\\t{%1, %0|%0, %1}"
+  [(set_attr "type" "test")
+   (set_attr "modrm" "0,1,0,1,1")
+   (set_attr "mode" "SI,SI,DI,DI,DI")
+   (set_attr "pent_pair" "uv,np,uv,np,uv")])
 
 (define_insn "testsi_1"
   [(set (reg 17)
                 (const_int 0)))]
   "ix86_match_ccmode (insn, CCNOmode)
    && (GET_MODE (operands[0]) == SImode
+       || (TARGET_64BIT && GET_MODE (operands[0]) == DImode)
+       || GET_MODE (operands[0]) == HImode
+       || GET_MODE (operands[0]) == QImode)"
+  "#")
+
+(define_insn "*testqi_ext_3_rex64"
+  [(set (reg 17)
+        (compare (zero_extract:DI
+                  (match_operand 0 "nonimmediate_operand" "rm")
+                  (match_operand:DI 1 "const_int_operand" "")
+                  (match_operand:DI 2 "const_int_operand" ""))
+                (const_int 0)))]
+  "ix86_match_ccmode (insn, CCNOmode)
+   && TARGET_64BIT
+   && (GET_MODE (operands[0]) == SImode
+       || GET_MODE (operands[0]) == DImode
        || GET_MODE (operands[0]) == HImode
        || GET_MODE (operands[0]) == QImode)"
   "#")
 
 (define_split
   [(set (reg 17)
-        (compare (zero_extract:SI
+        (compare (zero_extract
                   (match_operand 0 "nonimmediate_operand" "rm")
-                  (match_operand:SI 1 "const_int_operand" "")
-                  (match_operand:SI 2 "const_int_operand" ""))
+                  (match_operand 1 "const_int_operand" "")
+                  (match_operand 2 "const_int_operand" ""))
                 (const_int 0)))]
   "ix86_match_ccmode (insn, CCNOmode)"
   [(set (reg:CCNO 17) (compare:CCNO (match_dup 3) (const_int 0)))]
 ;; and sometimes to QImode registers.  If this is considered useful,
 ;; it should be done with splitters.
 
+(define_expand "anddi3"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+       (and:DI (match_operand:DI 1 "nonimmediate_operand" "")
+               (match_operand:DI 2 "x86_64_szext_general_operand" "")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT"
+  "ix86_expand_binary_operator (AND, DImode, operands); DONE;")
+
+(define_insn "*anddi_1_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r")
+       (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,qm")
+               (match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm,L")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (AND, DImode, operands)"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_IMOVX:
+      {
+       enum machine_mode mode;
+
+       if (GET_CODE (operands[2]) != CONST_INT)
+         abort ();
+        if (INTVAL (operands[2]) == 0xff)
+         mode = QImode;
+       else if (INTVAL (operands[2]) == 0xffff)
+         mode = HImode;
+       else
+         abort ();
+       
+       operands[1] = gen_lowpart (mode, operands[1]);
+       if (mode == QImode)
+         return \"movz{bq|x}\\t{%1,%0|%0, %1}\";
+       else
+         return \"movz{wq|x}\\t{%1,%0|%0, %1}\";
+      }
+
+    default:
+      if (! rtx_equal_p (operands[0], operands[1]))
+       abort ();
+      if (get_attr_mode (insn) == MODE_SI)
+       return \"and{l}\\t{%k2, %k0|%k0, %k2}\";
+      else
+       return \"and{q}\\t{%2, %0|%0, %2}\";
+    }
+}"
+  [(set_attr "type" "alu,alu,alu,imovx")
+   (set_attr "length_immediate" "*,*,*,0")
+   (set_attr "mode" "SI,DI,DI,DI")])
+
+(define_insn "*anddi_2"
+  [(set (reg 17)
+       (compare (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0")
+                        (match_operand:DI 2 "x86_64_szext_general_operand" "Z,rem,re"))
+                (const_int 0)))
+   (set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm")
+       (and:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
+   && ix86_binary_operator_ok (AND, DImode, operands)"
+  "@
+   and{l}\\t{%k2, %k0|%k0, %k2} 
+   and{q}\\t{%2, %0|%0, %2} 
+   and{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "SI,DI,DI")])
+
 (define_expand "andsi3"
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
        (and:SI (match_operand:SI 1 "nonimmediate_operand" "")
    (set_attr "mode" "SI")])
 
 (define_split
-  [(set (match_operand:SI 0 "register_operand" "")
-       (and:SI (match_dup 0)
-               (const_int -65536)))
+  [(set (match_operand 0 "register_operand" "")
+       (and (match_dup 0)
+            (const_int -65536)))
    (clobber (reg:CC 17))]
-  "optimize_size"
+  "optimize_size
+   && (GET_MODE (operands[0]) == SImode || GET_MODE (operands[0]) == HImode
+       || (TARGET_64BIT && GET_MODE (operands[0]) == DImode))"
   [(set (strict_low_part (match_dup 1)) (const_int 0))]
   "operands[1] = gen_lowpart (HImode, operands[0]);")
 
 (define_split
   [(set (match_operand 0 "q_regs_operand" "")
        (and (match_dup 0)
-               (const_int -256)))
+            (const_int -256)))
    (clobber (reg:CC 17))]
   "(optimize_size || !TARGET_PARTIAL_REG_STALL)
-   && (GET_MODE (operands[0]) == SImode || GET_MODE (operands[0]) == HImode)"
+   && (GET_MODE (operands[0]) == SImode || GET_MODE (operands[0]) == HImode
+       || (TARGET_64BIT && GET_MODE (operands[0]) == DImode))"
   [(set (strict_low_part (match_dup 1)) (const_int 0))]
   "operands[1] = gen_lowpart (QImode, operands[0]);")
 
 (define_split
-  [(set (match_operand 0 "q_regs_operand" "")
+  [(set (match_operand 0 "register_operand" "")
        (and (match_dup 0)
             (const_int -65281)))
    (clobber (reg:CC 17))]
   "(optimize_size || !TARGET_PARTIAL_REG_STALL)
-   && (GET_MODE (operands[0]) == SImode || GET_MODE (operands[0]) == HImode)"
+   && (GET_MODE (operands[0]) == SImode || GET_MODE (operands[0]) == HImode
+       || (TARGET_64BIT && GET_MODE (operands[0]) == DImode))"
   [(parallel [(set (zero_extract:SI (match_dup 0)
                                    (const_int 8)
                                    (const_int 8))
              (clobber (reg:CC 17))])]
   "operands[0] = gen_lowpart (SImode, operands[0]);")
 
+;; See comment for addsi_1_zext why we do use nonimmediate_operand
+(define_insn "*andsi_1_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+         (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
+                 (match_operand:SI 2 "general_operand" "rim"))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands)"
+  "and{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "SI")])
+
 (define_insn "*andsi_2"
   [(set (reg 17)
        (compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
   [(set_attr "type" "alu")
    (set_attr "mode" "SI")])
 
+;; See comment for addsi_1_zext why we do use nonimmediate_operand
+(define_insn "*andsi_2_zext"
+  [(set (reg 17)
+       (compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
+                        (match_operand:SI 2 "general_operand" "rim"))
+                (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
+   && ix86_binary_operator_ok (AND, SImode, operands)"
+  "and{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "SI")])
+
 (define_expand "andhi3"
   [(set (match_operand:HI 0 "nonimmediate_operand" "")
        (and:HI (match_operand:HI 1 "nonimmediate_operand" "")
 ;; %%% This used to optimize known byte-wide and operations to memory.
 ;; If this is considered useful, it should be done with splitters.
 
+(define_expand "iordi3"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+       (ior:DI (match_operand:DI 1 "nonimmediate_operand" "")
+               (match_operand:DI 2 "x86_64_general_operand" "")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT"
+  "ix86_expand_binary_operator (IOR, DImode, operands); DONE;")
+
+(define_insn "*iordi_1_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
+       (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
+               (match_operand:DI 2 "x86_64_general_operand" "re,rme")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT
+   && ix86_binary_operator_ok (IOR, DImode, operands)"
+  "or{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "DI")])
+
+(define_insn "*iordi_2_rex64"
+  [(set (reg 17)
+       (compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
+                        (match_operand:DI 2 "x86_64_general_operand" "rem,re"))
+                (const_int 0)))
+   (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
+       (ior:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT
+   && ix86_match_ccmode (insn, CCNOmode)
+   && ix86_binary_operator_ok (IOR, DImode, operands)"
+  "or{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "DI")])
+
+(define_insn "*iordi_3_rex64"
+  [(set (reg 17)
+       (compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
+                        (match_operand:DI 2 "x86_64_general_operand" "rem"))
+                (const_int 0)))
+   (clobber (match_scratch:DI 0 "=r"))]
+  "TARGET_64BIT
+   && ix86_match_ccmode (insn, CCNOmode)
+   && ix86_binary_operator_ok (IOR, DImode, operands)"
+  "or{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "DI")])
+
+
 (define_expand "iorsi3"
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
        (ior:SI (match_operand:SI 1 "nonimmediate_operand" "")
   [(set_attr "type" "alu")
    (set_attr "mode" "SI")])
 
+;; See comment for addsi_1_zext why we do use nonimmediate_operand
+(define_insn "*iorsi_1_zext"
+  [(set (match_operand:DI 0 "register_operand" "=rm")
+       (zero_extend:DI
+         (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
+                 (match_operand:SI 2 "general_operand" "rim"))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (IOR, SImode, operands)"
+  "or{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "SI")])
+
+(define_insn "*iorsi_1_zext_imm"
+  [(set (match_operand:DI 0 "register_operand" "=rm")
+       (ior:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
+               (match_operand:DI 2 "x86_64_zext_immediate_operand" "Z")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT"
+  "or{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "SI")])
+
 (define_insn "*iorsi_2"
   [(set (reg 17)
        (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
   [(set_attr "type" "alu")
    (set_attr "mode" "SI")])
 
+;; See comment for addsi_1_zext why we do use nonimmediate_operand
+;; ??? Special case for immediate operand is missing - it is tricky.
+(define_insn "*iorsi_2_zext"
+  [(set (reg 17)
+       (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
+                        (match_operand:SI 2 "general_operand" "rim"))
+                (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (ior:SI (match_dup 1) (match_dup 2))))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
+   && ix86_binary_operator_ok (IOR, SImode, operands)"
+  "or{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "SI")])
+
+(define_insn "*iorsi_2_zext_imm"
+  [(set (reg 17)
+       (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
+                        (match_operand 2 "x86_64_zext_immediate_operand" "Z"))
+                (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (ior:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
+   && ix86_binary_operator_ok (IOR, SImode, operands)"
+  "or{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "SI")])
+
 (define_insn "*iorsi_3"
   [(set (reg 17)
        (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
 ;; %%% This used to optimize known byte-wide and operations to memory.
 ;; If this is considered useful, it should be done with splitters.
 
+(define_expand "xordi3"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+       (xor:DI (match_operand:DI 1 "nonimmediate_operand" "")
+               (match_operand:DI 2 "x86_64_general_operand" "")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT"
+  "ix86_expand_binary_operator (XOR, DImode, operands); DONE;")
+
+(define_insn "*xordi_1_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
+       (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
+               (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT
+   && ix86_binary_operator_ok (XOR, DImode, operands)"
+  "@
+   xor{q}\\t{%2, %0|%0, %2} 
+   xor{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "DI,DI")])
+
+(define_insn "*xordi_2_rex64"
+  [(set (reg 17)
+       (compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
+                        (match_operand:DI 2 "x86_64_general_operand" "rem,re"))
+                (const_int 0)))
+   (set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
+       (xor:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT
+   && ix86_match_ccmode (insn, CCNOmode)
+   && ix86_binary_operator_ok (XOR, DImode, operands)"
+  "@
+   xor{q}\\t{%2, %0|%0, %2} 
+   xor{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "DI,DI")])
+
+(define_insn "*xordi_3_rex64"
+  [(set (reg 17)
+       (compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
+                        (match_operand:DI 2 "x86_64_general_operand" "rem"))
+                (const_int 0)))
+   (clobber (match_scratch:DI 0 "=r"))]
+  "TARGET_64BIT
+   && ix86_match_ccmode (insn, CCNOmode)
+   && ix86_binary_operator_ok (XOR, DImode, operands)"
+  "xor{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "DI")])
+
 (define_expand "xorsi3"
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
        (xor:SI (match_operand:SI 1 "nonimmediate_operand" "")
   [(set_attr "type" "alu")
    (set_attr "mode" "SI")])
 
+;; See comment for addsi_1_zext why we do use nonimmediate_operand
+;; Add speccase for immediates
+(define_insn "*xorsi_1_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+         (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
+                 (match_operand:SI 2 "general_operand" "rim"))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)"
+  "xor{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "SI")])
+
+(define_insn "*xorsi_1_zext_imm"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (xor:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
+               (match_operand:DI 2 "x86_64_zext_immediate_operand" "Z")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (XOR, SImode, operands)"
+  "xor{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "SI")])
+
 (define_insn "*xorsi_2"
   [(set (reg 17)
        (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
   [(set_attr "type" "alu")
    (set_attr "mode" "SI")])
 
+;; See comment for addsi_1_zext why we do use nonimmediate_operand
+;; ??? Special case for immediate operand is missing - it is tricky.
+(define_insn "*xorsi_2_zext"
+  [(set (reg 17)
+       (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
+                        (match_operand:SI 2 "general_operand" "rim"))
+                (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (xor:SI (match_dup 1) (match_dup 2))))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
+   && ix86_binary_operator_ok (XOR, SImode, operands)"
+  "xor{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "SI")])
+
+(define_insn "*xorsi_2_zext_imm"
+  [(set (reg 17)
+       (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
+                        (match_operand 2 "x86_64_zext_immediate_operand" "Z"))
+                (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (xor:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
+   && ix86_binary_operator_ok (XOR, SImode, operands)"
+  "xor{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "alu")
+   (set_attr "mode" "SI")])
+
 (define_insn "*xorsi_3"
   [(set (reg 17)
        (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
   "split_di (operands+1, 1, operands+2, operands+3);
    split_di (operands+0, 1, operands+0, operands+1);")
 
+(define_insn "*negdi2_1_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+       (neg:DI (match_operand:DI 1 "nonimmediate_operand" "0")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)"
+  "neg{q}\\t%0"
+  [(set_attr "type" "negnot")
+   (set_attr "mode" "DI")])
+
+;; The problem with neg is that it does not perform (compare x 0),
+;; it really performs (compare 0 x), which leaves us with the zero
+;; flag being the only useful item.
+
+(define_insn "*negdi2_cmpz_rex64"
+  [(set (reg:CCZ 17)
+       (compare:CCZ (neg:DI (match_operand:DI 1 "nonimmediate_operand" "0"))
+                    (const_int 0)))
+   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+       (neg:DI (match_dup 1)))]
+  "TARGET_64BIT && ix86_unary_operator_ok (NEG, DImode, operands)"
+  "neg{q}\\t%0"
+  [(set_attr "type" "negnot")
+   (set_attr "mode" "DI")])
+
+
 (define_expand "negsi2"
   [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
                   (neg:SI (match_operand:SI 1 "nonimmediate_operand" "")))
   [(set_attr "type" "negnot")
    (set_attr "mode" "SI")])
 
+;; Combine is quite creative about this pattern.
+(define_insn "*negsi2_1_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (lshiftrt:DI (neg:DI (ashift:DI (match_operand:DI 1 "register_operand" "0")
+                                       (const_int 32)))
+                    (const_int 32)))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)"
+  "neg{l}\\t%k0"
+  [(set_attr "type" "negnot")
+   (set_attr "mode" "SI")])
+
 ;; The problem with neg is that it does not perform (compare x 0),
 ;; it really performs (compare 0 x), which leaves us with the zero
 ;; flag being the only useful item.
   [(set_attr "type" "negnot")
    (set_attr "mode" "SI")])
 
+(define_insn "*negsi2_cmpz_zext"
+  [(set (reg:CCZ 17)
+       (compare:CCZ (lshiftrt:DI
+                      (neg:DI (ashift:DI
+                                (match_operand:DI 1 "register_operand" "0")
+                                (const_int 32)))
+                      (const_int 32))
+                    (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (lshiftrt:DI (neg:DI (ashift:DI (match_dup 1)
+                                       (const_int 32)))
+                    (const_int 32)))]
+  "TARGET_64BIT && ix86_unary_operator_ok (NEG, SImode, operands)"
+  "neg{l}\\t%k0"
+  [(set_attr "type" "negnot")
+   (set_attr "mode" "SI")])
+
 (define_expand "neghi2"
   [(parallel [(set (match_operand:HI 0 "nonimmediate_operand" "")
                   (neg:HI (match_operand:HI 1 "nonimmediate_operand" "")))
 \f
 ;; One complement instructions
 
+(define_expand "one_cmpldi2"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+       (not:DI (match_operand:DI 1 "nonimmediate_operand" "")))]
+  "TARGET_64BIT"
+  "ix86_expand_unary_operator (NOT, DImode, operands); DONE;")
+
+(define_insn "*one_cmpldi2_1_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+       (not:DI (match_operand:DI 1 "nonimmediate_operand" "0")))]
+  "TARGET_64BIT && ix86_unary_operator_ok (NOT, DImode, operands)"
+  "not{q}\\t%0"
+  [(set_attr "type" "negnot")
+   (set_attr "mode" "DI")])
+
+(define_insn "*one_cmpldi2_2_rex64"
+  [(set (reg 17)
+       (compare (not:DI (match_operand:DI 1 "nonimmediate_operand" "0"))
+                (const_int 0)))
+   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+       (not:DI (match_dup 1)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
+   && ix86_unary_operator_ok (NOT, DImode, operands)"
+  "#"
+  [(set_attr "type" "alu1")
+   (set_attr "mode" "DI")])
+
+(define_split
+  [(set (reg 17)
+       (compare (not:DI (match_operand:DI 1 "nonimmediate_operand" ""))
+                (const_int 0)))
+   (set (match_operand:DI 0 "nonimmediate_operand" "")
+       (not:DI (match_dup 1)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
+  [(parallel [(set (reg:CCNO 17)
+                  (compare:CCNO (xor:DI (match_dup 1) (const_int -1))
+                                (const_int 0)))
+             (set (match_dup 0)
+                  (xor:DI (match_dup 1) (const_int -1)))])]
+  "")
+
 (define_expand "one_cmplsi2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
        (not:SI (match_operand:SI 1 "nonimmediate_operand" "")))]
   [(set_attr "type" "negnot")
    (set_attr "mode" "SI")])
 
+;; ??? Currently never generated - xor is used instead.
+(define_insn "*one_cmplsi2_1_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (not:SI (match_operand:SI 1 "register_operand" "0"))))]
+  "TARGET_64BIT && ix86_unary_operator_ok (NOT, SImode, operands)"
+  "not{l}\\t%k0"
+  [(set_attr "type" "negnot")
+   (set_attr "mode" "SI")])
+
 (define_insn "*one_cmplsi2_2"
   [(set (reg 17)
        (compare (not:SI (match_operand:SI 1 "nonimmediate_operand" "0"))
                   (xor:SI (match_dup 1) (const_int -1)))])]
   "")
 
+;; ??? Currently never generated - xor is used instead.
+(define_insn "*one_cmplsi2_2_zext"
+  [(set (reg 17)
+       (compare (not:SI (match_operand:SI 1 "register_operand" "0"))
+                (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (not:SI (match_dup 1))))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
+   && ix86_unary_operator_ok (NOT, SImode, operands)"
+  "#"
+  [(set_attr "type" "alu1")
+   (set_attr "mode" "SI")])
+
+(define_split
+  [(set (reg 17)
+       (compare (not:SI (match_operand:SI 1 "register_operand" ""))
+                (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "")
+       (zero_extend:DI (not:SI (match_dup 1))))]
+  "ix86_match_ccmode (insn, CCNOmode)"
+  [(parallel [(set (reg:CCNO 17)
+                  (compare:CCNO (xor:SI (match_dup 1) (const_int -1))
+                                (const_int 0)))
+             (set (match_dup 0)
+                  (zero_extend:DI (xor:SI (match_dup 1) (const_int -1))))])]
+  "")
+
 (define_expand "one_cmplhi2"
   [(set (match_operand:HI 0 "nonimmediate_operand" "")
        (not:HI (match_operand:HI 1 "nonimmediate_operand" "")))]