ia64.c (reg_or_5bit_operand): New.
authorRichard Henderson <rth@cygnus.com>
Sat, 19 Aug 2000 07:15:08 +0000 (00:15 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Sat, 19 Aug 2000 07:15:08 +0000 (00:15 -0700)
        * config/ia64/ia64.c (reg_or_5bit_operand): New.
        (ia64_depz_field_mask): New.
        * config/ia64/ia64.h (CONSTRAINT_OK_FOR_R): New.
        (PREDICATE_CODES): Update.
        * config/ia64/ia64.md: Update commentary.
        (depz_internal): New.
        (ashlsi3): Implement directly.
        (ashrsi3, lshrsi3): Simplify; rely on extv and extzv for constants.
        (ashldi3): Use shladd.
        * config/ia64/ia64-protos.h: Update.

From-SVN: r35802

gcc/ChangeLog
gcc/config/ia64/ia64-protos.h
gcc/config/ia64/ia64.c
gcc/config/ia64/ia64.h
gcc/config/ia64/ia64.md

index 76a9956e3aed603d85a6ac5080f4936c2c427269..d7ca945af2d3ad5eead08373311f1ece8dc9215e 100644 (file)
@@ -1,3 +1,16 @@
+2000-08-19  Richard Henderson  <rth@cygnus.com>
+
+       * config/ia64/ia64.c (reg_or_5bit_operand): New.
+       (ia64_depz_field_mask): New.
+       * config/ia64/ia64.h (CONSTRAINT_OK_FOR_R): New.
+       (PREDICATE_CODES): Update.
+       * config/ia64/ia64.md: Update commentary.
+       (depz_internal): New.
+       (ashlsi3): Implement directly.
+       (ashrsi3, lshrsi3): Simplify; rely on extv and extzv for constants.
+       (ashldi3): Use shladd.
+       * config/ia64/ia64-protos.h: Update.
+
 2000-08-18  Zack Weinberg  <zack@wolery.cumb.org>
 
        * toplev.c (independent_decode_option): Always process -g.
index af120609ca86391c0f881b1e9d1b349dd69e73e5..180418d94355758dc8858b3f0ec343355f6d2e97 100644 (file)
@@ -35,6 +35,7 @@ extern int function_operand PARAMS((rtx, enum machine_mode));
 extern int setjmp_operand PARAMS((rtx, enum machine_mode));
 extern int move_operand PARAMS((rtx, enum machine_mode));
 extern int reg_or_0_operand PARAMS((rtx, enum machine_mode));
+extern int reg_or_5bit_operand PARAMS((rtx, enum machine_mode));
 extern int reg_or_6bit_operand PARAMS((rtx, enum machine_mode));
 extern int reg_or_8bit_operand PARAMS((rtx, enum machine_mode));
 extern int reg_or_8bit_adjusted_operand PARAMS((rtx, enum machine_mode));
@@ -50,12 +51,6 @@ extern int normal_comparison_operator PARAMS((rtx, enum machine_mode));
 extern int adjusted_comparison_operator PARAMS((rtx, enum machine_mode));
 extern int call_multiple_values_operation PARAMS((rtx, enum machine_mode));
 extern int destination_operand PARAMS((rtx, enum machine_mode));
-extern HOST_WIDE_INT ia64_initial_elimination_offset PARAMS((int, int));
-extern void ia64_expand_prologue PARAMS((void));
-extern void ia64_expand_epilogue PARAMS((void));
-extern void ia64_function_prologue PARAMS((FILE *, int));
-extern void ia64_function_epilogue PARAMS((FILE *, int));
-extern int ia64_direct_return PARAMS((void));
 extern int predicate_operator PARAMS((rtx, enum machine_mode));
 extern int ar_lc_reg_operand PARAMS((rtx, enum machine_mode));
 extern int ar_ccv_reg_operand PARAMS((rtx, enum machine_mode));
@@ -64,10 +59,18 @@ extern int destination_tfmode_operand PARAMS((rtx, enum machine_mode));
 extern int tfreg_or_fp01_operand PARAMS((rtx, enum machine_mode));
 
 extern int ia64_move_ok PARAMS((rtx, rtx));
+extern int ia64_depz_field_mask PARAMS((rtx, rtx));
 extern rtx ia64_gp_save_reg PARAMS((int));
 extern rtx ia64_split_timode PARAMS((rtx[], rtx, rtx));
 extern rtx spill_tfmode_operand PARAMS((rtx, int));
 
+extern HOST_WIDE_INT ia64_initial_elimination_offset PARAMS((int, int));
+extern void ia64_expand_prologue PARAMS((void));
+extern void ia64_expand_epilogue PARAMS((void));
+extern void ia64_function_prologue PARAMS((FILE *, int));
+extern void ia64_function_epilogue PARAMS((FILE *, int));
+
+extern int ia64_direct_return PARAMS((void));
 extern void ia64_expand_load_address PARAMS((rtx, rtx));
 extern void ia64_expand_fetch_and_op PARAMS ((enum fetchop_code,
                                              enum machine_mode, rtx []));
index 0c16cd3a100001c2e24437abab4650f97436926d..3088a82a02830d0ad146ffb7b78c07ac21ce21e0 100644 (file)
@@ -316,6 +316,18 @@ reg_or_0_operand (op, mode)
   return (op == const0_rtx || register_operand (op, mode));
 }
 
+/* Return 1 if OP is a register operand, or a 5 bit immediate operand.  */
+
+int
+reg_or_5bit_operand (op, mode)
+     rtx op;
+     enum machine_mode mode;
+{
+  return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) < 32)
+         || GET_CODE (op) == CONSTANT_P_RTX
+         || register_operand (op, mode));
+}
+
 /* Return 1 if OP is a register operand, or a 6 bit immediate operand.  */
 
 int
@@ -635,6 +647,23 @@ ia64_move_ok (dst, src)
     return GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src);
 }
 
+/* Check if OP is a mask suitible for use with SHIFT in a dep.z instruction.
+   Return the length of the field, or <= 0 on failure.  */
+
+int
+ia64_depz_field_mask (rop, rshift)
+     rtx rop, rshift;
+{
+  unsigned HOST_WIDE_INT op = INTVAL (rop);
+  unsigned HOST_WIDE_INT shift = INTVAL (rshift);
+
+  /* Get rid of the zero bits we're shifting in.  */
+  op >>= shift;
+
+  /* We must now have a solid block of 1's at bit 0.  */
+  return exact_log2 (op + 1);
+}
+
 /* Expand a symbolic constant load.  */
 /* ??? Should generalize this, so that we can also support 32 bit pointers.  */
 
index 90717b8a14d0835033e78aeca47da42dbe5f4b73..c327b6cf4ec4177bd57162a9f29f6666286eb441 100644 (file)
@@ -1108,11 +1108,17 @@ enum reg_class
    letters (`Q', `R', `S', `T', `U') that can be used to segregate specific
    types of operands, usually memory references, for the target machine.  */
 
+/* Non-volatile memory for FP_REG loads/stores.  */
 #define CONSTRAINT_OK_FOR_Q(VALUE) \
   (memory_operand((VALUE), VOIDmode) && ! MEM_VOLATILE_P (VALUE))
+/* 1..4 for shladd arguments.  */
+#define CONSTRAINT_OK_FOR_R(VALUE) \
+  (GET_CODE (VALUE) == CONST_INT && INTVAL (VALUE) >= 1 && INTVAL (VALUE) <= 4)
 
 #define EXTRA_CONSTRAINT(VALUE, C) \
-  ((C) == 'Q' ? CONSTRAINT_OK_FOR_Q (VALUE) : 0)
+  ((C) == 'Q' ? CONSTRAINT_OK_FOR_Q (VALUE)    \
+   : (C) == 'R' ? CONSTRAINT_OK_FOR_R (VALUE)  \
+   : 0)
 \f
 /* Basic Stack Layout */
 
@@ -2639,6 +2645,7 @@ do {                                                                      \
 { "move_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,          \
                     CONSTANT_P_RTX, SYMBOL_REF, CONST, LABEL_REF}},    \
 { "reg_or_0_operand", {SUBREG, REG, CONST_INT}},                       \
+{ "reg_or_5bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}},    \
 { "reg_or_6bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}},    \
 { "reg_or_8bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}},    \
 { "reg_or_8bit_adjusted_operand", {SUBREG, REG, CONST_INT,             \
index 0734936d1e9c01cbf906d4dc8958a36adc3cbb70..e0173e6a34412eaa827adea1e175d3c2d36ba994 100644 (file)
 ;; ::
 ;; ::::::::::::::::::::
 
-;; ??? It would be useful to have SImode versions of the extract and insert
-;; patterns.
-
 (define_insn "extv"
   [(set (match_operand:DI 0 "register_operand" "=r")
        (sign_extract:DI (match_operand:DI 1 "register_operand" "r")
   "dep %0 = %3, %0, %2, %1"
   [(set_attr "type" "I")])
 
+;; Combine doesn't like to create bitfield insertions into zero.
+(define_insn "*depz_internal"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (and:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
+                          (match_operand:DI 2 "const_int_operand" "n"))
+               (match_operand:DI 3 "const_int_operand" "n")))]
+  "CONST_OK_FOR_M (INTVAL (operands[2]))
+   && ia64_depz_field_mask (operands[3], operands[2]) > 0"
+  "*
+{
+  operands[3] = GEN_INT (ia64_depz_field_mask (operands[3], operands[2]));
+  return \"%,dep.z %0 = %1, %2, %3\";
+}"
+  [(set_attr "type" "I")])
+
 (define_insn "shift_mix4left"
   [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
                         (const_int 32) (const_int 0))
   "#"
   [(set_attr "type" "unknown")])
 
-;; ??? Need to emit an instruction group barrier here because this gets split
-;; after md_reorg.
-
 (define_split
   [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "")
                         (const_int 32) (const_int 0))
 ;; ::
 ;; ::::::::::::::::::::
 
-;; There is no sign-extend form of dep, so we only get 32 bits of valid result
-;; instead of 64 like the patterns below.
-
-;; Using a predicate that accepts only constants doesn't work, because optabs
-;; will load the operand into a register and call the pattern if the predicate
-;; did not accept it on the first try.  So we use nonmemory_operand and then
-;; verify that we have an appropriate constant in the expander.
-
-(define_expand "ashlsi3"
-  [(set (match_operand:SI 0 "register_operand" "")
-       (ashift:SI (match_operand:SI 1 "register_operand" "")
-                  (match_operand:SI 2 "nonmemory_operand" "")))]
-  ""
-  "
-{
-  if (! shift_32bit_count_operand (operands[2], SImode))
-    FAIL;
-}")
-
-(define_insn "*ashlsi3_internal"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-       (ashift:SI (match_operand:SI 1 "register_operand" "r")
-                  (match_operand:SI 2 "shift_32bit_count_operand" "n")))]
+(define_insn "ashlsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+       (ashift:SI (match_operand:SI 1 "register_operand" "r,r,r")
+                  (match_operand:SI 2 "reg_or_5bit_operand" "R,n,r")))]
   ""
-  "dep.z %0 = %1, %2, %E2"
-  [(set_attr "type" "I")])
-
-;; This is really an extract, but this is how combine canonicalizes the
-;; operation.
+  "@
+   shladd %0 = %1, %2, r0
+   dep.z %0 = %1, %2, %E2
+   shl %0 = %1, %2"
+  [(set_attr "type" "A,I,I")])
 
 (define_expand "ashrsi3"
-  [(set (match_dup 3)
-       (ashiftrt:DI (sign_extend:DI
-                     (match_operand:SI 1 "register_operand" ""))
-                    (match_operand:DI 2 "nonmemory_operand" "")))
-   (set (match_operand:SI 0 "register_operand" "") (match_dup 4))]
+  [(set (match_operand:SI 0 "register_operand" "")
+       (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
+                    (match_operand:SI 2 "reg_or_5bit_operand" "")))]
   ""
   "
 {
-  if (! shift_32bit_count_operand (operands[2], SImode))
-    FAIL;
-
-  operands[3] = gen_reg_rtx (DImode);
-  operands[4] = gen_lowpart (SImode, operands[3]);
+  rtx subtarget = gen_reg_rtx (DImode);
+  if (GET_CODE (operands[2]) == CONST_INT)
+    emit_insn (gen_extv (subtarget, gen_lowpart (DImode, operands[1]),
+                        GEN_INT (32 - INTVAL (operands[2])), operands[2]));
+  else
+    {
+      emit_insn (gen_extendsidi2 (subtarget, operands[1]));
+      emit_insn (gen_ashrdi3 (subtarget, subtarget,
+                             gen_lowpart (DImode, operands[2])));
+    }
+  emit_move_insn (gen_lowpart (DImode, operands[0]), subtarget);
+  DONE;
 }")
 
-(define_insn "*ashrsi3_internal"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (ashiftrt:DI (sign_extend:DI
-                     (match_operand:SI 1 "register_operand" "r"))
-                    (match_operand:DI 2 "shift_32bit_count_operand" "n")))]
-  ""
-  "extr %0 = %1, %2, %E2"
-  [(set_attr "type" "I")])
-
-;; This is really an extract, but this is how combine canonicalizes the
-;; operation.
-
 (define_expand "lshrsi3"
-  [(set (match_dup 3)
-       (lshiftrt:DI (zero_extend:DI
-                     (match_operand:SI 1 "register_operand" ""))
-                    (match_operand:DI 2 "nonmemory_operand" "")))
-   (set (match_operand:SI 0 "register_operand" "") (match_dup 4))]
+  [(set (match_operand:SI 0 "register_operand" "")
+       (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
+                    (match_operand:SI 2 "reg_or_5bit_operand" "")))]
   ""
   "
 {
-  if (! shift_32bit_count_operand (operands[2], SImode))
-    FAIL;
-
-  operands[3] = gen_reg_rtx (DImode);
-  operands[4] = gen_lowpart (SImode, operands[3]);
+  rtx subtarget = gen_reg_rtx (DImode);
+  if (GET_CODE (operands[2]) == CONST_INT)
+    emit_insn (gen_extzv (subtarget, gen_lowpart (DImode, operands[1]),
+                         GEN_INT (32 - INTVAL (operands[2])), operands[2]));
+  else
+    {
+      emit_insn (gen_zero_extendsidi2 (subtarget, operands[1]));
+      emit_insn (gen_lshrdi3 (subtarget, subtarget,
+                             gen_lowpart (DImode, operands[2])));
+    }
+  emit_move_insn (gen_lowpart (DImode, operands[0]), subtarget);
+  DONE;
 }")
 
-(define_insn "*lshrsi3_internal"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (lshiftrt:DI (zero_extend:DI
-                     (match_operand:SI 1 "register_operand" "r"))
-                    (match_operand:DI 2 "shift_32bit_count_operand" "n")))]
-  ""
-  "extr.u %0 = %1, %2, %E2"
-  [(set_attr "type" "I")])
-
 ;; Use mix4.r/shr to implement rotrsi3.  We only get 32 bits of valid result
 ;; here, instead of 64 like the patterns above.
 
 {
   if (! shift_32bit_count_operand (operands[2], SImode))
     FAIL;
-
   operands[3] = gen_reg_rtx (DImode);
   operands[4] = gen_lowpart (SImode, operands[3]);
 }")
-
 \f
 ;; ::::::::::::::::::::
 ;; ::
 ;; ::::::::::::::::::::
 
 (define_insn "ashldi3"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-       (ashift:DI (match_operand:DI 1 "register_operand" "r")
-                  (match_operand:DI 2 "reg_or_6bit_operand" "rM")))]
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+       (ashift:DI (match_operand:DI 1 "register_operand" "r,r")
+                  (match_operand:DI 2 "reg_or_6bit_operand" "R,rM")))]
   ""
-  "shl %0 = %1, %2"
-  [(set_attr "type" "I")])
+  "@
+   shladd %0 = %1, %2, r0
+   shl %0 = %1, %2"
+  [(set_attr "type" "A,I")])
 
 ;; ??? Maybe combine this with the multiply and add instruction?