From: Richard Kenner Date: Sun, 12 Apr 1992 00:42:12 +0000 (-0400) Subject: *** empty log message *** X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f357808bc7f02b8254ab1c4fdce84925a150b458;p=gcc.git *** empty log message *** From-SVN: r728 --- diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 0791082f6b8..6a56c93b6c9 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1080,11 +1080,15 @@ struct rs6000_args {int words, fregno, nargs_prototype; }; gen_rtx (CONST_INT, VOIDmode, \ high_int << 16)), 0),\ gen_rtx (CONST_INT, VOIDmode, low_int)); \ + goto WIN; \ } \ else if (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 0)) == REG \ && GET_CODE (XEXP (X, 1)) != CONST_INT) \ - (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \ - force_operand (XEXP (X, 1), 0)); \ + { \ + (X) = gen_rtx (PLUS, SImode, XEXP (X, 0), \ + force_reg (SImode, force_operand (XEXP (X, 1), 0))); \ + goto WIN; \ + } \ } /* Go to LABEL if ADDR (a legitimate address expression) @@ -1814,6 +1818,7 @@ bss_section () \ #define PREDICATE_CODES \ {"short_cint_operand", {CONST_INT}}, \ {"u_short_cint_operand", {CONST_INT}}, \ + {"non_short_cint_operand", {CONST_INT}}, \ {"gen_reg_operand", {SUBREG, REG}}, \ {"cc_reg_operand", {SUBREG, REG}}, \ {"reg_or_short_operand", {SUBREG, REG, CONST_INT}}, \ @@ -1825,8 +1830,11 @@ bss_section () \ {"fp_reg_or_mem_operand", {SUBREG, MEM, REG}}, \ {"mem_or_easy_const_operand", {SUBREG, MEM, CONST_DOUBLE}}, \ {"add_operand", {SUBREG, REG, CONST_INT}}, \ + {"non_add_cint_operand", {CONST_INT}}, \ {"and_operand", {SUBREG, REG, CONST_INT}}, \ + {"non_and_cint_operand", {CONST_INT}}, \ {"logical_operand", {SUBREG, REG, CONST_INT}}, \ + {"non_logical_cint_operand", {CONST_INT}}, \ {"mask_operand", {CONST_INT}}, \ {"call_operand", {SYMBOL_REF, REG}}, \ {"input_operand", {SUBREG, MEM, REG, CONST_INT}}, \ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index e9edc98090b..ee49f299f29 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -165,7 +165,7 @@ [(set_attr "type" "compare")]) ;; Fixed-point arithmetic insns. -(define_insn "" +(define_insn "addsi3" [(set (match_operand:SI 0 "gen_reg_operand" "=r,r") (plus:SI (match_operand:SI 1 "gen_reg_operand" "%r,b") (match_operand:SI 2 "add_operand" "rI,J")))] @@ -195,28 +195,27 @@ "a%I2. %0,%1,%2" [(set_attr "type" "compare")]) -(define_expand "addsi3" +;; Split an add that we can't do in one insn into two insns, each of which +;; does one 16-bit part. This is used by combine. Note that the low-order +;; add should be last in case the result gets used in an address. + +(define_split [(set (match_operand:SI 0 "gen_reg_operand" "") (plus:SI (match_operand:SI 1 "gen_reg_operand" "") - (match_operand:SI 2 "reg_or_cint_operand" "")))] + (match_operand:SI 2 "non_add_cint_operand" "")))] "" - " + [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3))) + (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))] +" { - if (GET_CODE (operands[2]) == CONST_INT - && (unsigned) (INTVAL (operands[2]) + 0x8000) >= 0x10000 - && (INTVAL (operands[2]) & 0xffff) != 0) - { - int low = INTVAL (operands[2]) & 0xffff; - int high = (unsigned) INTVAL (operands[2]) >> 16; + int low = INTVAL (operands[2]) & 0xffff; + int high = (unsigned) INTVAL (operands[2]) >> 16; - if (low & 0x8000) - high++, low |= 0xffff0000; + if (low & 0x8000) + high++, low |= 0xffff0000; - emit_insn (gen_addsi3 (operands[0], operands[1], - gen_rtx (CONST_INT, VOIDmode, high << 16))); - operands[1] = operands[0]; - operands[2] = gen_rtx (CONST_INT, VOIDmode, low); - } + operands[3] = gen_rtx (CONST_INT, VOIDmode, high << 16); + operands[4] = gen_rtx (CONST_INT, VOIDmode, low); }") (define_insn "one_cmplsi2" @@ -657,7 +656,47 @@ rlinm. %0,%1,0,%m2,%M2" [(set_attr "type" "compare,compare,compare,delayed_compare")]) -(define_insn "" +;; Take a AND with a constant that cannot be done in a single insn and try to +;; split it into two insns. This does not verify that the insns are valid +;; since this need not be done as combine will do it. + +(define_split + [(set (match_operand:SI 0 "gen_reg_operand" "") + (and:SI (match_operand:SI 1 "gen_reg_operand" "") + (match_operand:SI 2 "non_and_cint_operand" "")))] + "" + [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 3))) + (set (match_dup 0) (and:SI (match_dup 0) (match_dup 4)))] + " +{ + int maskval = INTVAL (operands[2]); + int i, transitions, last_bit_value; + int orig = maskval, first_c = maskval, second_c; + + /* We know that MASKVAL must have more than 2 bit-transitions. Start at + the low-order bit and count for the third transition. When we get there, + make a first mask that has everything to the left of that position + a one. Then make the second mask to turn off whatever else is needed. */ + + for (i = 1, transitions = 0, last_bit_value = maskval & 1; i < 32; i++) + { + if (((maskval >>= 1) & 1) != last_bit_value) + last_bit_value ^= 1, transitions++; + + if (transitions > 2) + { + first_c |= (~0) << i; + break; + } + } + + second_c = orig | ~ first_c; + + operands[3] = gen_rtx (CONST_INT, VOIDmode, first_c); + operands[4] = gen_rtx (CONST_INT, VOIDmode, second_c); +}") + +(define_insn "iorsi3" [(set (match_operand:SI 0 "gen_reg_operand" "=r,r,r") (ior:SI (match_operand:SI 1 "gen_reg_operand" "%r,r,r") (match_operand:SI 2 "logical_operand" "r,K,J")))] @@ -688,26 +727,24 @@ "or. %0,%1,%2" [(set_attr "type" "compare")]) -(define_expand "iorsi3" +;; Split an IOR that we can't do in one insn into two insns, each of which +;; does one 16-bit part. This is used by combine. + +(define_split [(set (match_operand:SI 0 "gen_reg_operand" "") (ior:SI (match_operand:SI 1 "gen_reg_operand" "") - (match_operand:SI 2 "reg_or_cint_operand" "")))] + (match_operand:SI 2 "non_logical_cint_operand" "")))] "" - " + [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3))) + (set (match_dup 0) (ior:SI (match_dup 0) (match_dup 4)))] +" { - if (GET_CODE (operands[2]) == CONST_INT - && ! logical_operand (operands[2], SImode)) - { - emit_insn (gen_iorsi3 (operands[0], operands[1], - gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]) & 0xffff0000))); - operands[1] = operands[0]; - operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]) & 0xffff); - } + operands[3] = gen_rtx (CONST_INT, VOIDmode, + INTVAL (operands[2]) & 0xffff0000); + operands[4] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff); }") -(define_insn "" +(define_insn "xorsi3" [(set (match_operand:SI 0 "gen_reg_operand" "=r,r,r") (xor:SI (match_operand:SI 1 "gen_reg_operand" "%r,r,r") (match_operand:SI 2 "logical_operand" "r,K,J")))] @@ -738,23 +775,21 @@ "xor. %0,%1,%2" [(set_attr "type" "compare")]) -(define_expand "xorsi3" +;; Split an XOR that we can't do in one insn into two insns, each of which +;; does one 16-bit part. This is used by combine. + +(define_split [(set (match_operand:SI 0 "gen_reg_operand" "") (xor:SI (match_operand:SI 1 "gen_reg_operand" "") - (match_operand:SI 2 "reg_or_cint_operand" "")))] + (match_operand:SI 2 "non_logical_cint_operand" "")))] "" - " + [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 3))) + (set (match_dup 0) (xor:SI (match_dup 0) (match_dup 4)))] +" { - if (GET_CODE (operands[2]) == CONST_INT - && ! logical_operand (operands[2], SImode)) - { - emit_insn (gen_xorsi3 (operands[0], operands[1], - gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]) & 0xffff0000))); - operands[1] = operands[0]; - operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]) & 0xffff); - } + operands[3] = gen_rtx (CONST_INT, VOIDmode, + INTVAL (operands[2]) & 0xffff0000); + operands[4] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) & 0xffff); }") (define_insn "" @@ -3223,6 +3258,34 @@ "cmp%I2 %0,%1,%2" [(set_attr "type" "compare")]) +;; If we are comparing a register for equality with a large constant, +;; we can do this with an XOR followed by a compare. But we need a scratch +;; register for the result of the XOR. + +(define_split + [(set (match_operand:CC 0 "cc_reg_operand" "") + (compare:CC (match_operand:SI 1 "gen_reg_operand" "") + (match_operand:SI 2 "non_short_cint_operand" ""))) + (clobber (match_operand:SI 3 "gen_reg_operand" ""))] + "find_single_use (operands[0], insn, 0) + && (GET_CODE (*find_single_use (operands[0], insn, 0)) == EQ + || GET_CODE (*find_single_use (operands[0], insn, 0)) == NE)" + [(set (match_dup 3) (xor:SI (match_dup 1) (match_dup 4))) + (set (match_dup 0) (compare:CC (match_dup 3) (match_dup 5)))] + " +{ + /* Get the constant we are comparing against, C, and see what it looks like + sign-extended to 16 bits. Then see what constant could be XOR'ed + with C to get the sign-extended value. */ + + int c = INTVAL (operands[2]); + int sextc = (c << 16) >> 16; + int xorv = c ^ sextc; + + operands[4] = gen_rtx (CONST_INT, VOIDmode, xorv); + operands[5] = gen_rtx (CONST_INT, VOIDmode, sextc); +}") + (define_insn "" [(set (match_operand:CCUNS 0 "cc_reg_operand" "=y") (compare:CCUNS (match_operand:SI 1 "gen_reg_operand" "r")