diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2004-04-20 02:13:19 +0000 |
---|---|---|
committer | Aldy Hernandez <aldyh@gcc.gnu.org> | 2004-04-20 02:13:19 +0000 |
commit | 423c11897f8ba3d5ebac1e3c09d42c6b6a95e2fe (patch) | |
tree | 06e1d8b1a6d2c2176c501a12322e0fa187b494b3 /gcc | |
parent | f531010820afc86bde3e7d4b98850ee51c735de5 (diff) | |
download | gcc-423c11897f8ba3d5ebac1e3c09d42c6b6a95e2fe.zip gcc-423c11897f8ba3d5ebac1e3c09d42c6b6a95e2fe.tar.gz gcc-423c11897f8ba3d5ebac1e3c09d42c6b6a95e2fe.tar.bz2 |
rs6000.md (UNSPEC_MV_CR_GT): New constant.
* config/rs6000/rs6000.md (UNSPEC_MV_CR_GT): New constant.
(move_from_CR_gt_bit): New.
(cceq_ior_compare): Name previously unnamed pattern. Disable for
E500.
(cceq_rev_compare): Name previously unnamed pattern. Allow for
E500.
* config/rs6000/spe.md (cmpsfeq_gpr): Rewrite as unspec.
(tstsfeq_gpr): Same.
(cmpsfgt_gpr): Same.
(tstsfgt_gpr): Same.
(cmpsflt_gpr): Same.
(tstsflt_gpr): Same.
(e500_cceq_ior_compare): New.
(e500_flip_gt_bit): New.
* config/rs6000/rs6000.c (ccr_bit): Remove E500 specific code.
(print_operand): Add 'c' and 'D'.
(rs6000_generate_compare): Rewrite to generate correct rtl.
(rs6000_emit_sCOND): Handle E500.
(output_cbranch): Adjust for changes in rs6000_generate_compare.
(output_e500_flip_gt_bit): New.
* config/rs6000/rs6000-protos.h (output_e500_flip_gt_bit):
Protoize.
From-SVN: r80876
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 28 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 120 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 20 | ||||
-rw-r--r-- | gcc/config/rs6000/spe.md | 69 |
5 files changed, 168 insertions, 70 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e4d9bab..5aab80f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +2004-04-19 Aldy Hernandez <aldyh@redhat.com> + + * config/rs6000/rs6000.md (UNSPEC_MV_CR_GT): New constant. + (move_from_CR_gt_bit): New. + (cceq_ior_compare): Name previously unnamed pattern. Disable for + E500. + (cceq_rev_compare): Name previously unnamed pattern. Allow for + E500. + + * config/rs6000/spe.md (cmpsfeq_gpr): Rewrite as unspec. + (tstsfeq_gpr): Same. + (cmpsfgt_gpr): Same. + (tstsfgt_gpr): Same. + (cmpsflt_gpr): Same. + (tstsflt_gpr): Same. + (e500_cceq_ior_compare): New. + (e500_flip_gt_bit): New. + + * config/rs6000/rs6000.c (ccr_bit): Remove E500 specific code. + (print_operand): Add 'c' and 'D'. + (rs6000_generate_compare): Rewrite to generate correct rtl. + (rs6000_emit_sCOND): Handle E500. + (output_cbranch): Adjust for changes in rs6000_generate_compare. + (output_e500_flip_gt_bit): New. + + * config/rs6000/rs6000-protos.h (output_e500_flip_gt_bit): + Protoize. + 2004-04-19 Eric Christopher <echristo@redhat.com> * config/mips/mips.h (DWARF2_ADDR_SIZE): New. diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 95a506b..57e8886 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -116,6 +116,7 @@ extern enum rtx_code rs6000_reverse_condition (enum machine_mode, extern void rs6000_emit_sCOND (enum rtx_code, rtx); extern void rs6000_emit_cbranch (enum rtx_code, rtx); extern char * output_cbranch (rtx, const char *, int, rtx); +extern char * output_e500_flip_gt_bit (rtx, rtx); extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int); extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx); extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index a86ec22..5384c79 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -8798,14 +8798,8 @@ ccr_bit (rtx op, int scc_p) switch (code) { case NE: - if (TARGET_E500 && !TARGET_FPRS - && TARGET_HARD_FLOAT && cc_mode == CCFPmode) - return base_bit + 1; return scc_p ? base_bit + 3 : base_bit + 2; case EQ: - if (TARGET_E500 && !TARGET_FPRS - && TARGET_HARD_FLOAT && cc_mode == CCFPmode) - return base_bit + 1; return base_bit + 2; case GT: case GTU: case UNLE: return base_bit + 1; @@ -9025,6 +9019,26 @@ print_operand (FILE *file, rtx x, int code) /* %c is output_addr_const if a CONSTANT_ADDRESS_P, otherwise output_operand. */ + case 'c': + /* X is a CR register. Print the number of the GT bit of the CR. */ + if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x))) + output_operand_lossage ("invalid %%E value"); + else + fprintf (file, "%d", 4 * (REGNO (x) - CR0_REGNO) + 1); + return; + + case 'D': + /* Like 'J' but get to the GT bit. */ + if (GET_CODE (x) != REG) + abort (); + + /* Bit 1 is GT bit. */ + i = 4 * (REGNO (x) - CR0_REGNO) + 1; + + /* If we want bit 31, write a shift count of zero, not 32. */ + fprintf (file, "%d", i == 31 ? 0 : i + 1); + return; + case 'E': /* X is a CR register. Print the number of the EQ bit of the CR */ if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x))) @@ -9812,36 +9826,26 @@ rs6000_generate_compare (enum rtx_code code) { rtx cmp, or1, or2, or_result, compare_result2; + /* Note: The E500 comparison instructions set the GT bit (x + + 1), on success. This explains the mess. */ + switch (code) { - case EQ: - case UNEQ: - case NE: - case LTGT: + case EQ: case UNEQ: case NE: case LTGT: cmp = flag_finite_math_only ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0, rs6000_compare_op1) : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0, rs6000_compare_op1); break; - case GT: - case GTU: - case UNGT: - case UNGE: - case GE: - case GEU: + case GT: case GTU: case UNGT: case UNGE: case GE: case GEU: cmp = flag_finite_math_only ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0, rs6000_compare_op1) : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0, rs6000_compare_op1); break; - case LT: - case LTU: - case UNLT: - case UNLE: - case LE: - case LEU: + case LT: case LTU: case UNLT: case UNLE: case LE: case LEU: cmp = flag_finite_math_only ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0, rs6000_compare_op1) @@ -9855,8 +9859,6 @@ rs6000_generate_compare (enum rtx_code code) /* Synthesize LE and GE from LT/GT || EQ. */ if (code == LE || code == GE || code == LEU || code == GEU) { - /* Synthesize GE/LE frome GT/LT || EQ. */ - emit_insn (cmp); switch (code) @@ -9881,23 +9883,8 @@ rs6000_generate_compare (enum rtx_code code) rs6000_compare_op1); emit_insn (cmp); - /* The MC8540 FP compare instructions set the CR bits - differently than other PPC compare instructions. For - that matter, there is no generic test instruction, but a - testgt, testlt, and testeq. For a true condition, bit 2 - is set (x1xx) in the CR. Following the traditional CR - values: - - LT GT EQ OV - bit3 bit2 bit1 bit0 - - ... bit 2 would be a GT CR alias, so later on we - look in the GT bits for the branch instructions. - However, we must be careful to emit correct RTL in - the meantime, so optimizations don't get confused. */ - - or1 = gen_rtx_NE (SImode, compare_result, const0_rtx); - or2 = gen_rtx_NE (SImode, compare_result2, const0_rtx); + or1 = gen_rtx_GT (SImode, compare_result, const0_rtx); + or2 = gen_rtx_GT (SImode, compare_result2, const0_rtx); /* OR them together. */ cmp = gen_rtx_SET (VOIDmode, or_result, @@ -9909,16 +9896,10 @@ rs6000_generate_compare (enum rtx_code code) } else { - /* We only care about 1 bit (x1xx), so map everything to NE to - maintain rtl sanity. We'll get to the right bit (x1xx) at - code output time. */ if (code == NE || code == LTGT) - /* Do the inverse here because we have no cmpne - instruction. We use the cmpeq instruction and expect - to get a 0 instead. */ - code = EQ; - else code = NE; + else + code = EQ; } emit_insn (cmp); @@ -9983,6 +9964,24 @@ rs6000_emit_sCOND (enum rtx_code code, rtx result) condition_rtx = rs6000_generate_compare (code); cond_code = GET_CODE (condition_rtx); + if (TARGET_E500 && rs6000_compare_fp_p + && !TARGET_FPRS && TARGET_HARD_FLOAT) + { + rtx t; + + PUT_MODE (condition_rtx, SImode); + t = XEXP (condition_rtx, 0); + + if (cond_code != NE && cond_code != EQ) + abort (); + + if (cond_code == NE) + emit_insn (gen_e500_flip_gt_bit (t, t)); + + emit_insn (gen_move_from_CR_gt_bit (result, t)); + return; + } + if (cond_code == NE || cond_code == GE || cond_code == LE || cond_code == GEU || cond_code == LEU @@ -10079,9 +10078,9 @@ output_cbranch (rtx op, const char *label, int reversed, rtx insn) to the GT bit. */ if (code == EQ) /* Opposite of GT. */ - code = UNLE; - else if (code == NE) code = GT; + else if (code == NE) + code = UNLE; else abort (); } @@ -10160,6 +10159,25 @@ output_cbranch (rtx op, const char *label, int reversed, rtx insn) return string; } +/* Return the string to flip the GT bit on a CR. */ +char * +output_e500_flip_gt_bit (rtx dst, rtx src) +{ + static char string[64]; + int a, b; + + if (GET_CODE (dst) != REG || ! CR_REGNO_P (REGNO (dst)) + || GET_CODE (src) != REG || ! CR_REGNO_P (REGNO (src))) + abort (); + + /* GT bit. */ + a = 4 * (REGNO (dst) - CR0_REGNO) + 1; + b = 4 * (REGNO (src) - CR0_REGNO) + 1; + + sprintf (string, "crnot %d,%d", a, b); + return string; +} + /* Emit a conditional move: move TRUE_COND to DEST if OP of the operands of the last comparison is nonzero/true, FALSE_COND if it is zero/false. Return 0 if the hardware has no such operation. */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 4e96548..c1dabf8 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -50,6 +50,7 @@ (UNSPEC_TLSGOTTPREL 28) (UNSPEC_TLSTLS 29) (UNSPEC_FIX_TRUNC_TF 30) ; fadd, rounding towards zero + (UNSPEC_MV_CR_GT 31) ; move_from_CR_gt_bit ]) ;; @@ -11290,6 +11291,15 @@ (const_string "mfcr"))) (set_attr "length" "12")]) +;; Same as above, but get the GT bit. +(define_insn "move_from_CR_gt_bit" + [(set (match_operand:SI 0 "gpc_reg_operand" "=r") + (unspec:SI [(match_operand 1 "cc_reg_operand" "y")] UNSPEC_MV_CR_GT))] + "TARGET_E500" + "mfcr %0\;{rlinm|rlwinm} %0,%0,%D1,1" + [(set_attr "type" "mfcr") + (set_attr "length" "12")]) + ;; Same as above, but get the OV/ORDERED bit. (define_insn "move_from_CR_ov_bit" [(set (match_operand:SI 0 "gpc_reg_operand" "=r") @@ -13620,7 +13630,7 @@ ; which are generated by the branch logic. ; Prefer destructive operations where BT = BB (for crXX BT,BA,BB) -(define_insn "" +(define_insn "*cceq_ior_compare" [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y") (compare:CCEQ (match_operator:SI 1 "boolean_operator" [(match_operator:SI 2 @@ -13634,7 +13644,7 @@ "cc_reg_operand" "0,y") (const_int 0)])]) (const_int 1)))] - "" + "!(TARGET_E500 && TARGET_HARD_FLOAT && !TARGET_FPRS)" "cr%q1 %E0,%j2,%j4" [(set_attr "type" "cr_logical,delayed_cr")]) @@ -13658,7 +13668,7 @@ "cr%q1 %E0,%j2,%j4" [(set_attr "type" "cr_logical,delayed_cr")]) -(define_insn "" +(define_insn "*cceq_rev_compare" [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y") (compare:CCEQ (match_operator:SI 1 "branch_positive_comparison_operator" @@ -13666,9 +13676,7 @@ "cc_reg_operand" "0,y") (const_int 0)]) (const_int 0)))] - ;; This pattern is not available to SPE because the CR bits on an FP - ;; compare are different than traditional PPC. - "!TARGET_SPE" + "" "{crnor %E0,%j1,%j1|crnot %E0,%j1}" [(set_attr "type" "cr_logical,delayed_cr")]) diff --git a/gcc/config/rs6000/spe.md b/gcc/config/rs6000/spe.md index cd4771f..7e76575 100644 --- a/gcc/config/rs6000/spe.md +++ b/gcc/config/rs6000/spe.md @@ -2455,55 +2455,98 @@ "mfspefscr %0" [(set_attr "type" "vecsimple")]) +;; FP comparison stuff. + +(define_insn "e500_cceq_ior_compare" + [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y,?y") + (compare:CCEQ (match_operator:SI 1 "boolean_operator" + [(match_operator:SI 2 + "branch_positive_comparison_operator" + [(match_operand 3 + "cc_reg_operand" "y,y") + (const_int 0)]) + (match_operator:SI 4 + "branch_positive_comparison_operator" + [(match_operand 5 + "cc_reg_operand" "0,y") + (const_int 0)])]) + (const_int 1)))] + "TARGET_E500 && TARGET_HARD_FLOAT && !TARGET_FPRS" + "cr%q1 %c0,%j2,%j4" + [(set_attr "type" "cr_logical,delayed_cr")]) + +;; Flip the GT bit. +(define_insn "e500_flip_gt_bit" + [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") + (unspec:CCFP + [(match_operand:CCFP 1 "cc_reg_operand" "y")] 999))] + "!TARGET_FPRS && TARGET_HARD_FLOAT" + "* +{ + return output_e500_flip_gt_bit (operands[0], operands[1]); +}" + [(set_attr "type" "cr_logical")]) + ;; MPC8540 single-precision FP instructions on GPRs. ;; We have 2 variants for each. One for IEEE compliant math and one ;; for non IEEE compliant math. (define_insn "cmpsfeq_gpr" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") - (eq:CCFP (match_operand:SF 1 "gpc_reg_operand" "r") - (match_operand:SF 2 "gpc_reg_operand" "r")))] + (unspec:CCFP + [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r") + (match_operand:SF 2 "gpc_reg_operand" "r"))] + 1000))] "TARGET_HARD_FLOAT && !TARGET_FPRS && !flag_unsafe_math_optimizations" "efscmpeq %0,%1,%2" [(set_attr "type" "veccmp")]) (define_insn "tstsfeq_gpr" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") - (eq:CCFP (match_operand:SF 1 "gpc_reg_operand" "r") - (match_operand:SF 2 "gpc_reg_operand" "r")))] + (unspec:CCFP + [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r") + (match_operand:SF 2 "gpc_reg_operand" "r"))] + 1001))] "TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations" "efststeq %0,%1,%2" [(set_attr "type" "veccmpsimple")]) (define_insn "cmpsfgt_gpr" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") - (gt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r") - (match_operand:SF 2 "gpc_reg_operand" "r")))] + (unspec:CCFP + [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r") + (match_operand:SF 2 "gpc_reg_operand" "r"))] + 1002))] "TARGET_HARD_FLOAT && !TARGET_FPRS && !flag_unsafe_math_optimizations" "efscmpgt %0,%1,%2" [(set_attr "type" "veccmp")]) (define_insn "tstsfgt_gpr" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") - (gt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r") - (match_operand:SF 2 "gpc_reg_operand" "r")))] + (unspec:CCFP + [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r") + (match_operand:SF 2 "gpc_reg_operand" "r"))] + 1003))] "TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations" "efststgt %0,%1,%2" [(set_attr "type" "veccmpsimple")]) (define_insn "cmpsflt_gpr" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") - (lt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r") - (match_operand:SF 2 "gpc_reg_operand" "r")))] + (unspec:CCFP + [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r") + (match_operand:SF 2 "gpc_reg_operand" "r"))] + 1004))] "TARGET_HARD_FLOAT && !TARGET_FPRS && !flag_unsafe_math_optimizations" "efscmplt %0,%1,%2" [(set_attr "type" "veccmp")]) (define_insn "tstsflt_gpr" [(set (match_operand:CCFP 0 "cc_reg_operand" "=y") - (lt:CCFP (match_operand:SF 1 "gpc_reg_operand" "r") - (match_operand:SF 2 "gpc_reg_operand" "r")))] + (unspec:CCFP + [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r") + (match_operand:SF 2 "gpc_reg_operand" "r"))] + 1004))] "TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations" "efststlt %0,%1,%2" [(set_attr "type" "veccmpsimple")]) - |