From: Richard Kenner Date: Sun, 5 Apr 1992 22:44:18 +0000 (-0400) Subject: *** empty log message *** X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c5defebb1327cff5dbb383d5cf14d9a719994b16;p=gcc.git *** empty log message *** From-SVN: r691 --- diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 803c4a2bc14..3d8712e2a92 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -516,6 +516,9 @@ scc_comparison_operator (op, mode) && (cc_mode != CCUNSmode)) return 0; + if (cc_mode == CCEQmode && code != EQ && code != NE) + return 0; + return 1; } @@ -607,6 +610,12 @@ ccr_bit (op, scc_p) cc_regnum = REGNO (XEXP (op, 0)); base_bit = 4 * (cc_regnum - 68); + /* In CCEQmode cases we have made sure that the result is always in the + third bit of the CR field. */ + + if (cc_mode == CCEQmode) + return base_bit + 3; + switch (code) { case NE: @@ -817,6 +826,14 @@ print_operand (file, x, code) fprintf (file, "%d", 32 - 4 * (REGNO (x) - 68)); return; + case 'E': + /* X is a CR register. Print the number of the third bit of the CR */ + if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x))) + output_operand_lossage ("invalid %%E value"); + + fprintf(file, "%d", 4 * (REGNO (x) - 68) + 3); + break; + case 'R': /* X is a CR register. Print the mask for `mtcrf'. */ if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x))) diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 0ee28e0a464..8ef2cd06e60 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1245,22 +1245,26 @@ struct rs6000_args {int words, fregno, nargs_prototype; }; /* Add any extra modes needed to represent the condition code. For the RS/6000, we need separate modes when unsigned (logical) comparisons - are being done and we need a separate mode for floating-point. */ + are being done and we need a separate mode for floating-point. We also + use a mode for the case when we are comparing the results of two + comparisons. */ -#define EXTRA_CC_MODES CCUNSmode, CCFPmode +#define EXTRA_CC_MODES CCUNSmode, CCFPmode, CCEQmode /* Define the names for the modes specified above. */ -#define EXTRA_CC_NAMES "CCUNS", "CCFP" +#define EXTRA_CC_NAMES "CCUNS", "CCFP", "CCEQ" /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, return the mode to be used for the comparison. For floating-point, CCFPmode - should be used. CC_NOOVmode should be used when the first operand is a - PLUS, MINUS, or NEG. CCmode should be used when no special processing is - needed. */ + should be used. CCUNSmode should be used for unsigned comparisons. + CCEQmode should be used when we are doing an inequality comparison on + the result of a comparison. CCmode should be used in all other cases. */ + #define SELECT_CC_MODE(OP,X) \ (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CCFPmode \ - : ((OP) == GTU || (OP) == LTU || (OP) == GEU || (OP) == LEU \ - ? CCUNSmode : CCmode)) + : (OP) == GTU || (OP) == LTU || (OP) == GEU || (OP) == LEU ? CCUNSmode \ + : (((OP) == EQ || (OP) == NE) && GET_RTX_CLASS (GET_CODE (X)) == '<' \ + ? CCEQmode : CCmode)) /* Define the information needed to generate branch and scc insns. This is stored from the compare operation. Note that we can't use "rtx" here diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 09da0b7ebb8..e9edc98090b 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -3294,7 +3294,9 @@ ;; way the machine works. ;; ;; Note that this is probably faster if we can put an insn between the -;; mfcr and rlinm, but this is tricky. Let's leave it for now. +;; mfcr and rlinm, but this is tricky. Let's leave it for now. In most +;; cases the insns below which don't use an intermediate CR field will +;; be used instead. (define_insn "" [(set (match_operand:SI 0 "gen_reg_operand" "=r") (match_operator:SI 1 "scc_comparison_operator" @@ -3369,6 +3371,52 @@ }" [(set_attr "type" "delayed_compare")]) +;; If we are comparing the result of two comparisons, this can be done +;; using creqv or crxor. + +(define_insn "" + [(set (match_operand:CCEQ 0 "cc_reg_operand" "=y") + (compare:CCEQ (match_operator 1 "scc_comparison_operator" + [(match_operand 2 "cc_reg_operand" "y") + (const_int 0)]) + (match_operator 3 "scc_comparison_operator" + [(match_operand 4 "cc_reg_operand" "y") + (const_int 0)])))] + "REGNO (operands[2]) != REGNO (operands[4])" + "* +{ + enum rtx_code code1, code2; + + code1 = GET_CODE (operands[1]); + code2 = GET_CODE (operands[3]); + + if ((code1 == EQ || code1 == LT || code1 == GT + || code1 == LTU || code1 == GTU + || (code1 != NE && GET_MODE (operands[2]) == CCFPmode)) + != + (code2 == EQ || code2 == LT || code2 == GT + || code2 == LTU || code2 == GTU + || (code2 != NE && GET_MODE (operands[4]) == CCFPmode))) + return \"%C1%C3crxor %E0,%j1,%j3\"; + else + return \"%C1%C3creqv %E0,%j1,%j3\"; +}") + +;; There is a 3 cycle delay between consecutive mfcr instructions +;; so it is useful to combine 2 scc instructions to use only one mfcr. + +(define_peephole + [(set (match_operand:SI 0 "gen_reg_operand" "=r") + (match_operator:SI 1 "scc_comparison_operator" + [(match_operand 2 "cc_reg_operand" "y") + (const_int 0)])) + (set (match_operand:SI 3 "gen_reg_operand" "=r") + (match_operator:SI 4 "scc_comparison_operator" + [(match_operand 5 "cc_reg_operand" "y") + (const_int 0)]))] + "REGNO (operands[2]) != REGNO (operands[5])" + "%D1%D4mfcr %3\;rlinm %0,%3,%J1,31,31\;rlinm %3,%3,%J4,31,31") + ;; There are some scc insns that can be done directly, without a compare. ;; These are faster because they don't involve the communications between ;; the FXU and branch units. In fact, we will be replacing all of the