(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")
;; 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
(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
(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
(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. */
[(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")
""
"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
gcc_unreachable ();
}
}
- [(set_attr "type" "sselog1,ssemov,ssemov,*,*")
+ [(set_attr "isa" "*,*,*,x64,x64")
+ (set_attr "type" "sselog1,ssemov,ssemov,*,*")
(set_attr "prefix" "maybe_vex,maybe_vex,maybe_vex,*,*")
(set (attr "mode")
(cond [(eq_attr "alternative" "3,4")
]
(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
case 3:
case 4:
+ case 5:
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 ,Yi,r")
(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,r ,Yi"))]
+ "!(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
|| (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)
return "#";
case 5:
- case 9:
- return standard_sse_constant_opcode (insn, operands[1]);
-
case 6:
+ return "mov{q}\t{%1, %0|%0, %1}";
+
case 7:
+ return "mov{l}\t{%1, %k0|%k0, %1}";
+
case 8:
+ return "movabs{q}\t{%1, %0|%0, %1}";
+
+ case 9:
+ case 13:
+ return standard_sse_constant_opcode (insn, operands[1]);
+
case 10:
case 11:
case 12:
+ case 14:
+ case 15:
+ case 16:
switch (get_attr_mode (insn))
{
case MODE_V2DF:
gcc_unreachable ();
}
+ case 17:
+ case 18:
+ /* Handle broken assemblers that require movd instead of movq. */
+ return "%vmovd\t{%1, %0|%0, %1}";
+
default:
gcc_unreachable ();
}
}
[(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")
+ (if_then_else (eq_attr "alternative" "0,1,2,3,4,5,6,7,8")
(const_string "orig")
(const_string "maybe_vex")))
(set (attr "prefix_data16")
(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")
-
- /* 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"))
+ (eq_attr "alternative" "5,6,8,17,18")
+ (const_string "DI")
/* xorps is one byte shorter for !TARGET_AVX. */
- (eq_attr "alternative" "5,9")
- (cond [(match_test "TARGET_AVX")
+ (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")
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")
+ (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")
/* 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")
+ (eq_attr "alternative" "11,15")
+ (cond [(not (match_test "TARGET_SSE2"))
+ (const_string "V2SF")
+ (match_test "TARGET_SSE_SPLIT_REGS")
+ (const_string "V1DF")
+ ]
(const_string "DF"))
+
+ (eq_attr "alternative" "12,16")
+ (if_then_else (match_test "TARGET_SSE2")
+ (const_string "DF")
+ (const_string "V2SF"))
]
(const_string "DF")))])