OSDN Git Service

* config/i386/i386.md (lshr<mode>3): Macroize expander from
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.md
index 95220d3..03e4f38 100644 (file)
    (set_attr "modrm" "0,1")
    (set_attr "mode" "DI")])
 
-(define_insn "*ashrsi3_cvt_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:QI 2 "const_int_operand" ""))))
+(define_insn "ashrsi3_cvt"
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=*d,rm")
+       (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "*a,0")
+                    (match_operand:QI 2 "const_int_operand" "")))
    (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT && INTVAL (operands[2]) == 31
+  "INTVAL (operands[2]) == 31
    && (TARGET_USE_CLTD || optimize_function_for_size_p (cfun))
    && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
   "@
    {cltd|cdq}
-   sar{l}\t{%2, %k0|%k0, %2}"
+   sar{l}\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" "SI")])
 
-(define_insn "ashrsi3_cvt"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=*d,rm")
-       (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "*a,0")
-                    (match_operand:QI 2 "const_int_operand" "")))
+(define_insn "*ashrsi3_cvt_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:QI 2 "const_int_operand" ""))))
    (clobber (reg:CC FLAGS_REG))]
-  "INTVAL (operands[2]) == 31
+  "TARGET_64BIT && INTVAL (operands[2]) == 31
    && (TARGET_USE_CLTD || optimize_function_for_size_p (cfun))
    && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
   "@
    {cltd|cdq}
-   sar{l}\t{%2, %0|%0, %2}"
+   sar{l}\t{%2, %k0|%k0, %2}"
   [(set_attr "type" "imovx,ishift")
    (set_attr "prefix_0f" "0,*")
    (set_attr "length_immediate" "0,*")
 
 ;; See comment above `ashldi3' about how this works.
 
-(define_expand "lshrti3"
-  [(set (match_operand:TI 0 "register_operand" "")
-       (lshiftrt:TI (match_operand:TI 1 "register_operand" "")
-                    (match_operand:QI 2 "nonmemory_operand" "")))]
-  "TARGET_64BIT"
-  "ix86_expand_binary_operator (LSHIFTRT, TImode, operands); DONE;")
-
-(define_insn "*lshrti3_1"
-  [(set (match_operand:TI 0 "register_operand" "=r")
-       (lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
-                    (match_operand:QI 2 "nonmemory_operand" "Oc")))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT"
-  "#"
-  [(set_attr "type" "multi")])
-
-(define_peephole2
-  [(match_scratch:DI 3 "r")
-   (parallel [(set (match_operand:TI 0 "register_operand" "")
-                  (lshiftrt:TI (match_operand:TI 1 "register_operand" "")
-                               (match_operand:QI 2 "nonmemory_operand" "")))
-             (clobber (reg:CC FLAGS_REG))])
-   (match_dup 3)]
-  "TARGET_64BIT"
-  [(const_int 0)]
-  "ix86_split_lshr (operands, operands[3], TImode); DONE;")
-
-(define_split
-  [(set (match_operand:TI 0 "register_operand" "")
-       (lshiftrt:TI (match_operand:TI 1 "register_operand" "")
-                    (match_operand:QI 2 "nonmemory_operand" "")))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT && ((optimize > 0 && flag_peephole2)
-                   ? epilogue_completed : reload_completed)"
-  [(const_int 0)]
-  "ix86_split_lshr (operands, NULL_RTX, TImode); DONE;")
-
-(define_expand "lshrdi3"
-  [(set (match_operand:DI 0 "shiftdi_operand" "")
-       (lshiftrt:DI (match_operand:DI 1 "shiftdi_operand" "")
-                    (match_operand:QI 2 "nonmemory_operand" "")))]
+(define_expand "lshr<mode>3"
+  [(set (match_operand:SDWIM 0 "<shift_operand>" "")
+       (lshiftrt:SDWIM (match_operand:SDWIM 1 "<shift_operand>" "")
+                       (match_operand:QI 2 "nonmemory_operand" "")))]
   ""
-  "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 "const1_operand" "")))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT
-   && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))
-   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "shr{q}\t%0"
-  [(set_attr "type" "ishift")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "DI")])
-
-(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 FLAGS_REG))]
-  "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 FLAGS_REG)
-       (compare
-         (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
-                      (match_operand:QI 2 "const1_operand" ""))
-         (const_int 0)))
-   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
-       (lshiftrt:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT
-   && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))
-   && ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "shr{q}\t%0"
-  [(set_attr "type" "ishift")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "DI")])
-
-(define_insn "*lshrdi3_cconly_one_bit_rex64"
-  [(set (reg FLAGS_REG)
-       (compare
-         (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
-                      (match_operand:QI 2 "const1_operand" ""))
-         (const_int 0)))
-   (clobber (match_scratch:DI 0 "=r"))]
-  "TARGET_64BIT
-   && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))
-   && ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "shr{q}\t%0"
-  [(set_attr "type" "ishift")
-   (set_attr "length_immediate" "0")
-   (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_rex64"
-  [(set (reg FLAGS_REG)
-       (compare
-         (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
-                      (match_operand:QI 2 "const_1_to_63_operand" "J"))
-         (const_int 0)))
-   (set (match_operand:DI 0 "nonimmediate_operand" "=rm")
-       (lshiftrt:DI (match_dup 1) (match_dup 2)))]
-  "TARGET_64BIT
-   && (optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL)
-   && 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_cconly_rex64"
-  [(set (reg FLAGS_REG)
-       (compare
-         (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0")
-                      (match_operand:QI 2 "const_1_to_63_operand" "J"))
-         (const_int 0)))
-   (clobber (match_scratch:DI 0 "=r"))]
-  "TARGET_64BIT
-   && (optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL)
-   && 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")])
+  "ix86_expand_binary_operator (LSHIFTRT, <MODE>mode, operands); DONE;")
 
-(define_insn "*lshrdi3_1"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
-                    (match_operand:QI 2 "nonmemory_operand" "Jc")))
+(define_insn_and_split "*lshr<mode>3_doubleword"
+  [(set (match_operand:DWI 0 "register_operand" "=r")
+       (lshiftrt:DWI (match_operand:DWI 1 "register_operand" "0")
+                     (match_operand:QI 2 "nonmemory_operand" "<S>c")))
    (clobber (reg:CC FLAGS_REG))]
-  "!TARGET_64BIT"
+  ""
   "#"
+  "(optimize && flag_peephole2) ? epilogue_completed : reload_completed"
+  [(const_int 0)]
+  "ix86_split_lshr (operands, NULL_RTX, <MODE>mode); DONE;"
   [(set_attr "type" "multi")])
 
-;; By default we don't ask for a scratch register, because when DImode
+;; By default we don't ask for a scratch register, because when DWImode
 ;; values are manipulated, registers are already at a premium.  But if
 ;; we have one handy, we won't turn it away.
+
 (define_peephole2
-  [(match_scratch:SI 3 "r")
-   (parallel [(set (match_operand:DI 0 "register_operand" "")
-                  (lshiftrt:DI (match_operand:DI 1 "register_operand" "")
-                               (match_operand:QI 2 "nonmemory_operand" "")))
+  [(match_scratch:DWIH 3 "r")
+   (parallel [(set (match_operand:<DWI> 0 "register_operand" "")
+                  (lshiftrt:<DWI>
+                    (match_operand:<DWI> 1 "register_operand" "")
+                    (match_operand:QI 2 "nonmemory_operand" "")))
              (clobber (reg:CC FLAGS_REG))])
    (match_dup 3)]
-  "!TARGET_64BIT && TARGET_CMOVE"
-  [(const_int 0)]
-  "ix86_split_lshr (operands, operands[3], DImode); DONE;")
-
-(define_split
-  [(set (match_operand:DI 0 "register_operand" "")
-       (lshiftrt:DI (match_operand:DI 1 "register_operand" "")
-                    (match_operand:QI 2 "nonmemory_operand" "")))
-   (clobber (reg:CC FLAGS_REG))]
-  "!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
-                    ? epilogue_completed : reload_completed)"
+  "TARGET_CMOVE"
   [(const_int 0)]
-  "ix86_split_lshr (operands, NULL_RTX, DImode); DONE;")
-
-(define_expand "lshrsi3"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "")
-       (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "")
-                    (match_operand:QI 2 "nonmemory_operand" "")))]
-  ""
-  "ix86_expand_binary_operator (LSHIFTRT, SImode, operands); DONE;")
-
-(define_insn "*lshrsi3_1_one_bit"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
-       (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
-                    (match_operand:QI 2 "const1_operand" "")))
-   (clobber (reg:CC FLAGS_REG))]
-  "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun))
-   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "shr{l}\t%0"
-  [(set_attr "type" "ishift")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "SI")])
-
-(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 "const1_operand" "")))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT
-   && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))
-   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "shr{l}\t%k0"
-  [(set_attr "type" "ishift")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "SI")])
+  "ix86_split_lshr (operands, operands[3], <DWI>mode); DONE;")
 
-(define_insn "*lshrsi3_1"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
-       (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
-                    (match_operand:QI 2 "nonmemory_operand" "I,c")))
+(define_insn "*lshr<mode>3_1"
+  [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m")
+       (lshiftrt:SWI (match_operand:SWI 1 "nonimmediate_operand" "0")
+                     (match_operand:QI 2 "nonmemory_operand" "c<S>")))
    (clobber (reg:CC FLAGS_REG))]
-  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "@
-   shr{l}\t{%2, %0|%0, %2}
-   shr{l}\t{%b2, %0|%0, %b2}"
+  "ix86_binary_operator_ok (LSHIFTRT, <MODE>mode, operands)"
+{
+  if (REG_P (operands[2]))
+    return "shr{<imodesuffix>}\t{%b2, %0|%0, %b2}";
+  else if (operands[2] == const1_rtx
+          && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
+    return "shr{<imodesuffix>}\t%0";
+  else
+    return "shr{<imodesuffix>}\t{%2, %0|%0, %2}";
+}
   [(set_attr "type" "ishift")
-   (set_attr "mode" "SI")])
+   (set (attr "length_immediate")
+     (if_then_else
+       (and (match_operand 2 "const1_operand" "")
+           (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+               (const_int 0)))
+       (const_string "0")
+       (const_string "*")))
+   (set_attr "mode" "<MODE>")])
 
 (define_insn "*lshrsi3_1_zext"
-  [(set (match_operand:DI 0 "register_operand" "=r,r")
+  [(set (match_operand:DI 0 "register_operand" "=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 FLAGS_REG))]
-  "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.
-(define_insn "*lshrsi3_one_bit_cmp"
-  [(set (reg FLAGS_REG)
-       (compare
-         (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
-                      (match_operand:QI 2 "const1_operand" ""))
-         (const_int 0)))
-   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
-       (lshiftrt:SI (match_dup 1) (match_dup 2)))]
-  "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun))
-   && ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "shr{l}\t%0"
-  [(set_attr "type" "ishift")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "SI")])
-
-(define_insn "*lshrsi3_one_bit_cconly"
-  [(set (reg FLAGS_REG)
-       (compare
-         (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
-                      (match_operand:QI 2 "const1_operand" ""))
-         (const_int 0)))
-   (clobber (match_scratch:SI 0 "=r"))]
-  "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun))
-   && ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "shr{l}\t%0"
-  [(set_attr "type" "ishift")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "SI")])
-
-(define_insn "*lshrsi3_cmp_one_bit_zext"
-  [(set (reg FLAGS_REG)
-       (compare
-         (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
-                      (match_operand:QI 2 "const1_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
-   && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))
-   && ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "shr{l}\t%k0"
-  [(set_attr "type" "ishift")
-   (set_attr "length_immediate" "0")
-   (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.
-(define_insn "*lshrsi3_cmp"
-  [(set (reg FLAGS_REG)
-       (compare
-         (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
-                      (match_operand:QI 2 "const_1_to_31_operand" "I"))
-         (const_int 0)))
-   (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
-       (lshiftrt:SI (match_dup 1) (match_dup 2)))]
-  "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL)
-   && ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "shr{l}\t{%2, %0|%0, %2}"
-  [(set_attr "type" "ishift")
-   (set_attr "mode" "SI")])
-
-(define_insn "*lshrsi3_cconly"
-  [(set (reg FLAGS_REG)
-      (compare
-       (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
-                    (match_operand:QI 2 "const_1_to_31_operand" "I"))
-        (const_int 0)))
-   (clobber (match_scratch:SI 0 "=r"))]
-  "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL)
-   && ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "shr{l}\t{%2, %0|%0, %2}"
-  [(set_attr "type" "ishift")
-   (set_attr "mode" "SI")])
-
-(define_insn "*lshrsi3_cmp_zext"
-  [(set (reg FLAGS_REG)
-       (compare
          (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
-                      (match_operand:QI 2 "const_1_to_31_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
-   && (optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL)
-   && 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" "")
-                    (match_operand:QI 2 "nonmemory_operand" "")))]
-  "TARGET_HIMODE_MATH"
-  "ix86_expand_binary_operator (LSHIFTRT, HImode, operands); DONE;")
-
-(define_insn "*lshrhi3_1_one_bit"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
-       (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
-                    (match_operand:QI 2 "const1_operand" "")))
-   (clobber (reg:CC FLAGS_REG))]
-  "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun))
-   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "shr{w}\t%0"
-  [(set_attr "type" "ishift")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "HI")])
-
-(define_insn "*lshrhi3_1"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
-       (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
-                    (match_operand:QI 2 "nonmemory_operand" "I,c")))
-   (clobber (reg:CC FLAGS_REG))]
-  "ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "@
-   shr{w}\t{%2, %0|%0, %2}
-   shr{w}\t{%b2, %0|%0, %b2}"
-  [(set_attr "type" "ishift")
-   (set_attr "mode" "HI")])
-
-;; 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 "*lshrhi3_one_bit_cmp"
-  [(set (reg FLAGS_REG)
-       (compare
-         (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
-                      (match_operand:QI 2 "const1_operand" ""))
-         (const_int 0)))
-   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
-       (lshiftrt:HI (match_dup 1) (match_dup 2)))]
-  "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun))
-   && ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "shr{w}\t%0"
-  [(set_attr "type" "ishift")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "HI")])
-
-(define_insn "*lshrhi3_one_bit_cconly"
-  [(set (reg FLAGS_REG)
-       (compare
-         (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
-                      (match_operand:QI 2 "const1_operand" ""))
-         (const_int 0)))
-   (clobber (match_scratch:HI 0 "=r"))]
-  "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun))
-   && ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "shr{w}\t%0"
-  [(set_attr "type" "ishift")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "HI")])
-
-;; 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 "*lshrhi3_cmp"
-  [(set (reg FLAGS_REG)
-       (compare
-         (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
-                      (match_operand:QI 2 "const_1_to_31_operand" "I"))
-         (const_int 0)))
-   (set (match_operand:HI 0 "nonimmediate_operand" "=rm")
-       (lshiftrt:HI (match_dup 1) (match_dup 2)))]
-  "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL)
-   && ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "shr{w}\t{%2, %0|%0, %2}"
-  [(set_attr "type" "ishift")
-   (set_attr "mode" "HI")])
-
-(define_insn "*lshrhi3_cconly"
-  [(set (reg FLAGS_REG)
-       (compare
-         (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
-                      (match_operand:QI 2 "const_1_to_31_operand" "I"))
-         (const_int 0)))
-   (clobber (match_scratch:HI 0 "=r"))]
-  "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL)
-   && ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
-  "shr{w}\t{%2, %0|%0, %2}"
-  [(set_attr "type" "ishift")
-   (set_attr "mode" "HI")])
-
-(define_expand "lshrqi3"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "")
-       (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "")
-                    (match_operand:QI 2 "nonmemory_operand" "")))]
-  "TARGET_QIMODE_MATH"
-  "ix86_expand_binary_operator (LSHIFTRT, QImode, operands); DONE;")
-
-(define_insn "*lshrqi3_1_one_bit"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
-       (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
-                    (match_operand:QI 2 "const1_operand" "")))
-   (clobber (reg:CC FLAGS_REG))]
-  "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun))
-   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
-  "shr{b}\t%0"
-  [(set_attr "type" "ishift")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "QI")])
-
-(define_insn "*lshrqi3_1_one_bit_slp"
-  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
-       (lshiftrt:QI (match_dup 0)
-                    (match_operand:QI 1 "const1_operand" "")))
-   (clobber (reg:CC FLAGS_REG))]
-  "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
-   && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))"
-  "shr{b}\t%0"
-  [(set_attr "type" "ishift1")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "QI")])
-
-(define_insn "*lshrqi3_1"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
-       (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
-                    (match_operand:QI 2 "nonmemory_operand" "I,c")))
+                      (match_operand:QI 2 "nonmemory_operand" "cI"))))
    (clobber (reg:CC FLAGS_REG))]
-  "ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
-  "@
-   shr{b}\t{%2, %0|%0, %2}
-   shr{b}\t{%b2, %0|%0, %b2}"
+  "TARGET_64BIT && ix86_binary_operator_ok (LSHIFTRT, SImode, operands)"
+{
+  if (REG_P (operands[2]))
+    return "shr{l}\t{%b2, %k0|%k0, %b2}";
+  else if (operands[2] == const1_rtx
+          && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
+    return "shr{l}\t%k0";
+  else
+    return "shr{l}\t{%2, %k0|%k0, %2}";
+}
   [(set_attr "type" "ishift")
-   (set_attr "mode" "QI")])
+   (set (attr "length_immediate")
+     (if_then_else
+       (and (match_operand 2 "const1_operand" "")
+           (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+               (const_int 0)))
+       (const_string "0")
+       (const_string "*")))
+   (set_attr "mode" "SI")])
 
 (define_insn "*lshrqi3_1_slp"
-  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
+  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
        (lshiftrt:QI (match_dup 0)
-                    (match_operand:QI 1 "nonmemory_operand" "I,c")))
+                    (match_operand:QI 1 "nonmemory_operand" "cI")))
    (clobber (reg:CC FLAGS_REG))]
-  "(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
-   && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
-  "@
-   shr{b}\t{%1, %0|%0, %1}
-   shr{b}\t{%b1, %0|%0, %b1}"
+  "(optimize_function_for_size_p (cfun)
+    || !TARGET_PARTIAL_REG_STALL
+    || (operands[1] == const1_rtx
+       && TARGET_SHIFT1))"
+{
+  if (REG_P (operands[1]))
+    return "shr{b}\t{%b1, %0|%0, %b1}";
+  else if (operands[1] == const1_rtx
+          && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
+    return "shr{b}\t%0";
+  else
+    return "shr{b}\t{%1, %0|%0, %1}";
+}
   [(set_attr "type" "ishift1")
+   (set (attr "length_immediate")
+     (if_then_else
+       (and (match_operand 1 "const1_operand" "")
+           (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+               (const_int 0)))
+       (const_string "0")
+       (const_string "*")))
    (set_attr "mode" "QI")])
 
 ;; 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 "*lshrqi2_one_bit_cmp"
-  [(set (reg FLAGS_REG)
-       (compare
-         (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
-                      (match_operand:QI 2 "const1_operand" ""))
-         (const_int 0)))
-   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
-       (lshiftrt:QI (match_dup 1) (match_dup 2)))]
-  "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun))
-   && ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
-  "shr{b}\t%0"
-  [(set_attr "type" "ishift")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "QI")])
-
-(define_insn "*lshrqi2_one_bit_cconly"
+(define_insn "*lshr<mode>3_cmp"
   [(set (reg FLAGS_REG)
        (compare
-         (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
-                      (match_operand:QI 2 "const1_operand" ""))
+         (lshiftrt:SWI (match_operand:SWI 1 "nonimmediate_operand" "0")
+                       (match_operand:QI 2 "<shift_immediate_operand>" "<S>"))
          (const_int 0)))
-   (clobber (match_scratch:QI 0 "=q"))]
-  "(TARGET_SHIFT1 || optimize_function_for_size_p (cfun))
+   (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m")
+       (lshiftrt:SWI (match_dup 1) (match_dup 2)))]
+  "(optimize_function_for_size_p (cfun)
+    || !TARGET_PARTIAL_FLAG_REG_STALL
+    || (operands[2] == const1_rtx
+       && TARGET_SHIFT1))
    && ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
-  "shr{b}\t%0"
+   && ix86_binary_operator_ok (LSHIFTRT, <MODE>mode, operands)"
+{
+  if (operands[2] == const1_rtx
+      && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
+    return "shr{<imodesuffix>}\t%0";
+  else
+    return "shr{<imodesuffix>}\t{%2, %0|%0, %2}";
+}
   [(set_attr "type" "ishift")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "QI")])
+   (set (attr "length_immediate")
+     (if_then_else
+       (and (match_operand 2 "const1_operand" "")
+           (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+               (const_int 0)))
+       (const_string "0")
+       (const_string "*")))
+   (set_attr "mode" "<MODE>")])
 
-;; 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 "*lshrqi2_cmp"
+(define_insn "*lshrsi3_cmp_zext"
   [(set (reg FLAGS_REG)
        (compare
-         (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
+         (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
                       (match_operand:QI 2 "const_1_to_31_operand" "I"))
          (const_int 0)))
-   (set (match_operand:QI 0 "nonimmediate_operand" "=qm")
-       (lshiftrt:QI (match_dup 1) (match_dup 2)))]
-  "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL)
+   (set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (lshiftrt:SI (match_dup 1) (match_dup 2))))]
+  "TARGET_64BIT
+   && (optimize_function_for_size_p (cfun)
+       || !TARGET_PARTIAL_FLAG_REG_STALL
+       || (operands[2] == const1_rtx
+          && TARGET_SHIFT1))
    && ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
-  "shr{b}\t{%2, %0|%0, %2}"
+   && ix86_binary_operator_ok (LSHIFTRT, SImode, operands)"
+{
+  if (operands[2] == const1_rtx
+      && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
+    return "shr{l}\t%k0";
+  else
+    return "shr{l}\t{%2, %k0|%k0, %2}";
+}
   [(set_attr "type" "ishift")
-   (set_attr "mode" "QI")])
+   (set (attr "length_immediate")
+     (if_then_else
+       (and (match_operand 2 "const1_operand" "")
+           (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+               (const_int 0)))
+       (const_string "0")
+       (const_string "*")))
+   (set_attr "mode" "SI")])
 
-(define_insn "*lshrqi2_cconly"
+(define_insn "*lshr<mode>3_cconly"
   [(set (reg FLAGS_REG)
        (compare
-         (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
-                      (match_operand:QI 2 "const_1_to_31_operand" "I"))
+         (lshiftrt:SWI (match_operand:SWI 1 "nonimmediate_operand" "0")
+                       (match_operand:QI 2 "<shift_immediate_operand>" "<S>"))
          (const_int 0)))
-   (clobber (match_scratch:QI 0 "=q"))]
-  "(optimize_function_for_size_p (cfun) || !TARGET_PARTIAL_FLAG_REG_STALL)
+   (clobber (match_scratch:DI 0 "=<r>"))]
+  "(optimize_function_for_size_p (cfun)
+    || !TARGET_PARTIAL_FLAG_REG_STALL
+    || (operands[2] == const1_rtx
+       && TARGET_SHIFT1))
    && ix86_match_ccmode (insn, CCGOCmode)
-   && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
-  "shr{b}\t{%2, %0|%0, %2}"
+   && ix86_binary_operator_ok (LSHIFTRT, <MODE>mode, operands)"
+{
+  if (operands[2] == const1_rtx
+      && (TARGET_SHIFT1 || optimize_function_for_size_p (cfun)))
+    return "shr{<imodesuffix>}\t%0";
+  else
+    return "shr{<imodesuffix>}\t{%2, %0|%0, %2}";
+}
   [(set_attr "type" "ishift")
-   (set_attr "mode" "QI")])
+   (set (attr "length_immediate")
+     (if_then_else
+       (and (match_operand 2 "const1_operand" "")
+           (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+               (const_int 0)))
+       (const_string "0")
+       (const_string "*")))
+   (set_attr "mode" "<MODE>")])
 \f
 ;; Rotate instructions