aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/i386/i386.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/i386/i386.md')
-rw-r--r--gcc/config/i386/i386.md1055
1 files changed, 380 insertions, 675 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 24d1012d5ce..475da37cb9b 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -651,12 +651,14 @@
(define_attr "movu" "0,1" (const_string "0"))
;; Used to control the "enabled" attribute on a per-instruction basis.
-(define_attr "isa" "base,sse2,sse2_noavx,sse3,sse4,sse4_noavx,noavx,avx,
- avx2,noavx2,bmi2,fma4,fma"
+(define_attr "isa" "base,x64,nox64,sse2,sse2_noavx,sse3,sse4,sse4_noavx,
+ noavx,avx,avx2,noavx2,bmi2,fma4,fma"
(const_string "base"))
(define_attr "enabled" ""
- (cond [(eq_attr "isa" "sse2") (symbol_ref "TARGET_SSE2")
+ (cond [(eq_attr "isa" "x64") (symbol_ref "TARGET_64BIT")
+ (eq_attr "isa" "nox64") (symbol_ref "!TARGET_64BIT")
+ (eq_attr "isa" "sse2") (symbol_ref "TARGET_SSE2")
(eq_attr "isa" "sse2_noavx")
(symbol_ref "TARGET_SSE2 && !TARGET_AVX")
(eq_attr "isa" "sse3") (symbol_ref "TARGET_SSE3")
@@ -1654,6 +1656,40 @@
;; Move instructions.
+;; Reload patterns to support multi-word load/store
+;; with non-offsetable address.
+(define_expand "reload_noff_store"
+ [(parallel [(match_operand 0 "memory_operand" "=m")
+ (match_operand 1 "register_operand" "r")
+ (match_operand:DI 2 "register_operand" "=&r")])]
+ "TARGET_64BIT"
+{
+ rtx mem = operands[0];
+ rtx addr = XEXP (mem, 0);
+
+ emit_move_insn (operands[2], addr);
+ mem = replace_equiv_address_nv (mem, operands[2]);
+
+ emit_insn (gen_rtx_SET (VOIDmode, mem, operands[1]));
+ DONE;
+})
+
+(define_expand "reload_noff_load"
+ [(parallel [(match_operand 0 "register_operand" "=r")
+ (match_operand 1 "memory_operand" "m")
+ (match_operand:DI 2 "register_operand" "=r")])]
+ "TARGET_64BIT"
+{
+ rtx mem = operands[1];
+ rtx addr = XEXP (mem, 0);
+
+ emit_move_insn (operands[2], addr);
+ mem = replace_equiv_address_nv (mem, operands[2]);
+
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], mem));
+ DONE;
+})
+
(define_expand "movoi"
[(set (match_operand:OI 0 "nonimmediate_operand")
(match_operand:OI 1 "general_operand"))]
@@ -1722,12 +1758,12 @@
(match_operand:OI 1 "vector_move_operand" "C ,xm,x"))]
"TARGET_AVX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
- switch (which_alternative)
+ switch (get_attr_type (insn))
{
- case 0:
+ case TYPE_SSELOG1:
return standard_sse_constant_opcode (insn, operands[1]);
- case 1:
- case 2:
+
+ case TYPE_SSEMOV:
if (misaligned_operand (operands[0], OImode)
|| misaligned_operand (operands[1], OImode))
{
@@ -1743,6 +1779,7 @@
else
return "vmovdqa\t{%1, %0|%0, %1}";
}
+
default:
gcc_unreachable ();
}
@@ -1758,20 +1795,21 @@
]
(const_string "OI")))])
-(define_insn "*movti_internal_rex64"
+(define_insn "*movti_internal"
[(set (match_operand:TI 0 "nonimmediate_operand" "=!r ,o ,x,x ,m")
(match_operand:TI 1 "general_operand" "riFo,re,C,xm,x"))]
- "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "(TARGET_64BIT || TARGET_SSE)
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
- switch (which_alternative)
+ switch (get_attr_type (insn))
{
- case 0:
- case 1:
+ case TYPE_MULTI:
return "#";
- case 2:
+
+ case TYPE_SSELOG1:
return standard_sse_constant_opcode (insn, operands[1]);
- case 3:
- case 4:
+
+ case TYPE_SSEMOV:
/* TDmode values are passed as TImode on the stack. Moving them
to stack may result in unaligned memory access. */
if (misaligned_operand (operands[0], TImode)
@@ -1789,16 +1827,22 @@
else
return "%vmovdqa\t{%1, %0|%0, %1}";
}
+
default:
gcc_unreachable ();
}
}
- [(set_attr "type" "*,*,sselog1,ssemov,ssemov")
- (set_attr "prefix" "*,*,maybe_vex,maybe_vex,maybe_vex")
+ [(set_attr "isa" "x64,x64,*,*,*")
+ (set_attr "type" "multi,multi,sselog1,ssemov,ssemov")
+ (set (attr "prefix")
+ (if_then_else (eq_attr "type" "sselog1,ssemov")
+ (const_string "maybe_vex")
+ (const_string "orig")))
(set (attr "mode")
(cond [(eq_attr "alternative" "0,1")
(const_string "DI")
- (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
+ (ior (not (match_test "TARGET_SSE2"))
+ (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL"))
(const_string "V4SF")
(and (eq_attr "alternative" "4")
(match_test "TARGET_SSE_TYPELESS_STORES"))
@@ -1818,120 +1862,98 @@
[(const_int 0)]
"ix86_split_long_move (operands); DONE;")
-(define_insn "*movti_internal_sse"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=x,x ,m")
- (match_operand:TI 1 "vector_move_operand" "C ,xm,x"))]
- "TARGET_SSE && !TARGET_64BIT
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
-{
- switch (which_alternative)
- {
- case 0:
- return standard_sse_constant_opcode (insn, operands[1]);
- case 1:
- case 2:
- /* TDmode values are passed as TImode on the stack. Moving them
- to stack may result in unaligned memory access. */
- if (misaligned_operand (operands[0], TImode)
- || misaligned_operand (operands[1], TImode))
- {
- if (get_attr_mode (insn) == MODE_V4SF)
- return "%vmovups\t{%1, %0|%0, %1}";
- else
- return "%vmovdqu\t{%1, %0|%0, %1}";
- }
- else
- {
- if (get_attr_mode (insn) == MODE_V4SF)
- return "%vmovaps\t{%1, %0|%0, %1}";
- else
- return "%vmovdqa\t{%1, %0|%0, %1}";
- }
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "type" "sselog1,ssemov,ssemov")
- (set_attr "prefix" "maybe_vex")
- (set (attr "mode")
- (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
- (const_string "V4SF")
- (and (eq_attr "alternative" "2")
- (match_test "TARGET_SSE_TYPELESS_STORES"))
- (const_string "V4SF")
- (match_test "TARGET_AVX")
- (const_string "TI")
- (ior (not (match_test "TARGET_SSE2"))
- (match_test "optimize_function_for_size_p (cfun)"))
- (const_string "V4SF")
- ]
- (const_string "TI")))])
-
-(define_insn "*movdi_internal_rex64"
+(define_insn "*movdi_internal"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=r,r ,r,m ,*y,m*y,?*y,?r ,?*Ym,*x,m ,*x,*x,?r ,?*Yi,?*x,?*Ym")
+ "=r ,o ,r,r ,r,m ,*y,*y,?*y,?m,?r ,?*Ym,*x,*x,*x,m ,?r ,?*Yi,?*Ym,?*Yi")
(match_operand:DI 1 "general_operand"
- "Z ,rem,i,re,C ,*y ,m ,*Ym,r ,C ,*x,*x,m ,*Yi,r ,*Ym,*x"))]
- "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "riFo,riF,Z,rem,i,re,C ,*y,m ,*y,*Ym,r ,C ,*x,m ,*x,*Yi,r ,*Yi ,*Ym"))]
+ "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
switch (get_attr_type (insn))
{
- case TYPE_SSECVT:
- if (SSE_REG_P (operands[0]))
- return "movq2dq\t{%1, %0|%0, %1}";
- else
- return "movdq2q\t{%1, %0|%0, %1}";
-
- case TYPE_SSEMOV:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "%vmovaps\t{%1, %0|%0, %1}";
- else if (get_attr_mode (insn) == MODE_TI)
- return "%vmovdqa\t{%1, %0|%0, %1}";
+ case TYPE_MULTI:
+ return "#";
- /* Handle broken assemblers that require movd instead of movq. */
- if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
- return "%vmovd\t{%1, %0|%0, %1}";
- else
- return "%vmovq\t{%1, %0|%0, %1}";
+ case TYPE_MMX:
+ return "pxor\t%0, %0";
case TYPE_MMXMOV:
+#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ
/* Handle broken assemblers that require movd instead of movq. */
if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
return "movd\t{%1, %0|%0, %1}";
- else
- return "movq\t{%1, %0|%0, %1}";
+#endif
+ return "movq\t{%1, %0|%0, %1}";
case TYPE_SSELOG1:
return standard_sse_constant_opcode (insn, operands[1]);
- case TYPE_MMX:
- return "pxor\t%0, %0";
+ case TYPE_SSEMOV:
+ switch (get_attr_mode (insn))
+ {
+ case MODE_DI:
+#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ
+ /* Handle broken assemblers that require movd instead of movq. */
+ if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
+ return "%vmovd\t{%1, %0|%0, %1}";
+#endif
+ return "%vmovq\t{%1, %0|%0, %1}";
+ case MODE_TI:
+ return "%vmovdqa\t{%1, %0|%0, %1}";
+
+ case MODE_V2SF:
+ gcc_assert (!TARGET_AVX);
+ return "movlps\t{%1, %0|%0, %1}";
+ case MODE_V4SF:
+ return "%vmovaps\t{%1, %0|%0, %1}";
+
+ default:
+ gcc_unreachable ();
+ }
+
+ case TYPE_SSECVT:
+ if (SSE_REG_P (operands[0]))
+ return "movq2dq\t{%1, %0|%0, %1}";
+ else
+ return "movdq2q\t{%1, %0|%0, %1}";
case TYPE_LEA:
return "lea{q}\t{%E1, %0|%0, %E1}";
- default:
+ case TYPE_IMOV:
gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
if (get_attr_mode (insn) == MODE_SI)
return "mov{l}\t{%k1, %k0|%k0, %k1}";
- else if (which_alternative == 2)
+ else if (which_alternative == 4)
return "movabs{q}\t{%1, %0|%0, %1}";
else if (ix86_use_lea_for_mov (insn, operands))
return "lea{q}\t{%E1, %0|%0, %E1}";
else
return "mov{q}\t{%1, %0|%0, %1}";
+
+ default:
+ gcc_unreachable ();
}
}
- [(set (attr "type")
- (cond [(eq_attr "alternative" "4")
+ [(set (attr "isa")
+ (cond [(eq_attr "alternative" "0,1")
+ (const_string "nox64")
+ (eq_attr "alternative" "2,3,4,5,10,11,16,17")
+ (const_string "x64")
+ ]
+ (const_string "*")))
+ (set (attr "type")
+ (cond [(eq_attr "alternative" "0,1")
+ (const_string "multi")
+ (eq_attr "alternative" "6")
(const_string "mmx")
- (eq_attr "alternative" "5,6,7,8")
+ (eq_attr "alternative" "7,8,9,10,11")
(const_string "mmxmov")
- (eq_attr "alternative" "9")
+ (eq_attr "alternative" "12")
(const_string "sselog1")
- (eq_attr "alternative" "10,11,12,13,14")
+ (eq_attr "alternative" "13,14,15,16,17")
(const_string "ssemov")
- (eq_attr "alternative" "15,16")
+ (eq_attr "alternative" "18,19")
(const_string "ssecvt")
(match_operand 1 "pic_32bit_operand")
(const_string "lea")
@@ -1939,161 +1961,45 @@
(const_string "imov")))
(set (attr "modrm")
(if_then_else
- (and (eq_attr "alternative" "2") (eq_attr "type" "imov"))
+ (and (eq_attr "alternative" "4") (eq_attr "type" "imov"))
(const_string "0")
(const_string "*")))
(set (attr "length_immediate")
(if_then_else
- (and (eq_attr "alternative" "2") (eq_attr "type" "imov"))
+ (and (eq_attr "alternative" "4") (eq_attr "type" "imov"))
(const_string "8")
(const_string "*")))
(set (attr "prefix_rex")
- (if_then_else (eq_attr "alternative" "7,8")
- (const_string "1")
- (const_string "*")))
- (set (attr "prefix_data16")
- (if_then_else (eq_attr "alternative" "10")
+ (if_then_else (eq_attr "alternative" "10,11,16,17")
(const_string "1")
(const_string "*")))
(set (attr "prefix")
- (if_then_else (eq_attr "alternative" "9,10,11,12,13,14")
+ (if_then_else (eq_attr "type" "sselog1,ssemov")
(const_string "maybe_vex")
(const_string "orig")))
+ (set (attr "prefix_data16")
+ (if_then_else (and (eq_attr "type" "ssemov") (eq_attr "mode" "DI"))
+ (const_string "1")
+ (const_string "*")))
(set (attr "mode")
- (cond [(eq_attr "alternative" "0")
- (const_string "SI")
- (eq_attr "alternative" "9,11")
- (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
- (const_string "V4SF")
- (match_test "TARGET_AVX")
- (const_string "TI")
- (match_test "optimize_function_for_size_p (cfun)")
- (const_string "V4SF")
- ]
- (const_string "TI"))
- ]
- (const_string "DI")))])
-
-;; Reload patterns to support multi-word load/store
-;; with non-offsetable address.
-(define_expand "reload_noff_store"
- [(parallel [(match_operand 0 "memory_operand" "=m")
- (match_operand 1 "register_operand" "r")
- (match_operand:DI 2 "register_operand" "=&r")])]
- "TARGET_64BIT"
-{
- rtx mem = operands[0];
- rtx addr = XEXP (mem, 0);
-
- emit_move_insn (operands[2], addr);
- mem = replace_equiv_address_nv (mem, operands[2]);
-
- emit_insn (gen_rtx_SET (VOIDmode, mem, operands[1]));
- DONE;
-})
-
-(define_expand "reload_noff_load"
- [(parallel [(match_operand 0 "register_operand" "=r")
- (match_operand 1 "memory_operand" "m")
- (match_operand:DI 2 "register_operand" "=r")])]
- "TARGET_64BIT"
-{
- rtx mem = operands[1];
- rtx addr = XEXP (mem, 0);
-
- emit_move_insn (operands[2], addr);
- mem = replace_equiv_address_nv (mem, operands[2]);
-
- emit_insn (gen_rtx_SET (VOIDmode, operands[0], mem));
- DONE;
-})
-
-(define_insn "*movdi_internal"
- [(set (match_operand:DI 0 "nonimmediate_operand"
- "=r ,o ,*y,m*y,*y,*x,m ,*x,*x,*x,m ,*x,*x,?*x,?*Ym")
- (match_operand:DI 1 "general_operand"
- "riFo,riF,C ,*y ,m ,C ,*x,*x,m ,C ,*x,*x,m ,*Ym,*x"))]
- "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
-{
- switch (get_attr_type (insn))
- {
- case TYPE_SSECVT:
- if (SSE_REG_P (operands[0]))
- return "movq2dq\t{%1, %0|%0, %1}";
- else
- return "movdq2q\t{%1, %0|%0, %1}";
-
- case TYPE_SSEMOV:
- switch (get_attr_mode (insn))
- {
- case MODE_TI:
- return "%vmovdqa\t{%1, %0|%0, %1}";
- case MODE_DI:
- return "%vmovq\t{%1, %0|%0, %1}";
- case MODE_V4SF:
- return "%vmovaps\t{%1, %0|%0, %1}";
- case MODE_V2SF:
- return "movlps\t{%1, %0|%0, %1}";
- default:
- gcc_unreachable ();
- }
-
- case TYPE_MMXMOV:
- return "movq\t{%1, %0|%0, %1}";
-
- case TYPE_SSELOG1:
- return standard_sse_constant_opcode (insn, operands[1]);
-
- case TYPE_MMX:
- return "pxor\t%0, %0";
-
- case TYPE_MULTI:
- return "#";
+ (cond [(eq_attr "alternative" "2")
+ (const_string "SI")
+ (eq_attr "alternative" "12,13")
+ (cond [(ior (not (match_test "TARGET_SSE2"))
+ (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL"))
+ (const_string "V4SF")
+ (match_test "TARGET_AVX")
+ (const_string "TI")
+ (match_test "optimize_function_for_size_p (cfun)")
+ (const_string "V4SF")
+ ]
+ (const_string "TI"))
- default:
- gcc_unreachable ();
- }
-}
- [(set (attr "isa")
- (cond [(eq_attr "alternative" "5,6,7,8,13,14")
- (const_string "sse2")
- (eq_attr "alternative" "9,10,11,12")
- (const_string "noavx")
+ (and (eq_attr "alternative" "14,15")
+ (not (match_test "TARGET_SSE2")))
+ (const_string "V2SF")
]
- (const_string "*")))
- (set (attr "type")
- (cond [(eq_attr "alternative" "0,1")
- (const_string "multi")
- (eq_attr "alternative" "2")
- (const_string "mmx")
- (eq_attr "alternative" "3,4")
- (const_string "mmxmov")
- (eq_attr "alternative" "5,9")
- (const_string "sselog1")
- (eq_attr "alternative" "13,14")
- (const_string "ssecvt")
- ]
- (const_string "ssemov")))
- (set (attr "prefix")
- (if_then_else (eq_attr "alternative" "5,6,7,8")
- (const_string "maybe_vex")
- (const_string "orig")))
- (set (attr "mode")
- (cond [(eq_attr "alternative" "9,11")
- (const_string "V4SF")
- (eq_attr "alternative" "10,12")
- (const_string "V2SF")
- (eq_attr "alternative" "5,7")
- (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
- (const_string "V4SF")
- (match_test "TARGET_AVX")
- (const_string "TI")
- (match_test "optimize_function_for_size_p (cfun)")
- (const_string "V4SF")
- ]
- (const_string "TI"))
- ]
- (const_string "DI")))])
+ (const_string "DI")))])
(define_split
[(set (match_operand:DI 0 "nonimmediate_operand")
@@ -2106,9 +2012,9 @@
(define_insn "*movsi_internal"
[(set (match_operand:SI 0 "nonimmediate_operand"
- "=r,m ,*y,*y,?rm,?*y,*x,*x,?r ,m ,?*Yi,*x")
+ "=r,m ,*y,*y,?rm,?*y,*x,*x,*x,m ,?r ,?*Yi")
(match_operand:SI 1 "general_operand"
- "g ,re,C ,*y,*y ,rm ,C ,*x,*Yi,*x,r ,m"))]
+ "g ,re,C ,*y,*y ,rm ,C ,*x,m ,*x,*Yi,r"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
switch (get_attr_type (insn))
@@ -2119,14 +2025,18 @@
case TYPE_SSEMOV:
switch (get_attr_mode (insn))
{
+ case MODE_SI:
+ return "%vmovd\t{%1, %0|%0, %1}";
case MODE_TI:
return "%vmovdqa\t{%1, %0|%0, %1}";
+
case MODE_V4SF:
return "%vmovaps\t{%1, %0|%0, %1}";
- case MODE_SI:
- return "%vmovd\t{%1, %0|%0, %1}";
+
case MODE_SF:
- return "%vmovss\t{%1, %0|%0, %1}";
+ gcc_assert (!TARGET_AVX);
+ return "movss\t{%1, %0|%0, %1}";
+
default:
gcc_unreachable ();
}
@@ -2135,19 +2045,29 @@
return "pxor\t%0, %0";
case TYPE_MMXMOV:
- if (get_attr_mode (insn) == MODE_DI)
- return "movq\t{%1, %0|%0, %1}";
- return "movd\t{%1, %0|%0, %1}";
+ switch (get_attr_mode (insn))
+ {
+ case MODE_DI:
+ return "movq\t{%1, %0|%0, %1}";
+ case MODE_SI:
+ return "movd\t{%1, %0|%0, %1}";
+
+ default:
+ gcc_unreachable ();
+ }
case TYPE_LEA:
return "lea{l}\t{%E1, %0|%0, %E1}";
- default:
+ case TYPE_IMOV:
gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
if (ix86_use_lea_for_mov (insn, operands))
return "lea{l}\t{%E1, %0|%0, %E1}";
else
return "mov{l}\t{%1, %0|%0, %1}";
+
+ default:
+ gcc_unreachable ();
}
}
[(set (attr "type")
@@ -2164,9 +2084,9 @@
]
(const_string "imov")))
(set (attr "prefix")
- (if_then_else (eq_attr "alternative" "0,1,2,3,4,5")
- (const_string "orig")
- (const_string "maybe_vex")))
+ (if_then_else (eq_attr "type" "sselog1,ssemov")
+ (const_string "maybe_vex")
+ (const_string "orig")))
(set (attr "prefix_data16")
(if_then_else (and (eq_attr "type" "ssemov") (eq_attr "mode" "SI"))
(const_string "1")
@@ -2175,16 +2095,17 @@
(cond [(eq_attr "alternative" "2,3")
(const_string "DI")
(eq_attr "alternative" "6,7")
- (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
+ (cond [(ior (not (match_test "TARGET_SSE2"))
+ (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL"))
(const_string "V4SF")
(match_test "TARGET_AVX")
(const_string "TI")
- (ior (not (match_test "TARGET_SSE2"))
- (match_test "optimize_function_for_size_p (cfun)"))
+ (match_test "optimize_function_for_size_p (cfun)")
(const_string "V4SF")
]
(const_string "TI"))
- (and (eq_attr "alternative" "8,9,10,11")
+
+ (and (eq_attr "alternative" "8,9")
(not (match_test "TARGET_SSE2")))
(const_string "SF")
]
@@ -2582,16 +2503,17 @@
;; Floating point push instructions.
(define_insn "*pushtf"
- [(set (match_operand:TF 0 "push_operand" "=<,<,<")
- (match_operand:TF 1 "general_no_elim_operand" "x,Fo,*r"))]
- "TARGET_SSE"
+ [(set (match_operand:TF 0 "push_operand" "=<,<")
+ (match_operand:TF 1 "general_no_elim_operand" "x,*roF"))]
+ "TARGET_64BIT || TARGET_SSE"
{
/* This insn should be already split before reg-stack. */
gcc_unreachable ();
}
- [(set_attr "type" "multi")
- (set_attr "unit" "sse,*,*")
- (set_attr "mode" "TF,SI,SI")])
+ [(set_attr "isa" "*,x64")
+ (set_attr "type" "multi")
+ (set_attr "unit" "sse,*")
+ (set_attr "mode" "TF,DI")])
;; %%% Kill this when call knows how to work this out.
(define_split
@@ -2603,33 +2525,21 @@
(define_insn "*pushxf"
[(set (match_operand:XF 0 "push_operand" "=<,<")
- (match_operand:XF 1 "general_no_elim_operand" "f,ro"))]
- "optimize_function_for_speed_p (cfun)"
-{
- /* This insn should be already split before reg-stack. */
- gcc_unreachable ();
-}
- [(set_attr "type" "multi")
- (set_attr "unit" "i387,*")
- (set_attr "mode" "XF,SI")])
-
-;; Size of pushxf is 3 (for sub) + 2 (for fstp) + memory operand size.
-;; Size of pushxf using integer instructions is 3+3*memory operand size
-;; Pushing using integer instructions is longer except for constants
-;; and direct memory references (assuming that any given constant is pushed
-;; only once, but this ought to be handled elsewhere).
-
-(define_insn "*pushxf_nointeger"
- [(set (match_operand:XF 0 "push_operand" "=<,<")
- (match_operand:XF 1 "general_no_elim_operand" "f,*rFo"))]
- "optimize_function_for_size_p (cfun)"
+ (match_operand:XF 1 "general_no_elim_operand" "f,Yx*roF"))]
+ ""
{
/* This insn should be already split before reg-stack. */
gcc_unreachable ();
}
[(set_attr "type" "multi")
(set_attr "unit" "i387,*")
- (set_attr "mode" "XF,SI")])
+ (set (attr "mode")
+ (cond [(eq_attr "alternative" "1")
+ (if_then_else (match_test "TARGET_64BIT")
+ (const_string "DI")
+ (const_string "SI"))
+ ]
+ (const_string "XF")))])
;; %%% Kill this when call knows how to work this out.
(define_split
@@ -2640,34 +2550,18 @@
(set (mem:XF (reg:P SP_REG)) (match_dup 1))]
"operands[2] = GEN_INT (-GET_MODE_SIZE (XFmode));")
-(define_insn "*pushdf_rex64"
- [(set (match_operand:DF 0 "push_operand" "=<,<,<")
- (match_operand:DF 1 "general_no_elim_operand" "f,Yd*rFm,x"))]
- "TARGET_64BIT"
-{
- /* This insn should be already split before reg-stack. */
- gcc_unreachable ();
-}
- [(set_attr "type" "multi")
- (set_attr "unit" "i387,*,*")
- (set_attr "mode" "DF,DI,DF")])
-
-;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size.
-;; Size of pushdf using integer instructions is 2+2*memory operand size
-;; On the average, pushdf using integers can be still shorter.
-
(define_insn "*pushdf"
- [(set (match_operand:DF 0 "push_operand" "=<,<,<")
- (match_operand:DF 1 "general_no_elim_operand" "f,Yd*rFo,x"))]
- "!TARGET_64BIT"
+ [(set (match_operand:DF 0 "push_operand" "=<,<,<,<")
+ (match_operand:DF 1 "general_no_elim_operand" "f,Yd*roF,rmF,x"))]
+ ""
{
/* This insn should be already split before reg-stack. */
gcc_unreachable ();
}
- [(set_attr "isa" "*,*,sse2")
+ [(set_attr "isa" "*,nox64,x64,sse2")
(set_attr "type" "multi")
- (set_attr "unit" "i387,*,*")
- (set_attr "mode" "DF,DI,DF")])
+ (set_attr "unit" "i387,*,*,sse")
+ (set_attr "mode" "DF,SI,DI,DF")])
;; %%% Kill this when call knows how to work this out.
(define_split
@@ -2692,7 +2586,7 @@
(define_insn "*pushsf"
[(set (match_operand:SF 0 "push_operand" "=<,<,<")
- (match_operand:SF 1 "general_no_elim_operand" "f,rFm,x"))]
+ (match_operand:SF 1 "general_no_elim_operand" "f,rmF,x"))]
"!TARGET_64BIT"
{
/* Anything else should be already split before reg-stack. */
@@ -2736,10 +2630,7 @@
[(set (match_operand:TF 0 "nonimmediate_operand")
(match_operand:TF 1 "nonimmediate_operand"))]
"TARGET_64BIT || TARGET_SSE"
-{
- ix86_expand_move (TFmode, operands);
- DONE;
-})
+ "ix86_expand_move (TFmode, operands); DONE;")
(define_expand "mov<mode>"
[(set (match_operand:X87MODEF 0 "nonimmediate_operand")
@@ -2747,10 +2638,11 @@
""
"ix86_expand_move (<MODE>mode, operands); DONE;")
-(define_insn "*movtf_internal_rex64"
+(define_insn "*movtf_internal"
[(set (match_operand:TF 0 "nonimmediate_operand" "=x,x ,m,?*r ,!o")
(match_operand:TF 1 "general_operand" "C ,xm,x,*roF,*rC"))]
- "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))
+ "(TARGET_64BIT || TARGET_SSE)
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))
&& (!can_create_pseudo_p ()
|| (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
|| GET_CODE (operands[1]) != CONST_DOUBLE
@@ -2760,12 +2652,12 @@
|| (!TARGET_MEMORY_MISMATCH_STALL
&& memory_operand (operands[0], TFmode)))"
{
- switch (which_alternative)
+ switch (get_attr_type (insn))
{
- case 0:
+ case TYPE_SSELOG1:
return standard_sse_constant_opcode (insn, operands[1]);
- case 1:
- case 2:
+
+ case TYPE_SSEMOV:
/* Handle misaligned load/store since we
don't have movmisaligntf pattern. */
if (misaligned_operand (operands[0], TFmode)
@@ -2784,16 +2676,19 @@
return "%vmovdqa\t{%1, %0|%0, %1}";
}
- case 3:
- case 4:
+ case TYPE_MULTI:
return "#";
default:
gcc_unreachable ();
}
}
- [(set_attr "type" "sselog1,ssemov,ssemov,*,*")
- (set_attr "prefix" "maybe_vex,maybe_vex,maybe_vex,*,*")
+ [(set_attr "isa" "*,*,*,x64,x64")
+ (set_attr "type" "sselog1,ssemov,ssemov,multi,multi")
+ (set (attr "prefix")
+ (if_then_else (eq_attr "type" "sselog1,ssemov")
+ (const_string "maybe_vex")
+ (const_string "orig")))
(set (attr "mode")
(cond [(eq_attr "alternative" "3,4")
(const_string "DI")
@@ -2810,101 +2705,13 @@
]
(const_string "TI")))])
-(define_insn "*movtf_internal_sse"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=x,x ,m")
- (match_operand:TF 1 "general_operand" "C ,xm,x"))]
- "TARGET_SSE && !TARGET_64BIT
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))
- && (!can_create_pseudo_p ()
- || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
- || GET_CODE (operands[1]) != CONST_DOUBLE
- || (optimize_function_for_size_p (cfun)
- && standard_sse_constant_p (operands[1])
- && !memory_operand (operands[0], TFmode))
- || (!TARGET_MEMORY_MISMATCH_STALL
- && memory_operand (operands[0], TFmode)))"
-{
- switch (which_alternative)
- {
- case 0:
- return standard_sse_constant_opcode (insn, operands[1]);
- case 1:
- case 2:
- /* Handle misaligned load/store since we
- don't have movmisaligntf pattern. */
- if (misaligned_operand (operands[0], TFmode)
- || misaligned_operand (operands[1], TFmode))
- {
- if (get_attr_mode (insn) == MODE_V4SF)
- return "%vmovups\t{%1, %0|%0, %1}";
- else
- return "%vmovdqu\t{%1, %0|%0, %1}";
- }
- else
- {
- if (get_attr_mode (insn) == MODE_V4SF)
- return "%vmovaps\t{%1, %0|%0, %1}";
- else
- return "%vmovdqa\t{%1, %0|%0, %1}";
- }
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "type" "sselog1,ssemov,ssemov")
- (set_attr "prefix" "maybe_vex")
- (set (attr "mode")
- (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
- (const_string "V4SF")
- (and (eq_attr "alternative" "2")
- (match_test "TARGET_SSE_TYPELESS_STORES"))
- (const_string "V4SF")
- (match_test "TARGET_AVX")
- (const_string "TI")
- (ior (not (match_test "TARGET_SSE2"))
- (match_test "optimize_function_for_size_p (cfun)"))
- (const_string "V4SF")
- ]
- (const_string "TI")))])
-
-(define_insn "*movxf_internal_rex64"
- [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,?Yx*r ,!o")
- (match_operand:XF 1 "general_operand" "fm,f,G,Yx*roF,Yx*rC"))]
- "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))
- && (!can_create_pseudo_p ()
- || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
- || GET_CODE (operands[1]) != CONST_DOUBLE
- || (optimize_function_for_size_p (cfun)
- && standard_80387_constant_p (operands[1]) > 0
- && !memory_operand (operands[0], XFmode))
- || (!TARGET_MEMORY_MISMATCH_STALL
- && memory_operand (operands[0], XFmode)))"
-{
- switch (which_alternative)
- {
- case 0:
- case 1:
- return output_387_reg_move (insn, operands);
-
- case 2:
- return standard_80387_constant_opcode (operands[1]);
-
- case 3:
- case 4:
- return "#";
-
- default:
- gcc_unreachable ();
- }
-}
- [(set_attr "type" "fmov,fmov,fmov,multi,multi")
- (set_attr "mode" "XF,XF,XF,SI,SI")])
-
-;; Possible store forwarding (partial memory) stall in alternative 4.
+;; Possible store forwarding (partial memory) stall in alternatives 4 and 5.
(define_insn "*movxf_internal"
- [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,?Yx*r ,!o")
- (match_operand:XF 1 "general_operand" "fm,f,G,Yx*roF,Yx*rF"))]
- "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))
+ [(set (match_operand:XF 0 "nonimmediate_operand"
+ "=f,m,f,?Yx*r ,!o ,!o")
+ (match_operand:XF 1 "general_operand"
+ "fm,f,G,Yx*roF,Yx*rF,Yx*rC"))]
+ "!(MEM_P (operands[0]) && MEM_P (operands[1]))
&& (!can_create_pseudo_p ()
|| (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
|| GET_CODE (operands[1]) != CONST_DOUBLE
@@ -2914,177 +2721,37 @@
|| (!TARGET_MEMORY_MISMATCH_STALL
&& memory_operand (operands[0], XFmode)))"
{
- switch (which_alternative)
+ switch (get_attr_type (insn))
{
- case 0:
- case 1:
+ case TYPE_FMOV:
+ if (which_alternative == 2)
+ return standard_80387_constant_opcode (operands[1]);
return output_387_reg_move (insn, operands);
- case 2:
- return standard_80387_constant_opcode (operands[1]);
-
- case 3:
- case 4:
+ case TYPE_MULTI:
return "#";
default:
gcc_unreachable ();
}
}
- [(set_attr "type" "fmov,fmov,fmov,multi,multi")
- (set_attr "mode" "XF,XF,XF,SI,SI")])
-
-(define_insn "*movdf_internal_rex64"
- [(set (match_operand:DF 0 "nonimmediate_operand"
- "=Yf*f,m ,Yf*f,?r,?m,?r,?r,x,x,x,m,Yi,r")
- (match_operand:DF 1 "general_operand"
- "Yf*fm,Yf*f,G ,rm,rC,C ,F ,C,x,m,x,r ,Yi"))]
- "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))
- && (!can_create_pseudo_p ()
- || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
- || GET_CODE (operands[1]) != CONST_DOUBLE
- || (optimize_function_for_size_p (cfun)
- && ((!(TARGET_SSE2 && TARGET_SSE_MATH)
- && standard_80387_constant_p (operands[1]) > 0)
- || (TARGET_SSE2 && TARGET_SSE_MATH
- && standard_sse_constant_p (operands[1]))))
- || memory_operand (operands[0], DFmode))"
-{
- switch (which_alternative)
- {
- case 0:
- case 1:
- return output_387_reg_move (insn, operands);
-
- case 2:
- return standard_80387_constant_opcode (operands[1]);
-
- case 3:
- case 4:
- return "mov{q}\t{%1, %0|%0, %1}";
-
- case 5:
- return "mov{l}\t{%1, %k0|%k0, %1}";
-
- case 6:
- return "movabs{q}\t{%1, %0|%0, %1}";
-
- case 7:
- return standard_sse_constant_opcode (insn, operands[1]);
-
- case 8:
- case 9:
- case 10:
- switch (get_attr_mode (insn))
- {
- case MODE_V2DF:
- return "%vmovapd\t{%1, %0|%0, %1}";
- case MODE_V4SF:
- return "%vmovaps\t{%1, %0|%0, %1}";
-
- case MODE_DI:
- return "%vmovq\t{%1, %0|%0, %1}";
- case MODE_DF:
- if (TARGET_AVX && REG_P (operands[0]) && REG_P (operands[1]))
- return "vmovsd\t{%1, %0, %0|%0, %0, %1}";
- return "%vmovsd\t{%1, %0|%0, %1}";
- case MODE_V1DF:
- return "%vmovlpd\t{%1, %d0|%d0, %1}";
- case MODE_V2SF:
- return "%vmovlps\t{%1, %d0|%d0, %1}";
- default:
- gcc_unreachable ();
- }
-
- case 11:
- case 12:
- /* Handle broken assemblers that require movd instead of movq. */
- return "%vmovd\t{%1, %0|%0, %1}";
-
- default:
- gcc_unreachable();
- }
-}
- [(set (attr "type")
- (cond [(eq_attr "alternative" "0,1,2")
- (const_string "fmov")
- (eq_attr "alternative" "3,4,5,6")
- (const_string "imov")
- (eq_attr "alternative" "7")
- (const_string "sselog1")
- ]
- (const_string "ssemov")))
- (set (attr "modrm")
- (if_then_else
- (and (eq_attr "alternative" "6") (eq_attr "type" "imov"))
- (const_string "0")
- (const_string "*")))
- (set (attr "length_immediate")
- (if_then_else
- (and (eq_attr "alternative" "6") (eq_attr "type" "imov"))
- (const_string "8")
- (const_string "*")))
- (set (attr "prefix")
- (if_then_else (eq_attr "alternative" "0,1,2,3,4,5,6")
- (const_string "orig")
- (const_string "maybe_vex")))
- (set (attr "prefix_data16")
- (if_then_else (eq_attr "mode" "V1DF")
- (const_string "1")
- (const_string "*")))
+ [(set_attr "isa" "*,*,*,*,nox64,x64")
+ (set_attr "type" "fmov,fmov,fmov,multi,multi,multi")
(set (attr "mode")
- (cond [(eq_attr "alternative" "0,1,2")
- (const_string "DF")
- (eq_attr "alternative" "3,4,6,11,12")
- (const_string "DI")
- (eq_attr "alternative" "5")
- (const_string "SI")
-
- /* xorps is one byte shorter for !TARGET_AVX. */
- (eq_attr "alternative" "7")
- (cond [(match_test "TARGET_AVX")
- (const_string "V2DF")
- (match_test "optimize_function_for_size_p (cfun)")
- (const_string "V4SF")
- (match_test "TARGET_SSE_LOAD0_BY_PXOR")
- (const_string "TI")
- ]
- (const_string "V2DF"))
-
- /* For architectures resolving dependencies on
- whole SSE registers use APD move to break dependency
- chains, otherwise use short move to avoid extra work.
-
- movaps encodes one byte shorter for !TARGET_AVX. */
- (eq_attr "alternative" "8")
- (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
- (const_string "V4SF")
- (match_test "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
- (const_string "V2DF")
- (match_test "TARGET_AVX")
- (const_string "DF")
- (match_test "optimize_function_for_size_p (cfun)")
- (const_string "V4SF")
- ]
- (const_string "DF"))
- /* For architectures resolving dependencies on register
- parts we may avoid extra work to zero out upper part
- of register. */
- (eq_attr "alternative" "9")
- (if_then_else
- (match_test "TARGET_SSE_SPLIT_REGS")
- (const_string "V1DF")
- (const_string "DF"))
+ (cond [(eq_attr "alternative" "3,4,5")
+ (if_then_else (match_test "TARGET_64BIT")
+ (const_string "DI")
+ (const_string "SI"))
]
- (const_string "DF")))])
+ (const_string "XF")))])
;; Possible store forwarding (partial memory) stall in alternative 4.
(define_insn "*movdf_internal"
[(set (match_operand:DF 0 "nonimmediate_operand"
- "=Yf*f,m ,Yf*f,?Yd*r ,!o ,x,x,x,m,*x,*x,*x,m")
+ "=Yf*f,m ,Yf*f,?Yd*r ,!o ,?r,?m,?r,?r,x,x,x,m,*x,*x,*x,m ,r ,Yi")
(match_operand:DF 1 "general_operand"
- "Yf*fm,Yf*f,G ,Yd*roF,Yd*rF,C,x,m,x,C ,*x,m ,*x"))]
- "!TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))
+ "Yf*fm,Yf*f,G ,Yd*roF,Yd*rF,rm,rC,C ,F ,C,x,m,x,C ,*x,m ,*x,Yi,r"))]
+ "!(MEM_P (operands[0]) && MEM_P (operands[1]))
&& (!can_create_pseudo_p ()
|| (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
|| GET_CODE (operands[1]) != CONST_DOUBLE
@@ -3094,49 +2761,58 @@
|| (TARGET_SSE2 && TARGET_SSE_MATH
&& standard_sse_constant_p (operands[1])))
&& !memory_operand (operands[0], DFmode))
- || (!TARGET_MEMORY_MISMATCH_STALL
+ || ((TARGET_64BIT || !TARGET_MEMORY_MISMATCH_STALL)
&& memory_operand (operands[0], DFmode)))"
{
- switch (which_alternative)
+ switch (get_attr_type (insn))
{
- case 0:
- case 1:
+ case TYPE_FMOV:
+ if (which_alternative == 2)
+ return standard_80387_constant_opcode (operands[1]);
return output_387_reg_move (insn, operands);
- case 2:
- return standard_80387_constant_opcode (operands[1]);
-
- case 3:
- case 4:
+ case TYPE_MULTI:
return "#";
- case 5:
- case 9:
+ case TYPE_IMOV:
+ if (get_attr_mode (insn) == MODE_SI)
+ return "mov{l}\t{%1, %k0|%k0, %1}";
+ else if (which_alternative == 8)
+ return "movabs{q}\t{%1, %0|%0, %1}";
+ else
+ return "mov{q}\t{%1, %0|%0, %1}";
+
+ case TYPE_SSELOG1:
return standard_sse_constant_opcode (insn, operands[1]);
- case 6:
- case 7:
- case 8:
- case 10:
- case 11:
- case 12:
+ case TYPE_SSEMOV:
switch (get_attr_mode (insn))
{
- case MODE_V2DF:
- return "%vmovapd\t{%1, %0|%0, %1}";
- case MODE_V4SF:
- return "%vmovaps\t{%1, %0|%0, %1}";
-
- case MODE_DI:
- return "%vmovq\t{%1, %0|%0, %1}";
case MODE_DF:
if (TARGET_AVX && REG_P (operands[0]) && REG_P (operands[1]))
return "vmovsd\t{%1, %0, %0|%0, %0, %1}";
return "%vmovsd\t{%1, %0|%0, %1}";
- case MODE_V1DF:
- return "%vmovlpd\t{%1, %d0|%d0, %1}";
+
+ case MODE_V4SF:
+ return "%vmovaps\t{%1, %0|%0, %1}";
+ case MODE_V2DF:
+ return "%vmovapd\t{%1, %0|%0, %1}";
+
case MODE_V2SF:
- return "%vmovlps\t{%1, %d0|%d0, %1}";
+ gcc_assert (!TARGET_AVX);
+ return "movlps\t{%1, %0|%0, %1}";
+ case MODE_V1DF:
+ gcc_assert (!TARGET_AVX);
+ return "movlpd\t{%1, %0|%0, %1}";
+
+ case MODE_DI:
+#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ
+ /* Handle broken assemblers that require movd instead of movq. */
+ if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
+ return "%vmovd\t{%1, %0|%0, %1}";
+#endif
+ return "%vmovq\t{%1, %0|%0, %1}";
+
default:
gcc_unreachable ();
}
@@ -3146,42 +2822,54 @@
}
}
[(set (attr "isa")
- (if_then_else (eq_attr "alternative" "5,6,7,8")
- (const_string "sse2")
- (const_string "*")))
+ (cond [(eq_attr "alternative" "3,4")
+ (const_string "nox64")
+ (eq_attr "alternative" "5,6,7,8,17,18")
+ (const_string "x64")
+ (eq_attr "alternative" "9,10,11,12")
+ (const_string "sse2")
+ ]
+ (const_string "*")))
(set (attr "type")
(cond [(eq_attr "alternative" "0,1,2")
(const_string "fmov")
(eq_attr "alternative" "3,4")
(const_string "multi")
- (eq_attr "alternative" "5,9")
+ (eq_attr "alternative" "5,6,7,8")
+ (const_string "imov")
+ (eq_attr "alternative" "9,13")
(const_string "sselog1")
]
(const_string "ssemov")))
+ (set (attr "modrm")
+ (if_then_else (eq_attr "alternative" "8")
+ (const_string "0")
+ (const_string "*")))
+ (set (attr "length_immediate")
+ (if_then_else (eq_attr "alternative" "8")
+ (const_string "8")
+ (const_string "*")))
(set (attr "prefix")
- (if_then_else (eq_attr "alternative" "0,1,2,3,4")
- (const_string "orig")
- (const_string "maybe_vex")))
+ (if_then_else (eq_attr "type" "sselog1,ssemov")
+ (const_string "maybe_vex")
+ (const_string "orig")))
(set (attr "prefix_data16")
- (if_then_else (eq_attr "mode" "V1DF")
+ (if_then_else
+ (ior (and (eq_attr "type" "ssemov") (eq_attr "mode" "DI"))
+ (eq_attr "mode" "V1DF"))
(const_string "1")
(const_string "*")))
(set (attr "mode")
- (cond [(eq_attr "alternative" "0,1,2")
- (const_string "DF")
- (eq_attr "alternative" "3,4")
+ (cond [(eq_attr "alternative" "3,4,7")
(const_string "SI")
+ (eq_attr "alternative" "5,6,8,17,18")
+ (const_string "DI")
- /* For SSE1, we have many fewer alternatives. */
- (not (match_test "TARGET_SSE2"))
- (if_then_else
- (eq_attr "alternative" "5,6,9,10")
- (const_string "V4SF")
- (const_string "V2SF"))
-
- /* xorps is one byte shorter for !TARGET_AVX. */
- (eq_attr "alternative" "5,9")
- (cond [(match_test "TARGET_AVX")
+ /* xorps is one byte shorter for non-AVX targets. */
+ (eq_attr "alternative" "9,13")
+ (cond [(not (match_test "TARGET_SSE2"))
+ (const_string "V4SF")
+ (match_test "TARGET_AVX")
(const_string "V2DF")
(match_test "optimize_function_for_size_p (cfun)")
(const_string "V4SF")
@@ -3191,12 +2879,13 @@
(const_string "V2DF"))
/* For architectures resolving dependencies on
- whole SSE registers use APD move to break dependency
- chains, otherwise use short move to avoid extra work.
+ whole SSE registers use movapd to break dependency
+ chains, otherwise use short move to avoid extra work. */
- movaps encodes one byte shorter for !TARGET_AVX. */
- (eq_attr "alternative" "6,10")
- (cond [(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
+ /* movaps is one byte shorter for non-AVX targets. */
+ (eq_attr "alternative" "10,14")
+ (cond [(ior (not (match_test "TARGET_SSE2"))
+ (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL"))
(const_string "V4SF")
(match_test "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
(const_string "V2DF")
@@ -3204,25 +2893,33 @@
(const_string "DF")
(match_test "optimize_function_for_size_p (cfun)")
(const_string "V4SF")
- ]
- (const_string "DF"))
+ ]
+ (const_string "DF"))
/* For architectures resolving dependencies on register
parts we may avoid extra work to zero out upper part
of register. */
- (eq_attr "alternative" "7,11")
- (if_then_else
- (match_test "TARGET_SSE_SPLIT_REGS")
- (const_string "V1DF")
- (const_string "DF"))
+ (eq_attr "alternative" "11,15")
+ (cond [(not (match_test "TARGET_SSE2"))
+ (const_string "V2SF")
+ (match_test "TARGET_AVX")
+ (const_string "DF")
+ (match_test "TARGET_SSE_SPLIT_REGS")
+ (const_string "V1DF")
+ ]
+ (const_string "DF"))
+
+ (and (eq_attr "alternative" "12,16")
+ (not (match_test "TARGET_SSE2")))
+ (const_string "V2SF")
]
(const_string "DF")))])
(define_insn "*movsf_internal"
[(set (match_operand:SF 0 "nonimmediate_operand"
- "=Yf*f,m ,Yf*f,?r ,?m,x,x,x,m,!*y,!m,!*y,?Yi,?r,!*Ym,!r")
+ "=Yf*f,m ,Yf*f,?r ,?m,x,x,x,m,?r,?Yi,!*y,!*y,!m,!r ,!*Ym")
(match_operand:SF 1 "general_operand"
- "Yf*fm,Yf*f,G ,rmF,rF,C,x,m,x,m ,*y,*y ,r ,Yi,r ,*Ym"))]
+ "Yf*fm,Yf*f,G ,rmF,rF,C,x,m,x,Yi,r ,*y ,m ,*y,*Ym,r"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))
&& (!can_create_pseudo_p ()
|| (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE)
@@ -3234,44 +2931,48 @@
&& standard_sse_constant_p (operands[1]))))
|| memory_operand (operands[0], SFmode))"
{
- switch (which_alternative)
+ switch (get_attr_type (insn))
{
- case 0:
- case 1:
+ case TYPE_FMOV:
+ if (which_alternative == 2)
+ return standard_80387_constant_opcode (operands[1]);
return output_387_reg_move (insn, operands);
- case 2:
- return standard_80387_constant_opcode (operands[1]);
-
- case 3:
- case 4:
+ case TYPE_IMOV:
return "mov{l}\t{%1, %0|%0, %1}";
- case 5:
+ case TYPE_SSELOG1:
return standard_sse_constant_opcode (insn, operands[1]);
- case 6:
- if (get_attr_mode (insn) == MODE_V4SF)
- return "%vmovaps\t{%1, %0|%0, %1}";
- if (TARGET_AVX)
- return "vmovss\t{%1, %0, %0|%0, %0, %1}";
+ case TYPE_SSEMOV:
+ switch (get_attr_mode (insn))
+ {
+ case MODE_SF:
+ if (TARGET_AVX && REG_P (operands[0]) && REG_P (operands[1]))
+ return "vmovss\t{%1, %0, %0|%0, %0, %1}";
+ return "%vmovss\t{%1, %0|%0, %1}";
- case 7:
- case 8:
- return "%vmovss\t{%1, %0|%0, %1}";
+ case MODE_V4SF:
+ return "%vmovaps\t{%1, %0|%0, %1}";
- case 9:
- case 10:
- case 14:
- case 15:
- return "movd\t{%1, %0|%0, %1}";
+ case MODE_SI:
+ return "%vmovd\t{%1, %0|%0, %1}";
- case 11:
- return "movq\t{%1, %0|%0, %1}";
+ default:
+ gcc_unreachable ();
+ }
- case 12:
- case 13:
- return "%vmovd\t{%1, %0|%0, %1}";
+ case TYPE_MMXMOV:
+ switch (get_attr_mode (insn))
+ {
+ case MODE_DI:
+ return "movq\t{%1, %0|%0, %1}";
+ case MODE_SI:
+ return "movd\t{%1, %0|%0, %1}";
+
+ default:
+ gcc_unreachable ();
+ }
default:
gcc_unreachable ();
@@ -3281,27 +2982,34 @@
(cond [(eq_attr "alternative" "0,1,2")
(const_string "fmov")
(eq_attr "alternative" "3,4")
- (const_string "multi")
+ (const_string "imov")
(eq_attr "alternative" "5")
(const_string "sselog1")
- (eq_attr "alternative" "9,10,11,14,15")
+ (eq_attr "alternative" "11,12,13,14,15")
(const_string "mmxmov")
]
(const_string "ssemov")))
(set (attr "prefix")
- (if_then_else (eq_attr "alternative" "5,6,7,8,12,13")
+ (if_then_else (eq_attr "type" "sselog1,ssemov")
(const_string "maybe_vex")
(const_string "orig")))
+ (set (attr "prefix_data16")
+ (if_then_else (and (eq_attr "type" "ssemov") (eq_attr "mode" "SI"))
+ (const_string "1")
+ (const_string "*")))
(set (attr "mode")
- (cond [(eq_attr "alternative" "3,4,9,10")
+ (cond [(eq_attr "alternative" "3,4,9,10,14,15")
(const_string "SI")
+ (eq_attr "alternative" "11")
+ (const_string "DI")
(eq_attr "alternative" "5")
- (cond [(match_test "TARGET_AVX")
- (const_string "V4SF")
- (ior (not (match_test "TARGET_SSE2"))
- (match_test "optimize_function_for_size_p (cfun)"))
+ (cond [(not (match_test "TARGET_SSE2"))
(const_string "V4SF")
- (match_test "TARGET_SSE_LOAD0_BY_PXOR")
+ (match_test "TARGET_AVX")
+ (const_string "V4SF")
+ (match_test "optimize_function_for_size_p (cfun)")
+ (const_string "V4SF")
+ (match_test "TARGET_SSE_LOAD0_BY_PXOR")
(const_string "TI")
]
(const_string "V4SF"))
@@ -3316,15 +3024,12 @@
of instructions to load just part of the register. It is
better to maintain the whole registers in single format
to avoid problems on using packed logical operations. */
- (eq_attr "alternative" "6")
- (if_then_else
- (ior (match_test "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
- (match_test "TARGET_SSE_SPLIT_REGS"))
- (const_string "V4SF")
- (const_string "SF"))
- (eq_attr "alternative" "11")
- (const_string "DI")]
- (const_string "SF")))])
+ (and (eq_attr "alternative" "6")
+ (ior (match_test "TARGET_SSE_PARTIAL_REG_DEPENDENCY")
+ (match_test "TARGET_SSE_SPLIT_REGS")))
+ (const_string "V4SF")
+ ]
+ (const_string "SF")))])
(define_split
[(set (match_operand 0 "any_fp_register_operand")