Patchwork [8/n,i386] : Merge insns with zero-extracted arguments with corresponding base insns using nox64 isa attribute

login
register
mail settings
Submitter Uros Bizjak
Date March 26, 2013, 6:44 p.m.
Message ID <CAFULd4bQwTYk3d7P_uG34ZDQP30nvEsVeL89Nca4k1FdQ-v_kw@mail.gmail.com>
Download mbox | patch
Permalink /patch/231511/
State New
Headers show

Comments

Uros Bizjak - March 26, 2013, 6:44 p.m.
Hello!

The problem with insn that use high register parts (%ah,%bh,%ch,%dh)
is, that they can't be encoded with rex64 prefix. This includes
registers, as well as memory operands involving extended registers. To
handle this limitation, 64bit targets avoid memory operands when high
register parts are used.

Attached patch merges definitions of TARGET_64BIT insns that use high
register parts with their corresponding base instructions.

In future, peephole2 may be added in order to merge memory operand,
formed without extended registers, into the insn. However, these
instructions are quite rare, the prototype peephole2 triggered only
once in a full gcc bootstrap, so it is questionable, if peephole2 is
worth adding.

2013-03-26  Uros Bizjak  <ubizjak@gmail.com>

	* config/i386/i386.md (*cmpqi_ext_1): Merge with *cmpqi_ext_1_rex64
	using nox64 isa attribute.  Use nonimmediate_x86nomem_operand as
	operand 0 predicate.
	(*cmpqi_ext_3): Merge with *cmpqi_ext_3_rex64 using nox64 isa
	attribute.  Use general_x64nomem_operand as operand 1 predicate.
	(*movqi_extv_1): Merge with *movqi_extv_1_rex64 using nox64 isa
	attribute.  Use nonimmediate_x64nomem_operand as operand 0 predicate.
	(*movqi_extzv_2): Merge with *movqi_extzv_2_rex64 using nox64 isa
	attribute.  Use nonimmediate_x64nomem_operand as operand 0 predicate.
	(mov<mode>_insv_1): Remove expander.  Merge insn with
	movsi_insv_1 using SWI48 mode iterator and nox64 isa attribute.
	Use general_x64nomem_operand as operand 1 predicate.
	(addqi_ext_1): Merge with *addqi_ext_1_rex64 using nox64 isa attribute.
	(*testqi_ext_1): Merge with *testqi_ext_1_rex64 using nox64 isa
	attribute.  Use nonimmediate_x64nomem_operand as operand 1 predicate.
	(*andqi_ext_1): Merge with *andqi_ext_1_rex64 using nox64 isa
	attribute.  Use nonimmediate_x64nomem_operand as operand 2 predicate.
	(*<code>qi_ext_1): Merge with *<code>qi_ext_1_rex64 using nox64 isa
	attribute.  Use nonimmediate_x64nomem_operand as operand 1 predicate.
	(*xorqi_cc_ext_1): Merge with *xorqi_cc_ext_1_rex64 using nox64
	isa attribute.  Use general_x64nomem_operand as operand 2 predicate.
	* config/i386/predicates.md (nonimmediate_x64nomem_operand): New.
	(general_x64nomem_operand): Ditto.

Tested on x86_64-pc-linux-gnu {,-m32} and committed to mainline SVN.

Uros.

Patch

Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md	(revision 197113)
+++ config/i386/i386.md	(working copy)
@@ -1032,31 +1032,18 @@ 
 (define_insn "*cmpqi_ext_1"
   [(set (reg FLAGS_REG)
 	(compare
-	  (match_operand:QI 0 "general_operand" "Qm")
+	  (match_operand:QI 0 "nonimmediate_x64nomem_operand" "Q,m")
 	  (subreg:QI
 	    (zero_extract:SI
-	      (match_operand 1 "ext_register_operand" "Q")
+	      (match_operand 1 "ext_register_operand" "Q,Q")
 	      (const_int 8)
 	      (const_int 8)) 0)))]
-  "!TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
+  "ix86_match_ccmode (insn, CCmode)"
   "cmp{b}\t{%h1, %0|%0, %h1}"
-  [(set_attr "type" "icmp")
+  [(set_attr "isa" "*,nox64")
+   (set_attr "type" "icmp")
    (set_attr "mode" "QI")])
 
-(define_insn "*cmpqi_ext_1_rex64"
-  [(set (reg FLAGS_REG)
-	(compare
-	  (match_operand:QI 0 "register_operand" "Q")
-	  (subreg:QI
-	    (zero_extract:SI
-	      (match_operand 1 "ext_register_operand" "Q")
-	      (const_int 8)
-	      (const_int 8)) 0)))]
-  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
-  "cmp{b}\t{%h1, %0|%0, %h1}"
-  [(set_attr "type" "icmp")
-   (set_attr "mode" "QI")])
-
 (define_insn "*cmpqi_ext_2"
   [(set (reg FLAGS_REG)
 	(compare
@@ -1080,38 +1067,24 @@ 
 	      (match_operand 0 "ext_register_operand")
 	      (const_int 8)
 	      (const_int 8)) 0)
-	  (match_operand:QI 1 "immediate_operand")))])
+	  (match_operand:QI 1 "const_int_operand")))])
 
-(define_insn "*cmpqi_ext_3_insn"
+(define_insn "*cmpqi_ext_3"
   [(set (reg FLAGS_REG)
 	(compare
 	  (subreg:QI
 	    (zero_extract:SI
-	      (match_operand 0 "ext_register_operand" "Q")
+	      (match_operand 0 "ext_register_operand" "Q,Q")
 	      (const_int 8)
 	      (const_int 8)) 0)
-	  (match_operand:QI 1 "general_operand" "Qmn")))]
-  "!TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
+	  (match_operand:QI 1 "general_x64nomem_operand" "Qn,m")))]
+  "ix86_match_ccmode (insn, CCmode)"
   "cmp{b}\t{%1, %h0|%h0, %1}"
-  [(set_attr "type" "icmp")
+  [(set_attr "isa" "*,nox64")
+   (set_attr "type" "icmp")
    (set_attr "modrm" "1")
    (set_attr "mode" "QI")])
 
-(define_insn "*cmpqi_ext_3_insn_rex64"
-  [(set (reg FLAGS_REG)
-	(compare
-	  (subreg:QI
-	    (zero_extract:SI
-	      (match_operand 0 "ext_register_operand" "Q")
-	      (const_int 8)
-	      (const_int 8)) 0)
-	  (match_operand:QI 1 "nonmemory_operand" "Qn")))]
-  "TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
-  "cmp{b}\t{%1, %h0|%h0, %1}"
-  [(set_attr "type" "icmp")
-   (set_attr "modrm" "1")
-   (set_attr "mode" "QI")])
-
 (define_insn "*cmpqi_ext_4"
   [(set (reg FLAGS_REG)
 	(compare
@@ -2341,37 +2314,12 @@ 
   [(set_attr "type" "imovx")
    (set_attr "mode" "SI")])
 
-(define_insn "*movqi_extv_1_rex64"
-  [(set (match_operand:QI 0 "register_operand" "=Q,?R")
-        (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
-                         (const_int 8)
-                         (const_int 8)))]
-  "TARGET_64BIT"
-{
-  switch (get_attr_type (insn))
-    {
-    case TYPE_IMOVX:
-      return "movs{bl|x}\t{%h1, %k0|%k0, %h1}";
-    default:
-      return "mov{b}\t{%h1, %0|%0, %h1}";
-    }
-}
-  [(set (attr "type")
-     (if_then_else (ior (not (match_operand:QI 0 "QIreg_operand"))
-			(match_test "TARGET_MOVX"))
-	(const_string "imovx")
-	(const_string "imov")))
-   (set (attr "mode")
-     (if_then_else (eq_attr "type" "imovx")
-	(const_string "SI")
-	(const_string "QI")))])
-
 (define_insn "*movqi_extv_1"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?r")
-        (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
+  [(set (match_operand:QI 0 "nonimmediate_x64nomem_operand" "=Q,?R,m")
+        (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q,Q")
                          (const_int 8)
                          (const_int 8)))]
-  "!TARGET_64BIT"
+  ""
 {
   switch (get_attr_type (insn))
     {
@@ -2381,7 +2329,8 @@ 
       return "mov{b}\t{%h1, %0|%0, %h1}";
     }
 }
-  [(set (attr "type")
+  [(set_attr "isa" "*,*,nox64")
+   (set (attr "type")
      (if_then_else (and (match_operand:QI 0 "register_operand")
 			(ior (not (match_operand:QI 0 "QIreg_operand"))
 			     (match_test "TARGET_MOVX")))
@@ -2402,39 +2351,13 @@ 
   [(set_attr "type" "imovx")
    (set_attr "mode" "SI")])
 
-(define_insn "*movqi_extzv_2_rex64"
-  [(set (match_operand:QI 0 "register_operand" "=Q,?R")
-        (subreg:QI
-	  (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q")
-			   (const_int 8)
-			   (const_int 8)) 0))]
-  "TARGET_64BIT"
-{
-  switch (get_attr_type (insn))
-    {
-    case TYPE_IMOVX:
-      return "movz{bl|x}\t{%h1, %k0|%k0, %h1}";
-    default:
-      return "mov{b}\t{%h1, %0|%0, %h1}";
-    }
-}
-  [(set (attr "type")
-     (if_then_else (ior (not (match_operand:QI 0 "QIreg_operand"))
-			(match_test "TARGET_MOVX"))
-	(const_string "imovx")
-	(const_string "imov")))
-   (set (attr "mode")
-     (if_then_else (eq_attr "type" "imovx")
-	(const_string "SI")
-	(const_string "QI")))])
-
 (define_insn "*movqi_extzv_2"
-  [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?R")
+  [(set (match_operand:QI 0 "nonimmediate_x64nomem_operand" "=Q,?R,m")
         (subreg:QI
-	  (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q")
+	  (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q,Q")
 			   (const_int 8)
 			   (const_int 8)) 0))]
-  "!TARGET_64BIT"
+  ""
 {
   switch (get_attr_type (insn))
     {
@@ -2444,7 +2367,8 @@ 
       return "mov{b}\t{%h1, %0|%0, %h1}";
     }
 }
-  [(set (attr "type")
+  [(set_attr "isa" "*,*,nox64")
+   (set (attr "type")
      (if_then_else (and (match_operand:QI 0 "register_operand")
 			(ior (not (match_operand:QI 0 "QIreg_operand"))
 			     (match_test "TARGET_MOVX")))
@@ -2455,40 +2379,21 @@ 
 	(const_string "SI")
 	(const_string "QI")))])
 
-(define_expand "mov<mode>_insv_1"
-  [(set (zero_extract:SWI48 (match_operand 0 "ext_register_operand")
-			    (const_int 8)
-			    (const_int 8))
-	(match_operand:SWI48 1 "nonmemory_operand"))])
-
-(define_insn "*mov<mode>_insv_1_rex64"
-  [(set (zero_extract:SWI48x (match_operand 0 "ext_register_operand" "+Q")
+(define_insn "mov<mode>_insv_1"
+  [(set (zero_extract:SWI48 (match_operand 0 "ext_register_operand" "+Q,Q")
 			     (const_int 8)
 			     (const_int 8))
-	(match_operand:SWI48x 1 "nonmemory_operand" "Qn"))]
-  "TARGET_64BIT"
+	(match_operand:SWI48 1 "general_x64nomem_operand" "Qn,m"))]
+  ""
 {
   if (CONST_INT_P (operands[1]))
     operands[1] = simplify_gen_subreg (QImode, operands[1], <MODE>mode, 0);
   return "mov{b}\t{%b1, %h0|%h0, %b1}";
 }
-  [(set_attr "type" "imov")
+  [(set_attr "isa" "*,nox64")
+   (set_attr "type" "imov")
    (set_attr "mode" "QI")])
 
-(define_insn "*movsi_insv_1"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
-			 (const_int 8)
-			 (const_int 8))
-	(match_operand:SI 1 "general_operand" "Qmn"))]
-  "!TARGET_64BIT"
-{
-  if (CONST_INT_P (operands[1]))
-    operands[1] = simplify_gen_subreg (QImode, operands[1], SImode, 0);
-  return "mov{b}\t{%b1, %h0|%h0, %b1}";
-}
-  [(set_attr "type" "imov")
-   (set_attr "mode" "QI")])
-
 (define_insn "*movqi_insv_2"
   [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q")
 			 (const_int 8)
@@ -5841,18 +5746,18 @@ 
 	(const_string "*")))
    (set_attr "mode" "<MODE>")])
 
-(define_insn "*addqi_ext_1_rex64"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
+(define_insn "addqi_ext_1"
+  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q,Q")
 			 (const_int 8)
 			 (const_int 8))
 	(plus:SI
 	  (zero_extract:SI
-	    (match_operand 1 "ext_register_operand" "0")
+	    (match_operand 1 "ext_register_operand" "0,0")
 	    (const_int 8)
 	    (const_int 8))
-	  (match_operand:QI 2 "nonmemory_operand" "Qn")))
+	  (match_operand:QI 2 "general_x64nomem_operand" "Qn,m")))
    (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT"
+  ""
 {
   switch (get_attr_type (insn))
     {
@@ -5869,48 +5774,14 @@ 
       return "add{b}\t{%2, %h0|%h0, %2}";
     }
 }
-  [(set (attr "type")
+  [(set_attr "isa" "*,nox64")
+   (set (attr "type")
      (if_then_else (match_operand:QI 2 "incdec_operand")
 	(const_string "incdec")
 	(const_string "alu")))
    (set_attr "modrm" "1")
    (set_attr "mode" "QI")])
 
-(define_insn "addqi_ext_1"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
-			 (const_int 8)
-			 (const_int 8))
-	(plus:SI
-	  (zero_extract:SI
-	    (match_operand 1 "ext_register_operand" "0")
-	    (const_int 8)
-	    (const_int 8))
-	  (match_operand:QI 2 "general_operand" "Qmn")))
-   (clobber (reg:CC FLAGS_REG))]
-  "!TARGET_64BIT"
-{
-  switch (get_attr_type (insn))
-    {
-    case TYPE_INCDEC:
-      if (operands[2] == const1_rtx)
-	return "inc{b}\t%h0";
-      else
-        {
-	  gcc_assert (operands[2] == constm1_rtx);
-          return "dec{b}\t%h0";
-	}
-
-    default:
-      return "add{b}\t{%2, %h0|%h0, %2}";
-    }
-}
-  [(set (attr "type")
-     (if_then_else (match_operand:QI 2 "incdec_operand")
-	(const_string "incdec")
-	(const_string "alu")))
-   (set_attr "modrm" "1")
-   (set_attr "mode" "QI")])
-
 (define_insn "*addqi_ext_2"
   [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
 			 (const_int 8)
@@ -7228,36 +7099,21 @@ 
    (set_attr "modrm" "1")
    (set_attr "pent_pair" "np")])
 
-(define_insn "*testqi_ext_1_rex64"
-  [(set (reg FLAGS_REG)
-	(compare
-	  (and:SI
-	    (zero_extract:SI
-	      (match_operand 0 "ext_register_operand" "Q")
-	      (const_int 8)
-	      (const_int 8))
-	    (zero_extend:SI
-	      (match_operand:QI 1 "register_operand" "Q")))
-	  (const_int 0)))]
-  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
-  "test{b}\t{%1, %h0|%h0, %1}"
-  [(set_attr "type" "test")
-   (set_attr "mode" "QI")])
-
 (define_insn "*testqi_ext_1"
   [(set (reg FLAGS_REG)
 	(compare
 	  (and:SI
 	    (zero_extract:SI
-	      (match_operand 0 "ext_register_operand" "Q")
+	      (match_operand 0 "ext_register_operand" "Q,Q")
 	      (const_int 8)
 	      (const_int 8))
 	    (zero_extend:SI
-	      (match_operand:QI 1 "general_operand" "Qm")))
+	      (match_operand:QI 1 "nonimmediate_x64nomem_operand" "Q,m")))
 	  (const_int 0)))]
-  "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
+  "ix86_match_ccmode (insn, CCNOmode)"
   "test{b}\t{%1, %h0|%h0, %1}"
-  [(set_attr "type" "test")
+  [(set_attr "isa" "*,nox64")
+   (set_attr "type" "test")
    (set_attr "mode" "QI")])
 
 (define_insn "*testqi_ext_2"
@@ -7824,39 +7680,22 @@ 
    (set_attr "modrm" "1")
    (set_attr "mode" "QI")])
 
-(define_insn "*andqi_ext_1_rex64"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
-			 (const_int 8)
-			 (const_int 8))
-	(and:SI
-	  (zero_extract:SI
-	    (match_operand 1 "ext_register_operand" "0")
-	    (const_int 8)
-	    (const_int 8))
-	  (zero_extend:SI
-	    (match_operand 2 "ext_register_operand" "Q"))))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT"
-  "and{b}\t{%2, %h0|%h0, %2}"
-  [(set_attr "type" "alu")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "QI")])
-
 (define_insn "*andqi_ext_1"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
+  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q,Q")
 			 (const_int 8)
 			 (const_int 8))
 	(and:SI
 	  (zero_extract:SI
-	    (match_operand 1 "ext_register_operand" "0")
+	    (match_operand 1 "ext_register_operand" "0,0")
 	    (const_int 8)
 	    (const_int 8))
 	  (zero_extend:SI
-	    (match_operand:QI 2 "general_operand" "Qm"))))
+	    (match_operand:QI 2 "nonimmediate_x64nomem_operand" "Q,m"))))
    (clobber (reg:CC FLAGS_REG))]
-  "!TARGET_64BIT"
+  ""
   "and{b}\t{%2, %h0|%h0, %2}"
-  [(set_attr "type" "alu")
+  [(set_attr "isa" "*,nox64")
+   (set_attr "type" "alu")
    (set_attr "length_immediate" "0")
    (set_attr "mode" "QI")])
 
@@ -8088,41 +7927,22 @@ 
    (set_attr "modrm" "1")
    (set_attr "mode" "QI")])
 
-(define_insn "*<code>qi_ext_1_rex64"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
-			 (const_int 8)
-			 (const_int 8))
-	(any_or:SI
-	  (zero_extract:SI
-	    (match_operand 1 "ext_register_operand" "0")
-	    (const_int 8)
-	    (const_int 8))
-	  (zero_extend:SI
-	    (match_operand 2 "ext_register_operand" "Q"))))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT
-   && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))"
-  "<logic>{b}\t{%2, %h0|%h0, %2}"
-  [(set_attr "type" "alu")
-   (set_attr "length_immediate" "0")
-   (set_attr "mode" "QI")])
-
 (define_insn "*<code>qi_ext_1"
-  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
+  [(set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q,Q")
 			 (const_int 8)
 			 (const_int 8))
 	(any_or:SI
 	  (zero_extract:SI
-	    (match_operand 1 "ext_register_operand" "0")
+	    (match_operand 1 "ext_register_operand" "0,0")
 	    (const_int 8)
 	    (const_int 8))
 	  (zero_extend:SI
-	    (match_operand:QI 2 "general_operand" "Qm"))))
+	    (match_operand:QI 2 "nonimmediate_x64nomem_operand" "Q,m"))))
    (clobber (reg:CC FLAGS_REG))]
-  "!TARGET_64BIT
-   && (!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))"
+  "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
   "<logic>{b}\t{%2, %h0|%h0, %2}"
-  [(set_attr "type" "alu")
+  [(set_attr "isa" "*,nox64")
+   (set_attr "type" "alu")
    (set_attr "length_immediate" "0")
    (set_attr "mode" "QI")])
 
@@ -8197,7 +8017,7 @@ 
 		(match_operand 1 "ext_register_operand")
 		(const_int 8)
 		(const_int 8))
-	      (match_operand:QI 2 "general_operand"))
+	      (match_operand:QI 2 "const_int_operand"))
 	    (const_int 0)))
      (set (zero_extract:SI (match_operand 0 "ext_register_operand")
 			   (const_int 8)
@@ -8209,42 +8029,17 @@ 
 	     (const_int 8))
 	    (match_dup 2)))])])
 
-(define_insn "*xorqi_cc_ext_1_rex64"
-  [(set (reg FLAGS_REG)
-	(compare
-	  (xor:SI
-	    (zero_extract:SI
-	      (match_operand 1 "ext_register_operand" "0")
-	      (const_int 8)
-	      (const_int 8))
-	    (match_operand:QI 2 "nonmemory_operand" "Qn"))
-	  (const_int 0)))
-   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q")
-			 (const_int 8)
-			 (const_int 8))
-	(xor:SI
-	  (zero_extract:SI
-	   (match_dup 1)
-	   (const_int 8)
-	   (const_int 8))
-	  (match_dup 2)))]
-  "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
-  "xor{b}\t{%2, %h0|%h0, %2}"
-  [(set_attr "type" "alu")
-   (set_attr "modrm" "1")
-   (set_attr "mode" "QI")])
-
 (define_insn "*xorqi_cc_ext_1"
   [(set (reg FLAGS_REG)
 	(compare
 	  (xor:SI
 	    (zero_extract:SI
-	      (match_operand 1 "ext_register_operand" "0")
+	      (match_operand 1 "ext_register_operand" "0,0")
 	      (const_int 8)
 	      (const_int 8))
-	    (match_operand:QI 2 "general_operand" "qmn"))
+	    (match_operand:QI 2 "general_x64nomem_operand" "Qn,m"))
 	  (const_int 0)))
-   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=q")
+   (set (zero_extract:SI (match_operand 0 "ext_register_operand" "=Q,Q")
 			 (const_int 8)
 			 (const_int 8))
 	(xor:SI
@@ -8253,9 +8048,10 @@ 
 	   (const_int 8)
 	   (const_int 8))
 	  (match_dup 2)))]
-  "!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
+  "ix86_match_ccmode (insn, CCNOmode)"
   "xor{b}\t{%2, %h0|%h0, %2}"
-  [(set_attr "type" "alu")
+  [(set_attr "isa" "*,nox64")
+   (set_attr "type" "alu")
    (set_attr "modrm" "1")
    (set_attr "mode" "QI")])
 
Index: config/i386/predicates.md
===================================================================
--- config/i386/predicates.md	(revision 197113)
+++ config/i386/predicates.md	(working copy)
@@ -71,6 +71,18 @@ 
 	  && (REGNO (op) > LAST_VIRTUAL_REGISTER || REGNO (op) <= BX_REG));
 })
 
+;; Match nonimmediate operands, but exclude memory operands on 64bit targets.
+(define_predicate "nonimmediate_x64nomem_operand"
+  (if_then_else (match_test "TARGET_64BIT")
+    (match_operand 0 "register_operand")
+    (match_operand 0 "nonimmediate_operand")))
+
+;; Match general operands, but exclude memory operands on 64bit targets.
+(define_predicate "general_x64nomem_operand"
+  (if_then_else (match_test "TARGET_64BIT")
+    (match_operand 0 "nonmemory_operand")
+    (match_operand 0 "general_operand")))
+
 ;; Return true if op is the AX register.
 (define_predicate "ax_reg_operand"
   (and (match_code "reg")