rs6000-protos.h: Add output_cbranch.

* config/rs6000/rs6000-protos.h: Add output_cbranch.
* config/rs6000/rs6000.c (ccr_bit_negated_p): Delete.
(print_operand): Delete %t and %T codes.
(output_cbranch): New function.  Support branch prediction.
* config/rs6000/rs6000.md: Use output_cbranch for
conditional branches and returns.

From-SVN: r33686
This commit is contained in:
Geoff Keating 2000-05-04 22:15:23 +00:00 committed by Geoffrey Keating
parent 233844c0ea
commit 12a4e8c50d
4 changed files with 144 additions and 58 deletions

View File

@ -1,3 +1,12 @@
2000-05-04 Geoff Keating <geoffk@cygnus.com>
* config/rs6000/rs6000-protos.h: Add output_cbranch.
* config/rs6000/rs6000.c (ccr_bit_negated_p): Delete.
(print_operand): Delete %t and %T codes.
(output_cbranch): New function. Support branch prediction.
* config/rs6000/rs6000.md: Use output_cbranch for
conditional branches and returns.
2000-05-04 Jason Merrill <jason@casey.cygnus.com>
* simplify-rtx.c (simplify_ternary_operation): Cast to unsigned.

View File

@ -84,6 +84,7 @@ extern enum reg_class secondary_reload_class PARAMS ((enum reg_class,
extern int ccr_bit PARAMS ((rtx, int));
extern void print_operand PARAMS ((FILE *, rtx, int));
extern void print_operand_address PARAMS ((FILE *, rtx));
extern char * output_cbranch PARAMS ((rtx, const char *, int, rtx));
extern void output_toc PARAMS ((FILE *, rtx, int));
extern int rs6000_adjust_cost PARAMS ((rtx, rtx, rtx, int));
extern int rs6000_adjust_priority PARAMS ((rtx, int));

View File

@ -119,7 +119,6 @@ static int rs6000_sr_alias_set;
static void rs6000_add_gc_roots PARAMS ((void));
static int num_insns_constant_wide PARAMS ((HOST_WIDE_INT));
static rtx expand_block_move_mem PARAMS ((enum machine_mode, rtx, rtx));
static int ccr_bit_negated_p PARAMS((rtx));
static void rs6000_emit_stack_tie PARAMS ((void));
static void rs6000_frame_related PARAMS ((rtx, rtx, HOST_WIDE_INT, rtx, rtx));
static void rs6000_emit_allocate_stack PARAMS ((HOST_WIDE_INT, int));
@ -3195,29 +3194,6 @@ ccr_bit (op, scc_p)
abort ();
}
}
/* Given a comparison operation, say whether the bit tested (as returned
by ccr_bit) should be negated. */
static int
ccr_bit_negated_p (op)
rtx op;
{
enum rtx_code code = GET_CODE (op);
enum machine_mode mode = GET_MODE (XEXP (op, 0));
if (code == EQ
|| code == LT || code == GT
|| code == LTU || code == GTU)
return 0;
else if (mode != CCFPmode
|| code == NE
|| code == ORDERED
|| code == UNGE || code == UNLE)
return 1;
else
return 0;
}
/* Return the GOT register. */
@ -3732,29 +3708,6 @@ print_operand (file, x, code)
return;
}
case 't':
/* Write 12 if this jump operation will branch if true, 4 otherwise. */
if (GET_RTX_CLASS (GET_CODE (x)) != '<')
output_operand_lossage ("invalid %%t value");
else if (! ccr_bit_negated_p (x))
fputs ("12", file);
else
putc ('4', file);
return;
case 'T':
/* Opposite of 't': write 4 if this jump operation will branch if true,
12 otherwise. */
if (GET_RTX_CLASS (GET_CODE (x)) != '<')
output_operand_lossage ("invalid %%T value");
else if (! ccr_bit_negated_p (x))
putc ('4', file);
else
fputs ("12", file);
return;
case 'u':
/* High-order 16 bits of constant for use in unsigned operand. */
if (! INT_P (x))
@ -4011,6 +3964,130 @@ print_operand_address (file, x)
abort ();
}
/* Return the string to output a conditional branch to LABEL, which is
the operand number of the label, or -1 if the branch is really a
conditional return.
OP is the conditional expression. XEXP (OP, 0) is assumed to be a
condition code register and its mode specifies what kind of
comparison we made.
REVERSED is non-zero if we should reverse the sense of the comparison.
INSN is the insn. */
char *
output_cbranch (op, label, reversed, insn)
rtx op;
const char * label;
int reversed;
rtx insn;
{
static char string[64];
enum rtx_code code = GET_CODE (op);
rtx cc_reg = XEXP (op, 0);
enum machine_mode mode = GET_MODE (cc_reg);
int cc_regno = REGNO (cc_reg) - CR0_REGNO;
int need_longbranch = label != NULL && get_attr_length (insn) == 12;
int really_reversed = reversed ^ need_longbranch;
char *s = string;
const char *ccode;
const char *pred;
rtx note;
/* Work out which way this really branches. */
if (really_reversed)
{
/* Reversal of FP compares takes care -- an ordered compare
becomes an unordered compare and vice versa. */
if (mode == CCFPmode)
code = reverse_condition_maybe_unordered (code);
else
code = reverse_condition (code);
}
/* If needed, print the CROR required for various floating-point
comparisons; and decide on the condition code to test. */
if ((code == LE || code == GE
|| code == UNEQ || code == LTGT
|| code == UNGT || code == UNLT)
&& mode == CCFPmode)
{
int base_bit = 4 * cc_regno;
int bit0, bit1;
if (code == UNEQ)
bit0 = 2;
else if (code == UNGT || code == GE)
bit0 = 1;
else
bit0 = 0;
if (code == LTGT)
bit1 = 1;
else if (code == LE || code == GE)
bit1 = 2;
else
bit1 = 3;
s += sprintf (s, "cror %d,%d,%d\n\t", base_bit + 3,
base_bit + bit1, base_bit + bit0);
ccode = "so";
}
else switch (code)
{
/* Not all of these are actually distinct opcodes, but
we distinguish them for clarity of the resulting assembler. */
case NE: ccode = "ne"; break;
case EQ: ccode = "eq"; break;
case GE: case GEU: ccode = "ge"; break;
case GT: case GTU: ccode = "gt"; break;
case LE: case LEU: ccode = "le"; break;
case LT: case LTU: ccode = "lt"; break;
case UNORDERED: ccode = "un"; break;
case ORDERED: ccode = "nu"; break;
case UNGE: ccode = "nl"; break;
case UNLE: ccode = "ng"; break;
default:
abort();
}
/* Maybe we have a guess as to how likely the branch is. */
note = find_reg_note (insn, REG_BR_PROB, NULL_RTX);
if (note != NULL_RTX)
{
/* PROB is the difference from 50%. */
int prob = INTVAL (XEXP (note, 0)) - REG_BR_PROB_BASE / 2;
/* For branches that are very close to 50%, assume not-taken. */
if (abs (prob) > REG_BR_PROB_BASE / 20
&& ((prob > 0) ^ need_longbranch))
pred = "+";
else
pred = "-";
}
else
pred = "";
if (label == NULL)
s += sprintf (s, "{b%sr|b%slr}%s ", ccode, ccode, pred);
else
s += sprintf (s, "b%s%s ", ccode, pred);
s += sprintf (s, "cr%d", cc_regno);
if (label != NULL)
{
/* If the branch distance was too far, we may have to use an
unconditional branch to go the distance. */
if (need_longbranch)
s += sprintf (s, ",%c$+8 ; b %s", '%', label);
else
s += sprintf (s, ",%s", label);
}
return string;
}
/* This page contains routines that are used to determine what the function
prologue and epilogue code will do and write them out. */

View File

@ -13992,11 +13992,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
""
"*
{
if (get_attr_length (insn) == 8)
return \"%C1bc %t1,%j1,%l0\";
else
return \"%C1bc %T1,%j1,%$+8\;b %l0\";
return output_cbranch (operands[1], \"%l0\", 0, insn);
}"
[(set_attr "type" "branch")])
@ -14009,7 +14005,10 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
(return)
(pc)))]
"direct_return ()"
"{%C0bcr|%C0bclr} %t0,%j0"
"*
{
return output_cbranch (operands[0], NULL, 0, insn);
}"
[(set_attr "type" "branch")
(set_attr "length" "8")])
@ -14024,10 +14023,7 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
""
"*
{
if (get_attr_length (insn) == 8)
return \"%C1bc %T1,%j1,%l0\";
else
return \"%C1bc %t1,%j1,%$+8\;b %l0\";
return output_cbranch (operands[1], \"%l0\", 1, insn);
}"
[(set_attr "type" "branch")])
@ -14040,7 +14036,10 @@ operands[2] = GEN_INT (INTVAL (operands[1]) >> 32);
(pc)
(return)))]
"direct_return ()"
"{%C0bcr|%C0bclr} %T0,%j0"
"*
{
return output_cbranch (operands[0], NULL, 1, insn);
}"
[(set_attr "type" "branch")
(set_attr "length" "8")])