Commit 440eb8de by Richard Henderson Committed by Richard Henderson

rx: Uncomplicate fp comparisons.

It turns out that the middle-end will happily take care of
doing the swapping and splitting of compound fp comparisons.
No need for us to replicate that here.

From-SVN: r169169
parent 3ff79f99
2011-01-24 Richard Henderson <rth@redhat.com>
* config/rx/predicates.md (rx_fp_comparison_operator): Don't accept
compound unordered comparisons.
* config/rx/rx.c (rx_split_fp_compare): Remove.
* config/rx/rx-protos.h: Update.
* config/rx/rx.md (gcc_conds, rx_conds): Remove.
(cbranchsf4): Don't call rx_split_fp_compare.
(*cbranchsf4): Use rx_split_cbranch.
(*cmpsf): Don't accept "i" constraint.
(*conditional_branch): Only valid after reload.
(cstoresf4): Merge expander with insn. Don't call rx_split_fp_compare.
2011-01-24 Michael Meissner <meissner@linux.vnet.ibm.com>
PR target/47385
......
......@@ -287,9 +287,9 @@
(match_code "eq,ne,lt,ge")
)
;; GT, LE, UNLE, UNGT omitted due to operand swap required.
;; GT and LE omitted due to operand swap required.
(define_predicate "rx_fp_comparison_operator"
(match_code "eq,ne,lt,ge,ordered,unordered,uneq,unlt,unge,ltgt")
(match_code "eq,ne,lt,ge,ordered,unordered")
)
(define_predicate "rshift_operator"
......
......@@ -39,7 +39,6 @@ extern bool rx_is_mode_dependent_addr (rtx);
extern bool rx_is_restricted_memory_address (rtx, Mmode);
extern void rx_notice_update_cc (rtx body, rtx insn);
extern void rx_split_cbranch (Mmode, Rcode, rtx, rtx, rtx);
extern bool rx_split_fp_compare (Rcode, Rcode *, Rcode *);
extern Mmode rx_select_cc_mode (Rcode, rtx, rtx);
extern bool rx_match_ccmode (rtx, Mmode);
#endif
......
......@@ -2665,68 +2665,6 @@ rx_select_cc_mode (enum rtx_code cmp_code, rtx x, rtx y ATTRIBUTE_UNUSED)
return mode_from_flags (flags_from_code (cmp_code));
}
/* Split the floating-point comparison IN into individual comparisons
O1 and O2. O2 may be UNKNOWN if there is no second comparison.
Return true iff the comparison operands must be swapped. */
bool
rx_split_fp_compare (enum rtx_code in, enum rtx_code *o1, enum rtx_code *o2)
{
enum rtx_code cmp1 = in, cmp2 = UNKNOWN;
bool swap = false;
switch (in)
{
case ORDERED:
case UNORDERED:
case LT:
case GE:
case EQ:
case NE:
break;
case GT:
case LE:
cmp1 = swap_condition (cmp1);
swap = true;
break;
case UNEQ:
cmp1 = UNORDERED;
cmp2 = EQ;
break;
case UNLT:
cmp1 = UNORDERED;
cmp2 = LT;
break;
case UNGE:
cmp1 = UNORDERED;
cmp2 = GE;
break;
case UNLE:
cmp1 = UNORDERED;
cmp2 = GT;
swap = true;
break;
case UNGT:
cmp1 = UNORDERED;
cmp2 = LE;
swap = true;
break;
case LTGT:
cmp1 = ORDERED;
cmp2 = NE;
break;
default:
gcc_unreachable ();
}
*o1 = cmp1;
*o2 = cmp2;
return swap;
}
/* Split the conditional branch. Emit (COMPARE C1 C2) into CC_REG with
CC_MODE, and use that in branches based on that compare. */
......
......@@ -29,16 +29,6 @@
(define_mode_iterator register_modes
[(SF "ALLOW_RX_FPU_INSNS") (SI "") (HI "") (QI "")])
;; Used to map RX condition names to GCC
;; condition names for builtin instructions.
(define_code_iterator gcc_conds [eq ne gt ge lt le gtu geu ltu leu
unge unlt uneq ltgt])
(define_code_attr rx_conds [(eq "eq") (ne "ne") (gt "gt") (ge "ge") (lt "lt")
(le "le") (gtu "gtu") (geu "geu") (ltu "ltu")
(leu "leu") (unge "pz") (unlt "n") (uneq "o")
(ltgt "no")])
(define_constants
[
(SP_REG 0)
......@@ -259,46 +249,20 @@
(define_expand "cbranchsf4"
[(set (pc)
(if_then_else
(match_operator 0 "comparison_operator"
(match_operator 0 "rx_fp_comparison_operator"
[(match_operand:SF 1 "register_operand")
(match_operand:SF 2 "register_operand")])
(label_ref (match_operand 3 ""))
(match_operand:SF 2 "rx_source_operand")])
(label_ref (match_operand 3 ""))
(pc)))]
"ALLOW_RX_FPU_INSNS"
{
enum rtx_code cmp1, cmp2;
/* If the comparison needs swapping of operands, do that now.
Do not split the comparison in two yet. */
if (rx_split_fp_compare (GET_CODE (operands[0]), &cmp1, &cmp2))
{
rtx op1, op2;
if (cmp2 != UNKNOWN)
{
gcc_assert (cmp1 == UNORDERED);
if (cmp2 == GT)
cmp1 = UNGT;
else if (cmp2 == LE)
cmp1 = UNLE;
else
gcc_unreachable ();
}
op1 = operands[2];
op2 = operands[1];
operands[0] = gen_rtx_fmt_ee (cmp1, VOIDmode, op1, op2);
operands[1] = op1;
operands[2] = op2;
}
})
)
(define_insn_and_split "*cbranchsf4"
[(set (pc)
(if_then_else
(match_operator 3 "rx_fp_comparison_operator"
[(match_operand:SF 0 "register_operand" "r")
(match_operand:SF 1 "rx_source_operand" "rFiQ")])
(match_operand:SF 1 "rx_source_operand" "rFQ")])
(match_operand 2 "label_ref_operand" "")
(pc)))]
"ALLOW_RX_FPU_INSNS"
......@@ -306,46 +270,8 @@
"&& reload_completed"
[(const_int 0)]
{
enum rtx_code cmp0, cmp1, cmp2;
rtx flags, lab1, lab2, over, x;
bool swap;
cmp0 = GET_CODE (operands[3]);
swap = rx_split_fp_compare (cmp0, &cmp1, &cmp2);
gcc_assert (!swap);
flags = gen_rtx_REG (CC_Fmode, CC_REG);
x = gen_rtx_COMPARE (CC_Fmode, operands[0], operands[1]);
x = gen_rtx_SET (VOIDmode, flags, x);
emit_insn (x);
over = NULL;
lab1 = lab2 = operands[2];
/* The one case of LTGT needs to be split into cmp1 && cmp2. */
if (cmp0 == LTGT)
{
over = gen_label_rtx ();
lab1 = gen_rtx_LABEL_REF (VOIDmode, over);
cmp1 = reverse_condition_maybe_unordered (cmp1);
}
/* Otherwise we split into cmp1 || cmp2. */
x = gen_rtx_fmt_ee (cmp1, VOIDmode, flags, const0_rtx);
x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, lab1, pc_rtx);
x = gen_rtx_SET (VOIDmode, pc_rtx, x);
emit_jump_insn (x);
if (cmp2 != UNKNOWN)
{
x = gen_rtx_fmt_ee (cmp2, VOIDmode, flags, const0_rtx);
x = gen_rtx_IF_THEN_ELSE (VOIDmode, x, lab2, pc_rtx);
x = gen_rtx_SET (VOIDmode, pc_rtx, x);
emit_jump_insn (x);
}
if (over)
emit_label (over);
rx_split_cbranch (CC_Fmode, GET_CODE (operands[3]),
operands[0], operands[1], operands[2]);
DONE;
})
......@@ -353,7 +279,7 @@
[(set (reg:CC_F CC_REG)
(compare:CC_F
(match_operand:SF 0 "register_operand" "r,r,r")
(match_operand:SF 1 "rx_source_operand" "r,iF,Q")))]
(match_operand:SF 1 "rx_source_operand" "r,F,Q")))]
"ALLOW_RX_FPU_INSNS && reload_completed"
"fcmp\t%1, %0"
[(set_attr "timings" "11,11,33")
......@@ -369,7 +295,7 @@
[(reg CC_REG) (const_int 0)])
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"reload_completed"
"b%B1\t%0"
[(set_attr "length" "8") ;; This length is wrong, but it is
;; too hard to compute statically.
......@@ -750,95 +676,26 @@
[(set_attr "length" "3")]
)
(define_expand "cstoresf4"
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(match_operator:SI 1 "comparison_operator"
[(match_operand:SF 2 "register_operand" "")
(match_operand:SF 3 "register_operand" "")]))
(clobber (match_scratch:SI 4))])]
"ALLOW_RX_FPU_INSNS"
{
enum rtx_code cmp1, cmp2;
/* If the comparison needs swapping of operands, do that now.
Do not split the comparison in two yet. */
if (rx_split_fp_compare (GET_CODE (operands[1]), &cmp1, &cmp2))
{
rtx op2, op3;
if (cmp2 != UNKNOWN)
{
gcc_assert (cmp1 == UNORDERED);
if (cmp2 == GT)
cmp1 = UNGT;
else if (cmp2 == LE)
cmp1 = UNLE;
else
gcc_unreachable ();
}
op2 = operands[3];
op3 = operands[2];
operands[0] = gen_rtx_fmt_ee (cmp1, VOIDmode, op2, op3);
operands[2] = op2;
operands[3] = op3;
}
})
(define_insn_and_split "*cstoresf4"
(define_insn_and_split "cstoresf4"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 4 "rx_fp_comparison_operator"
(match_operator:SI 1 "rx_fp_comparison_operator"
[(match_operand:SF 2 "register_operand" "r")
(match_operand:SF 3 "rx_source_operand" "rFiQ")]))
(clobber (match_scratch:SI 1 "=r"))]
(match_operand:SF 3 "rx_source_operand" "rFQ")]))]
"ALLOW_RX_FPU_INSNS"
"#"
"reload_completed"
[(const_int 0)]
{
enum rtx_code cmp0, cmp1, cmp2;
rtx flags, x;
bool swap;
cmp0 = GET_CODE (operands[4]);
swap = rx_split_fp_compare (cmp0, &cmp1, &cmp2);
gcc_assert (!swap);
flags = gen_rtx_REG (CC_Fmode, CC_REG);
x = gen_rtx_COMPARE (CC_Fmode, operands[2], operands[3]);
x = gen_rtx_SET (VOIDmode, flags, x);
emit_insn (x);
x = gen_rtx_fmt_ee (cmp1, SImode, flags, const0_rtx);
x = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode, flags, const0_rtx);
x = gen_rtx_SET (VOIDmode, operands[0], x);
emit_insn (x);
if (cmp0 == LTGT)
{
/* The one case of LTGT needs to be split into ORDERED && NE. */
x = gen_rtx_fmt_ee (EQ, VOIDmode, flags, const0_rtx);
x = gen_rtx_IF_THEN_ELSE (SImode, x, const0_rtx, operands[0]);
x = gen_rtx_SET (VOIDmode, operands[0], x);
emit_insn (x);
}
else if (cmp2 == EQ || cmp2 == NE)
{
/* Oring the two flags can be performed with a movcc operation. */
x = gen_rtx_fmt_ee (cmp2, VOIDmode, flags, const0_rtx);
x = gen_rtx_IF_THEN_ELSE (SImode, x, const1_rtx, operands[0]);
x = gen_rtx_SET (VOIDmode, operands[0], x);
emit_insn (x);
}
else if (cmp2 != UNKNOWN)
{
/* We can't use movcc, but need to or in another compare.
Do this by storing the second operation into the scratch. */
x = gen_rtx_fmt_ee (cmp2, SImode, flags, const0_rtx);
x = gen_rtx_SET (VOIDmode, operands[1], x);
emit_insn (x);
emit_insn (gen_iorsi3 (operands[0], operands[0], operands[1]));
}
DONE;
})
......
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