;; insn. So we pretend we can output to a reg in order to get better
;; register preferencing, but we really use a stack slot.
-(define_expand "truncdfsf2"
- [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
- (float_truncate:SF
- (match_operand:DF 1 "register_operand" "")))
- (clobber (match_dup 2))])]
- "TARGET_80387 || TARGET_SSE2"
- "
- if (!TARGET_80387)
- {
- emit_insn (gen_truncdfsf2_sse_only (operands[0], operands[1]));
- DONE;
- }
- else if (flag_unsafe_math_optimizations)
- {
- rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SFmode);
- emit_insn (gen_truncdfsf2_noop (reg, operands[1]));
- if (reg != operands[0])
- emit_move_insn (operands[0], reg);
- DONE;
- }
- else
- operands[2] = assign_386_stack_local (SFmode, 0);
-")
+;; Conversion from DFmode to SFmode.
-(define_insn "truncdfsf2_noop"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))]
- "TARGET_80387 && flag_unsafe_math_optimizations"
+(define_expand "truncdfsf2"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
+ (float_truncate:SF
+ (match_operand:DF 1 "nonimmediate_operand" "")))]
+ "TARGET_80387 || (TARGET_SSE2 && TARGET_SSE_MATH)"
{
- return output_387_reg_move (insn, operands);
-}
- [(set_attr "type" "fmov")
- (set_attr "mode" "SF")])
+ if (MEM_P (operands[0]) && MEM_P (operands[1]))
+ operands[1] = force_reg (DFmode, operands[1]);
-(define_insn "*truncdfsf2_1"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#rx,?r#fx,?x#rf")
- (float_truncate:SF
- (match_operand:DF 1 "register_operand" "f,f,f,f")))
- (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))]
- "TARGET_80387 && !TARGET_SSE2"
+ if (TARGET_SSE2 && TARGET_SSE_MATH && !TARGET_MIX_SSE_I387)
+ ;
+ else if (flag_unsafe_math_optimizations)
+ ;
+ else
+ {
+ rtx temp = assign_386_stack_local (SFmode, 0);
+ emit_insn (gen_truncdfsf2_with_temp (operands[0], operands[1], temp));
+ DONE;
+ }
+})
+
+(define_expand "truncdfsf2_with_temp"
+ [(parallel [(set (match_operand:SF 0 "" "")
+ (float_truncate:SF (match_operand:DF 1 "" "")))
+ (clobber (match_operand:SF 2 "" ""))])]
+ "")
+
+(define_insn "*truncdfsf_fast_mixed"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m,f,Y")
+ (float_truncate:SF
+ (match_operand:DF 1 "nonimmediate_operand" "f ,f,Ym")))]
+ "TARGET_SSE2 && TARGET_MIX_SSE_I387 && flag_unsafe_math_optimizations"
{
switch (which_alternative)
{
return "fstp%z0\t%y0";
else
return "fst%z0\t%y0";
+ case 1:
+ return output_387_reg_move (insn, operands);
+ case 2:
+ return "cvtsd2ss\t{%1, %0|%0, %1}";
default:
abort ();
}
}
- [(set_attr "type" "fmov,multi,multi,multi")
- (set_attr "mode" "SF,SF,SF,SF")])
+ [(set_attr "type" "fmov,fmov,ssecvt")
+ (set_attr "mode" "SF")])
+
+;; Yes, this one doesn't depend on flag_unsafe_math_optimizations,
+;; because nothing we do here is unsafe.
+(define_insn "*truncdfsf_fast_sse"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=Y")
+ (float_truncate:SF
+ (match_operand:DF 1 "nonimmediate_operand" "Ym")))]
+ "TARGET_SSE2 && TARGET_SSE_MATH"
+ "cvtsd2ss\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "SF")])
+
+(define_insn "*truncdfsf_fast_i387"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=fm")
+ (float_truncate:SF
+ (match_operand:DF 1 "nonimmediate_operand" "f")))]
+ "TARGET_80387 && flag_unsafe_math_optimizations"
+ "* return output_387_reg_move (insn, operands);"
+ [(set_attr "type" "fmov")
+ (set_attr "mode" "SF")])
-(define_insn "*truncdfsf2_1_sse"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=*!m#fxr,?f#xr,?r#fx,?x#fr,Y#fr")
+(define_insn "*truncdfsf_mixed"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?fx*r,Y")
(float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "f#Y,f#Y,f#Y,f#Y,mY#f")))
- (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m,X"))]
- "TARGET_80387 && TARGET_SSE2"
+ (match_operand:DF 1 "nonimmediate_operand" "f ,f ,Ym")))
+ (clobber (match_operand:SF 2 "memory_operand" "=X,m ,X"))]
+ "TARGET_MIX_SSE_I387"
{
switch (which_alternative)
{
return "fstp%z0\t%y0";
else
return "fst%z0\t%y0";
- case 4:
+ case 1:
return "#";
+ case 2:
+ return "cvtsd2ss\t{%1, %0|%0, %1}";
default:
abort ();
}
}
- [(set_attr "type" "fmov,multi,multi,multi,ssecvt")
- (set_attr "mode" "SF,SF,SF,SF,DF")])
+ [(set_attr "type" "fmov,multi,ssecvt")
+ (set_attr "mode" "SF")])
-(define_insn "*truncdfsf2_2"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=Y,Y,!m")
+(define_insn "*truncdfsf_i387"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?fx*r")
(float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "Y,mY,f#Y")))]
- "TARGET_80387 && TARGET_SSE2
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ (match_operand:DF 1 "nonimmediate_operand" "f,f")))
+ (clobber (match_operand:SF 2 "memory_operand" "=X,m"))]
+ "TARGET_80387"
{
switch (which_alternative)
{
case 0:
- case 1:
- return "cvtsd2ss\t{%1, %0|%0, %1}";
- case 2:
if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
return "fstp%z0\t%y0";
else
return "fst%z0\t%y0";
+ case 1:
+ return "#";
default:
abort ();
}
}
- [(set_attr "type" "ssecvt,ssecvt,fmov")
- (set_attr "athlon_decode" "vector,double,*")
- (set_attr "mode" "SF,SF,SF")])
-
-(define_insn "*truncdfsf2_3"
- [(set (match_operand:SF 0 "memory_operand" "=m")
- (float_truncate:SF
- (match_operand:DF 1 "register_operand" "f")))]
- "TARGET_80387"
-{
- if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
- return "fstp%z0\t%y0";
- else
- return "fst%z0\t%y0";
-}
- [(set_attr "type" "fmov")
- (set_attr "mode" "SF")])
-
-(define_insn "truncdfsf2_sse_only"
- [(set (match_operand:SF 0 "register_operand" "=Y,Y")
- (float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "Y,mY")))]
- "!TARGET_80387 && TARGET_SSE2"
- "cvtsd2ss\t{%1, %0|%0, %1}"
- [(set_attr "type" "ssecvt")
- (set_attr "athlon_decode" "vector,double")
+ [(set_attr "type" "fmov,multi")
(set_attr "mode" "SF")])
-(define_split
- [(set (match_operand:SF 0 "memory_operand" "")
- (float_truncate:SF
- (match_operand:DF 1 "register_operand" "")))
- (clobber (match_operand:SF 2 "memory_operand" ""))]
- "TARGET_80387"
- [(set (match_dup 0) (float_truncate:SF (match_dup 1)))]
- "")
-
(define_split
[(set (match_operand:SF 0 "register_operand" "")
(float_truncate:SF
- (match_operand:DF 1 "nonimmediate_operand" "")))
+ (match_operand:DF 1 "fp_register_operand" "")))
(clobber (match_operand 2 "" ""))]
- "TARGET_80387 && reload_completed
- && SSE_REG_P (operands[0])
- && !STACK_REG_P (operands[1])"
- [(const_int 0)]
+ "reload_completed"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0) (match_dup 2))]
{
- emit_insn (gen_truncdfsf2_sse_only (operands[0], operands[1]));
- DONE;
+ operands[1] = gen_rtx_REG (SFmode, true_regnum (operands[1]));
})
-(define_split
- [(set (match_operand:SF 0 "register_operand" "")
- (float_truncate:SF
- (match_operand:DF 1 "fp_register_operand" "")))
- (clobber (match_operand:SF 2 "memory_operand" ""))]
- "TARGET_80387 && reload_completed"
- [(set (match_dup 2) (float_truncate:SF (match_dup 1)))
- (set (match_dup 0) (match_dup 2))]
- "")
+;; Conversion from XFmode to SFmode.
(define_expand "truncxfsf2"
[(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
(match_operand:XF 1 "register_operand" "")))
(clobber (match_dup 2))])]
"TARGET_80387"
- "
+{
if (flag_unsafe_math_optimizations)
{
rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (SFmode);
- emit_insn (gen_truncxfsf2_noop (reg, operands[1]));
+ emit_insn (gen_truncxfsf2_i387_noop (reg, operands[1]));
if (reg != operands[0])
emit_move_insn (operands[0], reg);
DONE;
}
else
operands[2] = assign_386_stack_local (SFmode, 0);
- ")
+})
-(define_insn "truncxfsf2_noop"
+(define_insn "*truncxfsf2_mixed"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#rx,?r#fx,?x#rf")
+ (float_truncate:SF
+ (match_operand:XF 1 "register_operand" "f,f,f,f")))
+ (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))]
+ "TARGET_MIX_SSE_I387"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+ return "fstp%z0\t%y0";
+ else
+ return "fst%z0\t%y0";
+ default:
+ abort();
+ }
+}
+ [(set_attr "type" "fmov,multi,multi,multi")
+ (set_attr "mode" "SF")])
+
+(define_insn "truncxfsf2_i387_noop"
[(set (match_operand:SF 0 "register_operand" "=f")
(float_truncate:SF (match_operand:XF 1 "register_operand" "f")))]
"TARGET_80387 && flag_unsafe_math_optimizations"
[(set_attr "type" "fmov")
(set_attr "mode" "SF")])
-(define_insn "*truncxfsf2_1"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#rx,?r#fx,?x#rf")
+(define_insn "*truncxfsf2_i387"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#r,?r#f")
(float_truncate:SF
- (match_operand:XF 1 "register_operand" "f,f,f,f")))
- (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))]
+ (match_operand:XF 1 "register_operand" "f,f,f")))
+ (clobber (match_operand:SF 2 "memory_operand" "=X,m,m"))]
"TARGET_80387"
{
switch (which_alternative)
else
return "fst%z0\t%y0";
default:
- abort();
+ abort ();
}
}
- [(set_attr "type" "fmov,multi,multi,multi")
+ [(set_attr "type" "fmov,multi,multi")
(set_attr "mode" "SF")])
-(define_insn "*truncxfsf2_2"
+(define_insn "*truncxfsf2_i387_1"
[(set (match_operand:SF 0 "memory_operand" "=m")
(float_truncate:SF
(match_operand:XF 1 "register_operand" "f")))]
(set_attr "mode" "SF")])
(define_split
- [(set (match_operand:SF 0 "memory_operand" "")
+ [(set (match_operand:SF 0 "register_operand" "")
(float_truncate:SF
(match_operand:XF 1 "register_operand" "")))
(clobber (match_operand:SF 2 "memory_operand" ""))]
- "TARGET_80387"
- [(set (match_dup 0) (float_truncate:SF (match_dup 1)))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 2) (float_truncate:SF (match_dup 1)))
+ (set (match_dup 0) (match_dup 2))]
"")
(define_split
- [(set (match_operand:SF 0 "register_operand" "")
+ [(set (match_operand:SF 0 "memory_operand" "")
(float_truncate:SF
(match_operand:XF 1 "register_operand" "")))
(clobber (match_operand:SF 2 "memory_operand" ""))]
- "TARGET_80387 && reload_completed"
- [(set (match_dup 2) (float_truncate:SF (match_dup 1)))
- (set (match_dup 0) (match_dup 2))]
+ "TARGET_80387"
+ [(set (match_dup 0) (float_truncate:SF (match_dup 1)))]
"")
+;; Conversion from XFmode to DFmode.
+
(define_expand "truncxfdf2"
[(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
(float_truncate:DF
(match_operand:XF 1 "register_operand" "")))
(clobber (match_dup 2))])]
"TARGET_80387"
- "
+{
if (flag_unsafe_math_optimizations)
{
rtx reg = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DFmode);
- emit_insn (gen_truncxfdf2_noop (reg, operands[1]));
+ emit_insn (gen_truncxfdf2_i387_noop (reg, operands[1]));
if (reg != operands[0])
emit_move_insn (operands[0], reg);
DONE;
}
else
operands[2] = assign_386_stack_local (DFmode, 0);
- ")
+})
-(define_insn "truncxfdf2_noop"
+(define_insn "*truncxfdf2_mixed"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f#rY,?r#fY,?Y#rf")
+ (float_truncate:DF
+ (match_operand:XF 1 "register_operand" "f,f,f,f")))
+ (clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))]
+ "TARGET_SSE2 && TARGET_MIX_SSE_I387"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+ return "fstp%z0\t%y0";
+ else
+ return "fst%z0\t%y0";
+ default:
+ abort();
+ }
+ abort ();
+}
+ [(set_attr "type" "fmov,multi,multi,multi")
+ (set_attr "mode" "DF")])
+
+(define_insn "truncxfdf2_i387_noop"
[(set (match_operand:DF 0 "register_operand" "=f")
(float_truncate:DF (match_operand:XF 1 "register_operand" "f")))]
"TARGET_80387 && flag_unsafe_math_optimizations"
[(set_attr "type" "fmov")
(set_attr "mode" "DF")])
-(define_insn "*truncxfdf2_1"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f#rY,?r#fY,?Y#rf")
+(define_insn "*truncxfdf2_i387"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f#r,?r#f")
(float_truncate:DF
- (match_operand:XF 1 "register_operand" "f,f,f,f")))
- (clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))]
+ (match_operand:XF 1 "register_operand" "f,f,f")))
+ (clobber (match_operand:DF 2 "memory_operand" "=X,m,m"))]
"TARGET_80387"
{
switch (which_alternative)
else
return "fst%z0\t%y0";
default:
- abort();
+ abort ();
}
- abort ();
}
- [(set_attr "type" "fmov,multi,multi,multi")
+ [(set_attr "type" "fmov,multi,multi")
(set_attr "mode" "DF")])
-(define_insn "*truncxfdf2_2"
+(define_insn "*truncxfdf2_i387_1"
[(set (match_operand:DF 0 "memory_operand" "=m")
(float_truncate:DF
(match_operand:XF 1 "register_operand" "f")))]
(set_attr "mode" "DF")])
(define_split
- [(set (match_operand:DF 0 "memory_operand" "")
+ [(set (match_operand:DF 0 "register_operand" "")
(float_truncate:DF
(match_operand:XF 1 "register_operand" "")))
(clobber (match_operand:DF 2 "memory_operand" ""))]
- "TARGET_80387"
- [(set (match_dup 0) (float_truncate:DF (match_dup 1)))]
+ "TARGET_80387 && reload_completed"
+ [(set (match_dup 2) (float_truncate:DF (match_dup 1)))
+ (set (match_dup 0) (match_dup 2))]
"")
(define_split
- [(set (match_operand:DF 0 "register_operand" "")
+ [(set (match_operand:DF 0 "memory_operand" "")
(float_truncate:DF
(match_operand:XF 1 "register_operand" "")))
(clobber (match_operand:DF 2 "memory_operand" ""))]
- "TARGET_80387 && reload_completed"
- [(set (match_dup 2) (float_truncate:DF (match_dup 1)))
- (set (match_dup 0) (match_dup 2))]
+ "TARGET_80387"
+ [(set (match_dup 0) (float_truncate:DF (match_dup 1)))]
"")
-
\f
;; %%% Break up all these bad boys.
emit_insn (gen_fpremxf4 (op1, op2, op1, op2));
ix86_emit_fp_unordered_jump (label);
- emit_insn (gen_truncxfsf2_noop (operands[0], op1));
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op1));
DONE;
})
emit_insn (gen_fpremxf4 (op1, op2, op1, op2));
ix86_emit_fp_unordered_jump (label);
- emit_insn (gen_truncxfdf2_noop (operands[0], op1));
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op1));
DONE;
})
emit_insn (gen_fprem1xf4 (op1, op2, op1, op2));
ix86_emit_fp_unordered_jump (label);
- emit_insn (gen_truncxfsf2_noop (operands[0], op1));
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op1));
DONE;
})
emit_insn (gen_fprem1xf4 (op1, op2, op1, op2));
ix86_emit_fp_unordered_jump (label);
- emit_insn (gen_truncxfdf2_noop (operands[0], op1));
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op1));
DONE;
})
emit_insn (gen_extendsfxf2 (op1, operands[1]));
ix86_emit_i387_log1p (op0, op1);
- emit_insn (gen_truncxfsf2_noop (operands[0], op0));
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
DONE;
})
emit_insn (gen_extenddfxf2 (op1, operands[1]));
ix86_emit_i387_log1p (op0, op1);
- emit_insn (gen_truncxfdf2_noop (operands[0], op0));
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
DONE;
})
emit_insn (gen_extenddfxf2 (op1, operands[1]));
emit_insn (gen_frndintxf2 (op0, op1));
- emit_insn (gen_truncxfdf2_noop (operands[0], op0));
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
DONE;
})
emit_insn (gen_extendsfxf2 (op1, operands[1]));
emit_insn (gen_frndintxf2 (op0, op1));
- emit_insn (gen_truncxfsf2_noop (operands[0], op0));
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
DONE;
})
emit_insn (gen_extenddfxf2 (op1, operands[1]));
emit_insn (gen_frndintxf2_floor (op0, op1, op2, op3));
- emit_insn (gen_truncxfdf2_noop (operands[0], op0));
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
DONE;
})
emit_insn (gen_extendsfxf2 (op1, operands[1]));
emit_insn (gen_frndintxf2_floor (op0, op1, op2, op3));
- emit_insn (gen_truncxfsf2_noop (operands[0], op0));
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
DONE;
})
emit_insn (gen_extenddfxf2 (op1, operands[1]));
emit_insn (gen_frndintxf2_ceil (op0, op1, op2, op3));
- emit_insn (gen_truncxfdf2_noop (operands[0], op0));
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
DONE;
})
emit_insn (gen_extendsfxf2 (op1, operands[1]));
emit_insn (gen_frndintxf2_ceil (op0, op1, op2, op3));
- emit_insn (gen_truncxfsf2_noop (operands[0], op0));
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
DONE;
})
emit_insn (gen_extenddfxf2 (op1, operands[1]));
emit_insn (gen_frndintxf2_trunc (op0, op1, op2, op3));
- emit_insn (gen_truncxfdf2_noop (operands[0], op0));
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
DONE;
})
emit_insn (gen_extendsfxf2 (op1, operands[1]));
emit_insn (gen_frndintxf2_trunc (op0, op1, op2, op3));
- emit_insn (gen_truncxfsf2_noop (operands[0], op0));
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
DONE;
})
emit_insn (gen_extenddfxf2 (op1, operands[1]));
emit_insn (gen_frndintxf2_mask_pm (op0, op1, op2, op3));
- emit_insn (gen_truncxfdf2_noop (operands[0], op0));
+ emit_insn (gen_truncxfdf2_i387_noop (operands[0], op0));
DONE;
})
emit_insn (gen_extendsfxf2 (op1, operands[1]));
emit_insn (gen_frndintxf2_mask_pm (op0, op1, op2, op3));
- emit_insn (gen_truncxfsf2_noop (operands[0], op0));
+ emit_insn (gen_truncxfsf2_i387_noop (operands[0], op0));
DONE;
})