Commit e267e177 by Richard Henderson Committed by Richard Henderson

sparc-protos.h (select_cc_mode): Declare.

        * sparc-protos.h (select_cc_mode): Declare.
        * sparc.c (select_cc_mode): New.  Handle unordered compares.
        (output_cbranch): Always reverse via code change.  Handle
        unordered compares.  Factor tests and string updates.
        * sparc.h (SELECT_CC_MODE): Split out to select_cc_mode.
        (REVERSIBLE_CC_MODE): Also exclude CCFPmode.
        * sparc.md (bunordered, bordered): New.
        (bungt, bunlt, buneq, bunge, bunle): New.

From-SVN: r31609
parent ddcc7cf6
2000-01-25 Richard Henderson <rth@cygnus.com> 2000-01-25 Richard Henderson <rth@cygnus.com>
* sparc-protos.h (select_cc_mode): Declare.
* sparc.c (select_cc_mode): New. Handle unordered compares.
(output_cbranch): Always reverse via code change. Handle
unordered compares. Factor tests and string updates.
* sparc.h (SELECT_CC_MODE): Split out to select_cc_mode.
(REVERSIBLE_CC_MODE): Also exclude CCFPmode.
* sparc.md (bunordered, bordered): New.
(bungt, bunlt, buneq, bunge, bunle): New.
2000-01-25 Richard Henderson <rth@cygnus.com>
* dwarf2out.c (dwarf2out_init): Use ggc_add_rtx_varray_root. * dwarf2out.c (dwarf2out_init): Use ggc_add_rtx_varray_root.
* ggc-common.c (ggc_add_rtx_varray_root): New. * ggc-common.c (ggc_add_rtx_varray_root): New.
(ggc_mark_rtx_varray): New. (ggc_mark_rtx_varray): New.
......
...@@ -77,6 +77,7 @@ extern void sparc_flat_save_restore PARAMS ((FILE *, const char *, ...@@ -77,6 +77,7 @@ extern void sparc_flat_save_restore PARAMS ((FILE *, const char *,
const char *, unsigned long)); const char *, unsigned long));
#ifdef RTX_CODE #ifdef RTX_CODE
extern enum machine_mode select_cc_mode PARAMS ((enum rtx_code, rtx, rtx));
/* Define the function that build the compare insn for scc and bcc. */ /* Define the function that build the compare insn for scc and bcc. */
extern rtx gen_compare_reg PARAMS ((enum rtx_code code, rtx, rtx)); extern rtx gen_compare_reg PARAMS ((enum rtx_code code, rtx, rtx));
extern void sparc_emit_float_lib_cmp PARAMS ((rtx, rtx, enum rtx_code)); extern void sparc_emit_float_lib_cmp PARAMS ((rtx, rtx, enum rtx_code));
......
...@@ -2072,6 +2072,61 @@ sparc_emit_set_const64 (op0, op1) ...@@ -2072,6 +2072,61 @@ sparc_emit_set_const64 (op0, op1)
sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits); sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits);
} }
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. For floating-point,
CCFP[E]mode is used. CC_NOOVmode should be used when the first operand
is a PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special
processing is needed. */
enum machine_mode
select_cc_mode (op, x, y)
enum rtx_code op;
rtx x;
rtx y ATTRIBUTE_UNUSED;
{
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
{
switch (op)
{
case EQ:
case NE:
case UNORDERED:
case ORDERED:
case UNLT:
case UNLE:
case UNGT:
case UNGE:
case UNEQ:
case UNNE:
return CCFPmode;
case LT:
case LE:
case GT:
case GE:
return CCFPEmode;
default:
abort ();
}
}
else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
|| GET_CODE (x) == NEG || GET_CODE (x) == ASHIFT)
{
if (TARGET_ARCH64 && GET_MODE (x) == DImode)
return CCX_NOOVmode;
else
return CC_NOOVmode;
}
else
{
if (TARGET_ARCH64 && GET_MODE (x) == DImode)
return CCXmode;
else
return CCmode;
}
}
/* X and Y are two things to compare using CODE. Emit the compare insn and /* X and Y are two things to compare using CODE. Emit the compare insn and
return the rtx for the cc reg in the proper mode. */ return the rtx for the cc reg in the proper mode. */
...@@ -4583,6 +4638,7 @@ output_cbranch (op, label, reversed, annul, noop, insn) ...@@ -4583,6 +4638,7 @@ output_cbranch (op, label, reversed, annul, noop, insn)
static char v9_xcc_labelno[] = "%%xcc, %lX"; static char v9_xcc_labelno[] = "%%xcc, %lX";
static char v9_fcc_labelno[] = "%%fccX, %lY"; static char v9_fcc_labelno[] = "%%fccX, %lY";
char *labelno; char *labelno;
const char *branch;
int labeloff, spaces = 8; int labeloff, spaces = 8;
/* ??? !v9: FP branches cannot be preceded by another floating point insn. /* ??? !v9: FP branches cannot be preceded by another floating point insn.
...@@ -4594,147 +4650,158 @@ output_cbranch (op, label, reversed, annul, noop, insn) ...@@ -4594,147 +4650,158 @@ output_cbranch (op, label, reversed, annul, noop, insn)
else else
string[0] = '\0'; string[0] = '\0';
/* If not floating-point or if EQ or NE, we can just reverse the code. */ if (reversed)
if (reversed
&& ((mode != CCFPmode && mode != CCFPEmode) || code == EQ || code == NE))
code = reverse_condition (code), reversed = 0;
/* Start by writing the branch condition. */
switch (code)
{ {
case NE: /* Reversal of FP compares takes care -- an ordered compare
if (mode == CCFPmode || mode == CCFPEmode) becomes an unordered compare and vice versa. */
{
strcat (string, "fbne");
spaces -= 4;
}
else
{
strcpy (string, "bne");
spaces -= 3;
}
break;
case EQ:
if (mode == CCFPmode || mode == CCFPEmode)
{
strcat (string, "fbe");
spaces -= 3;
}
else
{
strcpy (string, "be");
spaces -= 2;
}
break;
case GE:
if (mode == CCFPmode || mode == CCFPEmode) if (mode == CCFPmode || mode == CCFPEmode)
{ {
if (reversed) switch (code)
strcat (string, "fbul");
else
strcat (string, "fbge");
spaces -= 4;
}
else if (mode == CC_NOOVmode)
{
strcpy (string, "bpos");
spaces -= 4;
}
else
{
strcpy (string, "bge");
spaces -= 3;
}
break;
case GT:
if (mode == CCFPmode || mode == CCFPEmode)
{
if (reversed)
{ {
strcat (string, "fbule"); case EQ:
spaces -= 5; code = NE;
} break;
else case NE:
{ code = EQ;
strcat (string, "fbg"); break;
spaces -= 3; case GE:
} code = UNLT;
} break;
else case GT:
{ code = UNLE;
strcpy (string, "bg"); break;
spaces -= 2; case LE:
} code = UNGT;
break; break;
case LT:
case LE: code = UNGE;
if (mode == CCFPmode || mode == CCFPEmode) break;
{ case UNORDERED:
if (reversed) code = ORDERED;
strcat (string, "fbug"); break;
else case ORDERED:
strcat (string, "fble"); code = UNORDERED;
spaces -= 4; break;
} case UNGT:
else code = LE;
{ break;
strcpy (string, "ble"); case UNLT:
spaces -= 3; code = GE;
} break;
break; case UNEQ:
/* ??? We don't have a "less or greater" rtx code. */
code = UNKNOWN;
break;
case UNGE:
code = LT;
break;
case UNLE:
code = GT;
break;
case LT: default:
if (mode == CCFPmode || mode == CCFPEmode) abort ();
{
if (reversed)
{
strcat (string, "fbuge");
spaces -= 5;
} }
else
{
strcat (string, "fbl");
spaces -= 3;
}
}
else if (mode == CC_NOOVmode)
{
strcpy (string, "bneg");
spaces -= 4;
} }
else else
{ code = reverse_condition (code);
strcpy (string, "bl"); }
spaces -= 2;
}
break;
case GEU:
strcpy (string, "bgeu");
spaces -= 4;
break;
case GTU:
strcpy (string, "bgu");
spaces -= 3;
break;
case LEU: /* Start by writing the branch condition. */
strcpy (string, "bleu"); if (mode == CCFPmode || mode == CCFPEmode)
spaces -= 4; switch (code)
break; {
case NE:
branch = "fbne";
break;
case EQ:
branch = "fbe";
break;
case GE:
branch = "fbge";
break;
case GT:
branch = "fbg";
break;
case LE:
branch = "fble";
break;
case LT:
branch = "fbl";
break;
case UNORDERED:
branch = "fbu";
break;
case ORDERED:
branch = "fbo";
break;
case UNGT:
branch = "fbug";
break;
case UNLT:
branch = "fbul";
break;
case UNEQ:
branch = "fbue";
break;
case UNGE:
branch = "fbuge";
break;
case UNLE:
branch = "fbule";
break;
case UNKNOWN:
branch = "fblg";
break;
case LTU: default:
strcpy (string, "blu"); abort ();
spaces -= 3; }
break; else
switch (code)
{
case NE:
branch = "bne";
break;
case EQ:
branch = "be";
break;
case GE:
if (mode == CC_NOOVmode)
branch = "bpos";
else
branch = "bge";
break;
case GT:
branch = "bg";
break;
case LE:
branch = "ble";
break;
case LT:
if (mode == CC_NOOVmode)
branch = "bneg";
else
branch = "bl";
break;
case GEU:
branch = "bgeu";
break;
case GTU:
branch = "bgu";
break;
case LEU:
branch = "bleu";
break;
case LTU:
branch = "blu";
break;
default: default:
abort (); abort ();
} }
strcpy (string, branch);
spaces -= strlen (branch);
/* Now add the annulling, the label, and a possible noop. */ /* Now add the annulling, the label, and a possible noop. */
if (annul) if (annul)
......
...@@ -2672,18 +2672,12 @@ do { \ ...@@ -2672,18 +2672,12 @@ do { \
CCFP[E]mode is used. CC_NOOVmode should be used when the first operand is a CCFP[E]mode is used. CC_NOOVmode should be used when the first operand is a
PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special PLUS, MINUS, NEG, or ASHIFT. CCmode should be used when no special
processing is needed. */ processing is needed. */
#define SELECT_CC_MODE(OP,X,Y) \ #define SELECT_CC_MODE(OP,X,Y) select_cc_mode ((OP), (X), (Y))
(GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \
: ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \
|| GET_CODE (X) == NEG || GET_CODE (X) == ASHIFT) \
? (TARGET_ARCH64 && GET_MODE (X) == DImode ? CCX_NOOVmode : CC_NOOVmode) \
: ((TARGET_ARCH64 || TARGET_V8PLUS) && GET_MODE (X) == DImode ? CCXmode : CCmode)))
/* Return non-zero if SELECT_CC_MODE will never return MODE for a /* Return non-zero if SELECT_CC_MODE will never return MODE for a
floating point inequality comparison. */ floating point inequality comparison. */
#define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode) #define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode && (MODE) != CCFPmode)
/* A function address in a call instruction /* A function address in a call instruction
is a byte address (for indexing purposes) is a byte address (for indexing purposes)
......
...@@ -1794,6 +1794,135 @@ ...@@ -1794,6 +1794,135 @@
" "
{ operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1); { operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
}") }")
(define_expand "bunordered"
[(set (pc)
(if_then_else (unordered (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
if (GET_MODE (sparc_compare_op0) == TFmode
&& TARGET_ARCH64 && ! TARGET_HARD_QUAD)
{
sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1,
UNORDERED);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
operands[1] = gen_compare_reg (UNORDERED, sparc_compare_op0,
sparc_compare_op1);
}")
(define_expand "bordered"
[(set (pc)
(if_then_else (ordered (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
if (GET_MODE (sparc_compare_op0) == TFmode
&& TARGET_ARCH64 && ! TARGET_HARD_QUAD)
{
sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
operands[1] = gen_compare_reg (ORDERED, sparc_compare_op0,
sparc_compare_op1);
}")
(define_expand "bungt"
[(set (pc)
(if_then_else (ungt (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
if (GET_MODE (sparc_compare_op0) == TFmode
&& TARGET_ARCH64 && ! TARGET_HARD_QUAD)
{
sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
operands[1] = gen_compare_reg (UNGT, sparc_compare_op0, sparc_compare_op1);
}")
(define_expand "bunlt"
[(set (pc)
(if_then_else (unlt (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
if (GET_MODE (sparc_compare_op0) == TFmode
&& TARGET_ARCH64 && ! TARGET_HARD_QUAD)
{
sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
operands[1] = gen_compare_reg (UNLT, sparc_compare_op0, sparc_compare_op1);
}")
(define_expand "buneq"
[(set (pc)
(if_then_else (uneq (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
if (GET_MODE (sparc_compare_op0) == TFmode
&& TARGET_ARCH64 && ! TARGET_HARD_QUAD)
{
sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
operands[1] = gen_compare_reg (UNEQ, sparc_compare_op0, sparc_compare_op1);
}")
(define_expand "bunge"
[(set (pc)
(if_then_else (unge (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
if (GET_MODE (sparc_compare_op0) == TFmode
&& TARGET_ARCH64 && ! TARGET_HARD_QUAD)
{
sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
operands[1] = gen_compare_reg (UNGE, sparc_compare_op0, sparc_compare_op1);
}")
(define_expand "bunle"
[(set (pc)
(if_then_else (unle (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
if (GET_MODE (sparc_compare_op0) == TFmode
&& TARGET_ARCH64 && ! TARGET_HARD_QUAD)
{
sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE);
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
operands[1] = gen_compare_reg (UNLE, sparc_compare_op0, sparc_compare_op1);
}")
;; Now match both normal and inverted jump. ;; Now match both normal and inverted jump.
......
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