OSDN Git Service

* i386.md (ashldi3, ashrdi3, lshrdi3): Change predicates to
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 25 Mar 2001 13:03:31 +0000 (13:03 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 25 Mar 2001 13:03:31 +0000 (13:03 +0000)
shiftdi_operand;
use ix86_expand_binary_operator
(?sh??i_?): Disable for 64bit.
* i386.h (PREDICATE_CODES): Add shiftdi_operand.
* i386.c (shiftdi_operand): New predicate.

* (ashldi3_1_rex64, ashldi3_cmp_rex64, ashlsi3_1_zext, ashlsi3_cmp_zext,
ashrdi3_63_rex64, ashrdi3_1_one_bit_rex64, ashrdi3_1_rex64,
ashrdi3_one_bit_cmp_rex64, ashrdi3_cmp_rex64, ashrsi3_31_zext,
ashrsi3_1_one_bit_zext, ashrsi3_1_zext, ashrsi3_one_bit_cmp_zext,
ashrsi3_cmp_zext, lshrdi3_1_one_bit_rex64, lshrdi3_1_rex64,
lshrdi3_cmp_one_bit_rex64, lshrdi3_cmp_rex64, lshrsi3_1_one_bit_zext,
lshrsi3_1_zext, lshrsi3_cmp_one_bit_zext, lshrsi3_cmp_zext,
rotlsi3_1_one_bit_rex64, rotldi3_1_rex64,
rotlsi3_1_one_bit_zext, rotlsi3_1_zext, rotrdi3_1_one_bit_rex64,
rotrdi3_1_rex64, rotrsi3_1_one_bit_zext, rotrsi3_1_zext): New patterns.
(rotldi3, rotrdi3): New expanders.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@40827 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/i386/i386.md

index e681730..bd87ea7 100644 (file)
@@ -1,3 +1,24 @@
+Sun Mar 25 15:01:40 CEST 2001  Jan Hubicka  <jh@suse.cz>
+
+       * i386.md (ashldi3, ashrdi3, lshrdi3): Change predicates to
+       shiftdi_operand;
+       use ix86_expand_binary_operator
+       (?sh??i_?): Disable for 64bit.
+       * i386.h (PREDICATE_CODES): Add shiftdi_operand.
+       * i386.c (shiftdi_operand): New predicate.
+
+       * (ashldi3_1_rex64, ashldi3_cmp_rex64, ashlsi3_1_zext, ashlsi3_cmp_zext,
+       ashrdi3_63_rex64, ashrdi3_1_one_bit_rex64, ashrdi3_1_rex64,
+       ashrdi3_one_bit_cmp_rex64, ashrdi3_cmp_rex64, ashrsi3_31_zext,
+       ashrsi3_1_one_bit_zext, ashrsi3_1_zext, ashrsi3_one_bit_cmp_zext,
+       ashrsi3_cmp_zext, lshrdi3_1_one_bit_rex64, lshrdi3_1_rex64,
+       lshrdi3_cmp_one_bit_rex64, lshrdi3_cmp_rex64, lshrsi3_1_one_bit_zext,
+       lshrsi3_1_zext, lshrsi3_cmp_one_bit_zext, lshrsi3_cmp_zext,
+       rotlsi3_1_one_bit_rex64, rotldi3_1_rex64,
+       rotlsi3_1_one_bit_zext, rotlsi3_1_zext, rotrdi3_1_one_bit_rex64,
+       rotrdi3_1_rex64, rotrsi3_1_one_bit_zext, rotrsi3_1_zext): New patterns.
+       (rotldi3, rotrdi3): New expanders.
+
 Sun Mar 25 14:25:33 CEST 2001  Jan Hubicka  <jh@suse.cz>
 
        * i386.md (movstrsi): Move offline.
index 962d053..fa6633d 100644 (file)
@@ -1411,6 +1411,20 @@ incdec_operand (op, mode)
   return 0;
 }
 
+/* Return nonzero if OP is acceptable as operand of DImode shift
+   expander.  */
+
+int
+shiftdi_operand (op, mode)
+     rtx op;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  if (TARGET_64BIT)
+    return nonimmediate_operand (op, mode);
+  else
+    return register_operand (op, mode);
+}
+
 /* Return false if this is the stack pointer, or any other fake
    register eliminable to the stack pointer.  Otherwise, this is
    a register operand.
index efc1e65..7312108 100644 (file)
@@ -3036,6 +3036,7 @@ do { long l;                                              \
                                   SYMBOL_REF, LABEL_REF, CONST}},      \
   {"x86_64_zext_immediate_operand", {CONST_INT, CONST_DOUBLE, CONST,   \
                                       SYMBOL_REF, LABEL_REF}},         \
+  {"shiftdi_operand", {SUBREG, REG, MEM}},                             \
   {"const_int_1_operand", {CONST_INT}},                                        \
   {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},                        \
   {"aligned_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,     \
index 7a4e0fc..4850ca4 100644 (file)
 ;; than 31.
 
 (define_expand "ashldi3"
-  [(parallel [(set (match_operand:DI 0 "register_operand" "")
-                  (ashift:DI (match_operand:DI 1 "register_operand" "")
+  [(parallel [(set (match_operand:DI 0 "shiftdi_operand" "")
+                  (ashift:DI (match_operand:DI 1 "shiftdi_operand" "")
                              (match_operand:QI 2 "nonmemory_operand" "")))
              (clobber (reg:CC 17))])]
   ""
       emit_insn (gen_ashldi3_1 (operands[0], operands[1], operands[2]));
       DONE;
     }
-  ix86_expand_binary_operator (ASHIFT, DImode, operands); DONE;
+  ix86_expand_binary_operator (ASHIFT, DImode, operands);
+  DONE;
 }")
 
+(define_insn "*ashldi3_1_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
+       (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0,r")
+                  (match_operand:QI 2 "nonmemory_operand" "c,M")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFT, DImode, operands)"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_ALU:
+      if (operands[2] != const1_rtx)
+       abort ();
+      if (!rtx_equal_p (operands[0], operands[1]))
+       abort ();
+      return \"add{q}\\t{%0, %0|%0, %0}\";
+
+    case TYPE_LEA:
+      if (GET_CODE (operands[2]) != CONST_INT
+         || (unsigned HOST_WIDE_INT) INTVAL (operands[2]) > 3)
+       abort ();
+      operands[1] = gen_rtx_MULT (DImode, operands[1],
+                                 GEN_INT (1 << INTVAL (operands[2])));
+      return \"lea{q}\\t{%a1, %0|%0, %a1}\";
+
+    default:
+      if (REG_P (operands[2]))
+       return \"sal{q}\\t{%b2, %0|%0, %b2}\";
+      else if (GET_CODE (operands[2]) == CONST_INT
+              && INTVAL (operands[2]) == 1
+              && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+       return \"sal{q}\\t%0\";
+      else
+       return \"sal{q}\\t{%2, %0|%0, %2}\";
+    }
+}"
+  [(set (attr "type")
+     (cond [(eq_attr "alternative" "1")
+             (const_string "lea")
+            (and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+                         (const_int 0))
+                     (match_operand 0 "register_operand" ""))
+                (match_operand 2 "const1_operand" ""))
+             (const_string "alu")
+          ]
+          (const_string "ishift")))
+   (set_attr "mode" "DI")])
+
+;; Convert lea to the lea pattern to avoid flags dependency.
+(define_split
+  [(set (match_operand:DI 0 "register_operand" "")
+       (ashift:DI (match_operand:DI 1 "register_operand" "")
+                  (match_operand:QI 2 "immediate_operand" "")))
+   (clobber (reg:CC 17))]
+  "reload_completed
+   && TARGET_64BIT
+   && true_regnum (operands[0]) != true_regnum (operands[1])"
+  [(set (match_dup 0)
+       (mult:DI (match_dup 1)
+                (match_dup 2)))]
+  "operands[2] = GEN_INT (1 << INTVAL (operands[2]));")
+
+;; This pattern can't accept a variable shift count, since shifts by
+;; zero don't affect the flags.  We assume that shifts by constant
+;; zero are optimized away.
+(define_insn "*ashldi3_cmp_rex64"
+  [(set (reg 17)
+       (compare
+         (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+                    (match_operand:QI 2 "immediate_operand" "e"))
+         (const_int 0)))
+   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+       (ashift:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+   && ix86_binary_operator_ok (ASHIFT, DImode, operands)"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_ALU:
+      if (operands[2] != const1_rtx)
+       abort ();
+      return \"add{q}\\t{%0, %0|%0, %0}\";
+
+    default:
+      if (REG_P (operands[2]))
+       return \"sal{q}\\t{%b2, %0|%0, %b2}\";
+      else if (GET_CODE (operands[2]) == CONST_INT
+              && INTVAL (operands[2]) == 1
+              && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+       return \"sal{q}\\t%0\";
+      else
+       return \"sal{q}\\t{%2, %0|%0, %2}\";
+    }
+}"
+  [(set (attr "type")
+     (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+                         (const_int 0))
+                     (match_operand 0 "register_operand" ""))
+                (match_operand 2 "const1_operand" ""))
+             (const_string "alu")
+          ]
+          (const_string "ishift")))
+   (set_attr "mode" "DI")])
+
 (define_insn "ashldi3_1"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (ashift:DI (match_operand:DI 1 "register_operand" "0")
                   (match_operand:QI 2 "nonmemory_operand" "Jc")))
    (clobber (match_scratch:SI 3 "=&r"))
    (clobber (reg:CC 17))]
-  "TARGET_CMOVE"
+  "!TARGET_64BIT && TARGET_CMOVE"
   "#"
   [(set_attr "type" "multi")])
 
        (ashift:DI (match_operand:DI 1 "register_operand" "0")
                   (match_operand:QI 2 "nonmemory_operand" "Jc")))
    (clobber (reg:CC 17))]
-  ""
+  "!TARGET_64BIT"
   "#"
   [(set_attr "type" "multi")])
 
                   (match_operand:QI 2 "nonmemory_operand" "")))
    (clobber (match_scratch:SI 3 ""))
    (clobber (reg:CC 17))]
-  "TARGET_CMOVE && reload_completed"
+  "!TARGET_64BIT && TARGET_CMOVE && reload_completed"
   [(const_int 0)]
   "ix86_split_ashldi (operands, operands[3]); DONE;")
 
        (ashift:DI (match_operand:DI 1 "register_operand" "")
                   (match_operand:QI 2 "nonmemory_operand" "")))
    (clobber (reg:CC 17))]
-  "reload_completed"
+  "!TARGET_64BIT && reload_completed"
   [(const_int 0)]
   "ix86_split_ashldi (operands, NULL_RTX); DONE;")
 
   DONE;
 }")
 
+(define_insn "*ashlsi3_1_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (zero_extend:DI (ashift:SI (match_operand:SI 1 "register_operand" "0,r")
+                       (match_operand:QI 2 "nonmemory_operand" "cI,M"))))
+   (clobber (reg:CC 17))]
+  "ix86_binary_operator_ok (ASHIFT, SImode, operands) && TARGET_64BIT"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_ALU:
+      if (operands[2] != const1_rtx)
+       abort ();
+      return \"add{l}\\t{%k0, %k0|%k0, %k0}\";
+
+    case TYPE_LEA:
+      return \"#\";
+
+    default:
+      if (REG_P (operands[2]))
+       return \"sal{l}\\t{%b2, %k0|%k0, %b2}\";
+      else if (GET_CODE (operands[2]) == CONST_INT
+              && INTVAL (operands[2]) == 1
+              && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+       return \"sal{l}\\t%k0\";
+      else
+       return \"sal{l}\\t{%2, %k0|%k0, %2}\";
+    }
+}"
+  [(set (attr "type")
+     (cond [(eq_attr "alternative" "1")
+             (const_string "lea")
+            (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+                    (const_int 0))
+                (match_operand 2 "const1_operand" ""))
+             (const_string "alu")
+          ]
+          (const_string "ishift")))
+   (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 (ashift (match_operand 1 "register_operand" "")
+                               (match_operand:QI 2 "const_int_operand" ""))))
+   (clobber (reg:CC 17))]
+  "reload_completed
+   && true_regnum (operands[0]) != true_regnum (operands[1])"
+  [(set (match_dup 0) (zero_extend:DI (subreg:SI (mult:SI (match_dup 1) (match_dup 2)) 0)))]
+  "
+{
+  operands[1] = gen_lowpart (Pmode, operands[1]);
+  operands[2] = GEN_INT (1 << INTVAL (operands[2]));
+}")
+
 ;; This pattern can't accept a variable shift count, since shifts by
 ;; zero don't affect the flags.  We assume that shifts by constant
 ;; zero are optimized away.
           (const_string "ishift")))
    (set_attr "mode" "SI")])
 
+(define_insn "*ashlsi3_cmp_zext"
+  [(set (reg 17)
+       (compare
+         (ashift:SI (match_operand:SI 1 "register_operand" "0")
+                    (match_operand:QI 2 "immediate_operand" "I"))
+         (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+   && ix86_binary_operator_ok (ASHIFT, SImode, operands)"
+  "*
+{
+  switch (get_attr_type (insn))
+    {
+    case TYPE_ALU:
+      if (operands[2] != const1_rtx)
+       abort ();
+      return \"add{l}\\t{%k0, %k0|%k0, %k0}\";
+
+    default:
+      if (REG_P (operands[2]))
+       return \"sal{l}\\t{%b2, %k0|%k0, %b2}\";
+      else if (GET_CODE (operands[2]) == CONST_INT
+              && INTVAL (operands[2]) == 1
+              && (TARGET_PENTIUM || TARGET_PENTIUMPRO))
+       return \"sal{l}\\t%k0\";
+      else
+       return \"sal{l}\\t{%2, %k0|%k0, %2}\";
+    }
+}"
+  [(set (attr "type")
+     (cond [(and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD")
+                    (const_int 0))
+                (match_operand 2 "const1_operand" ""))
+             (const_string "alu")
+          ]
+          (const_string "ishift")))
+   (set_attr "mode" "SI")])
+
 (define_expand "ashlhi3"
   [(set (match_operand:HI 0 "nonimmediate_operand" "")
        (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "")
 ;; See comment above `ashldi3' about how this works.
 
 (define_expand "ashrdi3"
-  [(parallel [(set (match_operand:DI 0 "register_operand" "=r")
-                  (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
-                               (match_operand:QI 2 "nonmemory_operand" "Jc")))
+  [(parallel [(set (match_operand:DI 0 "shiftdi_operand" "")
+                  (ashiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
+                               (match_operand:QI 2 "nonmemory_operand" "")))
              (clobber (reg:CC 17))])]
   ""
   "
 {
-  if (TARGET_CMOVE && ! immediate_operand (operands[2], QImode))
+  if (!TARGET_64BIT && TARGET_CMOVE && ! immediate_operand (operands[2], QImode))
     {
       emit_insn (gen_ashrdi3_1 (operands[0], operands[1], operands[2]));
       DONE;
     }
+  ix86_expand_binary_operator (ASHIFTRT, DImode, operands);
+  DONE;
 }")
 
+(define_insn "ashrdi3_63_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=*d,rm")
+       (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "*a,0")
+                    (match_operand:DI 2 "const_int_operand" "i,i")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && INTVAL (operands[2]) == 63 && (TARGET_USE_CLTD || optimize_size)
+   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
+  "@
+   {cqto|cqo}
+   sar{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "imovx,ishift")
+   (set_attr "prefix_0f" "0,*")
+   (set_attr "length_immediate" "0,*")
+   (set_attr "modrm" "0,1")
+   (set_attr "mode" "DI")])
+
+(define_insn "*ashrdi3_1_one_bit_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+       (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+                    (match_operand:QI 2 "const_int_1_operand" "")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)
+   && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+  "sar{q}\\t%0"
+  [(set_attr "type" "ishift")
+   (set (attr "length") 
+     (if_then_else (match_operand:DI 0 "register_operand" "") 
+       (const_string "2")
+       (const_string "*")))])
+
+(define_insn "*ashrdi3_1_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
+       (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
+                    (match_operand:QI 2 "nonmemory_operand" "n,c")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
+  "@
+   sar{q}\\t{%2, %0|%0, %2}
+   sar{q}\\t{%b2, %0|%0, %b2}"
+  [(set_attr "type" "ishift")
+   (set_attr "mode" "DI")])
+
+;; This pattern can't accept a variable shift count, since shifts by
+;; zero don't affect the flags.  We assume that shifts by constant
+;; zero are optimized away.
+(define_insn "*ashrdi3_one_bit_cmp_rex64"
+  [(set (reg 17)
+       (compare
+         (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+                      (match_operand:QI 2 "const_int_1_operand" ""))
+         (const_int 0)))
+   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+       (ashiftrt:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+   && (TARGET_PENTIUM || TARGET_PENTIUMPRO)
+   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
+  "sar{q}\\t%0"
+  [(set_attr "type" "ishift")
+   (set (attr "length") 
+     (if_then_else (match_operand:DI 0 "register_operand" "") 
+       (const_string "2")
+       (const_string "*")))])
+
+;; This pattern can't accept a variable shift count, since shifts by
+;; zero don't affect the flags.  We assume that shifts by constant
+;; zero are optimized away.
+(define_insn "*ashrdi3_cmp_rex64"
+  [(set (reg 17)
+       (compare
+         (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+                      (match_operand:QI 2 "const_int_operand" "n"))
+         (const_int 0)))
+   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+       (ashiftrt:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+   && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
+  "sar{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "ishift")
+   (set_attr "mode" "DI")])
+
+
 (define_insn "ashrdi3_1"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
                     (match_operand:QI 2 "nonmemory_operand" "Jc")))
    (clobber (match_scratch:SI 3 "=&r"))
    (clobber (reg:CC 17))]
-  "TARGET_CMOVE"
+  "!TARGET_64BIT && TARGET_CMOVE"
   "#"
   [(set_attr "type" "multi")])
 
        (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
                     (match_operand:QI 2 "nonmemory_operand" "Jc")))
    (clobber (reg:CC 17))]
-  ""
+  "!TARGET_64BIT"
   "#"
   [(set_attr "type" "multi")])
 
                     (match_operand:QI 2 "nonmemory_operand" "")))
    (clobber (match_scratch:SI 3 ""))
    (clobber (reg:CC 17))]
-  "TARGET_CMOVE && reload_completed"
+  "!TARGET_64BIT && TARGET_CMOVE && reload_completed"
   [(const_int 0)]
   "ix86_split_ashrdi (operands, operands[3]); DONE;")
 
        (ashiftrt:DI (match_operand:DI 1 "register_operand" "")
                     (match_operand:QI 2 "nonmemory_operand" "")))
    (clobber (reg:CC 17))]
-  "reload_completed"
+  "!TARGET_64BIT && reload_completed"
   [(const_int 0)]
   "ix86_split_ashrdi (operands, NULL_RTX); DONE;")
 
    (set_attr "modrm" "0,1")
    (set_attr "mode" "SI")])
 
+(define_insn "*ashrsi3_31_zext"
+  [(set (match_operand:DI 0 "register_operand" "=*d,r")
+       (zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "*a,0")
+                                    (match_operand:SI 2 "const_int_operand" "i,i"))))
+   (clobber (reg:CC 17))]
+  "INTVAL (operands[2]) == 31 && (TARGET_USE_CLTD || optimize_size)
+   && TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
+  "@
+   {cltd|cdq}
+   sar{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "imovx,ishift")
+   (set_attr "prefix_0f" "0,*")
+   (set_attr "length_immediate" "0,*")
+   (set_attr "modrm" "0,1")
+   (set_attr "mode" "SI")])
+
 (define_expand "ashrsi3"
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
        (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "")
        (const_string "2")
        (const_string "*")))])
 
+(define_insn "*ashrsi3_1_one_bit_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+                                    (match_operand:QI 2 "const_int_1_operand" ""))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)
+   && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+  "sar{l}\\t%k0"
+  [(set_attr "type" "ishift")
+   (set_attr "length" "2")])
+
 (define_insn "*ashrsi3_1"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
        (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
   [(set_attr "type" "ishift")
    (set_attr "mode" "SI")])
 
+(define_insn "*ashrsi3_1_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (zero_extend:DI (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
+                                    (match_operand:QI 2 "nonmemory_operand" "I,c"))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
+  "@
+   sar{l}\\t{%2, %k0|%k0, %2}
+   sar{l}\\t{%b2, %k0|%k0, %b2}"
+  [(set_attr "type" "ishift")
+   (set_attr "mode" "SI")])
+
 ;; This pattern can't accept a variable shift count, since shifts by
 ;; zero don't affect the flags.  We assume that shifts by constant
 ;; zero are optimized away.
        (const_string "2")
        (const_string "*")))])
 
+(define_insn "*ashrsi3_one_bit_cmp_zext"
+  [(set (reg 17)
+       (compare
+         (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+                      (match_operand:QI 2 "const_int_1_operand" ""))
+         (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)
+   && (TARGET_PENTIUM || TARGET_PENTIUMPRO)
+   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
+  "sar{l}\\t%k0"
+  [(set_attr "type" "ishift")
+   (set_attr "length" "2")])
+
 ;; This pattern can't accept a variable shift count, since shifts by
 ;; zero don't affect the flags.  We assume that shifts by constant
 ;; zero are optimized away.
   [(set_attr "type" "ishift")
    (set_attr "mode" "SI")])
 
+(define_insn "*ashrsi3_cmp_zext"
+  [(set (reg 17)
+       (compare
+         (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
+                      (match_operand:QI 2 "immediate_operand" "I"))
+         (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+   && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
+  "sar{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "ishift")
+   (set_attr "mode" "SI")])
+
 (define_expand "ashrhi3"
   [(set (match_operand:HI 0 "nonimmediate_operand" "")
        (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
 ;; See comment above `ashldi3' about how this works.
 
 (define_expand "lshrdi3"
-  [(parallel [(set (match_operand:DI 0 "register_operand" "=r")
-                  (lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
-                               (match_operand:QI 2 "nonmemory_operand" "Jc")))
+  [(parallel [(set (match_operand:DI 0 "shiftdi_operand" "")
+                  (lshiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
+                               (match_operand:QI 2 "nonmemory_operand" "")))
              (clobber (reg:CC 17))])]
   ""
   "
 {
-  if (TARGET_CMOVE && ! immediate_operand (operands[2], QImode))
+  if (!TARGET_64BIT && TARGET_CMOVE && ! immediate_operand (operands[2], QImode))
     {
       emit_insn (gen_lshrdi3_1 (operands[0], operands[1], operands[2]));
       DONE;
     }
+  ix86_expand_binary_operator (LSHIFTRT, DImode, operands);
+  DONE;
 }")
 
+(define_insn "*lshrdi3_1_one_bit_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+       (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+                    (match_operand:QI 2 "const_int_1_operand" "")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+   && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+  "shr{q}\\t%0"
+  [(set_attr "type" "ishift")
+   (set (attr "length") 
+     (if_then_else (match_operand:DI 0 "register_operand" "") 
+       (const_string "2")
+       (const_string "*")))])
+
+(define_insn "*lshrdi3_1_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
+       (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
+                    (match_operand:QI 2 "nonmemory_operand" "J,c")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+  "@
+   shr{q}\\t{%2, %0|%0, %2}
+   shr{q}\\t{%b2, %0|%0, %b2}"
+  [(set_attr "type" "ishift")
+   (set_attr "mode" "DI")])
+
+;; This pattern can't accept a variable shift count, since shifts by
+;; zero don't affect the flags.  We assume that shifts by constant
+;; zero are optimized away.
+(define_insn "*lshrdi3_cmp_one_bit_rex64"
+  [(set (reg 17)
+       (compare
+         (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+                      (match_operand:QI 2 "const_int_1_operand" ""))
+         (const_int 0)))
+   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+       (lshiftrt:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+   && (TARGET_PENTIUM || TARGET_PENTIUMPRO)
+   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+  "shr{q}\\t%0"
+  [(set_attr "type" "ishift")
+   (set (attr "length") 
+     (if_then_else (match_operand:DI 0 "register_operand" "") 
+       (const_string "2")
+       (const_string "*")))])
+
+;; This pattern can't accept a variable shift count, since shifts by
+;; zero don't affect the flags.  We assume that shifts by constant
+;; zero are optimized away.
+(define_insn "*lshrdi3_cmp_rex64"
+  [(set (reg 17)
+       (compare
+         (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+                      (match_operand:QI 2 "const_int_operand" "e"))
+         (const_int 0)))
+   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+       (lshiftrt:DI (match_dup 1) (match_dup 2)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+  "shr{q}\\t{%2, %0|%0, %2}"
+  [(set_attr "type" "ishift")
+   (set_attr "mode" "DI")])
+
 (define_insn "lshrdi3_1"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
        (const_string "2")
        (const_string "*")))])
 
+(define_insn "*lshrsi3_1_one_bit_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (lshiftrt:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "0"))
+                    (match_operand:QI 2 "const_int_1_operand" "")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)
+   && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+  "shr{l}\\t%k0"
+  [(set_attr "type" "ishift")
+   (set_attr "length" "2")])
+
 (define_insn "*lshrsi3_1"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
        (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
   [(set_attr "type" "ishift")
    (set_attr "mode" "SI")])
 
+(define_insn "*lshrsi3_1_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (zero_extend:DI
+         (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
+                      (match_operand:QI 2 "nonmemory_operand" "I,c"))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+  "@
+   shr{l}\\t{%2, %k0|%k0, %2}
+   shr{l}\\t{%b2, %k0|%k0, %b2}"
+  [(set_attr "type" "ishift")
+   (set_attr "mode" "SI")])
+
 ;; This pattern can't accept a variable shift count, since shifts by
 ;; zero don't affect the flags.  We assume that shifts by constant
 ;; zero are optimized away.
        (const_string "2")
        (const_string "*")))])
 
+(define_insn "*lshrsi3_cmp_one_bit_zext"
+  [(set (reg 17)
+       (compare
+         (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+                      (match_operand:QI 2 "const_int_1_operand" ""))
+         (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+   && (TARGET_PENTIUM || TARGET_PENTIUMPRO)
+   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+  "shr{l}\\t%k0"
+  [(set_attr "type" "ishift")
+   (set_attr "length" "2")])
+
 ;; This pattern can't accept a variable shift count, since shifts by
 ;; zero don't affect the flags.  We assume that shifts by constant
 ;; zero are optimized away.
   [(set_attr "type" "ishift")
    (set_attr "mode" "SI")])
 
+(define_insn "*lshrsi3_cmp_zext"
+  [(set (reg 17)
+       (compare
+         (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
+                      (match_operand:QI 2 "immediate_operand" "I"))
+         (const_int 0)))
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))]
+  "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode)
+   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
+  "shr{l}\\t{%2, %k0|%k0, %2}"
+  [(set_attr "type" "ishift")
+   (set_attr "mode" "SI")])
+
 (define_expand "lshrhi3"
   [(set (match_operand:HI 0 "nonimmediate_operand" "")
        (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "")
 \f
 ;; Rotate instructions
 
+(define_expand "rotldi3"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+       (rotate:DI (match_operand:DI 1 "nonimmediate_operand" "")
+                  (match_operand:QI 2 "nonmemory_operand" "")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT"
+  "ix86_expand_binary_operator (ROTATE, DImode, operands); DONE;")
+
+(define_insn "*rotlsi3_1_one_bit_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+       (rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+                  (match_operand:QI 2 "const_int_1_operand" "")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands)
+   && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+  "rol{q}\\t%0"
+  [(set_attr "type" "ishift")
+   (set (attr "length") 
+     (if_then_else (match_operand:DI 0 "register_operand" "") 
+       (const_string "2")
+       (const_string "*")))])
+
+(define_insn "*rotldi3_1_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
+       (rotate:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
+                  (match_operand:QI 2 "nonmemory_operand" "e,c")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, DImode, operands)"
+  "@
+   rol{q}\\t{%2, %0|%0, %2}
+   rol{q}\\t{%b2, %0|%0, %b2}"
+  [(set_attr "type" "ishift")
+   (set_attr "mode" "DI")])
+
 (define_expand "rotlsi3"
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
        (rotate:SI (match_operand:SI 1 "nonimmediate_operand" "")
        (const_string "2")
        (const_string "*")))])
 
+(define_insn "*rotlsi3_1_one_bit_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+         (rotate:SI (match_operand:SI 1 "register_operand" "0")
+                    (match_operand:QI 2 "const_int_1_operand" ""))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands)
+   && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+  "rol{l}\\t%k0"
+  [(set_attr "type" "ishift")
+   (set_attr "length" "2")])
+
 (define_insn "*rotlsi3_1"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
        (rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
   [(set_attr "type" "ishift")
    (set_attr "mode" "SI")])
 
+(define_insn "*rotlsi3_1_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (zero_extend:DI
+         (rotate:SI (match_operand:SI 1 "register_operand" "0,0")
+                    (match_operand:QI 2 "nonmemory_operand" "I,c"))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (ROTATE, SImode, operands)"
+  "@
+   rol{l}\\t{%2, %k0|%k0, %2}
+   rol{l}\\t{%b2, %k0|%k0, %b2}"
+  [(set_attr "type" "ishift")
+   (set_attr "mode" "SI")])
+
 (define_expand "rotlhi3"
   [(set (match_operand:HI 0 "nonimmediate_operand" "")
        (rotate:HI (match_operand:HI 1 "nonimmediate_operand" "")
   [(set_attr "type" "ishift")
    (set_attr "mode" "QI")])
 
+(define_expand "rotrdi3"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+       (rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "")
+                    (match_operand:QI 2 "nonmemory_operand" "")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT"
+  "ix86_expand_binary_operator (ROTATERT, DImode, operands); DONE;")
+
+(define_insn "*rotrdi3_1_one_bit_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+       (rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0")
+                    (match_operand:QI 2 "const_int_1_operand" "")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands)
+   && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+  "ror{q}\\t%0"
+  [(set_attr "type" "ishift")
+   (set (attr "length") 
+     (if_then_else (match_operand:DI 0 "register_operand" "") 
+       (const_string "2")
+       (const_string "*")))])
+
+(define_insn "*rotrdi3_1_rex64"
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
+       (rotatert:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
+                    (match_operand:QI 2 "nonmemory_operand" "J,c")))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, DImode, operands)"
+  "@
+   ror{q}\\t{%2, %0|%0, %2}
+   ror{q}\\t{%b2, %0|%0, %b2}"
+  [(set_attr "type" "ishift")
+   (set_attr "mode" "DI")])
+
 (define_expand "rotrsi3"
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
        (rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "")
        (const_string "2")
        (const_string "*")))])
 
+(define_insn "*rotrsi3_1_one_bit_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
+                      (match_operand:QI 2 "const_int_1_operand" ""))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands)
+   && (TARGET_PENTIUM || TARGET_PENTIUMPRO)"
+  "ror{l}\\t%k0"
+  [(set_attr "type" "ishift")
+   (set (attr "length") 
+     (if_then_else (match_operand:SI 0 "register_operand" "") 
+       (const_string "2")
+       (const_string "*")))])
+
 (define_insn "*rotrsi3_1"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
        (rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
   [(set_attr "type" "ishift")
    (set_attr "mode" "SI")])
 
+(define_insn "*rotrsi3_1_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (zero_extend:DI
+         (rotatert:SI (match_operand:SI 1 "register_operand" "0,0")
+                      (match_operand:QI 2 "nonmemory_operand" "I,c"))))
+   (clobber (reg:CC 17))]
+  "TARGET_64BIT && ix86_binary_operator_ok (ROTATERT, SImode, operands)"
+  "@
+   ror{l}\\t{%2, %k0|%k0, %2}
+   ror{l}\\t{%b2, %k0|%k0, %b2}"
+  [(set_attr "type" "ishift")
+   (set_attr "mode" "SI")])
+
 (define_expand "rotrhi3"
   [(set (match_operand:HI 0 "nonimmediate_operand" "")
        (rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "")
                 (const_int 4)))
    (use (reg:SI 19))]
   "!TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
-  "movsl|movsd"
+  "{movsl|movsd}"
   [(set_attr "type" "str")
    (set_attr "mode" "SI")
    (set_attr "memory" "both")])
                 (const_int 4)))
    (use (reg:SI 19))]
   "TARGET_64BIT && (TARGET_SINGLE_STRINGOP || optimize_size)"
-  "movsl|movsd"
+  "{movsl|movsd}"
   [(set_attr "type" "str")
    (set_attr "mode" "SI")
    (set_attr "memory" "both")])