This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH 8/n, i386]: Merge insns with zero-extracted arguments with corresponding base insns using nox64 isa attribute
- From: Uros Bizjak <ubizjak at gmail dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 26 Mar 2013 19:44:47 +0100
- Subject: [PATCH 8/n, i386]: Merge insns with zero-extracted arguments with corresponding base insns using nox64 isa attribute
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.
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")