*** empty log message ***
authorRichard Kenner <kenner@gcc.gnu.org>
Sun, 12 Apr 1992 00:42:12 +0000 (20:42 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Sun, 12 Apr 1992 00:42:12 +0000 (20:42 -0400)
From-SVN: r728

gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md

index 0791082f6b815c7a591e9b1ad14d43216cb1cd59..6a56c93b6c92cc9c5e2fc3ef09b40113a821122c 100644 (file)
@@ -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}},            \
index e9edc98090be939f66605084bd678c96dd6bdfc2..ee49f299f290da379e4874fecb77acbb7b617d6f 100644 (file)
   [(set_attr "type" "compare")])
 \f
 ;; 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")))]
   "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"
    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")))]
   "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")))]
   "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 ""
   "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")