OSDN Git Service

PR target/47715
[pf3gnuchains/gcc-fork.git] / gcc / config / i386 / i386.md
index 2b1da4c..2210bc8 100644 (file)
 \f
 ;; Processor type.
 (define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2,corei7,
-                   atom,generic64,amdfam10,bdver1,btver1"
+                   atom,generic64,amdfam10,bdver1,bdver2,btver1"
   (const (symbol_ref "ix86_schedule")))
 
 ;; A basic instruction type.  Refinements due to arguments to be
 (define_mode_attr r [(QI "q") (HI "r") (SI "r") (DI "r")])
 
 ;; Immediate operand constraint for integer modes.
-(define_mode_attr i [(QI "n") (HI "n") (SI "i") (DI "e")])
+(define_mode_attr i [(QI "n") (HI "n") (SI "e") (DI "e")])
 
 ;; General operand constraint for word modes.
-(define_mode_attr g [(QI "qmn") (HI "rmn") (SI "g") (DI "rme")])
+(define_mode_attr g [(QI "qmn") (HI "rmn") (SI "rme") (DI "rme")])
 
 ;; Immediate operand constraint for double integer modes.
-(define_mode_attr di [(SI "iF") (DI "e")])
+(define_mode_attr di [(SI "nF") (DI "e")])
 
 ;; Immediate operand constraint for shifts.
 (define_mode_attr S [(QI "I") (HI "I") (SI "I") (DI "J") (TI "O")])
 (define_mode_attr general_operand
        [(QI "general_operand")
         (HI "general_operand")
-        (SI "general_operand")
+        (SI "x86_64_general_operand")
         (DI "x86_64_general_operand")
         (TI "x86_64_general_operand")])
 
 (define_mode_attr general_szext_operand
        [(QI "general_operand")
         (HI "general_operand")
-        (SI "general_operand")
+        (SI "x86_64_szext_general_operand")
         (DI "x86_64_szext_general_operand")])
 
 ;; Immediate operand predicate for integer modes.
 (define_mode_attr immediate_operand
        [(QI "immediate_operand")
         (HI "immediate_operand")
-        (SI "immediate_operand")
+        (SI "x86_64_immediate_operand")
         (DI "x86_64_immediate_operand")])
 
 ;; Nonmemory operand predicate for integer modes.
 (define_mode_attr nonmemory_operand
        [(QI "nonmemory_operand")
         (HI "nonmemory_operand")
-        (SI "nonmemory_operand")
+        (SI "x86_64_nonmemory_operand")
         (DI "x86_64_nonmemory_operand")])
 
 ;; Operand predicate for shifts.
              (const_string "ssemov")
            (eq_attr "alternative" "16,17")
              (const_string "ssecvt")
-           (match_operand:DI 1 "pic_32bit_operand" "")
+           (match_operand 1 "pic_32bit_operand" "")
              (const_string "lea")
           ]
           (const_string "imov")))
   [(set (match_operand:SI 0 "nonimmediate_operand"
                        "=r,m ,*y,*y,?rm,?*y,*x,*x,?r ,m ,?*Yi,*x")
        (match_operand:SI 1 "general_operand"
-                       "g ,ri,C ,*y,*y ,rm ,C ,*x,*Yi,*x,r   ,m "))]
+                       "g ,re,C ,*y,*y ,rm ,C ,*x,*Yi,*x,r   ,m "))]
   "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
 {
   switch (get_attr_type (insn))
              (const_string "sselog1")
            (eq_attr "alternative" "7,8,9,10,11")
              (const_string "ssemov")
-           (match_operand:DI 1 "pic_32bit_operand" "")
+           (match_operand 1 "pic_32bit_operand" "")
              (const_string "lea")
           ]
           (const_string "imov")))
   if (GET_CODE (op1) == SUBREG)
     op1 = SUBREG_REG (op1);
 
-  if (GENERAL_REG_P (op1) && TARGET_INTER_UNIT_MOVES)
+  if (GENERAL_REG_P (op1))
     {
       operands[4] = simplify_gen_subreg (V4SImode, operands[0], <MODE>mode, 0);
-      emit_insn (gen_sse2_loadld (operands[4],
-                                 CONST0_RTX (V4SImode), operands[1]));
+      if (TARGET_INTER_UNIT_MOVES)
+       emit_insn (gen_sse2_loadld (operands[4],
+                                   CONST0_RTX (V4SImode), operands[1]));
+      else
+       {
+         operands[5] = ix86_force_to_memory (GET_MODE (operands[1]),
+                                             operands[1]);
+         emit_insn (gen_sse2_loadld (operands[4],
+                                     CONST0_RTX (V4SImode), operands[5]));
+         ix86_free_from_memory (GET_MODE (operands[1]));
+       }
     }
   /* We can ignore possible trapping value in the
      high part of SSE register for non-trapping math. */
    (set_attr "mode" "QI")])
 
 (define_insn "*lea_1"
-  [(set (match_operand:P 0 "register_operand" "=r")
-       (match_operand:P 1 "no_seg_address_operand" "p"))]
+  [(set (match_operand:SWI48 0 "register_operand" "=r")
+       (match_operand:SWI48 1 "no_seg_address_operand" "p"))]
   ""
   "lea{<imodesuffix>}\t{%a1, %0|%0, %a1}"
   [(set_attr "type" "lea")
    (set_attr "mode" "<MODE>")])
 
+(define_insn "*lea_1_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+         (match_operand:SI 1 "no_seg_address_operand" "p")))]
+  "TARGET_64BIT"
+  "lea{l}\t{%a1, %k0|%k0, %a1}"
+  [(set_attr "type" "lea")
+   (set_attr "mode" "SI")])
+
 (define_insn "*lea_2"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (subreg:SI (match_operand:DI 1 "no_seg_address_operand" "p") 0))]
   [(set (match_operand:SWI48 0 "nonimmediate_operand" "=r,rm,r,r")
        (plus:SWI48
          (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r")
-         (match_operand:SWI48 2 "<general_operand>" "<g>,r<i>,0,l<i>")))
+         (match_operand:SWI48 2 "x86_64_general_operand" "rme,re,0,le")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
 {
 ;; operands so proper swapping will be done in reload.  This allow
 ;; patterns constructed from addsi_1 to match.
 
-(define_insn "*addsi_1_zext"
+(define_insn "addsi_1_zext"
   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
        (zero_extend:DI
          (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,r,r")
-                  (match_operand:SI 2 "general_operand" "g,0,li"))))
+                  (match_operand:SI 2 "x86_64_general_operand" "rme,0,le"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
 {
         (const_string "none")))
    (set_attr "mode" "QI")])
 
-;; Convert lea to the lea pattern to avoid flags dependency.
+;; Convert add 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:SWI 0 "register_operand" "")
+       (plus:SWI (match_operand:SWI 1 "register_operand" "")
+                 (match_operand:SWI 2 "<nonmemory_operand>" "")))
    (clobber (reg:CC FLAGS_REG))]
   "reload_completed && ix86_lea_for_add_ok (insn, operands)" 
   [(const_int 0)]
 {
+  enum machine_mode mode = <MODE>mode;
   rtx pat;
-  enum machine_mode mode = GET_MODE (operands[0]);
-
-  /* In -fPIC mode the constructs like (const (unspec [symbol_ref]))
-     may confuse gen_lowpart.  */
-  if (mode != Pmode)
-    {
-      operands[1] = gen_lowpart (Pmode, operands[1]);
-      operands[2] = gen_lowpart (Pmode, operands[2]);
-    }
-
-  pat = gen_rtx_PLUS (Pmode, operands[1], operands[2]);
 
   if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode))
-    operands[0] = gen_lowpart (SImode, operands[0]);
+    { 
+      mode = SImode; 
+      operands[0] = gen_lowpart (mode, operands[0]);
+      operands[1] = gen_lowpart (mode, operands[1]);
+      operands[2] = gen_lowpart (mode, operands[2]);
+    }
 
-  if (TARGET_64BIT && mode != Pmode)
-    pat = gen_rtx_SUBREG (SImode, pat, 0);
+  pat = gen_rtx_PLUS (mode, operands[1], operands[2]);
 
   emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
   DONE;
 })
 
-;; Convert lea to the lea pattern to avoid flags dependency.
-;; ??? This pattern handles immediate operands that do not satisfy immediate
-;; operand predicate (TARGET_LEGITIMATE_CONSTANT_P) in the previous pattern.
-(define_split
-  [(set (match_operand:DI 0 "register_operand" "")
-       (plus:DI (match_operand:DI 1 "register_operand" "")
-                (match_operand:DI 2 "x86_64_immediate_operand" "")))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT && reload_completed 
-   && true_regnum (operands[0]) != true_regnum (operands[1])"
-  [(set (match_dup 0)
-       (plus:DI (match_dup 1) (match_dup 2)))])
-
-;; Convert lea to the lea pattern to avoid flags dependency.
+;; Convert add 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" ""))))
+                  (match_operand:SI 2 "x86_64_nonmemory_operand" ""))))
    (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT && reload_completed
-   && ix86_lea_for_add_ok (insn, operands)"
+  "TARGET_64BIT && reload_completed && ix86_lea_for_add_ok (insn, operands)"
   [(set (match_dup 0)
-       (zero_extend:DI (subreg:SI (plus:DI (match_dup 1) (match_dup 2)) 0)))]
-{
-  operands[1] = gen_lowpart (DImode, operands[1]);
-  operands[2] = gen_lowpart (DImode, operands[2]);
-})
+       (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))])
 
 (define_insn "*add<mode>_2"
   [(set (reg FLAGS_REG)
   [(set (reg FLAGS_REG)
        (compare
          (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
-                  (match_operand:SI 2 "general_operand" "g"))
+                  (match_operand:SI 2 "x86_64_general_operand" "rme"))
          (const_int 0)))
    (set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
 (define_insn "*addsi_3_zext"
   [(set (reg FLAGS_REG)
        (compare
-         (neg:SI (match_operand:SI 2 "general_operand" "g"))
+         (neg:SI (match_operand:SI 2 "x86_64_general_operand" "rme"))
          (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))))]
   [(set_attr "type" "alu")
    (set_attr "mode" "QI")])
 
-;; The lea patterns for non-Pmodes needs to be matched by
+;; The lea patterns for modes less than 32 bits need to be matched by
 ;; several insns converted to real lea by splitters.
 
 (define_insn_and_split "*lea_general_1"
        (plus (plus (match_operand 1 "index_register_operand" "l")
                    (match_operand 2 "register_operand" "r"))
              (match_operand 3 "immediate_operand" "i")))]
-  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
-    || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
+  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode)
    && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
    && GET_MODE (operands[0]) == GET_MODE (operands[1])
    && GET_MODE (operands[0]) == GET_MODE (operands[2])
   "&& reload_completed"
   [(const_int 0)]
 {
+  enum machine_mode mode = SImode;
   rtx pat;
-  operands[0] = gen_lowpart (SImode, operands[0]);
-  operands[1] = gen_lowpart (Pmode, operands[1]);
-  operands[2] = gen_lowpart (Pmode, operands[2]);
-  operands[3] = gen_lowpart (Pmode, operands[3]);
-  pat = gen_rtx_PLUS (Pmode, gen_rtx_PLUS (Pmode, operands[1], operands[2]),
+
+  operands[0] = gen_lowpart (mode, operands[0]);
+  operands[1] = gen_lowpart (mode, operands[1]);
+  operands[2] = gen_lowpart (mode, operands[2]);
+  operands[3] = gen_lowpart (mode, operands[3]);
+
+  pat = gen_rtx_PLUS (mode, gen_rtx_PLUS (mode, operands[1], operands[2]),
                      operands[3]);
-  if (Pmode != SImode)
-    pat = gen_rtx_SUBREG (SImode, pat, 0);
+
   emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
   DONE;
 }
   [(set_attr "type" "lea")
    (set_attr "mode" "SI")])
 
-(define_insn_and_split "*lea_general_1_zext"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (zero_extend:DI
-         (plus:SI (plus:SI
-                    (match_operand:SI 1 "index_register_operand" "l")
-                    (match_operand:SI 2 "register_operand" "r"))
-                  (match_operand:SI 3 "immediate_operand" "i"))))]
-  "TARGET_64BIT"
-  "#"
-  "&& reload_completed"
-  [(set (match_dup 0)
-       (zero_extend:DI (subreg:SI (plus:DI (plus:DI (match_dup 1)
-                                                    (match_dup 2))
-                                           (match_dup 3)) 0)))]
-{
-  operands[1] = gen_lowpart (Pmode, operands[1]);
-  operands[2] = gen_lowpart (Pmode, operands[2]);
-  operands[3] = gen_lowpart (Pmode, operands[3]);
-}
-  [(set_attr "type" "lea")
-   (set_attr "mode" "SI")])
-
 (define_insn_and_split "*lea_general_2"
   [(set (match_operand 0 "register_operand" "=r")
        (plus (mult (match_operand 1 "index_register_operand" "l")
-                   (match_operand 2 "const248_operand" "i"))
+                   (match_operand 2 "const248_operand" "n"))
              (match_operand 3 "nonmemory_operand" "ri")))]
-  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
-    || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
-   && (!TARGET_PARTIAL_REG_STALL
-       || GET_MODE (operands[0]) == SImode
-       || optimize_function_for_size_p (cfun))
+  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode)
+   && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
    && GET_MODE (operands[0]) == GET_MODE (operands[1])
    && (GET_MODE (operands[0]) == GET_MODE (operands[3])
        || GET_MODE (operands[3]) == VOIDmode)"
   "&& reload_completed"
   [(const_int 0)]
 {
+  enum machine_mode mode = SImode;
   rtx pat;
-  operands[0] = gen_lowpart (SImode, operands[0]);
-  operands[1] = gen_lowpart (Pmode, operands[1]);
-  operands[3] = gen_lowpart (Pmode, operands[3]);
-  pat = gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1], operands[2]),
-                     operands[3]);
-  if (Pmode != SImode)
-    pat = gen_rtx_SUBREG (SImode, pat, 0);
+
+  operands[0] = gen_lowpart (mode, operands[0]);
+  operands[1] = gen_lowpart (mode, operands[1]);
+  operands[3] = gen_lowpart (mode, operands[3]);
+
+  pat = gen_rtx_PLUS (mode, gen_rtx_MULT (mode, operands[1], operands[2]),
+                     operands[3]);
+
   emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
   DONE;
 }
   [(set_attr "type" "lea")
    (set_attr "mode" "SI")])
 
-(define_insn_and_split "*lea_general_2_zext"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (zero_extend:DI
-         (plus:SI (mult:SI
-                    (match_operand:SI 1 "index_register_operand" "l")
-                    (match_operand:SI 2 "const248_operand" "n"))
-                  (match_operand:SI 3 "nonmemory_operand" "ri"))))]
-  "TARGET_64BIT"
-  "#"
-  "&& reload_completed"
-  [(set (match_dup 0)
-       (zero_extend:DI (subreg:SI (plus:DI (mult:DI (match_dup 1)
-                                                    (match_dup 2))
-                                           (match_dup 3)) 0)))]
-{
-  operands[1] = gen_lowpart (Pmode, operands[1]);
-  operands[3] = gen_lowpart (Pmode, operands[3]);
-}
-  [(set_attr "type" "lea")
-   (set_attr "mode" "SI")])
-
 (define_insn_and_split "*lea_general_3"
   [(set (match_operand 0 "register_operand" "=r")
        (plus (plus (mult (match_operand 1 "index_register_operand" "l")
-                         (match_operand 2 "const248_operand" "i"))
+                         (match_operand 2 "const248_operand" "n"))
                    (match_operand 3 "register_operand" "r"))
              (match_operand 4 "immediate_operand" "i")))]
-  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode
-    || (TARGET_64BIT && GET_MODE (operands[0]) == SImode))
-   && (!TARGET_PARTIAL_REG_STALL
-       || GET_MODE (operands[0]) == SImode
-       || optimize_function_for_size_p (cfun))
+  "(GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode)
+   && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
    && GET_MODE (operands[0]) == GET_MODE (operands[1])
    && GET_MODE (operands[0]) == GET_MODE (operands[3])"
   "#"
   "&& reload_completed"
   [(const_int 0)]
 {
+  enum machine_mode mode = SImode;
   rtx pat;
-  operands[0] = gen_lowpart (SImode, operands[0]);
-  operands[1] = gen_lowpart (Pmode, operands[1]);
-  operands[3] = gen_lowpart (Pmode, operands[3]);
-  operands[4] = gen_lowpart (Pmode, operands[4]);
-  pat = gen_rtx_PLUS (Pmode,
-                     gen_rtx_PLUS (Pmode, gen_rtx_MULT (Pmode, operands[1],
-                                                        operands[2]),
+
+  operands[0] = gen_lowpart (mode, operands[0]);
+  operands[1] = gen_lowpart (mode, operands[1]);
+  operands[3] = gen_lowpart (mode, operands[3]);
+  operands[4] = gen_lowpart (mode, operands[4]);
+
+  pat = gen_rtx_PLUS (mode,
+                     gen_rtx_PLUS (mode,
+                                   gen_rtx_MULT (mode, operands[1],
+                                                       operands[2]),
                                    operands[3]),
                      operands[4]);
-  if (Pmode != SImode)
-    pat = gen_rtx_SUBREG (SImode, pat, 0);
+
   emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
   DONE;
 }
   [(set_attr "type" "lea")
    (set_attr "mode" "SI")])
 
-(define_insn_and_split "*lea_general_3_zext"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (zero_extend:DI
-         (plus:SI (plus:SI
-                    (mult:SI
-                      (match_operand:SI 1 "index_register_operand" "l")
-                      (match_operand:SI 2 "const248_operand" "n"))
-                    (match_operand:SI 3 "register_operand" "r"))
-                  (match_operand:SI 4 "immediate_operand" "i"))))]
-  "TARGET_64BIT"
-  "#"
-  "&& reload_completed"
-  [(set (match_dup 0)
-       (zero_extend:DI (subreg:SI (plus:DI (plus:DI (mult:DI (match_dup 1)
-                                                             (match_dup 2))
-                                                    (match_dup 3))
-                                           (match_dup 4)) 0)))]
-{
-  operands[1] = gen_lowpart (Pmode, operands[1]);
-  operands[3] = gen_lowpart (Pmode, operands[3]);
-  operands[4] = gen_lowpart (Pmode, operands[4]);
-}
-  [(set_attr "type" "lea")
-   (set_attr "mode" "SI")])
-
 (define_insn_and_split "*lea_general_4"
-  [(set (match_operand:SWI 0 "register_operand" "=r")
-       (any_or:SWI (ashift:SWI (match_operand:SWI 1 "index_register_operand" "l")
-                               (match_operand:SWI 2 "const_int_operand" "n"))
-                   (match_operand 3 "const_int_operand" "n")))]
-  "(<MODE>mode == DImode
-    || <MODE>mode == SImode
-    || !TARGET_PARTIAL_REG_STALL
-    || optimize_function_for_size_p (cfun))
+  [(set (match_operand 0 "register_operand" "=r")
+       (any_or (ashift
+                 (match_operand 1 "index_register_operand" "l")
+                 (match_operand 2 "const_int_operand" "n"))
+               (match_operand 3 "const_int_operand" "n")))]
+  "(((GET_MODE (operands[0]) == QImode || GET_MODE (operands[0]) == HImode)
+      && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)))
+    || GET_MODE (operands[0]) == SImode
+    || (TARGET_64BIT && GET_MODE (operands[0]) == DImode))
+   && GET_MODE (operands[0]) == GET_MODE (operands[1])
    && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) - 1 < 3
    && ((unsigned HOST_WIDE_INT) INTVAL (operands[3])
        < ((unsigned HOST_WIDE_INT) 1 << INTVAL (operands[2])))"
   "&& reload_completed"
   [(const_int 0)]
 {
+  enum machine_mode mode = GET_MODE (operands[0]);
   rtx pat;
-  if (<MODE>mode != DImode)
-    operands[0] = gen_lowpart (SImode, operands[0]);
-  operands[1] = gen_lowpart (Pmode, operands[1]);
+
+  if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode))
+    { 
+      mode = SImode; 
+      operands[0] = gen_lowpart (mode, operands[0]);
+      operands[1] = gen_lowpart (mode, operands[1]);
+    }
+
   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
-  pat = plus_constant (gen_rtx_MULT (Pmode, operands[1], operands[2]),
+
+  pat = plus_constant (gen_rtx_MULT (mode, operands[1], operands[2]),
                       INTVAL (operands[3]));
-  if (Pmode != SImode && <MODE>mode != DImode)
-    pat = gen_rtx_SUBREG (SImode, pat, 0);
+
   emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
   DONE;
 }
   [(set_attr "type" "lea")
    (set (attr "mode")
-      (if_then_else (eq (symbol_ref "<MODE>mode == DImode") (const_int 0))
-       (const_string "SI")
-       (const_string "DI")))])
+      (if_then_else (match_operand:DI 0 "" "")
+       (const_string "DI")
+       (const_string "SI")))])
 \f
 ;; Subtract instructions
 
   [(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" "g"))))
+                   (match_operand:SI 2 "x86_64_general_operand" "rme"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
   "sub{l}\t{%2, %k0|%k0, %2}"
   [(set (reg FLAGS_REG)
        (compare
          (minus:SI (match_operand:SI 1 "register_operand" "0")
-                   (match_operand:SI 2 "general_operand" "g"))
+                   (match_operand:SI 2 "x86_64_general_operand" "rme"))
          (const_int 0)))
    (set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI
 (define_insn "*subsi_3_zext"
   [(set (reg FLAGS_REG)
        (compare (match_operand:SI 1 "register_operand" "0")
-                (match_operand:SI 2 "general_operand" "g")))
+                (match_operand:SI 2 "x86_64_general_operand" "rme")))
    (set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI
          (minus:SI (match_dup 1)
          (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
                   (plus:SI (match_operator 3 "ix86_carry_flag_operator"
                             [(reg FLAGS_REG) (const_int 0)])
-                           (match_operand:SI 2 "general_operand" "g")))))
+                           (match_operand:SI 2 "x86_64_general_operand" "rme")))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
   "adc{l}\t{%2, %k0|%k0, %2}"
          (minus:SI (match_operand:SI 1 "register_operand" "0")
                    (plus:SI (match_operator 3 "ix86_carry_flag_operator"
                              [(reg FLAGS_REG) (const_int 0)])
-                            (match_operand:SI 2 "general_operand" "g")))))
+                            (match_operand:SI 2 "x86_64_general_operand" "rme")))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
   "sbb{l}\t{%2, %k0|%k0, %2}"
        (compare:CCC
          (plusminus:SI
            (match_operand:SI 1 "nonimmediate_operand" "<comm>0")
-           (match_operand:SI 2 "general_operand" "g"))
+           (match_operand:SI 2 "x86_64_general_operand" "rme"))
          (match_dup 1)))
    (set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))]
   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
        (zero_extend:DI
          (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%rm,rm,0")
-                  (match_operand:SI 2 "general_operand" "K,i,mr"))))
+                  (match_operand:SI 2 "x86_64_general_operand" "K,e,mr"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT
    && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
   [(set (reg:CCNO FLAGS_REG)
        (compare:CCNO
          (and:SI (match_operand:SI 0 "nonimmediate_operand" "")
-                 (match_operand:SI 1 "nonmemory_operand" ""))
+                 (match_operand:SI 1 "x86_64_nonmemory_operand" ""))
          (const_int 0)))])
 
 (define_expand "testqi_ccz_1"
        (compare
         (and:SWI124
          (match_operand:SWI124 0 "nonimmediate_operand" "%!*a,<r>,<r>m")
-         (match_operand:SWI124 1 "general_operand" "<i>,<i>,<r><i>"))
+         (match_operand:SWI124 1 "<general_operand>" "<i>,<i>,<r><i>"))
         (const_int 0)))]
   "ix86_match_ccmode (insn, CCNOmode)
    && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
 (define_insn "*andsi_1"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r,r")
        (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,qm")
-               (match_operand:SI 2 "general_operand" "ri,rm,L")))
+               (match_operand:SI 2 "x86_64_general_operand" "re,rm,L")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (AND, SImode, operands)"
 {
   [(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" "g"))))
+                 (match_operand:SI 2 "x86_64_general_operand" "rme"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && ix86_binary_operator_ok (AND, SImode, operands)"
   "and{l}\t{%2, %k0|%k0, %2}"
   [(set (reg FLAGS_REG)
        (compare (and:SWI124
                  (match_operand:SWI124 1 "nonimmediate_operand" "%0,0")
-                 (match_operand:SWI124 2 "general_operand" "<g>,<r><i>"))
+                 (match_operand:SWI124 2 "<general_operand>" "<g>,<r><i>"))
                 (const_int 0)))
    (set (match_operand:SWI124 0 "nonimmediate_operand" "=<r>,<r>m")
        (and:SWI124 (match_dup 1) (match_dup 2)))]
   [(set (reg FLAGS_REG)
        (compare (and:SI
                  (match_operand:SI 1 "nonimmediate_operand" "%0")
-                 (match_operand:SI 2 "general_operand" "g"))
+                 (match_operand:SI 2 "x86_64_general_operand" "rme"))
                 (const_int 0)))
    (set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI (and:SI (match_dup 1) (match_dup 2))))]
   [(set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI
         (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
-                   (match_operand:SI 2 "general_operand" "g"))))
+                   (match_operand:SI 2 "x86_64_general_operand" "rme"))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && ix86_binary_operator_ok (<CODE>, SImode, operands)"
   "<logic>{l}\t{%2, %k0|%k0, %2}"
 (define_insn "*<code>si_2_zext"
   [(set (reg FLAGS_REG)
        (compare (any_or:SI (match_operand:SI 1 "nonimmediate_operand" "%0")
-                           (match_operand:SI 2 "general_operand" "g"))
+                           (match_operand:SI 2 "x86_64_general_operand" "rme"))
                 (const_int 0)))
    (set (match_operand:DI 0 "register_operand" "=r")
        (zero_extend:DI (any_or:SI (match_dup 1) (match_dup 2))))]
        (const_string "*")))
    (set_attr "mode" "QI")])
 
-;; Convert lea to the lea pattern to avoid flags dependency.
+;; Convert ashift to the lea pattern to avoid flags dependency.
 (define_split
   [(set (match_operand 0 "register_operand" "")
        (ashift (match_operand 1 "index_register_operand" "")
                 (match_operand:QI 2 "const_int_operand" "")))
    (clobber (reg:CC FLAGS_REG))]
-  "reload_completed
+  "GET_MODE (operands[0]) == GET_MODE (operands[1])
+   && reload_completed
    && true_regnum (operands[0]) != true_regnum (operands[1])"
   [(const_int 0)]
 {
-  rtx pat;
   enum machine_mode mode = GET_MODE (operands[0]);
-
-  if (mode != Pmode)
-    operands[1] = gen_lowpart (Pmode, operands[1]);
-  operands[2] = gen_int_mode (1 << INTVAL (operands[2]), Pmode);
-
-  pat = gen_rtx_MULT (Pmode, operands[1], operands[2]);
+  rtx pat;
 
   if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode))
-    operands[0] = gen_lowpart (SImode, operands[0]);
+    { 
+      mode = SImode; 
+      operands[0] = gen_lowpart (mode, operands[0]);
+      operands[1] = gen_lowpart (mode, operands[1]);
+    }
 
-  if (TARGET_64BIT && mode != Pmode)
-    pat = gen_rtx_SUBREG (SImode, pat, 0);
+  operands[2] = gen_int_mode (1 << INTVAL (operands[2]), mode);
+
+  pat = gen_rtx_MULT (mode, operands[1], operands[2]);
 
   emit_insn (gen_rtx_SET (VOIDmode, operands[0], pat));
   DONE;
 })
 
-;; Convert lea to the lea pattern to avoid flags dependency.
+;; Convert ashift to the lea pattern to avoid flags dependency.
 (define_split
   [(set (match_operand:DI 0 "register_operand" "")
        (zero_extend:DI
          (zero_extract:SWI48
            (match_operand:SWI48 0 "register_operand" "r")
            (const_int 1)
-           (match_operand:SWI48 1 "nonmemory_operand" "rN"))
+           (match_operand:SWI48 1 "x86_64_nonmemory_operand" "rN"))
          (const_int 0)))]
   "TARGET_USE_BT || optimize_function_for_size_p (cfun)"
   "bt{<imodesuffix>}\t{%1, %0|%0, %1}"
    (set_attr "modrm" "0")])
 
 (define_expand "indirect_jump"
-  [(set (pc) (match_operand 0 "nonimmediate_operand" ""))]
-  ""
-  "")
+  [(set (pc) (match_operand 0 "indirect_branch_operand" ""))])
 
 (define_insn "*indirect_jump"
-  [(set (pc) (match_operand:P 0 "nonimmediate_operand" "rm"))]
+  [(set (pc) (match_operand:P 0 "indirect_branch_operand" "rw"))]
   ""
   "jmp\t%A0"
   [(set_attr "type" "ibr")
    (set_attr "length_immediate" "0")])
 
 (define_expand "tablejump"
-  [(parallel [(set (pc) (match_operand 0 "nonimmediate_operand" ""))
+  [(parallel [(set (pc) (match_operand 0 "indirect_branch_operand" ""))
              (use (label_ref (match_operand 1 "" "")))])]
   ""
 {
       operands[0] = expand_simple_binop (Pmode, code, op0, op1, NULL_RTX, 0,
                                         OPTAB_DIRECT);
     }
+  else if (TARGET_X32)
+    operands[0] = convert_memory_address (Pmode, operands[0]);
 })
 
 (define_insn "*tablejump_1"
-  [(set (pc) (match_operand:P 0 "nonimmediate_operand" "rm"))
+  [(set (pc) (match_operand:P 0 "indirect_branch_operand" "rw"))
    (use (label_ref (match_operand 1 "" "")))]
   ""
   "jmp\t%A0"
 })
 
 (define_insn_and_split "*call_vzeroupper"
-  [(call (mem:QI (match_operand:P 0 "call_insn_operand" "<c>zm"))
+  [(call (mem:QI (match_operand:P 0 "call_insn_operand" "<c>zw"))
         (match_operand 1 "" ""))
    (unspec [(match_operand 2 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
   [(set_attr "type" "call")])
 
 (define_insn "*call"
-  [(call (mem:QI (match_operand:P 0 "call_insn_operand" "<c>zm"))
+  [(call (mem:QI (match_operand:P 0 "call_insn_operand" "<c>zw"))
         (match_operand 1 "" ""))]
   "!SIBLING_CALL_P (insn)"
   "* return ix86_output_call_insn (insn, operands[0]);"
 
 (define_insn_and_split "*call_rex64_ms_sysv_vzeroupper"
   [(parallel
-    [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rzm"))
+    [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rzw"))
           (match_operand 1 "" ""))
      (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)
      (clobber (reg:TI XMM6_REG))
   [(set_attr "type" "call")])
 
 (define_insn "*call_rex64_ms_sysv"
-  [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rzm"))
+  [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rzw"))
         (match_operand 1 "" ""))
    (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)
    (clobber (reg:TI XMM6_REG))
 
 (define_insn_and_split "*call_value_vzeroupper"
   [(set (match_operand 0 "" "")
-       (call (mem:QI (match_operand:P 1 "call_insn_operand" "<c>zm"))
+       (call (mem:QI (match_operand:P 1 "call_insn_operand" "<c>zw"))
              (match_operand 2 "" "")))
    (unspec [(match_operand 3 "const_int_operand" "")]
           UNSPEC_CALL_NEEDS_VZEROUPPER)]
 
 (define_insn "*call_value"
   [(set (match_operand 0 "" "")
-       (call (mem:QI (match_operand:P 1 "call_insn_operand" "<c>zm"))
+       (call (mem:QI (match_operand:P 1 "call_insn_operand" "<c>zw"))
              (match_operand 2 "" "")))]
   "!SIBLING_CALL_P (insn)"
   "* return ix86_output_call_insn (insn, operands[1]);"
 (define_insn_and_split "*call_value_rex64_ms_sysv_vzeroupper"
   [(parallel
     [(set (match_operand 0 "" "")
-         (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rzm"))
+         (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rzw"))
                (match_operand 2 "" "")))
      (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)
      (clobber (reg:TI XMM6_REG))
 
 (define_insn "*call_value_rex64_ms_sysv"
   [(set (match_operand 0 "" "")
-       (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rzm"))
+       (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rzw"))
              (match_operand 2 "" "")))
    (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)
    (clobber (reg:TI XMM6_REG))
        (unspec:DI
          [(label_ref (match_operand 1 "" ""))]
          UNSPEC_SET_GOT_OFFSET))]
-  "TARGET_64BIT"
+  "TARGET_LP64"
   "movabs{q}\t{$_GLOBAL_OFFSET_TABLE_-%l1, %0|%0, OFFSET FLAT:_GLOBAL_OFFSET_TABLE_-%l1}"
   [(set_attr "type" "imov")
    (set_attr "length_immediate" "0")
        (call:DI
         (mem:QI (match_operand:DI 2 "constant_call_address_operand" "z"))
         (match_operand:DI 3 "" "")))
-   (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
+   (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
              UNSPEC_TLS_GD)]
   "TARGET_64BIT"
 {
-  fputs (ASM_BYTE "0x66\n", asm_out_file);
+  if (!TARGET_X32)
+    fputs (ASM_BYTE "0x66\n", asm_out_file);
   output_asm_insn
     ("lea{q}\t{%a1@tlsgd(%%rip), %%rdi|rdi, %a1@tlsgd[rip]}", operands);
   fputs (ASM_SHORT "0x6666\n", asm_out_file);
   return "call\t%P2";
 }
   [(set_attr "type" "multi")
-   (set_attr "length" "16")])
+   (set (attr "length")
+       (symbol_ref "TARGET_X32 ? 15 : 16"))])
 
 (define_expand "tls_global_dynamic_64"
   [(parallel
          (call:DI
           (mem:QI (match_operand:DI 2 "constant_call_address_operand" ""))
           (const_int 0)))
-     (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
+     (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
                UNSPEC_TLS_GD)])])
 
 (define_insn "*tls_local_dynamic_base_32_gnu"
 (define_mode_attr tp_seg [(SI "gs") (DI "fs")])
 
 ;; Load and add the thread base pointer from %<tp_seg>:0.
+(define_insn "*load_tp_x32"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (unspec:SI [(const_int 0)] UNSPEC_TP))]
+  "TARGET_X32"
+  "mov{l}\t{%%fs:0, %0|%0, DWORD PTR fs:0}"
+  [(set_attr "type" "imov")
+   (set_attr "modrm" "0")
+   (set_attr "length" "7")
+   (set_attr "memory" "load")
+   (set_attr "imm_disp" "false")])
+
+(define_insn "*load_tp_x32_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI (unspec:SI [(const_int 0)] UNSPEC_TP)))]
+  "TARGET_X32"
+  "mov{l}\t{%%fs:0, %k0|%k0, DWORD PTR fs:0}"
+  [(set_attr "type" "imov")
+   (set_attr "modrm" "0")
+   (set_attr "length" "7")
+   (set_attr "memory" "load")
+   (set_attr "imm_disp" "false")])
+
 (define_insn "*load_tp_<mode>"
   [(set (match_operand:P 0 "register_operand" "=r")
        (unspec:P [(const_int 0)] UNSPEC_TP))]
-  ""
+  "!TARGET_X32"
   "mov{<imodesuffix>}\t{%%<tp_seg>:0, %0|%0, <iptrsize> PTR <tp_seg>:0}"
   [(set_attr "type" "imov")
    (set_attr "modrm" "0")
    (set_attr "memory" "load")
    (set_attr "imm_disp" "false")])
 
+(define_insn "*add_tp_x32"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP)
+                (match_operand:SI 1 "register_operand" "0")))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_X32"
+  "add{l}\t{%%fs:0, %0|%0, DWORD PTR fs:0}"
+  [(set_attr "type" "alu")
+   (set_attr "modrm" "0")
+   (set_attr "length" "7")
+   (set_attr "memory" "load")
+   (set_attr "imm_disp" "false")])
+
+(define_insn "*add_tp_x32_zext"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+         (plus:SI (unspec:SI [(const_int 0)] UNSPEC_TP)
+                  (match_operand:SI 1 "register_operand" "0"))))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_X32"
+  "add{l}\t{%%fs:0, %k0|%k0, DWORD PTR fs:0}"
+  [(set_attr "type" "alu")
+   (set_attr "modrm" "0")
+   (set_attr "length" "7")
+   (set_attr "memory" "load")
+   (set_attr "imm_disp" "false")])
+
 (define_insn "*add_tp_<mode>"
   [(set (match_operand:P 0 "register_operand" "=r")
        (plus:P (unspec:P [(const_int 0)] UNSPEC_TP)
                (match_operand:P 1 "register_operand" "0")))
    (clobber (reg:CC FLAGS_REG))]
-  ""
+  "!TARGET_X32"
   "add{<imodesuffix>}\t{%%<tp_seg>:0, %0|%0, <iptrsize> PTR <tp_seg>:0}"
   [(set_attr "type" "alu")
    (set_attr "modrm" "0")
   ix86_tls_descriptor_calls_expanded_in_cfun = true;
 })
 
-(define_insn "*tls_dynamic_lea_32"
+(define_insn "*tls_dynamic_gnu2_lea_32"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (plus:SI (match_operand:SI 1 "register_operand" "b")
                 (const:SI
    (set_attr "length" "6")
    (set_attr "length_address" "4")])
 
-(define_insn "*tls_dynamic_call_32"
+(define_insn "*tls_dynamic_gnu2_call_32"
   [(set (match_operand:SI 0 "register_operand" "=a")
        (unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")
                    (match_operand:SI 2 "register_operand" "0")
 
 (define_expand "tls_dynamic_gnu2_64"
   [(set (match_dup 2)
-       (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
+       (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
                   UNSPEC_TLSDESC))
    (parallel
     [(set (match_operand:DI 0 "register_operand" "")
   ix86_tls_descriptor_calls_expanded_in_cfun = true;
 })
 
-(define_insn "*tls_dynamic_lea_64"
+(define_insn "*tls_dynamic_gnu2_lea_64"
   [(set (match_operand:DI 0 "register_operand" "=r")
-       (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
+       (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
                   UNSPEC_TLSDESC))]
   "TARGET_64BIT && TARGET_GNU2_TLS"
   "lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[rip]}"
    (set_attr "length" "7")
    (set_attr "length_address" "4")])
 
-(define_insn "*tls_dynamic_call_64"
+(define_insn "*tls_dynamic_gnu2_call_64"
   [(set (match_operand:DI 0 "register_operand" "=a")
-       (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")
+       (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")
                    (match_operand:DI 2 "register_operand" "0")
                    (reg:DI SP_REG)]
                   UNSPEC_TLSDESC))
                     (reg:DI SP_REG)]
                    UNSPEC_TLSDESC)
         (const:DI (unspec:DI
-                   [(match_operand:DI 1 "tls_symbolic_operand" "")]
+                   [(match_operand 1 "tls_symbolic_operand" "")]
                    UNSPEC_DTPOFF))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && TARGET_GNU2_TLS"
    (set_attr "prefix_rep" "1")])
 
 (define_expand "strlen<mode>"
-  [(set (match_operand:SWI48x 0 "register_operand" "")
-       (unspec:SWI48x [(match_operand:BLK 1 "general_operand" "")
-                       (match_operand:QI 2 "immediate_operand" "")
-                       (match_operand 3 "immediate_operand" "")]
-                      UNSPEC_SCAS))]
+  [(set (match_operand:P 0 "register_operand" "")
+       (unspec:P [(match_operand:BLK 1 "general_operand" "")
+                  (match_operand:QI 2 "immediate_operand" "")
+                  (match_operand 3 "immediate_operand" "")]
+                 UNSPEC_SCAS))]
   ""
 {
  if (ix86_expand_strlen (operands[0], operands[1], operands[2], operands[3]))
 (define_expand "mov<mode>cc"
   [(set (match_operand:SWIM 0 "register_operand" "")
        (if_then_else:SWIM (match_operand 1 "ordered_comparison_operator" "")
-                          (match_operand:SWIM 2 "general_operand" "")
-                          (match_operand:SWIM 3 "general_operand" "")))]
+                          (match_operand:SWIM 2 "<general_operand>" "")
+                          (match_operand:SWIM 3 "<general_operand>" "")))]
   ""
   "if (ix86_expand_int_movcc (operands)) DONE; else FAIL;")