Commit eaa49b49 by Richard Henderson Committed by Richard Henderson

re PR target/19009 (Loading of FP constants into FP reg via SSE reg)

        PR target/19099
        PR target/19250
        PR target/19252
        * config/i386/i386.md (cmpdf, cmpsf, bunordered, bordered, buneq,
        bunge, bungt, bunle, bunlt, bltgt): Enable for TARGET_SSE_MATH,
        not just TARGET_SSE.
        (cmpfp_i_387): Rename from cmpfp_i.  Move after sse patterns.
        (cmpfp_i_mixed): Rename from cmpfp_i_sse; use for TARGET_MIX_SSE_I387.
        (cmpfp_i_sse): Rename from cmpfp_i_sse_only; use for TARGET_SSE_MATH.
        (cmpfp_iu_mixed, cmpfp_iu_sse, cmpfp_iu_387): Similarly.
        (fp_jcc_1_mixed, fp_jcc_1_sse, fp_jcc_1_387): Similarly.
        (fp_jcc_2_mixed, fp_jcc_2_sse, fp_jcc_2_387): Similarly.
        (fp_jcc_3_387, fp_jcc_4_387, fp_jcc_5_387, fp_jcc_6_387,
        fp_jcc_7_387, fp_jcc_8_387): Rename from fp_jcc_N.
        (movdicc_c_rex64): Rename with '*'.
        (movsfcc, movdfcc): Add checks for 387 and sse math to condition.
        (movsfcc_1_sse_min, movsfcc_1_sse_max, movsfcc_1_sse): New.
        (movsfcc_1_387): Rename from movsfcc_1.
        (movdfcc_1_sse_min, movdfcc_1_sse_max, movdfcc_1_sse): New.
        (movdfcc_1, movdfcc_1_rex64): Add check for 387.
        (sminsf3, smaxsf3, smindf3, smaxdf3): New.
        (minsf3, minsf, minsf_nonieee, minsf_sse, mindf3, mindf,
        mindf_nonieee, mindf_sse, maxsf3, maxsf, maxsf_nonieee, maxsf_sse,
        maxdf3, maxdf, maxdf_nonieee, maxdf_sse, sse_movsfcc, sse_movsfcc_eq,
        sse_movdfcc, sse_movdfcc_eq, sse_movsfcc_const0_1,
        sse_movsfcc_const0_2, sse_movsfcc_const0_3, sse_movsfcc_const0_4,
        sse_movdfcc_const0_1, sse_movdfcc_const0_2, sse_movdfcc_const0_3,
        sse_movdfcc_const0_4): Remove.
        * config/i386/i386.c (ix86_expand_fp_movcc): For TARGET_SSE_MATH,
        recognize min/max early.  Update for changed sse cmove patterns.
        (ix86_split_sse_movcc): New.
        * config/i386/i386-protos.h: Update.

From-SVN: r93620
parent 997e120f
2005-01-13 Richard Henderson <rth@redhat.com>
PR target/19099
PR target/19250
PR target/19252
* config/i386/i386.md (cmpdf, cmpsf, bunordered, bordered, buneq,
bunge, bungt, bunle, bunlt, bltgt): Enable for TARGET_SSE_MATH,
not just TARGET_SSE.
(cmpfp_i_387): Rename from cmpfp_i. Move after sse patterns.
(cmpfp_i_mixed): Rename from cmpfp_i_sse; use for TARGET_MIX_SSE_I387.
(cmpfp_i_sse): Rename from cmpfp_i_sse_only; use for TARGET_SSE_MATH.
(cmpfp_iu_mixed, cmpfp_iu_sse, cmpfp_iu_387): Similarly.
(fp_jcc_1_mixed, fp_jcc_1_sse, fp_jcc_1_387): Similarly.
(fp_jcc_2_mixed, fp_jcc_2_sse, fp_jcc_2_387): Similarly.
(fp_jcc_3_387, fp_jcc_4_387, fp_jcc_5_387, fp_jcc_6_387,
fp_jcc_7_387, fp_jcc_8_387): Rename from fp_jcc_N.
(movdicc_c_rex64): Rename with '*'.
(movsfcc, movdfcc): Add checks for 387 and sse math to condition.
(movsfcc_1_sse_min, movsfcc_1_sse_max, movsfcc_1_sse): New.
(movsfcc_1_387): Rename from movsfcc_1.
(movdfcc_1_sse_min, movdfcc_1_sse_max, movdfcc_1_sse): New.
(movdfcc_1, movdfcc_1_rex64): Add check for 387.
(sminsf3, smaxsf3, smindf3, smaxdf3): New.
(minsf3, minsf, minsf_nonieee, minsf_sse, mindf3, mindf,
mindf_nonieee, mindf_sse, maxsf3, maxsf, maxsf_nonieee, maxsf_sse,
maxdf3, maxdf, maxdf_nonieee, maxdf_sse, sse_movsfcc, sse_movsfcc_eq,
sse_movdfcc, sse_movdfcc_eq, sse_movsfcc_const0_1,
sse_movsfcc_const0_2, sse_movsfcc_const0_3, sse_movsfcc_const0_4,
sse_movdfcc_const0_1, sse_movdfcc_const0_2, sse_movdfcc_const0_3,
sse_movdfcc_const0_4): Remove.
* config/i386/i386.c (ix86_expand_fp_movcc): For TARGET_SSE_MATH,
recognize min/max early. Update for changed sse cmove patterns.
(ix86_split_sse_movcc): New.
* config/i386/i386-protos.h: Update.
2005-01-13 Steven Bosscher <stevenb@suse.de> 2005-01-13 Steven Bosscher <stevenb@suse.de>
* tree-ssa-dse.c (fix_phi_uses): Use SSA operand iterators. * tree-ssa-dse.c (fix_phi_uses): Use SSA operand iterators.
......
...@@ -145,6 +145,7 @@ extern void ix86_expand_branch (enum rtx_code, rtx); ...@@ -145,6 +145,7 @@ extern void ix86_expand_branch (enum rtx_code, rtx);
extern int ix86_expand_setcc (enum rtx_code, rtx); extern int ix86_expand_setcc (enum rtx_code, rtx);
extern int ix86_expand_int_movcc (rtx[]); extern int ix86_expand_int_movcc (rtx[]);
extern int ix86_expand_fp_movcc (rtx[]); extern int ix86_expand_fp_movcc (rtx[]);
extern void ix86_split_sse_movcc (rtx[]);
extern int ix86_expand_int_addcc (rtx[]); extern int ix86_expand_int_addcc (rtx[]);
extern void ix86_expand_call (rtx, rtx, rtx, rtx, rtx, int); extern void ix86_expand_call (rtx, rtx, rtx, rtx, rtx, int);
extern void x86_initialize_trampoline (rtx, rtx, rtx); extern void x86_initialize_trampoline (rtx, rtx, rtx);
......
...@@ -9743,118 +9743,95 @@ ix86_expand_int_movcc (rtx operands[]) ...@@ -9743,118 +9743,95 @@ ix86_expand_int_movcc (rtx operands[])
int int
ix86_expand_fp_movcc (rtx operands[]) ix86_expand_fp_movcc (rtx operands[])
{ {
enum rtx_code code; enum machine_mode mode = GET_MODE (operands[0]);
rtx tmp; enum rtx_code code = GET_CODE (operands[1]);
rtx compare_op, second_test, bypass_test; rtx tmp, compare_op, second_test, bypass_test;
/* For SF/DFmode conditional moves based on comparisons if (TARGET_SSE_MATH && SSE_FLOAT_MODE_P (mode))
in same mode, we may want to use SSE min/max instructions. */ {
if (((TARGET_SSE_MATH && GET_MODE (operands[0]) == SFmode) rtx cmp_op0, cmp_op1, if_true, if_false;
|| (TARGET_SSE2 && TARGET_SSE_MATH && GET_MODE (operands[0]) == DFmode)) rtx clob;
&& GET_MODE (ix86_compare_op0) == GET_MODE (operands[0]) enum machine_mode vmode, cmode;
/* The SSE comparisons does not support the LTGT/UNEQ pair. */ bool is_minmax = false;
&& (!TARGET_IEEE_FP
|| (GET_CODE (operands[1]) != LTGT && GET_CODE (operands[1]) != UNEQ)) cmp_op0 = ix86_compare_op0;
/* We may be called from the post-reload splitter. */ cmp_op1 = ix86_compare_op1;
&& (!REG_P (operands[0]) if_true = operands[2];
|| SSE_REG_P (operands[0]) if_false = operands[3];
|| REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER))
{ /* Since we've no cmove for sse registers, don't force bad register
rtx op0 = ix86_compare_op0, op1 = ix86_compare_op1; allocation just to gain access to it. Deny movcc when the
code = GET_CODE (operands[1]); comparison mode doesn't match the move mode. */
cmode = GET_MODE (cmp_op0);
/* See if we have (cross) match between comparison operands and if (cmode == VOIDmode)
conditional move operands. */ cmode = GET_MODE (cmp_op1);
if (rtx_equal_p (operands[2], op1)) if (cmode != mode)
return 0;
/* Massage condition to satisfy sse_comparison_operator. In case we
are in non-ieee mode, try to canonicalize the destination operand
to be first in the comparison - this helps reload to avoid extra
moves. */
if (!sse_comparison_operator (operands[1], VOIDmode)
|| ((COMMUTATIVE_P (operands[1]) || !TARGET_IEEE_FP)
&& rtx_equal_p (operands[0], cmp_op1)))
{ {
rtx tmp = op0; tmp = cmp_op0;
op0 = op1; cmp_op0 = cmp_op1;
op1 = tmp; cmp_op1 = tmp;
code = reverse_condition_maybe_unordered (code); code = swap_condition (code);
} }
if (rtx_equal_p (operands[2], op0) && rtx_equal_p (operands[3], op1))
{ /* Detect conditional moves that exactly match min/max operational
/* Check for min operation. */ semantics. Note that this is IEEE safe, as long as we don't
if (code == LT || code == UNLE) interchange the operands. Which is why we keep this in the form
{ if an IF_THEN_ELSE instead of reducing to SMIN/SMAX. */
if (code == UNLE) if ((code == LT || code == UNGE) && REG_P (cmp_op0) && REG_P (cmp_op1))
{ {
rtx tmp = op0; if (((cmp_op0 == if_true && cmp_op1 == if_false)
op0 = op1; || (cmp_op0 == if_false && cmp_op1 == if_true)))
op1 = tmp;
}
operands[0] = force_reg (GET_MODE (operands[0]), operands[0]);
if (memory_operand (op0, VOIDmode))
op0 = force_reg (GET_MODE (operands[0]), op0);
if (GET_MODE (operands[0]) == SFmode)
emit_insn (gen_minsf3 (operands[0], op0, op1));
else
emit_insn (gen_mindf3 (operands[0], op0, op1));
return 1;
}
/* Check for max operation. */
if (code == GT || code == UNGE)
{ {
is_minmax = true;
if (code == UNGE) if (code == UNGE)
{ {
rtx tmp = op0; code = LT;
op0 = op1; tmp = if_true;
op1 = tmp; if_true = if_false;
if_false = tmp;
} }
operands[0] = force_reg (GET_MODE (operands[0]), operands[0]);
if (memory_operand (op0, VOIDmode))
op0 = force_reg (GET_MODE (operands[0]), op0);
if (GET_MODE (operands[0]) == SFmode)
emit_insn (gen_maxsf3 (operands[0], op0, op1));
else
emit_insn (gen_maxdf3 (operands[0], op0, op1));
return 1;
} }
} }
/* Manage condition to be sse_comparison_operator. In case we are
in non-ieee mode, try to canonicalize the destination operand if (mode == SFmode)
to be first in the comparison - this helps reload to avoid extra vmode = V4SFmode;
moves. */ else if (mode == DFmode)
if (!sse_comparison_operator (operands[1], VOIDmode) vmode = V2DFmode;
|| (rtx_equal_p (operands[0], ix86_compare_op1) && !TARGET_IEEE_FP)) else
gcc_unreachable ();
cmp_op0 = force_reg (mode, cmp_op0);
if (!nonimmediate_operand (cmp_op1, mode))
cmp_op1 = force_reg (mode, cmp_op1);
tmp = gen_rtx_fmt_ee (code, mode, cmp_op0, cmp_op1);
gcc_assert (sse_comparison_operator (tmp, VOIDmode));
tmp = gen_rtx_IF_THEN_ELSE (mode, tmp, if_true, if_false);
tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
if (!is_minmax)
{ {
rtx tmp = ix86_compare_op0; clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (vmode));
ix86_compare_op0 = ix86_compare_op1; tmp = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, tmp, clob));
ix86_compare_op1 = tmp;
operands[1] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[1])),
VOIDmode, ix86_compare_op0,
ix86_compare_op1);
}
/* Similarly try to manage result to be first operand of conditional
move. We also don't support the NE comparison on SSE, so try to
avoid it. */
if ((rtx_equal_p (operands[0], operands[3])
&& (!TARGET_IEEE_FP || GET_CODE (operands[1]) != EQ))
|| (GET_CODE (operands[1]) == NE && TARGET_IEEE_FP))
{
rtx tmp = operands[2];
operands[2] = operands[3];
operands[3] = tmp;
operands[1] = gen_rtx_fmt_ee (reverse_condition_maybe_unordered
(GET_CODE (operands[1])),
VOIDmode, ix86_compare_op0,
ix86_compare_op1);
} }
if (GET_MODE (operands[0]) == SFmode)
emit_insn (gen_sse_movsfcc (operands[0], operands[1], emit_insn (tmp);
operands[2], operands[3],
ix86_compare_op0, ix86_compare_op1));
else
emit_insn (gen_sse_movdfcc (operands[0], operands[1],
operands[2], operands[3],
ix86_compare_op0, ix86_compare_op1));
return 1; return 1;
} }
/* The floating point conditional move instructions don't directly /* The floating point conditional move instructions don't directly
support conditions resulting from a signed integer comparison. */ support conditions resulting from a signed integer comparison. */
code = GET_CODE (operands[1]);
compare_op = ix86_expand_compare (code, &second_test, &bypass_test); compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
/* The floating point conditional move instructions don't directly /* The floating point conditional move instructions don't directly
...@@ -9873,38 +9850,86 @@ ix86_expand_fp_movcc (rtx operands[]) ...@@ -9873,38 +9850,86 @@ ix86_expand_fp_movcc (rtx operands[])
} }
if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3])) if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3]))
{ {
tmp = gen_reg_rtx (GET_MODE (operands[0])); tmp = gen_reg_rtx (mode);
emit_move_insn (tmp, operands[3]); emit_move_insn (tmp, operands[3]);
operands[3] = tmp; operands[3] = tmp;
} }
if (second_test && reg_overlap_mentioned_p (operands[0], operands[2])) if (second_test && reg_overlap_mentioned_p (operands[0], operands[2]))
{ {
tmp = gen_reg_rtx (GET_MODE (operands[0])); tmp = gen_reg_rtx (mode);
emit_move_insn (tmp, operands[2]); emit_move_insn (tmp, operands[2]);
operands[2] = tmp; operands[2] = tmp;
} }
emit_insn (gen_rtx_SET (VOIDmode, operands[0], emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), gen_rtx_IF_THEN_ELSE (mode, compare_op,
compare_op, operands[2], operands[3])));
operands[2],
operands[3])));
if (bypass_test) if (bypass_test)
emit_insn (gen_rtx_SET (VOIDmode, operands[0], emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), gen_rtx_IF_THEN_ELSE (mode, bypass_test,
bypass_test, operands[3], operands[0])));
operands[3],
operands[0])));
if (second_test) if (second_test)
emit_insn (gen_rtx_SET (VOIDmode, operands[0], emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), gen_rtx_IF_THEN_ELSE (mode, second_test,
second_test, operands[2], operands[0])));
operands[2],
operands[0])));
return 1; return 1;
} }
void
ix86_split_sse_movcc (rtx operands[])
{
rtx dest, scratch, cmp, op_true, op_false, x;
enum machine_mode mode, vmode;
/* Note that the operator CMP has been set up with matching constraints
such that dest is valid for the comparison. Unless one of the true
or false operands are zero, the true operand has already been placed
in SCRATCH. */
dest = operands[0];
scratch = operands[1];
op_true = operands[2];
op_false = operands[3];
cmp = operands[4];
mode = GET_MODE (dest);
vmode = GET_MODE (scratch);
emit_insn (gen_rtx_SET (VOIDmode, dest, cmp));
dest = simplify_gen_subreg (vmode, dest, mode, 0);
if (op_false == CONST0_RTX (mode))
{
op_true = simplify_gen_subreg (vmode, op_true, mode, 0);
x = gen_rtx_AND (vmode, dest, op_true);
emit_insn (gen_rtx_SET (VOIDmode, dest, x));
}
else
{
op_false = simplify_gen_subreg (vmode, op_false, mode, 0);
if (op_true == CONST0_RTX (mode))
{
x = gen_rtx_NOT (vmode, dest);
x = gen_rtx_AND (vmode, x, op_false);
emit_insn (gen_rtx_SET (VOIDmode, dest, x));
}
else
{
x = gen_rtx_AND (vmode, scratch, dest);
emit_insn (gen_rtx_SET (VOIDmode, scratch, x));
x = gen_rtx_NOT (vmode, dest);
x = gen_rtx_AND (vmode, x, op_false);
emit_insn (gen_rtx_SET (VOIDmode, dest, x));
x = gen_rtx_IOR (vmode, dest, scratch);
emit_insn (gen_rtx_SET (VOIDmode, dest, x));
}
}
}
/* Expand conditional increment or decrement using adb/sbb instructions. /* Expand conditional increment or decrement using adb/sbb instructions.
The default case using setcc followed by the conditional move can be The default case using setcc followed by the conditional move can be
done by generic code. */ done by generic code. */
......
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