Commit a8ecfc9f by Uros Bizjak

i386.md (SWI1248x): New mode iterator.

	* config/i386/i386.md (SWI1248x): New mode iterator.
	(SWI48x): Ditto.
	(SWI12): Ditto.
	(SWI24): Ditto.
	
	(mov<mode>): Macroize expander from mov{qi,hi,si,di} using
	SWI1248x mode iterator.
	(*push<mode>2_rex64): Macroize insn from *push{qi,hi,si}_rex64
	using SWI124 mode iterator.
	(*push<mode>2): Macroize insn from *push{qi,hi} using SWI12
	mode iterator.
	(*push<mode>2_prologue): Macroize insn from  *pushsi2_prologue and
	*pushdi2_prologue_rex64 using P mode iterator.
	(*mov<mode>_xor): Macroize insn from *movsi_xor and *movdi_xor_rex64
	using SWI48 mode iterator.
	(*mov<mode>_or): Ditto from *movsi_or and *movdi_or_rex64.
	(*movabs<mode>_1): Macroize insn from *movabs{qi,hi,si,di}_1_rex64
	using SWI1248x mode iterator.
	(*movabs<mode>_2): Ditto from *movabs{qi,hi,si,di}_1_rex64.
	(*swap<mode>): Macroize insn from *swapsi and *swapdi_rex64 using
	SWI48 mode iterator.
	(*swap<mode>_1): Macroize insn from *swap{qi,hi}_1 using SWI12 mode
	iterator.
	(*swap<mode>_2): Ditto from *swap{qi,hi}_2.
	(movstrict<mode>): Macroize expander from movstrict{qi,hi} using
	SWI12 mode iterator.
	(*movstrict<mode>_1): Macroize insn from *movstrict{qi,hi}_1 using
	SWI12 mode iterator.
	(*movstrict<mode>_xor): Ditto from *movstrict{qi,hi}_xor.
	(*mov<mode>_extv_1): Macroize insn from *mov{hi,si}_extv_1 using
	SWI24 mode iterator.
	(*mov<mode>_extzv_1): Macroize insn from *mov{si,di}_extzv_1 using
	SWI48 mode iterator.
	(mov<mode>_insn_1): New expander.
	(*mov<mode>_insv_1_rex64): Macroize insn from *mov{si,di}_insv_1_rex64
	using SWI48x mode iterator.

	(*movoi_internal_avx): Rename from *movoi_internal.
	(*movti_internal_rex64): Rename from *movti_rex64.
	(*movti_internal_sse): Rename from *movti_sse.
	(*movdi_internal_rex64): Rename from *movdi_1_rex64.
	(*movdi_internal): Rename from *movdi_2.
	(*movsi_internal): Rename from *movsi_1.
	(*movhi_internal): Rename from *movhi_1.
	(*movqi_internal): Rename from *movqi_1.

	(insv): Update the call to gen_movsi_insv_1 for rename.
	* config/i386/i386.c (promote_duplicated_reg): Ditto.

From-SVN: r161185
parent b81a5940
2010-06-22 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.md (SWI1248x): New mode iterator.
(SWI48x): Ditto.
(SWI12): Ditto.
(SWI24): Ditto.
(mov<mode>): Macroize expander from mov{qi,hi,si,di} using
SWI1248x mode iterator.
(*push<mode>2_rex64): Macroize insn from *push{qi,hi,si}_rex64
using SWI124 mode iterator.
(*push<mode>2): Macroize insn from *push{qi,hi} using SWI12
mode iterator.
(*push<mode>2_prologue): Macroize insn from *pushsi2_prologue and
*pushdi2_prologue_rex64 using P mode iterator.
(*mov<mode>_xor): Macroize insn from *movsi_xor and *movdi_xor_rex64
using SWI48 mode iterator.
(*mov<mode>_or): Ditto from *movsi_or and *movdi_or_rex64.
(*movabs<mode>_1): Macroize insn from *movabs{qi,hi,si,di}_1_rex64
using SWI1248x mode iterator.
(*movabs<mode>_2): Ditto from *movabs{qi,hi,si,di}_1_rex64.
(*swap<mode>): Macroize insn from *swapsi and *swapdi_rex64 using
SWI48 mode iterator.
(*swap<mode>_1): Macroize insn from *swap{qi,hi}_1 using SWI12 mode
iterator.
(*swap<mode>_2): Ditto from *swap{qi,hi}_2.
(movstrict<mode>): Macroize expander from movstrict{qi,hi} using
SWI12 mode iterator.
(*movstrict<mode>_1): Macroize insn from *movstrict{qi,hi}_1 using
SWI12 mode iterator.
(*movstrict<mode>_xor): Ditto from *movstrict{qi,hi}_xor.
(*mov<mode>_extv_1): Macroize insn from *mov{hi,si}_extv_1 using
SWI24 mode iterator.
(*mov<mode>_extzv_1): Macroize insn from *mov{si,di}_extzv_1 using
SWI48 mode iterator.
(mov<mode>_insn_1): New expander.
(*mov<mode>_insv_1_rex64): Macroize insn from *mov{si,di}_insv_1_rex64
using SWI48x mode iterator.
(*movoi_internal_avx): Rename from *movoi_internal.
(*movti_internal_rex64): Rename from *movti_rex64.
(*movti_internal_sse): Rename from *movti_sse.
(*movdi_internal_rex64): Rename from *movdi_1_rex64.
(*movdi_internal): Rename from *movdi_2.
(*movsi_internal): Rename from *movsi_1.
(*movhi_internal): Rename from *movhi_1.
(*movqi_internal): Rename from *movqi_1.
(insv): Update the call to gen_movsi_insv_1 for rename.
* config/i386/i386.c (promote_duplicated_reg): Ditto.
2010-06-22 Jan Hubicka <jh@suse.cz> 2010-06-22 Jan Hubicka <jh@suse.cz>
* passes.c (execute_function_todo): Move call of statistics_fini_pass * passes.c (execute_function_todo): Move call of statistics_fini_pass
...@@ -231,8 +282,7 @@ ...@@ -231,8 +282,7 @@
2010-06-19 Philip Herron <herron.philip@googlemail.com> 2010-06-19 Philip Herron <herron.philip@googlemail.com>
* c-decl.c (c_write_global_declarations): Don't check * c-decl.c (c_write_global_declarations): Don't check flag_syntax_only.
flag_syntax_only.
2010-06-18 H.J. Lu <hongjiu.lu@intel.com> 2010-06-18 H.J. Lu <hongjiu.lu@intel.com>
...@@ -269,8 +319,7 @@ ...@@ -269,8 +319,7 @@
* function.h (types_used_by_cur_var_decl): Change type to a VEC. * function.h (types_used_by_cur_var_decl): Change type to a VEC.
* function.c (types_used_by_cur_var_decl): Likewise. * function.c (types_used_by_cur_var_decl): Likewise.
(used_types_insert): Adjust for new type of (used_types_insert): Adjust for new type of types_used_by_cur_var_decl.
types_used_by_cur_var_decl.
2010-06-18 Nathan Froyd <froydnj@codesourcery.com> 2010-06-18 Nathan Froyd <froydnj@codesourcery.com>
...@@ -512,8 +561,7 @@ ...@@ -512,8 +561,7 @@
(PRINT_OPERAND_PUNCT_VALID_P): Delete. (PRINT_OPERAND_PUNCT_VALID_P): Delete.
(PRINT_OPERAND_ADDRESS, ARM_PRINT_OPERAND_ADDRESS): (PRINT_OPERAND_ADDRESS, ARM_PRINT_OPERAND_ADDRESS):
(THUMB_PRINT_OPERAND_ADDRESS): Delete and move code to... (THUMB_PRINT_OPERAND_ADDRESS): Delete and move code to...
* config/arm/arm.c (arm_print_operand_address): ...here. New * config/arm/arm.c (arm_print_operand_address): ...here. New function.
function.
(arm_print_operand): Make static. (arm_print_operand): Make static.
(arm_print_operand_punct_valid_p): New function. (arm_print_operand_punct_valid_p): New function.
(TARGET_PRINT_OPERAND, TARGET_PRINT_OPERAND_ADDRESS): (TARGET_PRINT_OPERAND, TARGET_PRINT_OPERAND_ADDRESS):
......
...@@ -18838,7 +18838,7 @@ promote_duplicated_reg (enum machine_mode mode, rtx val) ...@@ -18838,7 +18838,7 @@ promote_duplicated_reg (enum machine_mode mode, rtx val)
if (mode == SImode) if (mode == SImode)
emit_insn (gen_movsi_insv_1 (reg, reg)); emit_insn (gen_movsi_insv_1 (reg, reg));
else else
emit_insn (gen_movdi_insv_1_rex64 (reg, reg)); emit_insn (gen_movdi_insv_1 (reg, reg));
else else
{ {
tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (8), tmp = expand_simple_binop (mode, ASHIFT, reg, GEN_INT (8),
......
...@@ -765,12 +765,24 @@ ...@@ -765,12 +765,24 @@
(define_code_attr sgnprefix [(sign_extend "i") (zero_extend "") (define_code_attr sgnprefix [(sign_extend "i") (zero_extend "")
(div "i") (udiv "")]) (div "i") (udiv "")])
;; All single word integer modes. ;; 64bit single word integer modes.
(define_mode_iterator SWI1248x [QI HI SI DI])
;; 64bit single word integer modes without QImode and HImode.
(define_mode_iterator SWI48x [SI DI])
;; Single word integer modes.
(define_mode_iterator SWI [QI HI SI (DI "TARGET_64BIT")]) (define_mode_iterator SWI [QI HI SI (DI "TARGET_64BIT")])
;; Single word integer modes without SImode and DImode.
(define_mode_iterator SWI12 [QI HI])
;; Single word integer modes without DImode. ;; Single word integer modes without DImode.
(define_mode_iterator SWI124 [QI HI SI]) (define_mode_iterator SWI124 [QI HI SI])
;; Single word integer modes without QImode and DImode.
(define_mode_iterator SWI24 [HI SI])
;; Single word integer modes without QImode. ;; Single word integer modes without QImode.
(define_mode_iterator SWI248 [HI SI (DI "TARGET_64BIT")]) (define_mode_iterator SWI248 [HI SI (DI "TARGET_64BIT")])
...@@ -1585,13 +1597,47 @@ ...@@ -1585,13 +1597,47 @@
;; Move instructions. ;; Move instructions.
;; General case of fullword move. (define_expand "movoi"
[(set (match_operand:OI 0 "nonimmediate_operand" "")
(match_operand:OI 1 "general_operand" ""))]
"TARGET_AVX"
"ix86_expand_move (OImode, operands); DONE;")
(define_expand "movsi" (define_expand "movti"
[(set (match_operand:SI 0 "nonimmediate_operand" "") [(set (match_operand:TI 0 "nonimmediate_operand" "")
(match_operand:SI 1 "general_operand" ""))] (match_operand:TI 1 "nonimmediate_operand" ""))]
"TARGET_64BIT || TARGET_SSE"
{
if (TARGET_64BIT)
ix86_expand_move (TImode, operands);
else if (push_operand (operands[0], TImode))
ix86_expand_push (TImode, operands[1]);
else
ix86_expand_vector_move (TImode, operands);
DONE;
})
;; This expands to what emit_move_complex would generate if we didn't
;; have a movti pattern. Having this avoids problems with reload on
;; 32-bit targets when SSE is present, but doesn't seem to be harmful
;; to have around all the time.
(define_expand "movcdi"
[(set (match_operand:CDI 0 "nonimmediate_operand" "")
(match_operand:CDI 1 "general_operand" ""))]
""
{
if (push_operand (operands[0], CDImode))
emit_move_complex_push (CDImode, operands[0], operands[1]);
else
emit_move_complex_parts (operands[0], operands[1]);
DONE;
})
(define_expand "mov<mode>"
[(set (match_operand:SWI1248x 0 "nonimmediate_operand" "")
(match_operand:SWI1248x 1 "general_operand" ""))]
"" ""
"ix86_expand_move (SImode, operands); DONE;") "ix86_expand_move (<MODE>mode, operands); DONE;")
;; Push/pop instructions. They are separate since autoinc/dec is not a ;; Push/pop instructions. They are separate since autoinc/dec is not a
;; general_operand. ;; general_operand.
...@@ -1602,6 +1648,79 @@ ...@@ -1602,6 +1648,79 @@
;; targets without our curiosities, and it is just as easy to represent ;; targets without our curiosities, and it is just as easy to represent
;; this differently. ;; this differently.
(define_insn "*pushdi2_rex64"
[(set (match_operand:DI 0 "push_operand" "=<,!<")
(match_operand:DI 1 "general_no_elim_operand" "re*m,n"))]
"TARGET_64BIT"
"@
push{q}\t%1
#"
[(set_attr "type" "push,multi")
(set_attr "mode" "DI")])
;; Convert impossible pushes of immediate to existing instructions.
;; First try to get scratch register and go through it. In case this
;; fails, push sign extended lower part first and then overwrite
;; upper part by 32bit move.
(define_peephole2
[(match_scratch:DI 2 "r")
(set (match_operand:DI 0 "push_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode)"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (match_dup 2))]
"")
;; We need to define this as both peepholer and splitter for case
;; peephole2 pass is not run.
;; "&& 1" is needed to keep it from matching the previous pattern.
(define_peephole2
[(set (match_operand:DI 0 "push_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode) && 1"
[(set (match_dup 0) (match_dup 1))
(set (match_dup 2) (match_dup 3))]
{
split_di (&operands[1], 1, &operands[2], &operands[3]);
operands[1] = gen_lowpart (DImode, operands[2]);
operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
GEN_INT (4)));
})
(define_split
[(set (match_operand:DI 0 "push_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && ((optimize > 0 && flag_peephole2)
? epilogue_completed : reload_completed)
&& !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode)"
[(set (match_dup 0) (match_dup 1))
(set (match_dup 2) (match_dup 3))]
{
split_di (&operands[1], 1, &operands[2], &operands[3]);
operands[1] = gen_lowpart (DImode, operands[2]);
operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
GEN_INT (4)));
})
(define_insn "*pushdi2"
[(set (match_operand:DI 0 "push_operand" "=<")
(match_operand:DI 1 "general_no_elim_operand" "riF*m"))]
"!TARGET_64BIT"
"#")
(define_split
[(set (match_operand:DI 0 "push_operand" "")
(match_operand:DI 1 "general_operand" ""))]
"!TARGET_64BIT && reload_completed
&& !(MMX_REG_P (operands[1]) || SSE_REG_P (operands[1]))"
[(const_int 0)]
"ix86_split_long_move (operands); DONE;")
(define_insn "*pushsi2" (define_insn "*pushsi2"
[(set (match_operand:SI 0 "push_operand" "=<") [(set (match_operand:SI 0 "push_operand" "=<")
(match_operand:SI 1 "general_no_elim_operand" "ri*m"))] (match_operand:SI 1 "general_no_elim_operand" "ri*m"))]
...@@ -1610,761 +1729,335 @@ ...@@ -1610,761 +1729,335 @@
[(set_attr "type" "push") [(set_attr "type" "push")
(set_attr "mode" "SI")]) (set_attr "mode" "SI")])
;; emit_push_insn when it calls move_by_pieces requires an insn to
;; "push a byte/word". But actually we use pushl, which has the effect
;; of rounding the amount pushed up to a word.
;; For 64BIT abi we always round up to 8 bytes. ;; For 64BIT abi we always round up to 8 bytes.
(define_insn "*pushsi2_rex64" (define_insn "*push<mode>2_rex64"
[(set (match_operand:SI 0 "push_operand" "=X") [(set (match_operand:SWI124 0 "push_operand" "=X")
(match_operand:SI 1 "nonmemory_no_elim_operand" "ri"))] (match_operand:SWI124 1 "nonmemory_no_elim_operand" "r<i>"))]
"TARGET_64BIT" "TARGET_64BIT"
"push{q}\t%q1" "push{q}\t%q1"
[(set_attr "type" "push") [(set_attr "type" "push")
(set_attr "mode" "SI")]) (set_attr "mode" "DI")])
(define_insn "*pushsi2_prologue" (define_insn "*push<mode>2"
[(set (match_operand:SI 0 "push_operand" "=<") [(set (match_operand:SWI12 0 "push_operand" "=X")
(match_operand:SI 1 "general_no_elim_operand" "ri*m")) (match_operand:SWI12 1 "nonmemory_no_elim_operand" "rn"))]
(clobber (mem:BLK (scratch)))]
"!TARGET_64BIT" "!TARGET_64BIT"
"push{l}\t%1" "push{l}\t%k1"
[(set_attr "type" "push") [(set_attr "type" "push")
(set_attr "mode" "SI")]) (set_attr "mode" "SI")])
(define_insn "*popsi1_epilogue" (define_insn "*push<mode>2_prologue"
[(set (match_operand:P 0 "push_operand" "=<")
(match_operand:P 1 "general_no_elim_operand" "r<i>*m"))
(clobber (mem:BLK (scratch)))]
""
"push{<imodesuffix>}\t%1"
[(set_attr "type" "push")
(set_attr "mode" "<MODE>")])
(define_insn "popdi1"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
(mem:DI (reg:DI SP_REG)))
(set (reg:DI SP_REG)
(plus:DI (reg:DI SP_REG) (const_int 8)))]
"TARGET_64BIT"
"pop{q}\t%0"
[(set_attr "type" "pop")
(set_attr "mode" "DI")])
(define_insn "popsi1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r*m") [(set (match_operand:SI 0 "nonimmediate_operand" "=r*m")
(mem:SI (reg:SI SP_REG))) (mem:SI (reg:SI SP_REG)))
(set (reg:SI SP_REG) (set (reg:SI SP_REG)
(plus:SI (reg:SI SP_REG) (const_int 4))) (plus:SI (reg:SI SP_REG) (const_int 4)))]
(clobber (mem:BLK (scratch)))]
"!TARGET_64BIT" "!TARGET_64BIT"
"pop{l}\t%0" "pop{l}\t%0"
[(set_attr "type" "pop") [(set_attr "type" "pop")
(set_attr "mode" "SI")]) (set_attr "mode" "SI")])
(define_insn "popsi1" (define_insn "*popdi1_epilogue"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
(mem:DI (reg:DI SP_REG)))
(set (reg:DI SP_REG)
(plus:DI (reg:DI SP_REG) (const_int 8)))
(clobber (mem:BLK (scratch)))]
"TARGET_64BIT"
"pop{q}\t%0"
[(set_attr "type" "pop")
(set_attr "mode" "DI")])
(define_insn "*popsi1_epilogue"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r*m") [(set (match_operand:SI 0 "nonimmediate_operand" "=r*m")
(mem:SI (reg:SI SP_REG))) (mem:SI (reg:SI SP_REG)))
(set (reg:SI SP_REG) (set (reg:SI SP_REG)
(plus:SI (reg:SI SP_REG) (const_int 4)))] (plus:SI (reg:SI SP_REG) (const_int 4)))
(clobber (mem:BLK (scratch)))]
"!TARGET_64BIT" "!TARGET_64BIT"
"pop{l}\t%0" "pop{l}\t%0"
[(set_attr "type" "pop") [(set_attr "type" "pop")
(set_attr "mode" "SI")]) (set_attr "mode" "SI")])
(define_insn "*movsi_xor" (define_insn "*mov<mode>_xor"
[(set (match_operand:SI 0 "register_operand" "=r") [(set (match_operand:SWI48 0 "register_operand" "=r")
(match_operand:SI 1 "const0_operand" "")) (match_operand:SWI48 1 "const0_operand" ""))
(clobber (reg:CC FLAGS_REG))] (clobber (reg:CC FLAGS_REG))]
"reload_completed" "reload_completed"
"xor{l}\t%0, %0" "xor{l}\t%k0, %k0"
[(set_attr "type" "alu1") [(set_attr "type" "alu1")
(set_attr "mode" "SI") (set_attr "mode" "SI")
(set_attr "length_immediate" "0")]) (set_attr "length_immediate" "0")])
(define_insn "*movsi_or" (define_insn "*mov<mode>_or"
[(set (match_operand:SI 0 "register_operand" "=r") [(set (match_operand:SWI48 0 "register_operand" "=r")
(match_operand:SI 1 "immediate_operand" "i")) (match_operand:SWI48 1 "const_int_operand" ""))
(clobber (reg:CC FLAGS_REG))] (clobber (reg:CC FLAGS_REG))]
"reload_completed "reload_completed
&& operands[1] == constm1_rtx" && operands[1] == constm1_rtx"
{ "or{<imodesuffix>}\t{%1, %0|%0, %1}"
operands[1] = constm1_rtx;
return "or{l}\t{%1, %0|%0, %1}";
}
[(set_attr "type" "alu1") [(set_attr "type" "alu1")
(set_attr "mode" "SI") (set_attr "mode" "<MODE>")
(set_attr "length_immediate" "1")]) (set_attr "length_immediate" "1")])
(define_insn "*movsi_1" (define_insn "*movoi_internal_avx"
[(set (match_operand:SI 0 "nonimmediate_operand" [(set (match_operand:OI 0 "nonimmediate_operand" "=x,x,m")
"=r,m ,*y,*y,?rm,?*y,*x,*x,?r ,m ,?*Yi,*x") (match_operand:OI 1 "vector_move_operand" "C,xm,x"))]
(match_operand:SI 1 "general_operand" "TARGET_AVX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
"g ,ri,C ,*y,*y ,rm ,C ,*x,*Yi,*x,r ,m "))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))"
{ {
switch (get_attr_type (insn)) switch (which_alternative)
{ {
case TYPE_SSELOG1: case 0:
if (get_attr_mode (insn) == MODE_TI) return "vxorps\t%0, %0, %0";
return "%vpxor\t%0, %d0"; case 1:
return "%vxorps\t%0, %d0"; case 2:
if (misaligned_operand (operands[0], OImode)
|| misaligned_operand (operands[1], OImode))
return "vmovdqu\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" "vex")
(set_attr "mode" "OI")])
case TYPE_SSEMOV: (define_insn "*movti_internal_rex64"
switch (get_attr_mode (insn)) [(set (match_operand:TI 0 "nonimmediate_operand" "=!r,o,x,x,xm")
(match_operand:TI 1 "general_operand" "riFo,riF,C,xm,x"))]
"TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
switch (which_alternative)
{
case 0:
case 1:
return "#";
case 2:
if (get_attr_mode (insn) == MODE_V4SF)
return "%vxorps\t%0, %d0";
else
return "%vpxor\t%0, %d0";
case 3:
case 4:
/* 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))
{ {
case MODE_TI: if (get_attr_mode (insn) == MODE_V4SF)
return "%vmovdqa\t{%1, %0|%0, %1}"; return "%vmovups\t{%1, %0|%0, %1}";
case MODE_V4SF: else
return "%vmovaps\t{%1, %0|%0, %1}"; return "%vmovdqu\t{%1, %0|%0, %1}";
case MODE_SI: }
return "%vmovd\t{%1, %0|%0, %1}"; else
case MODE_SF: {
return "%vmovss\t{%1, %0|%0, %1}"; if (get_attr_mode (insn) == MODE_V4SF)
default: return "%vmovaps\t{%1, %0|%0, %1}";
gcc_unreachable (); else
return "%vmovdqa\t{%1, %0|%0, %1}";
} }
case TYPE_MMX:
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}";
case TYPE_LEA:
return "lea{l}\t{%a1, %0|%0, %a1}";
default: default:
gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1])); gcc_unreachable ();
return "mov{l}\t{%1, %0|%0, %1}";
} }
} }
[(set (attr "type") [(set_attr "type" "*,*,sselog1,ssemov,ssemov")
(cond [(eq_attr "alternative" "2") (set_attr "prefix" "*,*,maybe_vex,maybe_vex,maybe_vex")
(const_string "mmx")
(eq_attr "alternative" "3,4,5")
(const_string "mmxmov")
(eq_attr "alternative" "6")
(const_string "sselog1")
(eq_attr "alternative" "7,8,9,10,11")
(const_string "ssemov")
(match_operand:DI 1 "pic_32bit_operand" "")
(const_string "lea")
]
(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")))
(set (attr "prefix_data16")
(if_then_else (and (eq_attr "type" "ssemov") (eq_attr "mode" "SI"))
(const_string "1")
(const_string "*")))
(set (attr "mode") (set (attr "mode")
(cond [(eq_attr "alternative" "2,3") (cond [(eq_attr "alternative" "2,3")
(const_string "DI") (if_then_else
(eq_attr "alternative" "6,7") (ne (symbol_ref "optimize_function_for_size_p (cfun)")
(if_then_else (const_int 0))
(eq (symbol_ref "TARGET_SSE2") (const_int 0)) (const_string "V4SF")
(const_string "V4SF") (const_string "TI"))
(const_string "TI")) (eq_attr "alternative" "4")
(and (eq_attr "alternative" "8,9,10,11") (if_then_else
(eq (symbol_ref "TARGET_SSE2") (const_int 0))) (ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
(const_string "SF") (const_int 0))
] (ne (symbol_ref "optimize_function_for_size_p (cfun)")
(const_string "SI")))]) (const_int 0)))
(const_string "V4SF")
;; Stores and loads of ax to arbitrary constant address. (const_string "TI"))]
;; We fake an second form of instruction to force reload to load address (const_string "DI")))])
;; into register when rax is not available
(define_insn "*movabssi_1_rex64"
[(set (mem:SI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
(match_operand:SI 1 "nonmemory_operand" "a,er"))]
"TARGET_64BIT && ix86_check_movabs (insn, 0)"
"@
movabs{l}\t{%1, %P0|%P0, %1}
mov{l}\t{%1, %a0|%a0, %1}"
[(set_attr "type" "imov")
(set_attr "modrm" "0,*")
(set_attr "length_address" "8,0")
(set_attr "length_immediate" "0,*")
(set_attr "memory" "store")
(set_attr "mode" "SI")])
(define_insn "*movabssi_2_rex64"
[(set (match_operand:SI 0 "register_operand" "=a,r")
(mem:SI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
"TARGET_64BIT && ix86_check_movabs (insn, 1)"
"@
movabs{l}\t{%P1, %0|%0, %P1}
mov{l}\t{%a1, %0|%0, %a1}"
[(set_attr "type" "imov")
(set_attr "modrm" "0,*")
(set_attr "length_address" "8,0")
(set_attr "length_immediate" "0")
(set_attr "memory" "load")
(set_attr "mode" "SI")])
(define_insn "*swapsi"
[(set (match_operand:SI 0 "register_operand" "+r")
(match_operand:SI 1 "register_operand" "+r"))
(set (match_dup 1)
(match_dup 0))]
""
"xchg{l}\t%1, %0"
[(set_attr "type" "imov")
(set_attr "mode" "SI")
(set_attr "pent_pair" "np")
(set_attr "athlon_decode" "vector")
(set_attr "amdfam10_decode" "double")])
(define_expand "movhi"
[(set (match_operand:HI 0 "nonimmediate_operand" "")
(match_operand:HI 1 "general_operand" ""))]
""
"ix86_expand_move (HImode, operands); DONE;")
(define_insn "*pushhi2"
[(set (match_operand:HI 0 "push_operand" "=X")
(match_operand:HI 1 "nonmemory_no_elim_operand" "rn"))]
"!TARGET_64BIT"
"push{l}\t%k1"
[(set_attr "type" "push")
(set_attr "mode" "SI")])
;; For 64BIT abi we always round up to 8 bytes.
(define_insn "*pushhi2_rex64"
[(set (match_operand:HI 0 "push_operand" "=X")
(match_operand:HI 1 "nonmemory_no_elim_operand" "rn"))]
"TARGET_64BIT"
"push{q}\t%q1"
[(set_attr "type" "push")
(set_attr "mode" "DI")])
(define_insn "*movhi_1"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
(match_operand:HI 1 "general_operand" "r,rn,rm,rn"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
switch (get_attr_type (insn))
{
case TYPE_IMOVX:
/* movzwl is faster than movw on p2 due to partial word stalls,
though not as fast as an aligned movl. */
return "movz{wl|x}\t{%1, %k0|%k0, %1}";
default:
if (get_attr_mode (insn) == MODE_SI)
return "mov{l}\t{%k1, %k0|%k0, %k1}";
else
return "mov{w}\t{%1, %0|%0, %1}";
}
}
[(set (attr "type")
(cond [(ne (symbol_ref "optimize_function_for_size_p (cfun)") (const_int 0))
(const_string "imov")
(and (eq_attr "alternative" "0")
(ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
(const_int 0))
(eq (symbol_ref "TARGET_HIMODE_MATH")
(const_int 0))))
(const_string "imov")
(and (eq_attr "alternative" "1,2")
(match_operand:HI 1 "aligned_operand" ""))
(const_string "imov")
(and (ne (symbol_ref "TARGET_MOVX")
(const_int 0))
(eq_attr "alternative" "0,2"))
(const_string "imovx")
]
(const_string "imov")))
(set (attr "mode")
(cond [(eq_attr "type" "imovx")
(const_string "SI")
(and (eq_attr "alternative" "1,2")
(match_operand:HI 1 "aligned_operand" ""))
(const_string "SI")
(and (eq_attr "alternative" "0")
(ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
(const_int 0))
(eq (symbol_ref "TARGET_HIMODE_MATH")
(const_int 0))))
(const_string "SI")
]
(const_string "HI")))])
;; Stores and loads of ax to arbitrary constant address.
;; We fake an second form of instruction to force reload to load address
;; into register when rax is not available
(define_insn "*movabshi_1_rex64"
[(set (mem:HI (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
(match_operand:HI 1 "nonmemory_operand" "a,er"))]
"TARGET_64BIT && ix86_check_movabs (insn, 0)"
"@
movabs{w}\t{%1, %P0|%P0, %1}
mov{w}\t{%1, %a0|%a0, %1}"
[(set_attr "type" "imov")
(set_attr "modrm" "0,*")
(set_attr "length_address" "8,0")
(set_attr "length_immediate" "0,*")
(set_attr "memory" "store")
(set_attr "mode" "HI")])
(define_insn "*movabshi_2_rex64"
[(set (match_operand:HI 0 "register_operand" "=a,r")
(mem:HI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
"TARGET_64BIT && ix86_check_movabs (insn, 1)"
"@
movabs{w}\t{%P1, %0|%0, %P1}
mov{w}\t{%a1, %0|%0, %a1}"
[(set_attr "type" "imov")
(set_attr "modrm" "0,*")
(set_attr "length_address" "8,0")
(set_attr "length_immediate" "0")
(set_attr "memory" "load")
(set_attr "mode" "HI")])
(define_insn "*swaphi_1"
[(set (match_operand:HI 0 "register_operand" "+r")
(match_operand:HI 1 "register_operand" "+r"))
(set (match_dup 1)
(match_dup 0))]
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
"xchg{l}\t%k1, %k0"
[(set_attr "type" "imov")
(set_attr "mode" "SI")
(set_attr "pent_pair" "np")
(set_attr "athlon_decode" "vector")
(set_attr "amdfam10_decode" "double")])
;; Not added amdfam10_decode since TARGET_PARTIAL_REG_STALL is disabled for AMDFAM10
(define_insn "*swaphi_2"
[(set (match_operand:HI 0 "register_operand" "+r")
(match_operand:HI 1 "register_operand" "+r"))
(set (match_dup 1)
(match_dup 0))]
"TARGET_PARTIAL_REG_STALL"
"xchg{w}\t%1, %0"
[(set_attr "type" "imov")
(set_attr "mode" "HI")
(set_attr "pent_pair" "np")
(set_attr "athlon_decode" "vector")])
(define_expand "movstricthi" (define_split
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "")) [(set (match_operand:TI 0 "nonimmediate_operand" "")
(match_operand:HI 1 "general_operand" ""))] (match_operand:TI 1 "general_operand" ""))]
"" "reload_completed
{ && !SSE_REG_P (operands[0]) && !SSE_REG_P (operands[1])"
if (TARGET_PARTIAL_REG_STALL && optimize_function_for_speed_p (cfun)) [(const_int 0)]
FAIL; "ix86_split_long_move (operands); DONE;")
/* Don't generate memory->memory moves, go through a register */
if (MEM_P (operands[0]) && MEM_P (operands[1]))
operands[1] = force_reg (HImode, operands[1]);
})
(define_insn "*movstricthi_1" (define_insn "*movti_internal_sse"
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+rm,r")) [(set (match_operand:TI 0 "nonimmediate_operand" "=x,x,m")
(match_operand:HI 1 "general_operand" "rn,m"))] (match_operand:TI 1 "vector_move_operand" "C,xm,x"))]
"(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)) "TARGET_SSE && !TARGET_64BIT
&& !(MEM_P (operands[0]) && MEM_P (operands[1]))" && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
"mov{w}\t{%1, %0|%0, %1}"
[(set_attr "type" "imov")
(set_attr "mode" "HI")])
(define_insn "*movstricthi_xor"
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+r"))
(match_operand:HI 1 "const0_operand" ""))
(clobber (reg:CC FLAGS_REG))]
"reload_completed"
"xor{w}\t%0, %0"
[(set_attr "type" "alu1")
(set_attr "mode" "HI")
(set_attr "length_immediate" "0")])
(define_expand "movqi"
[(set (match_operand:QI 0 "nonimmediate_operand" "")
(match_operand:QI 1 "general_operand" ""))]
""
"ix86_expand_move (QImode, operands); DONE;")
;; emit_push_insn when it calls move_by_pieces requires an insn to
;; "push a byte". But actually we use pushl, which has the effect
;; of rounding the amount pushed up to a word.
(define_insn "*pushqi2"
[(set (match_operand:QI 0 "push_operand" "=X")
(match_operand:QI 1 "nonmemory_no_elim_operand" "rn"))]
"!TARGET_64BIT"
"push{l}\t%k1"
[(set_attr "type" "push")
(set_attr "mode" "SI")])
;; For 64BIT abi we always round up to 8 bytes.
(define_insn "*pushqi2_rex64"
[(set (match_operand:QI 0 "push_operand" "=X")
(match_operand:QI 1 "nonmemory_no_elim_operand" "qn"))]
"TARGET_64BIT"
"push{q}\t%q1"
[(set_attr "type" "push")
(set_attr "mode" "DI")])
;; Situation is quite tricky about when to choose full sized (SImode) move
;; over QImode moves. For Q_REG -> Q_REG move we use full size only for
;; partial register dependency machines (such as AMD Athlon), where QImode
;; moves issue extra dependency and for partial register stalls machines
;; that don't use QImode patterns (and QImode move cause stall on the next
;; instruction).
;;
;; For loads of Q_REG to NONQ_REG we use full sized moves except for partial
;; register stall machines with, where we use QImode instructions, since
;; partial register stall can be caused there. Then we use movzx.
(define_insn "*movqi_1"
[(set (match_operand:QI 0 "nonimmediate_operand" "=q,q ,q ,r,r ,?r,m")
(match_operand:QI 1 "general_operand" " q,qn,qm,q,rn,qm,qn"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))"
{ {
switch (get_attr_type (insn)) switch (which_alternative)
{ {
case TYPE_IMOVX: case 0:
gcc_assert (ANY_QI_REG_P (operands[1]) || MEM_P (operands[1])); if (get_attr_mode (insn) == MODE_V4SF)
return "movz{bl|x}\t{%1, %k0|%k0, %1}"; return "%vxorps\t%0, %d0";
default:
if (get_attr_mode (insn) == MODE_SI)
return "mov{l}\t{%k1, %k0|%k0, %k1}";
else else
return "mov{b}\t{%1, %0|%0, %1}"; return "%vpxor\t%0, %d0";
} case 1:
} case 2:
[(set (attr "type") /* TDmode values are passed as TImode on the stack. Moving them
(cond [(and (eq_attr "alternative" "5") to stack may result in unaligned memory access. */
(not (match_operand:QI 1 "aligned_operand" ""))) if (misaligned_operand (operands[0], TImode)
(const_string "imovx") || misaligned_operand (operands[1], TImode))
(ne (symbol_ref "optimize_function_for_size_p (cfun)") (const_int 0)) {
(const_string "imov") if (get_attr_mode (insn) == MODE_V4SF)
(and (eq_attr "alternative" "3") return "%vmovups\t{%1, %0|%0, %1}";
(ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL") else
(const_int 0)) return "%vmovdqu\t{%1, %0|%0, %1}";
(eq (symbol_ref "TARGET_QIMODE_MATH") }
(const_int 0)))) else
(const_string "imov") {
(eq_attr "alternative" "3,5") if (get_attr_mode (insn) == MODE_V4SF)
(const_string "imovx") return "%vmovaps\t{%1, %0|%0, %1}";
(and (ne (symbol_ref "TARGET_MOVX") else
(const_int 0)) return "%vmovdqa\t{%1, %0|%0, %1}";
(eq_attr "alternative" "2")) }
(const_string "imovx")
]
(const_string "imov")))
(set (attr "mode")
(cond [(eq_attr "alternative" "3,4,5")
(const_string "SI")
(eq_attr "alternative" "6")
(const_string "QI")
(eq_attr "type" "imovx")
(const_string "SI")
(and (eq_attr "type" "imov")
(and (eq_attr "alternative" "0,1")
(and (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY")
(const_int 0))
(and (eq (symbol_ref "optimize_function_for_size_p (cfun)")
(const_int 0))
(eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
(const_int 0))))))
(const_string "SI")
;; Avoid partial register stalls when not using QImode arithmetic
(and (eq_attr "type" "imov")
(and (eq_attr "alternative" "0,1")
(and (ne (symbol_ref "TARGET_PARTIAL_REG_STALL")
(const_int 0))
(eq (symbol_ref "TARGET_QIMODE_MATH")
(const_int 0)))))
(const_string "SI")
]
(const_string "QI")))])
(define_insn "*swapqi_1"
[(set (match_operand:QI 0 "register_operand" "+r")
(match_operand:QI 1 "register_operand" "+r"))
(set (match_dup 1)
(match_dup 0))]
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
"xchg{l}\t%k1, %k0"
[(set_attr "type" "imov")
(set_attr "mode" "SI")
(set_attr "pent_pair" "np")
(set_attr "athlon_decode" "vector")
(set_attr "amdfam10_decode" "vector")])
;; Not added amdfam10_decode since TARGET_PARTIAL_REG_STALL is disabled for AMDFAM10
(define_insn "*swapqi_2"
[(set (match_operand:QI 0 "register_operand" "+q")
(match_operand:QI 1 "register_operand" "+q"))
(set (match_dup 1)
(match_dup 0))]
"TARGET_PARTIAL_REG_STALL"
"xchg{b}\t%1, %0"
[(set_attr "type" "imov")
(set_attr "mode" "QI")
(set_attr "pent_pair" "np")
(set_attr "athlon_decode" "vector")])
(define_expand "movstrictqi"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
(match_operand:QI 1 "general_operand" ""))]
""
{
if (TARGET_PARTIAL_REG_STALL && optimize_function_for_speed_p (cfun))
FAIL;
/* Don't generate memory->memory moves, go through a register. */
if (MEM_P (operands[0]) && MEM_P (operands[1]))
operands[1] = force_reg (QImode, operands[1]);
})
(define_insn "*movstrictqi_1"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
(match_operand:QI 1 "general_operand" "*qn,m"))]
"(! TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
&& !(MEM_P (operands[0]) && MEM_P (operands[1]))"
"mov{b}\t{%1, %0|%0, %1}"
[(set_attr "type" "imov")
(set_attr "mode" "QI")])
(define_insn "*movstrictqi_xor"
[(set (strict_low_part (match_operand:QI 0 "q_regs_operand" "+q"))
(match_operand:QI 1 "const0_operand" ""))
(clobber (reg:CC FLAGS_REG))]
"reload_completed"
"xor{b}\t%0, %0"
[(set_attr "type" "alu1")
(set_attr "mode" "QI")
(set_attr "length_immediate" "0")])
(define_insn "*movsi_extv_1"
[(set (match_operand:SI 0 "register_operand" "=R")
(sign_extract:SI (match_operand 1 "ext_register_operand" "Q")
(const_int 8)
(const_int 8)))]
""
"movs{bl|x}\t{%h1, %0|%0, %h1}"
[(set_attr "type" "imovx")
(set_attr "mode" "SI")])
(define_insn "*movhi_extv_1"
[(set (match_operand:HI 0 "register_operand" "=R")
(sign_extract:HI (match_operand 1 "ext_register_operand" "Q")
(const_int 8)
(const_int 8)))]
""
"movs{bl|x}\t{%h1, %k0|%k0, %h1}"
[(set_attr "type" "imovx")
(set_attr "mode" "SI")])
(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")
(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 (and (match_operand:QI 0 "register_operand" "")
(ior (not (match_operand:QI 0 "q_regs_operand" ""))
(ne (symbol_ref "TARGET_MOVX")
(const_int 0))))
(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_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: default:
return "mov{b}\t{%h1, %0|%0, %h1}"; gcc_unreachable ();
} }
} }
[(set (attr "type") [(set_attr "type" "sselog1,ssemov,ssemov")
(if_then_else (and (match_operand:QI 0 "register_operand" "") (set_attr "prefix" "maybe_vex")
(ior (not (match_operand:QI 0 "q_regs_operand" ""))
(ne (symbol_ref "TARGET_MOVX")
(const_int 0))))
(const_string "imovx")
(const_string "imov")))
(set (attr "mode") (set (attr "mode")
(if_then_else (eq_attr "type" "imovx") (cond [(ior (eq (symbol_ref "TARGET_SSE2") (const_int 0))
(const_string "SI") (ne (symbol_ref "optimize_function_for_size_p (cfun)")
(const_string "QI")))]) (const_int 0)))
(const_string "V4SF")
;; Stores and loads of ax to arbitrary constant address. (and (eq_attr "alternative" "2")
;; We fake an second form of instruction to force reload to load address (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
;; into register when rax is not available (const_int 0)))
(define_insn "*movabsqi_1_rex64" (const_string "V4SF")]
[(set (mem:QI (match_operand:DI 0 "x86_64_movabs_operand" "i,r")) (const_string "TI")))])
(match_operand:QI 1 "nonmemory_operand" "a,er"))]
"TARGET_64BIT && ix86_check_movabs (insn, 0)"
"@
movabs{b}\t{%1, %P0|%P0, %1}
mov{b}\t{%1, %a0|%a0, %1}"
[(set_attr "type" "imov")
(set_attr "modrm" "0,*")
(set_attr "length_address" "8,0")
(set_attr "length_immediate" "0,*")
(set_attr "memory" "store")
(set_attr "mode" "QI")])
(define_insn "*movabsqi_2_rex64"
[(set (match_operand:QI 0 "register_operand" "=a,r")
(mem:QI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
"TARGET_64BIT && ix86_check_movabs (insn, 1)"
"@
movabs{b}\t{%P1, %0|%0, %P1}
mov{b}\t{%a1, %0|%0, %a1}"
[(set_attr "type" "imov")
(set_attr "modrm" "0,*")
(set_attr "length_address" "8,0")
(set_attr "length_immediate" "0")
(set_attr "memory" "load")
(set_attr "mode" "QI")])
(define_insn "*movdi_extzv_1"
[(set (match_operand:DI 0 "register_operand" "=R")
(zero_extract:DI (match_operand 1 "ext_register_operand" "Q")
(const_int 8)
(const_int 8)))]
"TARGET_64BIT"
"movz{bl|x}\t{%h1, %k0|%k0, %h1}"
[(set_attr "type" "imovx")
(set_attr "mode" "SI")])
(define_insn "*movsi_extzv_1"
[(set (match_operand:SI 0 "register_operand" "=R")
(zero_extract:SI (match_operand 1 "ext_register_operand" "Q")
(const_int 8)
(const_int 8)))]
""
"movz{bl|x}\t{%h1, %0|%0, %h1}"
[(set_attr "type" "imovx")
(set_attr "mode" "SI")])
(define_insn "*movqi_extzv_2" (define_insn "*movdi_internal_rex64"
[(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?R") [(set (match_operand:DI 0 "nonimmediate_operand"
(subreg:QI (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q") "=r,r ,r,m ,!m,*y,*y,?r ,m ,?*Ym,?*y,*x,*x,?r ,m,?*Yi,*x,?*x,?*Ym")
(const_int 8) (match_operand:DI 1 "general_operand"
(const_int 8)) 0))] "Z ,rem,i,re,n ,C ,*y,*Ym,*y,r ,m ,C ,*x,*Yi,*x,r ,m ,*Ym,*x"))]
"!TARGET_64BIT" "TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
{ {
switch (get_attr_type (insn)) switch (get_attr_type (insn))
{ {
case TYPE_IMOVX: case TYPE_SSECVT:
return "movz{bl|x}\t{%h1, %k0|%k0, %h1}"; if (SSE_REG_P (operands[0]))
default: return "movq2dq\t{%1, %0|%0, %1}";
return "mov{b}\t{%h1, %0|%0, %h1}"; else
} return "movdq2q\t{%1, %0|%0, %1}";
}
[(set (attr "type")
(if_then_else (and (match_operand:QI 0 "register_operand" "")
(ior (not (match_operand:QI 0 "q_regs_operand" ""))
(ne (symbol_ref "TARGET_MOVX")
(const_int 0))))
(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_rex64" case TYPE_SSEMOV:
[(set (match_operand:QI 0 "register_operand" "=Q,?R") if (TARGET_AVX)
(subreg:QI (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q") {
(const_int 8) if (get_attr_mode (insn) == MODE_TI)
(const_int 8)) 0))] return "vmovdqa\t{%1, %0|%0, %1}";
"TARGET_64BIT" else
{ return "vmovq\t{%1, %0|%0, %1}";
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 "q_regs_operand" ""))
(ne (symbol_ref "TARGET_MOVX")
(const_int 0)))
(const_string "imovx")
(const_string "imov")))
(set (attr "mode")
(if_then_else (eq_attr "type" "imovx")
(const_string "SI")
(const_string "QI")))])
(define_insn "movsi_insv_1" if (get_attr_mode (insn) == MODE_TI)
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q") return "movdqa\t{%1, %0|%0, %1}";
(const_int 8) /* FALLTHRU */
(const_int 8))
(match_operand:SI 1 "general_operand" "Qmn"))]
"!TARGET_64BIT"
"mov{b}\t{%b1, %h0|%h0, %b1}"
[(set_attr "type" "imov")
(set_attr "mode" "QI")])
(define_insn "*movsi_insv_1_rex64" case TYPE_MMXMOV:
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q") /* Moves from and into integer register is done using movd
(const_int 8) opcode with REX prefix. */
(const_int 8)) if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
(match_operand:SI 1 "nonmemory_operand" "Qn"))] return "movd\t{%1, %0|%0, %1}";
"TARGET_64BIT" return "movq\t{%1, %0|%0, %1}";
"mov{b}\t{%b1, %h0|%h0, %b1}"
[(set_attr "type" "imov")
(set_attr "mode" "QI")])
(define_insn "movdi_insv_1_rex64" case TYPE_SSELOG1:
[(set (zero_extract:DI (match_operand 0 "ext_register_operand" "+Q") return "%vpxor\t%0, %d0";
(const_int 8)
(const_int 8))
(match_operand:DI 1 "nonmemory_operand" "Qn"))]
"TARGET_64BIT"
"mov{b}\t{%b1, %h0|%h0, %b1}"
[(set_attr "type" "imov")
(set_attr "mode" "QI")])
(define_insn "*movqi_insv_2" case TYPE_MMX:
[(set (zero_extract:SI (match_operand 0 "ext_register_operand" "+Q") return "pxor\t%0, %0";
(const_int 8)
(const_int 8))
(lshiftrt:SI (match_operand:SI 1 "register_operand" "Q")
(const_int 8)))]
""
"mov{b}\t{%h1, %h0|%h0, %h1}"
[(set_attr "type" "imov")
(set_attr "mode" "QI")])
(define_expand "movdi" case TYPE_MULTI:
[(set (match_operand:DI 0 "nonimmediate_operand" "") return "#";
(match_operand:DI 1 "general_operand" ""))]
""
"ix86_expand_move (DImode, operands); DONE;")
(define_insn "*pushdi" case TYPE_LEA:
[(set (match_operand:DI 0 "push_operand" "=<") return "lea{q}\t{%a1, %0|%0, %a1}";
(match_operand:DI 1 "general_no_elim_operand" "riF*m"))]
"!TARGET_64BIT"
"#")
(define_insn "*pushdi2_rex64" default:
[(set (match_operand:DI 0 "push_operand" "=<,!<") gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
(match_operand:DI 1 "general_no_elim_operand" "re*m,n"))] if (get_attr_mode (insn) == MODE_SI)
"TARGET_64BIT" return "mov{l}\t{%k1, %k0|%k0, %k1}";
"@ else if (which_alternative == 2)
push{q}\t%1 return "movabs{q}\t{%1, %0|%0, %1}";
#" else
[(set_attr "type" "push,multi") return "mov{q}\t{%1, %0|%0, %1}";
(set_attr "mode" "DI")]) }
}
[(set (attr "type")
(cond [(eq_attr "alternative" "5")
(const_string "mmx")
(eq_attr "alternative" "6,7,8,9,10")
(const_string "mmxmov")
(eq_attr "alternative" "11")
(const_string "sselog1")
(eq_attr "alternative" "12,13,14,15,16")
(const_string "ssemov")
(eq_attr "alternative" "17,18")
(const_string "ssecvt")
(eq_attr "alternative" "4")
(const_string "multi")
(match_operand:DI 1 "pic_32bit_operand" "")
(const_string "lea")
]
(const_string "imov")))
(set (attr "modrm")
(if_then_else
(and (eq_attr "alternative" "2") (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"))
(const_string "8")
(const_string "*")))
(set_attr "prefix_rex" "*,*,*,*,*,*,*,1,*,1,*,*,*,*,*,*,*,*,*")
(set_attr "prefix_data16" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,1,*,*,*")
(set (attr "prefix")
(if_then_else (eq_attr "alternative" "11,12,13,14,15,16")
(const_string "maybe_vex")
(const_string "orig")))
(set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,DI,DI,DI,TI,TI,DI,DI,DI,DI,DI,DI")])
;; Convert impossible pushes of immediate to existing instructions. ;; Convert impossible stores of immediate to existing instructions.
;; First try to get scratch register and go through it. In case this ;; First try to get scratch register and go through it. In case this
;; fails, push sign extended lower part first and then overwrite ;; fails, move by 32bit parts.
;; upper part by 32bit move.
(define_peephole2 (define_peephole2
[(match_scratch:DI 2 "r") [(match_scratch:DI 2 "r")
(set (match_operand:DI 0 "push_operand" "") (set (match_operand:DI 0 "memory_operand" "")
(match_operand:DI 1 "immediate_operand" ""))] (match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && !symbolic_operand (operands[1], DImode) "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode)" && !x86_64_immediate_operand (operands[1], DImode)"
...@@ -2376,94 +2069,26 @@ ...@@ -2376,94 +2069,26 @@
;; peephole2 pass is not run. ;; peephole2 pass is not run.
;; "&& 1" is needed to keep it from matching the previous pattern. ;; "&& 1" is needed to keep it from matching the previous pattern.
(define_peephole2 (define_peephole2
[(set (match_operand:DI 0 "push_operand" "") [(set (match_operand:DI 0 "memory_operand" "")
(match_operand:DI 1 "immediate_operand" ""))] (match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && !symbolic_operand (operands[1], DImode) "TARGET_64BIT && !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode) && 1" && !x86_64_immediate_operand (operands[1], DImode) && 1"
[(set (match_dup 0) (match_dup 1)) [(set (match_dup 2) (match_dup 3))
(set (match_dup 2) (match_dup 3))] (set (match_dup 4) (match_dup 5))]
{ "split_di (&operands[0], 2, &operands[2], &operands[4]);")
split_di (&operands[1], 1, &operands[2], &operands[3]);
operands[1] = gen_lowpart (DImode, operands[2]);
operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
GEN_INT (4)));
})
(define_split (define_split
[(set (match_operand:DI 0 "push_operand" "") [(set (match_operand:DI 0 "memory_operand" "")
(match_operand:DI 1 "immediate_operand" ""))] (match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && ((optimize > 0 && flag_peephole2) "TARGET_64BIT && ((optimize > 0 && flag_peephole2)
? epilogue_completed : reload_completed) ? epilogue_completed : reload_completed)
&& !symbolic_operand (operands[1], DImode) && !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode)" && !x86_64_immediate_operand (operands[1], DImode)"
[(set (match_dup 0) (match_dup 1)) [(set (match_dup 2) (match_dup 3))
(set (match_dup 2) (match_dup 3))] (set (match_dup 4) (match_dup 5))]
{ "split_di (&operands[0], 2, &operands[2], &operands[4]);")
split_di (&operands[1], 1, &operands[2], &operands[3]);
operands[1] = gen_lowpart (DImode, operands[2]);
operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
GEN_INT (4)));
})
(define_insn "*pushdi2_prologue_rex64"
[(set (match_operand:DI 0 "push_operand" "=<")
(match_operand:DI 1 "general_no_elim_operand" "re*m"))
(clobber (mem:BLK (scratch)))]
"TARGET_64BIT"
"push{q}\t%1"
[(set_attr "type" "push")
(set_attr "mode" "DI")])
(define_insn "*popdi1_epilogue_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
(mem:DI (reg:DI SP_REG)))
(set (reg:DI SP_REG)
(plus:DI (reg:DI SP_REG) (const_int 8)))
(clobber (mem:BLK (scratch)))]
"TARGET_64BIT"
"pop{q}\t%0"
[(set_attr "type" "pop")
(set_attr "mode" "DI")])
(define_insn "popdi1"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r*m")
(mem:DI (reg:DI SP_REG)))
(set (reg:DI SP_REG)
(plus:DI (reg:DI SP_REG) (const_int 8)))]
"TARGET_64BIT"
"pop{q}\t%0"
[(set_attr "type" "pop")
(set_attr "mode" "DI")])
(define_insn "*movdi_xor_rex64"
[(set (match_operand:DI 0 "register_operand" "=r")
(match_operand:DI 1 "const0_operand" ""))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& reload_completed"
"xor{l}\t%k0, %k0";
[(set_attr "type" "alu1")
(set_attr "mode" "SI")
(set_attr "length_immediate" "0")])
(define_insn "*movdi_or_rex64"
[(set (match_operand:DI 0 "register_operand" "=r")
(match_operand:DI 1 "const_int_operand" "i"))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT
&& reload_completed
&& operands[1] == constm1_rtx"
{
operands[1] = constm1_rtx;
return "or{q}\t{%1, %0|%0, %1}";
}
[(set_attr "type" "alu1")
(set_attr "mode" "DI")
(set_attr "length_immediate" "1")])
(define_insn "*movdi_2" (define_insn "*movdi_internal"
[(set (match_operand:DI 0 "nonimmediate_operand" [(set (match_operand:DI 0 "nonimmediate_operand"
"=r ,o ,*y,m*y,*y,*Y2,m ,*Y2,*Y2,*x,m ,*x,*x") "=r ,o ,*y,m*y,*y,*Y2,m ,*Y2,*Y2,*x,m ,*x,*x")
(match_operand:DI 1 "general_operand" (match_operand:DI 1 "general_operand"
...@@ -2491,369 +2116,493 @@ ...@@ -2491,369 +2116,493 @@
(set_attr "mode" "DI,DI,DI,DI,DI,TI,DI,TI,DI,V4SF,V2SF,V4SF,V2SF")]) (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI,TI,DI,V4SF,V2SF,V4SF,V2SF")])
(define_split (define_split
[(set (match_operand:DI 0 "push_operand" "")
(match_operand:DI 1 "general_operand" ""))]
"!TARGET_64BIT && reload_completed
&& (! MMX_REG_P (operands[1]) && !SSE_REG_P (operands[1]))"
[(const_int 0)]
"ix86_split_long_move (operands); DONE;")
;; %%% This multiword shite has got to go.
(define_split
[(set (match_operand:DI 0 "nonimmediate_operand" "") [(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" ""))] (match_operand:DI 1 "general_operand" ""))]
"!TARGET_64BIT && reload_completed "!TARGET_64BIT && reload_completed
&& (!MMX_REG_P (operands[0]) && !SSE_REG_P (operands[0])) && !(MMX_REG_P (operands[0]) || SSE_REG_P (operands[0]))
&& (!MMX_REG_P (operands[1]) && !SSE_REG_P (operands[1]))" && !(MMX_REG_P (operands[1]) || SSE_REG_P (operands[1]))"
[(const_int 0)] [(const_int 0)]
"ix86_split_long_move (operands); DONE;") "ix86_split_long_move (operands); DONE;")
(define_insn "*movdi_1_rex64" (define_insn "*movsi_internal"
[(set (match_operand:DI 0 "nonimmediate_operand" [(set (match_operand:SI 0 "nonimmediate_operand"
"=r,r ,r,m ,!m,*y,*y,?r ,m ,?*Ym,?*y,*x,*x,?r ,m,?*Yi,*x,?*x,?*Ym") "=r,m ,*y,*y,?rm,?*y,*x,*x,?r ,m ,?*Yi,*x")
(match_operand:DI 1 "general_operand" (match_operand:SI 1 "general_operand"
"Z ,rem,i,re,n ,C ,*y,*Ym,*y,r ,m ,C ,*x,*Yi,*x,r ,m ,*Ym,*x"))] "g ,ri,C ,*y,*y ,rm ,C ,*x,*Yi,*x,r ,m "))]
"TARGET_64BIT && !(MEM_P (operands[0]) && MEM_P (operands[1]))" "!(MEM_P (operands[0]) && MEM_P (operands[1]))"
{ {
switch (get_attr_type (insn)) switch (get_attr_type (insn))
{ {
case TYPE_SSECVT: case TYPE_SSELOG1:
if (SSE_REG_P (operands[0])) if (get_attr_mode (insn) == MODE_TI)
return "movq2dq\t{%1, %0|%0, %1}"; return "%vpxor\t%0, %d0";
else return "%vxorps\t%0, %d0";
return "movdq2q\t{%1, %0|%0, %1}";
case TYPE_SSEMOV: case TYPE_SSEMOV:
if (TARGET_AVX) switch (get_attr_mode (insn))
{ {
if (get_attr_mode (insn) == MODE_TI) case MODE_TI:
return "vmovdqa\t{%1, %0|%0, %1}"; return "%vmovdqa\t{%1, %0|%0, %1}";
else case MODE_V4SF:
return "vmovq\t{%1, %0|%0, %1}"; 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}";
default:
gcc_unreachable ();
} }
if (get_attr_mode (insn) == MODE_TI)
return "movdqa\t{%1, %0|%0, %1}";
/* FALLTHRU */
case TYPE_MMXMOV:
/* Moves from and into integer register is done using movd
opcode with REX prefix. */
if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))
return "movd\t{%1, %0|%0, %1}";
return "movq\t{%1, %0|%0, %1}";
case TYPE_SSELOG1:
return "%vpxor\t%0, %d0";
case TYPE_MMX: case TYPE_MMX:
return "pxor\t%0, %0"; return "pxor\t%0, %0";
case TYPE_MULTI: case TYPE_MMXMOV:
return "#"; if (get_attr_mode (insn) == MODE_DI)
return "movq\t{%1, %0|%0, %1}";
return "movd\t{%1, %0|%0, %1}";
case TYPE_LEA: case TYPE_LEA:
return "lea{q}\t{%a1, %0|%0, %a1}"; return "lea{l}\t{%a1, %0|%0, %a1}";
default: default:
gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1])); gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
if (get_attr_mode (insn) == MODE_SI) return "mov{l}\t{%1, %0|%0, %1}";
return "mov{l}\t{%k1, %k0|%k0, %k1}";
else if (which_alternative == 2)
return "movabs{q}\t{%1, %0|%0, %1}";
else
return "mov{q}\t{%1, %0|%0, %1}";
} }
} }
[(set (attr "type") [(set (attr "type")
(cond [(eq_attr "alternative" "5") (cond [(eq_attr "alternative" "2")
(const_string "mmx") (const_string "mmx")
(eq_attr "alternative" "6,7,8,9,10") (eq_attr "alternative" "3,4,5")
(const_string "mmxmov") (const_string "mmxmov")
(eq_attr "alternative" "11") (eq_attr "alternative" "6")
(const_string "sselog1") (const_string "sselog1")
(eq_attr "alternative" "12,13,14,15,16") (eq_attr "alternative" "7,8,9,10,11")
(const_string "ssemov") (const_string "ssemov")
(eq_attr "alternative" "17,18")
(const_string "ssecvt")
(eq_attr "alternative" "4")
(const_string "multi")
(match_operand:DI 1 "pic_32bit_operand" "") (match_operand:DI 1 "pic_32bit_operand" "")
(const_string "lea") (const_string "lea")
] ]
(const_string "imov"))) (const_string "imov")))
(set (attr "modrm")
(if_then_else
(and (eq_attr "alternative" "2") (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"))
(const_string "8")
(const_string "*")))
(set_attr "prefix_rex" "*,*,*,*,*,*,*,1,*,1,*,*,*,*,*,*,*,*,*")
(set_attr "prefix_data16" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,1,*,*,*")
(set (attr "prefix") (set (attr "prefix")
(if_then_else (eq_attr "alternative" "11,12,13,14,15,16") (if_then_else (eq_attr "alternative" "0,1,2,3,4,5")
(const_string "maybe_vex") (const_string "orig")
(const_string "orig"))) (const_string "maybe_vex")))
(set_attr "mode" "SI,DI,DI,DI,SI,DI,DI,DI,DI,DI,DI,TI,TI,DI,DI,DI,DI,DI,DI")]) (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" "2,3")
(const_string "DI")
(eq_attr "alternative" "6,7")
(if_then_else
(eq (symbol_ref "TARGET_SSE2") (const_int 0))
(const_string "V4SF")
(const_string "TI"))
(and (eq_attr "alternative" "8,9,10,11")
(eq (symbol_ref "TARGET_SSE2") (const_int 0)))
(const_string "SF")
]
(const_string "SI")))])
(define_insn "*movhi_internal"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
(match_operand:HI 1 "general_operand" "r,rn,rm,rn"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
switch (get_attr_type (insn))
{
case TYPE_IMOVX:
/* movzwl is faster than movw on p2 due to partial word stalls,
though not as fast as an aligned movl. */
return "movz{wl|x}\t{%1, %k0|%k0, %1}";
default:
if (get_attr_mode (insn) == MODE_SI)
return "mov{l}\t{%k1, %k0|%k0, %k1}";
else
return "mov{w}\t{%1, %0|%0, %1}";
}
}
[(set (attr "type")
(cond [(ne (symbol_ref "optimize_function_for_size_p (cfun)")
(const_int 0))
(const_string "imov")
(and (eq_attr "alternative" "0")
(ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
(const_int 0))
(eq (symbol_ref "TARGET_HIMODE_MATH")
(const_int 0))))
(const_string "imov")
(and (eq_attr "alternative" "1,2")
(match_operand:HI 1 "aligned_operand" ""))
(const_string "imov")
(and (ne (symbol_ref "TARGET_MOVX")
(const_int 0))
(eq_attr "alternative" "0,2"))
(const_string "imovx")
]
(const_string "imov")))
(set (attr "mode")
(cond [(eq_attr "type" "imovx")
(const_string "SI")
(and (eq_attr "alternative" "1,2")
(match_operand:HI 1 "aligned_operand" ""))
(const_string "SI")
(and (eq_attr "alternative" "0")
(ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
(const_int 0))
(eq (symbol_ref "TARGET_HIMODE_MATH")
(const_int 0))))
(const_string "SI")
]
(const_string "HI")))])
;; Situation is quite tricky about when to choose full sized (SImode) move
;; over QImode moves. For Q_REG -> Q_REG move we use full size only for
;; partial register dependency machines (such as AMD Athlon), where QImode
;; moves issue extra dependency and for partial register stalls machines
;; that don't use QImode patterns (and QImode move cause stall on the next
;; instruction).
;;
;; For loads of Q_REG to NONQ_REG we use full sized moves except for partial
;; register stall machines with, where we use QImode instructions, since
;; partial register stall can be caused there. Then we use movzx.
(define_insn "*movqi_internal"
[(set (match_operand:QI 0 "nonimmediate_operand" "=q,q ,q ,r,r ,?r,m")
(match_operand:QI 1 "general_operand" " q,qn,qm,q,rn,qm,qn"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))"
{
switch (get_attr_type (insn))
{
case TYPE_IMOVX:
gcc_assert (ANY_QI_REG_P (operands[1]) || MEM_P (operands[1]));
return "movz{bl|x}\t{%1, %k0|%k0, %1}";
default:
if (get_attr_mode (insn) == MODE_SI)
return "mov{l}\t{%k1, %k0|%k0, %k1}";
else
return "mov{b}\t{%1, %0|%0, %1}";
}
}
[(set (attr "type")
(cond [(and (eq_attr "alternative" "5")
(not (match_operand:QI 1 "aligned_operand" "")))
(const_string "imovx")
(ne (symbol_ref "optimize_function_for_size_p (cfun)")
(const_int 0))
(const_string "imov")
(and (eq_attr "alternative" "3")
(ior (eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
(const_int 0))
(eq (symbol_ref "TARGET_QIMODE_MATH")
(const_int 0))))
(const_string "imov")
(eq_attr "alternative" "3,5")
(const_string "imovx")
(and (ne (symbol_ref "TARGET_MOVX")
(const_int 0))
(eq_attr "alternative" "2"))
(const_string "imovx")
]
(const_string "imov")))
(set (attr "mode")
(cond [(eq_attr "alternative" "3,4,5")
(const_string "SI")
(eq_attr "alternative" "6")
(const_string "QI")
(eq_attr "type" "imovx")
(const_string "SI")
(and (eq_attr "type" "imov")
(and (eq_attr "alternative" "0,1")
(and (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY")
(const_int 0))
(and (eq (symbol_ref "optimize_function_for_size_p (cfun)")
(const_int 0))
(eq (symbol_ref "TARGET_PARTIAL_REG_STALL")
(const_int 0))))))
(const_string "SI")
;; Avoid partial register stalls when not using QImode arithmetic
(and (eq_attr "type" "imov")
(and (eq_attr "alternative" "0,1")
(and (ne (symbol_ref "TARGET_PARTIAL_REG_STALL")
(const_int 0))
(eq (symbol_ref "TARGET_QIMODE_MATH")
(const_int 0)))))
(const_string "SI")
]
(const_string "QI")))])
;; Stores and loads of ax to arbitrary constant address. ;; Stores and loads of ax to arbitrary constant address.
;; We fake an second form of instruction to force reload to load address ;; We fake an second form of instruction to force reload to load address
;; into register when rax is not available ;; into register when rax is not available
(define_insn "*movabsdi_1_rex64" (define_insn "*movabs<mode>_1"
[(set (mem:DI (match_operand:DI 0 "x86_64_movabs_operand" "i,r")) [(set (mem:SWI1248x (match_operand:DI 0 "x86_64_movabs_operand" "i,r"))
(match_operand:DI 1 "nonmemory_operand" "a,er"))] (match_operand:SWI1248x 1 "nonmemory_operand" "a,er"))]
"TARGET_64BIT && ix86_check_movabs (insn, 0)" "TARGET_64BIT && ix86_check_movabs (insn, 0)"
"@ "@
movabs{q}\t{%1, %P0|%P0, %1} movabs{<imodesuffix>}\t{%1, %P0|%P0, %1}
mov{q}\t{%1, %a0|%a0, %1}" mov{<imodesuffix>}\t{%1, %a0|%a0, %1}"
[(set_attr "type" "imov") [(set_attr "type" "imov")
(set_attr "modrm" "0,*") (set_attr "modrm" "0,*")
(set_attr "length_address" "8,0") (set_attr "length_address" "8,0")
(set_attr "length_immediate" "0,*") (set_attr "length_immediate" "0,*")
(set_attr "memory" "store") (set_attr "memory" "store")
(set_attr "mode" "DI")]) (set_attr "mode" "<MODE>")])
(define_insn "*movabsdi_2_rex64" (define_insn "*movabs<mode>_2"
[(set (match_operand:DI 0 "register_operand" "=a,r") [(set (match_operand:SWI1248x 0 "register_operand" "=a,r")
(mem:DI (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))] (mem:SWI1248x (match_operand:DI 1 "x86_64_movabs_operand" "i,r")))]
"TARGET_64BIT && ix86_check_movabs (insn, 1)" "TARGET_64BIT && ix86_check_movabs (insn, 1)"
"@ "@
movabs{q}\t{%P1, %0|%0, %P1} movabs{<imodesuffix>}\t{%P1, %0|%0, %P1}
mov{q}\t{%a1, %0|%0, %a1}" mov{<imodesuffix>}\t{%a1, %0|%0, %a1}"
[(set_attr "type" "imov") [(set_attr "type" "imov")
(set_attr "modrm" "0,*") (set_attr "modrm" "0,*")
(set_attr "length_address" "8,0") (set_attr "length_address" "8,0")
(set_attr "length_immediate" "0") (set_attr "length_immediate" "0")
(set_attr "memory" "load") (set_attr "memory" "load")
(set_attr "mode" "DI")]) (set_attr "mode" "<MODE>")])
;; Convert impossible stores of immediate to existing instructions.
;; First try to get scratch register and go through it. In case this
;; fails, move by 32bit parts.
(define_peephole2
[(match_scratch:DI 2 "r")
(set (match_operand:DI 0 "memory_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode)"
[(set (match_dup 2) (match_dup 1))
(set (match_dup 0) (match_dup 2))]
"")
;; We need to define this as both peepholer and splitter for case
;; peephole2 pass is not run.
;; "&& 1" is needed to keep it from matching the previous pattern.
(define_peephole2
[(set (match_operand:DI 0 "memory_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode) && 1"
[(set (match_dup 2) (match_dup 3))
(set (match_dup 4) (match_dup 5))]
"split_di (&operands[0], 2, &operands[2], &operands[4]);")
(define_split (define_insn "*swap<mode>"
[(set (match_operand:DI 0 "memory_operand" "") [(set (match_operand:SWI48 0 "register_operand" "+r")
(match_operand:DI 1 "immediate_operand" ""))] (match_operand:SWI48 1 "register_operand" "+r"))
"TARGET_64BIT && ((optimize > 0 && flag_peephole2) (set (match_dup 1)
? epilogue_completed : reload_completed) (match_dup 0))]
&& !symbolic_operand (operands[1], DImode) ""
&& !x86_64_immediate_operand (operands[1], DImode)" "xchg{<imodesuffix>}\t%1, %0"
[(set (match_dup 2) (match_dup 3)) [(set_attr "type" "imov")
(set (match_dup 4) (match_dup 5))] (set_attr "mode" "<MODE>")
"split_di (&operands[0], 2, &operands[2], &operands[4]);") (set_attr "pent_pair" "np")
(set_attr "athlon_decode" "vector")
(set_attr "amdfam10_decode" "double")])
(define_insn "*swapdi_rex64" (define_insn "*swap<mode>_1"
[(set (match_operand:DI 0 "register_operand" "+r") [(set (match_operand:SWI12 0 "register_operand" "+r")
(match_operand:DI 1 "register_operand" "+r")) (match_operand:SWI12 1 "register_operand" "+r"))
(set (match_dup 1) (set (match_dup 1)
(match_dup 0))] (match_dup 0))]
"TARGET_64BIT" "!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
"xchg{q}\t%1, %0" "xchg{l}\t%k1, %k0"
[(set_attr "type" "imov") [(set_attr "type" "imov")
(set_attr "mode" "DI") (set_attr "mode" "SI")
(set_attr "pent_pair" "np") (set_attr "pent_pair" "np")
(set_attr "athlon_decode" "vector") (set_attr "athlon_decode" "vector")
(set_attr "amdfam10_decode" "double")]) (set_attr "amdfam10_decode" "double")])
(define_expand "movoi" ;; Not added amdfam10_decode since TARGET_PARTIAL_REG_STALL
[(set (match_operand:OI 0 "nonimmediate_operand" "") ;; is disabled for AMDFAM10
(match_operand:OI 1 "general_operand" ""))] (define_insn "*swap<mode>_2"
"TARGET_AVX" [(set (match_operand:SWI12 0 "register_operand" "+<r>")
"ix86_expand_move (OImode, operands); DONE;") (match_operand:SWI12 1 "register_operand" "+<r>"))
(set (match_dup 1)
(match_dup 0))]
"TARGET_PARTIAL_REG_STALL"
"xchg{<imodesuffix>}\t%1, %0"
[(set_attr "type" "imov")
(set_attr "mode" "<MODE>")
(set_attr "pent_pair" "np")
(set_attr "athlon_decode" "vector")])
(define_expand "movstrict<mode>"
[(set (strict_low_part (match_operand:SWI12 0 "nonimmediate_operand" ""))
(match_operand:SWI12 1 "general_operand" ""))]
""
{
if (TARGET_PARTIAL_REG_STALL && optimize_function_for_speed_p (cfun))
FAIL;
/* Don't generate memory->memory moves, go through a register */
if (MEM_P (operands[0]) && MEM_P (operands[1]))
operands[1] = force_reg (<MODE>mode, operands[1]);
})
(define_insn "*movstrict<mode>_1"
[(set (strict_low_part
(match_operand:SWI12 0 "nonimmediate_operand" "+<r>m,<r>"))
(match_operand:SWI12 1 "general_operand" "<r>n,m"))]
"(!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun))
&& !(MEM_P (operands[0]) && MEM_P (operands[1]))"
"mov{<imodesuffix>}\t{%1, %0|%0, %1}"
[(set_attr "type" "imov")
(set_attr "mode" "<MODE>")])
(define_insn "*movstrict<mode>_xor"
[(set (strict_low_part (match_operand:SWI12 0 "register_operand" "+<r>"))
(match_operand:SWI12 1 "const0_operand" ""))
(clobber (reg:CC FLAGS_REG))]
"reload_completed"
"xor{<imodesuffix>}\t%0, %0"
[(set_attr "type" "alu1")
(set_attr "mode" "<MODE>")
(set_attr "length_immediate" "0")])
(define_insn "*mov<mode>_extv_1"
[(set (match_operand:SWI24 0 "register_operand" "=R")
(sign_extract:SWI24 (match_operand 1 "ext_register_operand" "Q")
(const_int 8)
(const_int 8)))]
""
"movs{bl|x}\t{%h1, %k0|%k0, %h1}"
[(set_attr "type" "imovx")
(set_attr "mode" "SI")])
(define_insn "*movoi_internal" (define_insn "*movqi_extv_1_rex64"
[(set (match_operand:OI 0 "nonimmediate_operand" "=x,x,m") [(set (match_operand:QI 0 "register_operand" "=Q,?R")
(match_operand:OI 1 "vector_move_operand" "C,xm,x"))] (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
"TARGET_AVX (const_int 8)
&& !(MEM_P (operands[0]) && MEM_P (operands[1]))" (const_int 8)))]
"TARGET_64BIT"
{ {
switch (which_alternative) switch (get_attr_type (insn))
{ {
case 0: case TYPE_IMOVX:
return "vxorps\t%0, %0, %0"; return "movs{bl|x}\t{%h1, %k0|%k0, %h1}";
case 1:
case 2:
if (misaligned_operand (operands[0], OImode)
|| misaligned_operand (operands[1], OImode))
return "vmovdqu\t{%1, %0|%0, %1}";
else
return "vmovdqa\t{%1, %0|%0, %1}";
default: default:
gcc_unreachable (); return "mov{b}\t{%h1, %0|%0, %h1}";
} }
} }
[(set_attr "type" "sselog1,ssemov,ssemov") [(set (attr "type")
(set_attr "prefix" "vex") (if_then_else (and (match_operand:QI 0 "register_operand" "")
(set_attr "mode" "OI")]) (ior (not (match_operand:QI 0 "q_regs_operand" ""))
(ne (symbol_ref "TARGET_MOVX")
(const_int 0))))
(const_string "imovx")
(const_string "imov")))
(set (attr "mode")
(if_then_else (eq_attr "type" "imovx")
(const_string "SI")
(const_string "QI")))])
(define_expand "movti" (define_insn "*movqi_extv_1"
[(set (match_operand:TI 0 "nonimmediate_operand" "") [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?r")
(match_operand:TI 1 "nonimmediate_operand" ""))] (sign_extract:QI (match_operand 1 "ext_register_operand" "Q,Q")
"TARGET_SSE || TARGET_64BIT" (const_int 8)
(const_int 8)))]
"!TARGET_64BIT"
{ {
if (TARGET_64BIT) switch (get_attr_type (insn))
ix86_expand_move (TImode, operands); {
else if (push_operand (operands[0], TImode)) case TYPE_IMOVX:
ix86_expand_push (TImode, operands[1]); return "movs{bl|x}\t{%h1, %k0|%k0, %h1}";
else default:
ix86_expand_vector_move (TImode, operands); return "mov{b}\t{%h1, %0|%0, %h1}";
DONE; }
}) }
[(set (attr "type")
(if_then_else (and (match_operand:QI 0 "register_operand" "")
(ior (not (match_operand:QI 0 "q_regs_operand" ""))
(ne (symbol_ref "TARGET_MOVX")
(const_int 0))))
(const_string "imovx")
(const_string "imov")))
(set (attr "mode")
(if_then_else (eq_attr "type" "imovx")
(const_string "SI")
(const_string "QI")))])
(define_insn "*movti_internal" (define_insn "*mov<mode>_extzv_1"
[(set (match_operand:TI 0 "nonimmediate_operand" "=x,x,m") [(set (match_operand:SWI48 0 "register_operand" "=R")
(match_operand:TI 1 "vector_move_operand" "C,xm,x"))] (zero_extract:SWI48 (match_operand 1 "ext_register_operand" "Q")
"TARGET_SSE && !TARGET_64BIT (const_int 8)
&& !(MEM_P (operands[0]) && MEM_P (operands[1]))" (const_int 8)))]
""
"movz{bl|x}\t{%h1, %k0|%k0, %h1}"
[(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 (which_alternative) switch (get_attr_type (insn))
{ {
case 0: case TYPE_IMOVX:
if (get_attr_mode (insn) == MODE_V4SF) return "movz{bl|x}\t{%h1, %k0|%k0, %h1}";
return "%vxorps\t%0, %d0";
else
return "%vpxor\t%0, %d0";
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: default:
gcc_unreachable (); return "mov{b}\t{%h1, %0|%0, %h1}";
} }
} }
[(set_attr "type" "sselog1,ssemov,ssemov") [(set (attr "type")
(set_attr "prefix" "maybe_vex") (if_then_else (ior (not (match_operand:QI 0 "q_regs_operand" ""))
(ne (symbol_ref "TARGET_MOVX")
(const_int 0)))
(const_string "imovx")
(const_string "imov")))
(set (attr "mode") (set (attr "mode")
(cond [(ior (eq (symbol_ref "TARGET_SSE2") (const_int 0)) (if_then_else (eq_attr "type" "imovx")
(ne (symbol_ref "optimize_function_for_size_p (cfun)") (const_int 0))) (const_string "SI")
(const_string "V4SF") (const_string "QI")))])
(and (eq_attr "alternative" "2")
(ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
(const_int 0)))
(const_string "V4SF")]
(const_string "TI")))])
(define_insn "*movti_rex64" (define_insn "*movqi_extzv_2"
[(set (match_operand:TI 0 "nonimmediate_operand" "=!r,o,x,x,xm") [(set (match_operand:QI 0 "nonimmediate_operand" "=Qm,?R")
(match_operand:TI 1 "general_operand" "riFo,riF,C,xm,x"))] (subreg:QI
"TARGET_64BIT (zero_extract:SI (match_operand 1 "ext_register_operand" "Q,Q")
&& !(MEM_P (operands[0]) && MEM_P (operands[1]))" (const_int 8)
(const_int 8)) 0))]
"!TARGET_64BIT"
{ {
switch (which_alternative) switch (get_attr_type (insn))
{ {
case 0: case TYPE_IMOVX:
case 1: return "movz{bl|x}\t{%h1, %k0|%k0, %h1}";
return "#";
case 2:
if (get_attr_mode (insn) == MODE_V4SF)
return "%vxorps\t%0, %d0";
else
return "%vpxor\t%0, %d0";
case 3:
case 4:
/* 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: default:
gcc_unreachable (); return "mov{b}\t{%h1, %0|%0, %h1}";
} }
} }
[(set_attr "type" "*,*,sselog1,ssemov,ssemov") [(set (attr "type")
(set_attr "prefix" "*,*,maybe_vex,maybe_vex,maybe_vex") (if_then_else (and (match_operand:QI 0 "register_operand" "")
(ior (not (match_operand:QI 0 "q_regs_operand" ""))
(ne (symbol_ref "TARGET_MOVX")
(const_int 0))))
(const_string "imovx")
(const_string "imov")))
(set (attr "mode") (set (attr "mode")
(cond [(eq_attr "alternative" "2,3") (if_then_else (eq_attr "type" "imovx")
(if_then_else (const_string "SI")
(ne (symbol_ref "optimize_function_for_size_p (cfun)") (const_string "QI")))])
(const_int 0))
(const_string "V4SF")
(const_string "TI"))
(eq_attr "alternative" "4")
(if_then_else
(ior (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
(const_int 0))
(ne (symbol_ref "optimize_function_for_size_p (cfun)")
(const_int 0)))
(const_string "V4SF")
(const_string "TI"))]
(const_string "DI")))])
(define_split (define_expand "mov<mode>_insv_1"
[(set (match_operand:TI 0 "nonimmediate_operand" "") [(set (zero_extract:SWI48 (match_operand 0 "ext_register_operand" "")
(match_operand:TI 1 "general_operand" ""))] (const_int 8)
"reload_completed && !SSE_REG_P (operands[0]) (const_int 8))
&& !SSE_REG_P (operands[1])" (match_operand:SWI48 1 "nonmemory_operand" ""))]
[(const_int 0)] ""
"ix86_split_long_move (operands); DONE;") "")
;; This expands to what emit_move_complex would generate if we didn't (define_insn "*mov<mode>_insv_1_rex64"
;; have a movti pattern. Having this avoids problems with reload on [(set (zero_extract:SWI48x (match_operand 0 "ext_register_operand" "+Q")
;; 32-bit targets when SSE is present, but doesn't seem to be harmful (const_int 8)
;; to have around all the time. (const_int 8))
(define_expand "movcdi" (match_operand:SWI48x 1 "nonmemory_operand" "Qn"))]
[(set (match_operand:CDI 0 "nonimmediate_operand" "") "TARGET_64BIT"
(match_operand:CDI 1 "general_operand" ""))] "mov{b}\t{%b1, %h0|%h0, %b1}"
[(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"
"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)
(const_int 8))
(lshiftrt:SI (match_operand:SI 1 "register_operand" "Q")
(const_int 8)))]
"" ""
{ "mov{b}\t{%h1, %h0|%h0, %h1}"
if (push_operand (operands[0], CDImode)) [(set_attr "type" "imov")
emit_move_complex_push (CDImode, operands[0], operands[1]); (set_attr "mode" "QI")])
else
emit_move_complex_parts (operands[0], operands[1]); ;; Floating point move instructions.
DONE;
})
(define_expand "movsf" (define_expand "movsf"
[(set (match_operand:SF 0 "nonimmediate_operand" "") [(set (match_operand:SF 0 "nonimmediate_operand" "")
...@@ -4137,7 +3886,7 @@ ...@@ -4137,7 +3886,7 @@
(zero_extend:DI (match_operand:SI 1 "general_operand" ""))) (zero_extend:DI (match_operand:SI 1 "general_operand" "")))
(clobber (reg:CC FLAGS_REG))] (clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && reload_completed "!TARGET_64BIT && reload_completed
&& !SSE_REG_P (operands[0]) && !MMX_REG_P (operands[0])" && !(MMX_REG_P (operands[0]) || SSE_REG_P (operands[0]))"
[(set (match_dup 3) (match_dup 1)) [(set (match_dup 3) (match_dup 1))
(set (match_dup 4) (const_int 0))] (set (match_dup 4) (const_int 0))]
"split_di (&operands[0], 1, &operands[3], &operands[4]);") "split_di (&operands[0], 1, &operands[3], &operands[4]);")
...@@ -10520,7 +10269,7 @@ ...@@ -10520,7 +10269,7 @@
FAIL; FAIL;
if (TARGET_64BIT) if (TARGET_64BIT)
emit_insn (gen_movdi_insv_1_rex64 (operands[0], operands[3])); emit_insn (gen_movdi_insv_1 (operands[0], operands[3]));
else else
emit_insn (gen_movsi_insv_1 (operands[0], operands[3])); emit_insn (gen_movsi_insv_1 (operands[0], operands[3]));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment