aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2004-04-20 02:13:19 +0000
committerAldy Hernandez <aldyh@gcc.gnu.org>2004-04-20 02:13:19 +0000
commit423c11897f8ba3d5ebac1e3c09d42c6b6a95e2fe (patch)
tree06e1d8b1a6d2c2176c501a12322e0fa187b494b3 /gcc
parentf531010820afc86bde3e7d4b98850ee51c735de5 (diff)
downloadgcc-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/ChangeLog28
-rw-r--r--gcc/config/rs6000/rs6000-protos.h1
-rw-r--r--gcc/config/rs6000/rs6000.c120
-rw-r--r--gcc/config/rs6000/rs6000.md20
-rw-r--r--gcc/config/rs6000/spe.md69
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")])
-