diff options
author | geoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-05-04 22:15:23 +0000 |
---|---|---|
committer | geoffk <geoffk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-05-04 22:15:23 +0000 |
commit | 2b3dfdb8611ae5a53b9a321c47c94a9182b12326 (patch) | |
tree | d493f07d81ae30e20225cca33c92741716320b92 /gcc/config | |
parent | 0618cd1d59bfb4ceb0aa6382de739c47343c9fb3 (diff) | |
download | gcc-2b3dfdb8611ae5a53b9a321c47c94a9182b12326.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@33686 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/rs6000/rs6000-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 171 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 21 |
3 files changed, 135 insertions, 58 deletions
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index c63360705a7..05201afafca 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -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)); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 215b8121c27..36c50b429cc 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 4573330a820..66a23508cf7 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -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")]) |