From b7053a3fde13f48ed6eb33ea89071aeebb4fc6f5 Mon Sep 17 00:00:00 2001 From: Geoffrey Keating Date: Sat, 3 May 2003 23:13:57 +0000 Subject: [PATCH] rs6000.c (scc_comparison_operator): Make equivalent to branch_positive_comparison_operator. * config/rs6000/rs6000.c (scc_comparison_operator): Make equivalent to branch_positive_comparison_operator. (ccr_bit): Check that sCOND conditions are actually a positive bit. (print_operand): Remove %D substitution. (rs6000_emit_sCOND): Generate complement operation to ensure that sCOND input is a positive bit. * config/rs6000/rs6000.md: Rearrange sCOND templates to be in the same order as bCOND, and add the missing ones. Remove the %D substitutions from the scc patterns. From-SVN: r66441 --- gcc/ChangeLog | 10 ++++ gcc/config/rs6000/rs6000.c | 87 ++++++++++++---------------------- gcc/config/rs6000/rs6000.md | 93 ++++++++++++++++++++++++++----------- 3 files changed, 106 insertions(+), 84 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c63385c4797..18b1d9eb7ba 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,15 @@ 2003-05-03 Geoffrey Keating + * config/rs6000/rs6000.c (scc_comparison_operator): Make equivalent + to branch_positive_comparison_operator. + (ccr_bit): Check that sCOND conditions are actually a positive bit. + (print_operand): Remove %D substitution. + (rs6000_emit_sCOND): Generate complement operation to ensure that + sCOND input is a positive bit. + * config/rs6000/rs6000.md: Rearrange sCOND templates to be in the + same order as bCOND, and add the missing ones. Remove the %D + substitutions from the scc patterns. + * simplify-rtx.c (simplify_relational_operation): Add case for ! (fabs(x) < 0.0). diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index ae4c3a091e6..9ecb6c0e099 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -7049,34 +7049,15 @@ branch_positive_comparison_operator (op, mode) || code == UNORDERED); } -/* Return 1 if OP is a comparison operation that is valid for an scc insn. - We check the opcode against the mode of the CC value and disallow EQ or - NE comparisons for integers. */ +/* Return 1 if OP is a comparison operation that is valid for an scc + insn: it must be a positive comparison. */ int scc_comparison_operator (op, mode) rtx op; enum machine_mode mode; { - enum rtx_code code = GET_CODE (op); - enum machine_mode cc_mode; - - if (GET_MODE (op) != mode && mode != VOIDmode) - return 0; - - if (GET_RTX_CLASS (code) != '<') - return 0; - - cc_mode = GET_MODE (XEXP (op, 0)); - if (GET_MODE_CLASS (cc_mode) != MODE_CC) - return 0; - - validate_condition_mode (code, cc_mode); - - if (code == NE && cc_mode != CCFPmode) - return 0; - - return 1; + return branch_positive_comparison_operator (op, mode); } int @@ -7501,6 +7482,12 @@ ccr_bit (op, scc_p) validate_condition_mode (code, cc_mode); + /* When generating a sCOND operation, only positive conditions are + allowed. */ + if (scc_p && code != EQ && code != GT && code != LT && code != UNORDERED + && code != GTU && code != LTU) + abort (); + switch (code) { case NE: @@ -7697,42 +7684,6 @@ print_operand (file, x, code) /* %c is output_addr_const if a CONSTANT_ADDRESS_P, otherwise output_operand. */ - case 'D': - /* There used to be a comment for 'C' reading "This is an - optional cror needed for certain floating-point - comparisons. Otherwise write nothing." */ - - /* Similar, except that this is for an scc, so we must be able to - encode the test in a single bit that is one. We do the above - for any LE, GE, GEU, or LEU and invert the bit for NE. */ - if (GET_CODE (x) == LE || GET_CODE (x) == GE - || GET_CODE (x) == LEU || GET_CODE (x) == GEU) - { - int base_bit = 4 * (REGNO (XEXP (x, 0)) - CR0_REGNO); - - fprintf (file, "cror %d,%d,%d\n\t", base_bit + 3, - base_bit + 2, - base_bit + (GET_CODE (x) == GE || GET_CODE (x) == GEU)); - } - - else if (GET_CODE (x) == NE) - { - int base_bit = 4 * (REGNO (XEXP (x, 0)) - CR0_REGNO); - - fprintf (file, "crnor %d,%d,%d\n\t", base_bit + 3, - base_bit + 2, base_bit + 2); - } - else if (TARGET_E500 && !TARGET_FPRS && TARGET_HARD_FLOAT - && GET_CODE (x) == EQ - && GET_MODE (XEXP (x, 0)) == CCFPmode) - { - int base_bit = 4 * (REGNO (XEXP (x, 0)) - CR0_REGNO); - - fprintf (file, "crnor %d,%d,%d\n\t", base_bit + 1, - base_bit + 1, base_bit + 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))) @@ -8686,8 +8637,28 @@ rs6000_emit_sCOND (code, result) { rtx condition_rtx; enum machine_mode op_mode; + enum rtx_code cond_code; condition_rtx = rs6000_generate_compare (code); + cond_code = GET_CODE (condition_rtx); + + if (cond_code == NE + || cond_code == GE || cond_code == LE + || cond_code == GEU || cond_code == LEU + || cond_code == ORDERED || cond_code == UNGE || cond_code == UNLE) + { + rtx not_result = gen_reg_rtx (CCEQmode); + rtx not_op, rev_cond_rtx; + enum machine_mode cc_mode; + + cc_mode = GET_MODE (XEXP (condition_rtx, 0)); + + rev_cond_rtx = gen_rtx (rs6000_reverse_condition (cc_mode, cond_code), + SImode, XEXP (condition_rtx, 0), const0_rtx); + not_op = gen_rtx_COMPARE (CCEQmode, rev_cond_rtx, const0_rtx); + emit_insn (gen_rtx_SET (VOIDmode, not_result, not_op)); + condition_rtx = gen_rtx_EQ (VOIDmode, not_result, const0_rtx); + } op_mode = GET_MODE (rs6000_compare_op0); if (op_mode == VOIDmode) diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index e97be3fcd7f..37b88d3d256 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -10919,8 +10919,8 @@ DONE; }") -;; A > 0 is best done using the portable sequence, so fail in that case. -(define_expand "sgt" +;; A >= 0 is best done the portable way for A an integer. +(define_expand "sge" [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] "" " @@ -10929,26 +10929,26 @@ && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx)) FAIL; - rs6000_emit_sCOND (GT, operands[0]); + rs6000_emit_sCOND (GE, operands[0]); DONE; }") -;; A < 0 is best done in the portable way for A an integer. -(define_expand "slt" +;; A > 0 is best done using the portable sequence, so fail in that case. +(define_expand "sgt" [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] "" " { - if (! rs6000_compare_fp_p + if (! rs6000_compare_fp_p && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx)) FAIL; - rs6000_emit_sCOND (LT, operands[0]); + rs6000_emit_sCOND (GT, operands[0]); DONE; }") -;; A >= 0 is best done the portable way for A an integer. -(define_expand "sge" +;; A <= 0 is best done the portable way for A an integer. +(define_expand "sle" [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] "" " @@ -10957,43 +10957,84 @@ && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx)) FAIL; - rs6000_emit_sCOND (GE, operands[0]); + rs6000_emit_sCOND (LE, operands[0]); DONE; }") -;; A <= 0 is best done the portable way for A an integer. -(define_expand "sle" +;; A < 0 is best done in the portable way for A an integer. +(define_expand "slt" [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] "" " { - if (! rs6000_compare_fp_p + if (! rs6000_compare_fp_p && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx)) FAIL; - rs6000_emit_sCOND (LE, operands[0]); + rs6000_emit_sCOND (LT, operands[0]); DONE; }") +(define_expand "sgeu" + [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] + "" + "{ rs6000_emit_sCOND (GEU, operands[0]); DONE; }") + (define_expand "sgtu" [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] "" "{ rs6000_emit_sCOND (GTU, operands[0]); DONE; }") +(define_expand "sleu" + [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] + "" + "{ rs6000_emit_sCOND (LEU, operands[0]); DONE; }") + (define_expand "sltu" [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] "" "{ rs6000_emit_sCOND (LTU, operands[0]); DONE; }") -(define_expand "sgeu" +(define_expand "sunordered" [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] "" - "{ rs6000_emit_sCOND (GEU, operands[0]); DONE; }") + "{ rs6000_emit_sCOND (UNORDERED, operands[0]); DONE; }") -(define_expand "sleu" +(define_expand "sordered" [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] "" - "{ rs6000_emit_sCOND (LEU, operands[0]); DONE; }") + "{ rs6000_emit_sCOND (ORDERED, operands[0]); DONE; }") + +(define_expand "suneq" + [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] + "" + "{ rs6000_emit_sCOND (UNEQ, operands[0]); DONE; }") + +(define_expand "sunge" + [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] + "" + "{ rs6000_emit_sCOND (UNGE, operands[0]); DONE; }") + +(define_expand "sungt" + [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] + "" + "{ rs6000_emit_sCOND (UNGT, operands[0]); DONE; }") + +(define_expand "sunle" + [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] + "" + "{ rs6000_emit_sCOND (UNLE, operands[0]); DONE; }") + +(define_expand "sunlt" + [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] + "" + "{ rs6000_emit_sCOND (UNLT, operands[0]); DONE; }") + +(define_expand "sltgt" + [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))] + "" + "{ rs6000_emit_sCOND (LTGT, operands[0]); DONE; }") + ;; Here are the actual compare insns. (define_insn "*cmpsi_internal1" @@ -11141,7 +11182,7 @@ [(match_operand 2 "cc_reg_operand" "y") (const_int 0)]))] "" - "%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1" + "mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1" [(set_attr "type" "mfcr") (set_attr "length" "12")]) @@ -11150,7 +11191,7 @@ [(set (match_operand:SI 0 "gpc_reg_operand" "=r") (unspec:SI [(match_operand 1 "cc_reg_operand" "y")] UNSPEC_MV_CR_OV))] "TARGET_ISEL" - "%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%t1,1" + "mfcr %0\;{rlinm|rlwinm} %0,%0,%t1,1" [(set_attr "type" "mfcr") (set_attr "length" "12")]) @@ -11160,7 +11201,7 @@ [(match_operand 2 "cc_reg_operand" "y") (const_int 0)]))] "TARGET_POWERPC64" - "%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1" + "mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1" [(set_attr "type" "mfcr") (set_attr "length" "12")]) @@ -11174,7 +11215,7 @@ (match_op_dup 1 [(match_dup 2) (const_int 0)]))] "! TARGET_POWERPC64" "@ - %D1mfcr %3\;{rlinm.|rlwinm.} %3,%3,%J1,1 + mfcr %3\;{rlinm.|rlwinm.} %3,%3,%J1,1 #" [(set_attr "type" "delayed_compare") (set_attr "length" "12,16")]) @@ -11216,7 +11257,7 @@ operands[4] = GEN_INT (count); operands[5] = GEN_INT (put_bit); - return \"%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%4,%5,%5\"; + return \"mfcr %0\;{rlinm|rlwinm} %0,%0,%4,%5,%5\"; }" [(set_attr "type" "mfcr") (set_attr "length" "12")]) @@ -11251,7 +11292,7 @@ operands[5] = GEN_INT (count); operands[6] = GEN_INT (put_bit); - return \"%D1mfcr %4\;{rlinm.|rlwinm.} %4,%4,%5,%6,%6\"; + return \"mfcr %4\;{rlinm.|rlwinm.} %4,%4,%5,%6,%6\"; }" [(set_attr "type" "delayed_compare") (set_attr "length" "12,16")]) @@ -11289,7 +11330,7 @@ [(match_operand 5 "cc_reg_operand" "y") (const_int 0)]))] "REGNO (operands[2]) != REGNO (operands[5])" - "%D1%D4mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1" + "mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1" [(set_attr "type" "mfcr") (set_attr "length" "20")]) @@ -11303,7 +11344,7 @@ [(match_operand 5 "cc_reg_operand" "y") (const_int 0)]))] "TARGET_POWERPC64 && REGNO (operands[2]) != REGNO (operands[5])" - "%D1%D4mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1" + "mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1" [(set_attr "type" "mfcr") (set_attr "length" "20")]) -- 2.30.2