Makefile.in (insn-preds.o): Depend on TREE_H.
authorRichard Henderson <rth@redhat.com>
Fri, 13 Aug 2004 19:11:35 +0000 (12:11 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Fri, 13 Aug 2004 19:11:35 +0000 (12:11 -0700)
        * Makefile.in (insn-preds.o): Depend on TREE_H.
        * genpreds.c (write_insn_preds_c): Include tree.h.
        * config/alpha/alpha.c (reg_or_0_operand, reg_or_6bit_operand,
        reg_or_8bit_operand, cint8_operand, add_operand, sext_add_operand,
        const48_operand, and_operand, or_operand, mode_width_operand,
        mode_mask_operand, mul8_operand, const0_operand,
        hard_fp_register_operand, hard_int_register_operand,
        reg_or_cint_operand, some_operand, some_ni_operand, input_operand,
        samegp_function_operand, direct_call_operand, small_symbolic_operand,
        global_symbolic_operand, call_operand, symbolic_operand,
        dtp16_symbolic_operand, dtp32_symbolic_operand,
        gotdtp_symbolic_operand, tp16_symbolic_operand, tp32_symbolic_operand,
        gottp_symbolic_operand, alpha_comparison_operator,
        alpha_zero_comparison_operator, alpha_swapped_comparison_operator,
        signed_comparison_operator, alpha_fp_comparison_operator,
        divmod_operator, fix_operator, aligned_memory_operand,
        unaligned_memory_operand, reg_or_unaligned_mem_operand,
        any_memory_operand, reg_not_elim_operand, normal_memory_operand,
        reg_no_subreg_operand, addition_operation): Move to predicates.md.
        (reg_or_const_int_operand): Remove.  Replace all users with
        reg_or_cint_operand.
        (tls_symbolic_operand_1): Export.  Don't check mode or for CONST.
        (resolve_reload_operand): Split out of aligned_memory_operand.
        * config/alpha/alpha-protos.h: Update for exports.
        * config/alpha/alpha.h (PREDICATE_CODES): Remove.
        * config/alpha/alpha.md: Include predicates.md.
        * config/alpha/predicates.md: New file.

From-SVN: r85953

gcc/ChangeLog
gcc/Makefile.in
gcc/config/alpha/alpha-protos.h
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.h
gcc/config/alpha/alpha.md
gcc/config/alpha/predicates.md [new file with mode: 0644]
gcc/genpreds.c

index ec30892263c563fe7a1d82f8195c145336dc15b5..f6376e36f7ffa3c8f9fd43fd8b537dde3fa7dafe 100644 (file)
@@ -1,3 +1,33 @@
+2004-08-13  Richard Henderson  <rth@redhat.com>
+
+       * Makefile.in (insn-preds.o): Depend on TREE_H.
+       * genpreds.c (write_insn_preds_c): Include tree.h.
+       * config/alpha/alpha.c (reg_or_0_operand, reg_or_6bit_operand,
+       reg_or_8bit_operand, cint8_operand, add_operand, sext_add_operand,
+       const48_operand, and_operand, or_operand, mode_width_operand,
+       mode_mask_operand, mul8_operand, const0_operand,
+       hard_fp_register_operand, hard_int_register_operand,
+       reg_or_cint_operand, some_operand, some_ni_operand, input_operand,
+       samegp_function_operand, direct_call_operand, small_symbolic_operand,
+       global_symbolic_operand, call_operand, symbolic_operand, 
+       dtp16_symbolic_operand, dtp32_symbolic_operand,
+       gotdtp_symbolic_operand, tp16_symbolic_operand, tp32_symbolic_operand,
+       gottp_symbolic_operand, alpha_comparison_operator,
+       alpha_zero_comparison_operator, alpha_swapped_comparison_operator,
+       signed_comparison_operator, alpha_fp_comparison_operator,
+       divmod_operator, fix_operator, aligned_memory_operand,
+       unaligned_memory_operand, reg_or_unaligned_mem_operand,
+       any_memory_operand, reg_not_elim_operand, normal_memory_operand,
+       reg_no_subreg_operand, addition_operation): Move to predicates.md.
+       (reg_or_const_int_operand): Remove.  Replace all users with
+       reg_or_cint_operand.
+       (tls_symbolic_operand_1): Export.  Don't check mode or for CONST.
+       (resolve_reload_operand): Split out of aligned_memory_operand.
+       * config/alpha/alpha-protos.h: Update for exports.
+       * config/alpha/alpha.h (PREDICATE_CODES): Remove.
+       * config/alpha/alpha.md: Include predicates.md.
+       * config/alpha/predicates.md: New file.
+
 2004-08-13  Richard Sandiford  <rsandifo@redhat.com>
 
        * genattrtab.c (insn_ent): Replace insn_code, insn_index and lineno
index c3bbe3ce922eb4f1043c9c2a65201638e37d7f19..1358b01546499bfbf70da6592d9487d85cd46354 100644 (file)
@@ -2350,8 +2350,8 @@ s-preds: $(md_file) genpreds$(build_exeext)
        $(STAMP) s-preds
 
 insn-preds.o : insn-preds.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
-  $(RTL_H) insn-config.h $(RECOG_H) real.h output.h $(FLAGS_H)  function.h \
-  hard-reg-set.h $(RESOURCE_H) $(TM_P_H) toplev.h reload.h
+  $(RTL_H) $(TREE_H) insn-config.h $(RECOG_H) real.h output.h $(FLAGS_H) \
+  function.h hard-reg-set.h $(RESOURCE_H) $(TM_P_H) toplev.h reload.h
 
 GTFILES = $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(CPP_ID_DATA_H) $(host_xm_file_list) \
index 95f1ad25c7c6638bb139731d7f6d14b3b3c52f75..f8fded816ed1b89535dc86c58c44ad32d9e9bfd3 100644 (file)
@@ -121,3 +121,7 @@ extern char * unicosmk_data_section (void);
 extern void unicosmk_output_common (FILE *, const char *, int, int);
 extern int unicosmk_initial_elimination_offset (int, int);
 #endif
+
+extern int some_small_symbolic_operand (rtx, enum machine_mode);
+extern int tls_symbolic_operand_1 (rtx, int, int);
+extern rtx resolve_reload_operand (rtx);
index 701d4cfe696f4429c0dc392959a65faf9f30f855..d9dc759107049bfa17ea2ba66e920f8b8ef4df1c 100644 (file)
@@ -519,527 +519,12 @@ zap_mask (HOST_WIDE_INT value)
   return 1;
 }
 
-/* Returns 1 if OP is either the constant zero or a register.  If a
-   register, it must be in the proper mode unless MODE is VOIDmode.  */
+/* Return true if OP is valid for a particular TLS relocation. 
+   We are already guaranteed that OP is a CONST.  */
 
 int
-reg_or_0_operand (rtx op, enum machine_mode mode)
+tls_symbolic_operand_1 (rtx op, int size, int unspec)
 {
-  return op == CONST0_RTX (mode) || register_operand (op, mode);
-}
-
-/* Return 1 if OP is a constant in the range of 0-63 (for a shift) or
-   any register.  */
-
-int
-reg_or_6bit_operand (rtx op, enum machine_mode mode)
-{
-  return ((GET_CODE (op) == CONST_INT
-          && (unsigned HOST_WIDE_INT) INTVAL (op) < 64)
-         || register_operand (op, mode));
-}
-
-
-/* Return 1 if OP is an 8-bit constant or any register.  */
-
-int
-reg_or_8bit_operand (rtx op, enum machine_mode mode)
-{
-  return ((GET_CODE (op) == CONST_INT
-          && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100)
-         || register_operand (op, mode));
-}
-
-/* Return 1 if OP is a constant or any register.  */
-
-int
-reg_or_const_int_operand (rtx op, enum machine_mode mode)
-{
-  return GET_CODE (op) == CONST_INT || register_operand (op, mode);
-}
-
-/* Return 1 if OP is an 8-bit constant.  */
-
-int
-cint8_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  return ((GET_CODE (op) == CONST_INT
-          && (unsigned HOST_WIDE_INT) INTVAL (op) < 0x100));
-}
-
-/* Return 1 if the operand is a valid second operand to an add insn.  */
-
-int
-add_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) == CONST_INT)
-    /* Constraints I, J, O and P are covered by K.  */
-    return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K')
-           || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
-
-  return register_operand (op, mode);
-}
-
-/* Return 1 if the operand is a valid second operand to a sign-extending
-   add insn.  */
-
-int
-sext_add_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) == CONST_INT)
-    return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
-           || CONST_OK_FOR_LETTER_P (INTVAL (op), 'O'));
-
-  return reg_not_elim_operand (op, mode);
-}
-
-/* Return 1 if OP is the constant 4 or 8.  */
-
-int
-const48_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  return (GET_CODE (op) == CONST_INT
-         && (INTVAL (op) == 4 || INTVAL (op) == 8));
-}
-
-/* Return 1 if OP is a valid first operand to an AND insn.  */
-
-int
-and_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode)
-    return (zap_mask (CONST_DOUBLE_LOW (op))
-           && zap_mask (CONST_DOUBLE_HIGH (op)));
-
-  if (GET_CODE (op) == CONST_INT)
-    return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
-           || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100
-           || zap_mask (INTVAL (op)));
-
-  return register_operand (op, mode);
-}
-
-/* Return 1 if OP is a valid first operand to an IOR or XOR insn.  */
-
-int
-or_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) == CONST_INT)
-    return ((unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
-           || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100);
-
-  return register_operand (op, mode);
-}
-
-/* Return 1 if OP is a constant that is the width, in bits, of an integral
-   mode smaller than DImode.  */
-
-int
-mode_width_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  return (GET_CODE (op) == CONST_INT
-         && (INTVAL (op) == 8 || INTVAL (op) == 16
-             || INTVAL (op) == 32 || INTVAL (op) == 64));
-}
-
-/* Return 1 if OP is a constant that is the width of an integral machine mode
-   smaller than an integer.  */
-
-int
-mode_mask_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  if (GET_CODE (op) == CONST_INT)
-    {
-      HOST_WIDE_INT value = INTVAL (op);
-
-      if (value == 0xff)
-       return 1;
-      if (value == 0xffff)
-       return 1;
-      if (value == 0xffffffff)
-       return 1;
-      if (value == -1)
-       return 1;
-    }
-  else if (HOST_BITS_PER_WIDE_INT == 32 && GET_CODE (op) == CONST_DOUBLE)
-    {
-      if (CONST_DOUBLE_LOW (op) == 0xffffffff && CONST_DOUBLE_HIGH (op) == 0)
-       return 1;
-    }
-
-  return 0;
-}
-
-/* Return 1 if OP is a multiple of 8 less than 64.  */
-
-int
-mul8_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  return (GET_CODE (op) == CONST_INT
-         && (unsigned HOST_WIDE_INT) INTVAL (op) < 64
-         && (INTVAL (op) & 7) == 0);
-}
-
-/* Return 1 if OP is the zero constant for MODE.  */
-
-int
-const0_operand (rtx op, enum machine_mode mode)
-{
-  return op == CONST0_RTX (mode);
-}
-
-/* Return 1 if OP is a hard floating-point register.  */
-
-int
-hard_fp_register_operand (rtx op, enum machine_mode mode)
-{
-  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
-    return 0;
-
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  return GET_CODE (op) == REG && REGNO_REG_CLASS (REGNO (op)) == FLOAT_REGS;
-}
-
-/* Return 1 if OP is a hard general register.  */
-
-int
-hard_int_register_operand (rtx op, enum machine_mode mode)
-{
-  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
-    return 0;
-
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-  return GET_CODE (op) == REG && REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS;
-}
-
-/* Return 1 if OP is a register or a constant integer.  */
-
-
-int
-reg_or_cint_operand (rtx op, enum machine_mode mode)
-{
-     return (GET_CODE (op) == CONST_INT
-            || register_operand (op, mode));
-}
-
-/* Return 1 if OP is something that can be reloaded into a register;
-   if it is a MEM, it need not be valid.  */
-
-int
-some_operand (rtx op, enum machine_mode mode)
-{
-  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
-    return 0;
-
-  switch (GET_CODE (op))
-    {
-    case REG:
-    case MEM:
-    case CONST_INT:
-    case CONST_DOUBLE:
-    case CONST_VECTOR:
-    case LABEL_REF:
-    case SYMBOL_REF:
-    case CONST:
-    case HIGH:
-      return 1;
-
-    case SUBREG:
-      return some_operand (SUBREG_REG (op), VOIDmode);
-
-    default:
-      break;
-    }
-
-  return 0;
-}
-
-/* Likewise, but don't accept constants.  */
-
-int
-some_ni_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_MODE (op) != mode && mode != VOIDmode)
-    return 0;
-
-  if (GET_CODE (op) == SUBREG)
-    op = SUBREG_REG (op);
-
-  return (GET_CODE (op) == REG || GET_CODE (op) == MEM);
-}
-
-/* Return 1 if OP is a valid operand for the source of a move insn.  */
-
-int
-input_operand (rtx op, enum machine_mode mode)
-{
-  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
-    return 0;
-
-  if (GET_MODE_CLASS (mode) == MODE_FLOAT && GET_MODE (op) != mode)
-    return 0;
-
-  switch (GET_CODE (op))
-    {
-    case LABEL_REF:
-    case SYMBOL_REF:
-    case CONST:
-      if (TARGET_EXPLICIT_RELOCS)
-       {
-         /* We don't split symbolic operands into something unintelligable
-            until after reload, but we do not wish non-small, non-global
-            symbolic operands to be reconstructed from their high/lo_sum
-            form.  */
-         return (small_symbolic_operand (op, mode)
-                 || global_symbolic_operand (op, mode)
-                 || gotdtp_symbolic_operand (op, mode)
-                 || gottp_symbolic_operand (op, mode));
-       }
-
-      /* This handles both the Windows/NT and OSF cases.  */
-      return mode == ptr_mode || mode == DImode;
-
-    case HIGH:
-      return (TARGET_EXPLICIT_RELOCS
-             && local_symbolic_operand (XEXP (op, 0), mode));
-
-    case REG:
-      return 1;
-
-    case SUBREG:
-      if (register_operand (op, mode))
-       return 1;
-      /* ... fall through ...  */
-    case MEM:
-      return ((TARGET_BWX || (mode != HImode && mode != QImode))
-             && general_operand (op, mode));
-
-    case CONST_DOUBLE:
-    case CONST_VECTOR:
-      return op == CONST0_RTX (mode);
-
-    case CONST_INT:
-      return mode == QImode || mode == HImode || add_operand (op, mode);
-
-    default:
-      break;
-    }
-
-  return 0;
-}
-
-/* Return 1 if OP is a SYMBOL_REF for a function known to be in this
-   file, and in the same section as the current function.  */
-
-int
-samegp_function_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  if (GET_CODE (op) != SYMBOL_REF)
-    return false;
-
-  /* Easy test for recursion.  */
-  if (op == XEXP (DECL_RTL (current_function_decl), 0))
-    return true;
-
-  /* Functions that are not local can be overridden, and thus may
-     not share the same gp.  */
-  if (! SYMBOL_REF_LOCAL_P (op))
-    return false;
-
-  /* If -msmall-data is in effect, assume that there is only one GP
-     for the module, and so any local symbol has this property.  We
-     need explicit relocations to be able to enforce this for symbols
-     not defined in this unit of translation, however.  */
-  if (TARGET_EXPLICIT_RELOCS && TARGET_SMALL_DATA)
-    return true;
-
-  /* Functions that are not external are defined in this UoT,
-     and thus must share the same gp.  */
-  return ! SYMBOL_REF_EXTERNAL_P (op);
-}
-
-/* Return 1 if OP is a SYMBOL_REF for which we can make a call via bsr.  */
-
-int
-direct_call_operand (rtx op, enum machine_mode mode)
-{
-  tree op_decl, cfun_sec, op_sec;
-
-  /* Must share the same GP.  */
-  if (!samegp_function_operand (op, mode))
-    return false;
-
-  /* If profiling is implemented via linker tricks, we can't jump
-     to the nogp alternate entry point.  Note that current_function_profile
-     would not be correct, since that doesn't indicate if the target
-     function uses profiling.  */
-  /* ??? TARGET_PROFILING_NEEDS_GP isn't really the right test,
-     but is approximately correct for the OSF ABIs.  Don't know
-     what to do for VMS, NT, or UMK.  */
-  if (!TARGET_PROFILING_NEEDS_GP && profile_flag)
-    return false;
-
-  /* Must be a function.  In some cases folks create thunks in static
-     data structures and then make calls to them.  If we allow the
-     direct call, we'll get an error from the linker about !samegp reloc
-     against a symbol without a .prologue directive.  */
-  if (!SYMBOL_REF_FUNCTION_P (op))
-    return false;
-  
-  /* Must be "near" so that the branch is assumed to reach.  With
-     -msmall-text, this is assumed true of all local symbols.  Since
-     we've already checked samegp, locality is already assured.  */
-  if (TARGET_SMALL_TEXT)
-    return true;
-
-  /* Otherwise, a decl is "near" if it is defined in the same section.  */
-  if (flag_function_sections)
-    return false;
-
-  op_decl = SYMBOL_REF_DECL (op);
-  if (DECL_ONE_ONLY (current_function_decl)
-      || (op_decl && DECL_ONE_ONLY (op_decl)))
-    return false;
-
-  cfun_sec = DECL_SECTION_NAME (current_function_decl);
-  op_sec = op_decl ? DECL_SECTION_NAME (op_decl) : NULL;
-  return ((!cfun_sec && !op_sec)
-         || (cfun_sec && op_sec
-             && strcmp (TREE_STRING_POINTER (cfun_sec),
-                        TREE_STRING_POINTER (op_sec)) == 0));
-}
-
-/* Return true if OP is a LABEL_REF, or SYMBOL_REF or CONST referencing
-   a (non-tls) variable known to be defined in this file.  */
-
-int
-local_symbolic_operand (rtx op, enum machine_mode mode)
-{
-  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
-    return 0;
-
-  if (GET_CODE (op) == LABEL_REF)
-    return 1;
-
-  if (GET_CODE (op) == CONST
-      && GET_CODE (XEXP (op, 0)) == PLUS
-      && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
-    op = XEXP (XEXP (op, 0), 0);
-
-  if (GET_CODE (op) != SYMBOL_REF)
-    return 0;
-
-  return SYMBOL_REF_LOCAL_P (op) && !SYMBOL_REF_TLS_MODEL (op);
-}
-
-/* Return true if OP is a SYMBOL_REF or CONST referencing a variable
-   known to be defined in this file in the small data area.  */
-
-int
-small_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  if (! TARGET_SMALL_DATA)
-    return 0;
-
-  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
-    return 0;
-
-  if (GET_CODE (op) == CONST
-      && GET_CODE (XEXP (op, 0)) == PLUS
-      && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
-    op = XEXP (XEXP (op, 0), 0);
-
-  if (GET_CODE (op) != SYMBOL_REF)
-    return 0;
-
-  /* ??? There's no encode_section_info equivalent for the rtl
-     constant pool, so SYMBOL_FLAG_SMALL never gets set.  */
-  if (CONSTANT_POOL_ADDRESS_P (op))
-    return GET_MODE_SIZE (get_pool_mode (op)) <= g_switch_value;
-
-  return (SYMBOL_REF_LOCAL_P (op)
-         && SYMBOL_REF_SMALL_P (op)
-         && SYMBOL_REF_TLS_MODEL (op) == 0);
-}
-
-/* Return true if OP is a SYMBOL_REF or CONST referencing a variable
-   not known (or known not) to be defined in this file.  */
-
-int
-global_symbolic_operand (rtx op, enum machine_mode mode)
-{
-  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
-    return 0;
-
-  if (GET_CODE (op) == CONST
-      && GET_CODE (XEXP (op, 0)) == PLUS
-      && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
-    op = XEXP (XEXP (op, 0), 0);
-
-  if (GET_CODE (op) != SYMBOL_REF)
-    return 0;
-
-  return !SYMBOL_REF_LOCAL_P (op) && !SYMBOL_REF_TLS_MODEL (op);
-}
-
-/* Return 1 if OP is a valid operand for the MEM of a CALL insn.  */
-
-int
-call_operand (rtx op, enum machine_mode mode)
-{
-  if (mode != Pmode)
-    return 0;
-
-  if (GET_CODE (op) == REG)
-    {
-      if (TARGET_ABI_OSF)
-       {
-         /* Disallow virtual registers to cope with pathological test cases
-            such as compile/930117-1.c in which the virtual reg decomposes
-            to the frame pointer.  Which is a hard reg that is not $27.  */
-         return (REGNO (op) == 27 || REGNO (op) > LAST_VIRTUAL_REGISTER);
-       }
-      else
-       return 1;
-    }
-  if (TARGET_ABI_UNICOSMK)
-    return 0;
-  if (GET_CODE (op) == SYMBOL_REF)
-    return 1;
-
-  return 0;
-}
-
-/* Returns 1 if OP is a symbolic operand, i.e. a symbol_ref or a label_ref,
-   possibly with an offset.  */
-
-int
-symbolic_operand (rtx op, enum machine_mode mode)
-{
-  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
-    return 0;
-  if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
-    return 1;
-  if (GET_CODE (op) == CONST
-      && GET_CODE (XEXP (op,0)) == PLUS
-      && GET_CODE (XEXP (XEXP (op,0), 0)) == SYMBOL_REF
-      && GET_CODE (XEXP (XEXP (op,0), 1)) == CONST_INT)
-    return 1;
-  return 0;
-}
-
-/* Return true if OP is valid for a particular TLS relocation.  */
-
-static int
-tls_symbolic_operand_1 (rtx op, enum machine_mode mode, int size, int unspec)
-{
-  if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
-    return 0;
-
-  if (GET_CODE (op) != CONST)
-    return 0;
   op = XEXP (op, 0);
 
   if (GET_CODE (op) != UNSPEC || XINT (op, 1) != unspec)
@@ -1073,203 +558,12 @@ tls_symbolic_operand_1 (rtx op, enum machine_mode mode, int size, int unspec)
     }
 }
 
-/* Return true if OP is valid for 16-bit DTP relative relocations.  */
-
-int
-dtp16_symbolic_operand (rtx op, enum machine_mode mode)
-{
-  return tls_symbolic_operand_1 (op, mode, 16, UNSPEC_DTPREL);
-}
-
-/* Return true if OP is valid for 32-bit DTP relative relocations.  */
-
-int
-dtp32_symbolic_operand (rtx op, enum machine_mode mode)
-{
-  return tls_symbolic_operand_1 (op, mode, 32, UNSPEC_DTPREL);
-}
-
-/* Return true if OP is valid for 64-bit DTP relative relocations.  */
-
-int
-gotdtp_symbolic_operand (rtx op, enum machine_mode mode)
-{
-  return tls_symbolic_operand_1 (op, mode, 64, UNSPEC_DTPREL);
-}
-
-/* Return true if OP is valid for 16-bit TP relative relocations.  */
-
-int
-tp16_symbolic_operand (rtx op, enum machine_mode mode)
-{
-  return tls_symbolic_operand_1 (op, mode, 16, UNSPEC_TPREL);
-}
-
-/* Return true if OP is valid for 32-bit TP relative relocations.  */
-
-int
-tp32_symbolic_operand (rtx op, enum machine_mode mode)
-{
-  return tls_symbolic_operand_1 (op, mode, 32, UNSPEC_TPREL);
-}
-
-/* Return true if OP is valid for 64-bit TP relative relocations.  */
-
-int
-gottp_symbolic_operand (rtx op, enum machine_mode mode)
-{
-  return tls_symbolic_operand_1 (op, mode, 64, UNSPEC_TPREL);
-}
-
-/* Return 1 if OP is a valid Alpha comparison operator.  Here we know which
-   comparisons are valid in which insn.  */
-
-int
-alpha_comparison_operator (rtx op, enum machine_mode mode)
-{
-  enum rtx_code code = GET_CODE (op);
-
-  if (mode != GET_MODE (op) && mode != VOIDmode)
-    return 0;
-
-  return (code == EQ || code == LE || code == LT
-         || code == LEU || code == LTU);
-}
-
-/* Return 1 if OP is a valid Alpha comparison operator against zero. 
-   Here we know which comparisons are valid in which insn.  */
-
-int
-alpha_zero_comparison_operator (rtx op, enum machine_mode mode)
-{
-  enum rtx_code code = GET_CODE (op);
-
-  if (mode != GET_MODE (op) && mode != VOIDmode)
-    return 0;
-
-  return (code == EQ || code == NE || code == LE || code == LT
-         || code == LEU || code == LTU);
-}
-
-/* Return 1 if OP is a valid Alpha swapped comparison operator.  */
-
-int
-alpha_swapped_comparison_operator (rtx op, enum machine_mode mode)
-{
-  enum rtx_code code;
-
-  if ((mode != GET_MODE (op) && mode != VOIDmode)
-      || !COMPARISON_P (op))
-    return 0;
-
-  code = swap_condition (GET_CODE (op));
-  return (code == EQ || code == LE || code == LT
-         || code == LEU || code == LTU);
-}
-
-/* Return 1 if OP is a signed comparison operation.  */
-
-int
-signed_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  enum rtx_code code = GET_CODE (op);
-
-  if (mode != GET_MODE (op) && mode != VOIDmode)
-    return 0;
-
-  return (code == EQ || code == NE
-         || code == LE || code == LT
-         || code == GE || code == GT);
-}
-
-/* Return 1 if OP is a valid Alpha floating point comparison operator.
-   Here we know which comparisons are valid in which insn.  */
-
-int
-alpha_fp_comparison_operator (rtx op, enum machine_mode mode)
-{
-  enum rtx_code code = GET_CODE (op);
-
-  if (mode != GET_MODE (op) && mode != VOIDmode)
-    return 0;
-
-  return (code == EQ || code == LE || code == LT || code == UNORDERED);
-}
-
-/* Return 1 if this is a divide or modulus operator.  */
-
-int
-divmod_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  enum rtx_code code = GET_CODE (op);
-
-  return (code == DIV || code == MOD || code == UDIV || code == UMOD);
-}
-
-/* Return 1 if this is a float->int conversion operator.  */
-
-int
-fix_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  enum rtx_code code = GET_CODE (op);
-
-  return (code == FIX || code == UNSIGNED_FIX);
-}
-
-/* Return 1 if this memory address is a known aligned register plus
-   a constant.  It must be a valid address.  This means that we can do
-   this as an aligned reference plus some offset.
-
-   Take into account what reload will do.  */
-
-int
-aligned_memory_operand (rtx op, enum machine_mode mode)
-{
-  rtx base;
-
-  if (reload_in_progress)
-    {
-      rtx tmp = op;
-      if (GET_CODE (tmp) == SUBREG)
-       tmp = SUBREG_REG (tmp);
-      if (GET_CODE (tmp) == REG
-         && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
-       {
-         op = reg_equiv_memory_loc[REGNO (tmp)];
-         if (op == 0)
-           return 0;
-       }
-    }
-
-  if (GET_CODE (op) != MEM)
-    return 0;
-  if (MEM_ALIGN (op) >= 32)
-    return 1;
-  op = XEXP (op, 0);
-
-  /* LEGITIMIZE_RELOAD_ADDRESS creates (plus (plus reg const_hi) const_lo)
-     sorts of constructs.  Dig for the real base register.  */
-  if (reload_in_progress
-      && GET_CODE (op) == PLUS
-      && GET_CODE (XEXP (op, 0)) == PLUS)
-    base = XEXP (XEXP (op, 0), 0);
-  else
-    {
-      if (! memory_address_p (mode, op))
-       return 0;
-      base = (GET_CODE (op) == PLUS ? XEXP (op, 0) : op);
-    }
-
-  return (GET_CODE (base) == REG && REGNO_POINTER_ALIGN (REGNO (base)) >= 32);
-}
-
-/* Similar, but return 1 if OP is a MEM which is not alignable.  */
+/* Used by aligned_memory_operand and unaligned_memory_operand to
+   resolve what reload is going to do with OP if it's a register.  */
 
-int
-unaligned_memory_operand (rtx op, enum machine_mode mode)
+rtx
+resolve_reload_operand (rtx op)
 {
-  rtx base;
-
   if (reload_in_progress)
     {
       rtx tmp = op;
@@ -1283,128 +577,7 @@ unaligned_memory_operand (rtx op, enum machine_mode mode)
            return 0;
        }
     }
-
-  if (GET_CODE (op) != MEM)
-    return 0;
-  if (MEM_ALIGN (op) >= 32)
-    return 0;
-  op = XEXP (op, 0);
-
-  /* LEGITIMIZE_RELOAD_ADDRESS creates (plus (plus reg const_hi) const_lo)
-     sorts of constructs.  Dig for the real base register.  */
-  if (reload_in_progress
-      && GET_CODE (op) == PLUS
-      && GET_CODE (XEXP (op, 0)) == PLUS)
-    base = XEXP (XEXP (op, 0), 0);
-  else
-    {
-      if (! memory_address_p (mode, op))
-       return 0;
-      base = (GET_CODE (op) == PLUS ? XEXP (op, 0) : op);
-    }
-
-  return (GET_CODE (base) == REG && REGNO_POINTER_ALIGN (REGNO (base)) < 32);
-}
-
-/* Return 1 if OP is either a register or an unaligned memory location.  */
-
-int
-reg_or_unaligned_mem_operand (rtx op, enum machine_mode mode)
-{
-  return register_operand (op, mode) || unaligned_memory_operand (op, mode);
-}
-
-/* Return 1 if OP is any memory location.  During reload a pseudo matches.  */
-
-int
-any_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  return (GET_CODE (op) == MEM
-         || (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
-         || (reload_in_progress && GET_CODE (op) == REG
-             && REGNO (op) >= FIRST_PSEUDO_REGISTER)
-         || (reload_in_progress && GET_CODE (op) == SUBREG
-             && GET_CODE (SUBREG_REG (op)) == REG
-             && REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER));
-}
-
-/* Returns 1 if OP is not an eliminable register.
-
-   This exists to cure a pathological abort in the s8addq (et al) patterns,
-
-       long foo () { long t; bar(); return (long) &t * 26107; }
-
-   which run afoul of a hack in reload to cure a (presumably) similar
-   problem with lea-type instructions on other targets.  But there is
-   one of us and many of them, so work around the problem by selectively
-   preventing combine from making the optimization.  */
-
-int
-reg_not_elim_operand (rtx op, enum machine_mode mode)
-{
-  rtx inner = op;
-  if (GET_CODE (op) == SUBREG)
-    inner = SUBREG_REG (op);
-  if (inner == frame_pointer_rtx || inner == arg_pointer_rtx)
-    return 0;
-
-  return register_operand (op, mode);
-}
-
-/* Return 1 is OP is a memory location that is not a reference (using
-   an AND) to an unaligned location.  Take into account what reload
-   will do.  */
-
-int
-normal_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-  if (reload_in_progress)
-    {
-      rtx tmp = op;
-      if (GET_CODE (tmp) == SUBREG)
-       tmp = SUBREG_REG (tmp);
-      if (GET_CODE (tmp) == REG
-         && REGNO (tmp) >= FIRST_PSEUDO_REGISTER)
-       {
-         op = reg_equiv_memory_loc[REGNO (tmp)];
-
-         /* This may not have been assigned an equivalent address if it will
-            be eliminated.  In that case, it doesn't matter what we do.  */
-         if (op == 0)
-           return 1;
-       }
-    }
-
-  return GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) != AND;
-}
-
-/* Accept a register, but not a subreg of any kind.  This allows us to
-   avoid pathological cases in reload wrt data movement common in 
-   int->fp conversion.  */
-
-int
-reg_no_subreg_operand (rtx op, enum machine_mode mode)
-{
-  if (GET_CODE (op) != REG)
-    return 0;
-  return register_operand (op, mode);
-}
-
-/* Recognize an addition operation that includes a constant.  Used to
-   convince reload to canonize (plus (plus reg c1) c2) during register
-   elimination.  */
-
-int
-addition_operation (rtx op, enum machine_mode mode)
-{
-  if (GET_MODE (op) != mode && mode != VOIDmode)
-    return 0;
-  if (GET_CODE (op) == PLUS
-      && register_operand (XEXP (op, 0), mode)
-      && GET_CODE (XEXP (op, 1)) == CONST_INT
-      && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op, 1)), 'K'))
-    return 1;
-  return 0;
+  return op;
 }
 
 /* Implements CONST_OK_FOR_LETTER_P.  Return true if the value matches
@@ -1984,6 +1157,10 @@ alpha_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
    small symbolic operand until after reload.  At which point we need
    to replace (mem (symbol_ref)) with (mem (lo_sum $29 symbol_ref))
    so that sched2 has the proper dependency information.  */
+/* 
+  {"some_small_symbolic_operand", {SET, PARALLEL, PREFETCH, UNSPEC,    \
+                                  UNSPEC_VOLATILE}},
+*/
 
 static int
 some_small_symbolic_operand_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
index 15b3a09d7a8f550356851e8801b0f9472d4d091c..43cdfff7f2a825ffb5dcf25162e4e7f38b47499b 100644 (file)
@@ -1609,68 +1609,11 @@ do {                                            \
 #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
   ((CODE) == '/' || (CODE) == ',' || (CODE) == '-' || (CODE) == '~' \
    || (CODE) == '#' || (CODE) == '*' || (CODE) == '&' || (CODE) == '+')
-\f
+
 /* Print a memory address as an operand to reference that memory location.  */
 
 #define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
   print_operand_address((FILE), (ADDR))
-
-/* Define the codes that are matched by predicates in alpha.c.  */
-
-#define PREDICATE_CODES                                                \
-  {"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE,          \
-                       CONST_VECTOR}},                                 \
-  {"reg_or_6bit_operand", {SUBREG, REG, CONST_INT}},                   \
-  {"reg_or_8bit_operand", {SUBREG, REG, CONST_INT}},                   \
-  {"reg_or_const_int_operand", {SUBREG, REG, CONST_INT}},              \
-  {"cint8_operand", {CONST_INT}},                                      \
-  {"reg_or_cint_operand", {SUBREG, REG, CONST_INT}},                   \
-  {"add_operand", {SUBREG, REG, CONST_INT}},                           \
-  {"sext_add_operand", {SUBREG, REG, CONST_INT}},                      \
-  {"const48_operand", {CONST_INT}},                                    \
-  {"and_operand", {SUBREG, REG, CONST_INT}},                           \
-  {"or_operand", {SUBREG, REG, CONST_INT}},                            \
-  {"mode_mask_operand", {CONST_INT}},                                  \
-  {"mul8_operand", {CONST_INT}},                                       \
-  {"mode_width_operand", {CONST_INT}},                                 \
-  {"alpha_comparison_operator", {EQ, LE, LT, LEU, LTU}},               \
-  {"alpha_zero_comparison_operator", {EQ, NE, LE, LT, LEU, LTU}},      \
-  {"alpha_swapped_comparison_operator", {EQ, GE, GT, GEU, GTU}},       \
-  {"signed_comparison_operator", {EQ, NE, LE, LT, GE, GT}},            \
-  {"alpha_fp_comparison_operator", {EQ, LE, LT, UNORDERED}},           \
-  {"divmod_operator", {DIV, MOD, UDIV, UMOD}},                         \
-  {"fix_operator", {FIX, UNSIGNED_FIX}},                               \
-  {"const0_operand", {CONST_INT, CONST_DOUBLE, CONST_VECTOR}},         \
-  {"samegp_function_operand", {SYMBOL_REF}},                           \
-  {"direct_call_operand", {SYMBOL_REF}},                               \
-  {"local_symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}},          \
-  {"small_symbolic_operand", {SYMBOL_REF, CONST}},                     \
-  {"global_symbolic_operand", {SYMBOL_REF, CONST}},                    \
-  {"dtp16_symbolic_operand", {CONST}},                                 \
-  {"dtp32_symbolic_operand", {CONST}},                                 \
-  {"gotdtp_symbolic_operand", {CONST}},                                        \
-  {"tp16_symbolic_operand", {CONST}},                                  \
-  {"tp32_symbolic_operand", {CONST}},                                  \
-  {"gottp_symbolic_operand", {CONST}},                                 \
-  {"call_operand", {REG, SYMBOL_REF}},                                 \
-  {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,                \
-                    CONST_VECTOR, SYMBOL_REF, CONST, LABEL_REF, HIGH}},\
-  {"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,         \
-                   CONST_VECTOR, SYMBOL_REF, CONST, LABEL_REF, HIGH}}, \
-  {"some_ni_operand", {SUBREG, REG, MEM}},                             \
-  {"aligned_memory_operand", {MEM}},                                   \
-  {"unaligned_memory_operand", {MEM}},                                 \
-  {"reg_or_unaligned_mem_operand", {SUBREG, REG, MEM}},                        \
-  {"any_memory_operand", {MEM}},                                       \
-  {"normal_memory_operand", {MEM}},                                    \
-  {"hard_fp_register_operand", {SUBREG, REG}},                         \
-  {"hard_int_register_operand", {SUBREG, REG}},                                \
-  {"reg_not_elim_operand", {SUBREG, REG}},                             \
-  {"reg_no_subreg_operand", {REG}},                                    \
-  {"addition_operation", {PLUS}},                                      \
-  {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},                        \
-  {"some_small_symbolic_operand", {SET, PARALLEL, PREFETCH, UNSPEC,    \
-                                  UNSPEC_VOLATILE}},
 \f
 /* Implement `va_start' for varargs and stdarg.  */
 #define EXPAND_BUILTIN_VA_START(valist, nextarg) \
index df2f0233fcb3e119f858947dc66494afe90002fb..4efff7ca220d7d60498f5805ddb0052f6e64f80a 100644 (file)
 (include "ev4.md")
 (include "ev5.md")
 (include "ev6.md")
+
+\f
+;; Include predicate definitions
+
+(include "predicates.md")
+
 \f
 ;; First define the arithmetic insns.  Note that the 32-bit forms also
 ;; sign-extend.
 (define_expand "builtin_zap"
   [(set (match_operand:DI 0 "register_operand" "")
        (and:DI (unspec:DI
-                 [(match_operand:DI 2 "reg_or_const_int_operand" "")]
+                 [(match_operand:DI 2 "reg_or_cint_operand" "")]
                  UNSPEC_ZAP)
-               (match_operand:DI 1 "reg_or_const_int_operand" "")))]
+               (match_operand:DI 1 "reg_or_cint_operand" "")))]
   ""
 {
   if (GET_CODE (operands[2]) == CONST_INT)
 (define_insn "*builtin_zap_1"
   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
        (and:DI (unspec:DI
-                 [(match_operand:QI 2 "reg_or_const_int_operand" "n,n,r,r")]
+                 [(match_operand:QI 2 "reg_or_cint_operand" "n,n,r,r")]
                  UNSPEC_ZAP)
-               (match_operand:DI 1 "reg_or_const_int_operand" "n,r,J,r")))]
+               (match_operand:DI 1 "reg_or_cint_operand" "n,r,J,r")))]
   ""
   "@
    #
 (define_expand "builtin_zapnot"
   [(set (match_operand:DI 0 "register_operand" "")
        (and:DI (unspec:DI
-                 [(not:QI (match_operand:DI 2 "reg_or_const_int_operand" ""))]
+                 [(not:QI (match_operand:DI 2 "reg_or_cint_operand" ""))]
                  UNSPEC_ZAP)
-               (match_operand:DI 1 "reg_or_const_int_operand" "")))]
+               (match_operand:DI 1 "reg_or_cint_operand" "")))]
   ""
 {
   if (GET_CODE (operands[2]) == CONST_INT)
diff --git a/gcc/config/alpha/predicates.md b/gcc/config/alpha/predicates.md
new file mode 100644 (file)
index 0000000..56486bc
--- /dev/null
@@ -0,0 +1,552 @@
+;; Predicate definitions for DEC Alpha.
+;; Copyright (C) 2004 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING.  If not, write to
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;; Return 1 if OP is the zero constant for MODE.
+(define_predicate "const0_operand"
+  (and (match_code "const_int,const_double,const_vector")
+       (match_test "op == CONST0_RTX (mode)")))
+
+;; Returns true if OP is either the constant zero or a register.
+(define_predicate "reg_or_0_operand"
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "const0_operand")))
+
+;; Return 1 if OP is a constant in the range of 0-63 (for a shift) or
+;; any register.
+(define_predicate "reg_or_6bit_operand"
+  (if_then_else (match_code "const_int")
+    (match_test "INTVAL (op) >= 0 && INTVAL (op) < 64")
+    (match_operand 0 "register_operand")))
+
+;; Return 1 if OP is an 8-bit constant.
+(define_predicate "cint8_operand"
+  (and (match_code "const_int")
+       (match_test "INTVAL (op) >= 0 && INTVAL (op) < 256")))
+
+;; Return 1 if OP is an 8-bit constant or any register.
+(define_predicate "reg_or_8bit_operand"
+  (if_then_else (match_code "const_int")
+    (match_test "INTVAL (op) >= 0 && INTVAL (op) < 256")
+    (match_operand 0 "register_operand")))
+
+;; Return 1 if OP is a constant or any register.
+(define_predicate "reg_or_cint_operand"
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "const_int_operand")))
+
+;; Return 1 if the operand is a valid second operand to an add insn.
+(define_predicate "add_operand"
+  (if_then_else (match_code "const_int")
+    (match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'K')
+                || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L')")
+    (match_operand 0 "register_operand")))
+
+;; Return 1 if the operand is a valid second operand to a
+;; sign-extending add insn.
+(define_predicate "sext_add_operand"
+  (if_then_else (match_code "const_int")
+    (match_test "CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
+                || CONST_OK_FOR_LETTER_P (INTVAL (op), 'O')")
+    (match_operand 0 "register_operand")))
+
+;; Return 1 if OP is the constant 4 or 8.
+(define_predicate "const48_operand"
+  (and (match_code "const_int")
+       (match_test "INTVAL (op) == 4 || INTVAL (op) == 8")))
+
+;; Return 1 if OP is a valid first operand to an AND insn.
+(define_predicate "and_operand"
+  (if_then_else (match_code "const_int")
+    (match_test "(unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
+                || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100
+                || zap_mask (INTVAL (op))")
+    (if_then_else (match_code "const_double")
+      (match_test "zap_mask (CONST_DOUBLE_LOW (op))
+                  && zap_mask (CONST_DOUBLE_HIGH (op))")
+      (match_operand 0 "register_operand"))))
+
+;; Return 1 if OP is a valid first operand to an IOR or XOR insn.
+(define_predicate "or_operand"
+  (if_then_else (match_code "const_int")
+    (match_test "(unsigned HOST_WIDE_INT) INTVAL (op) < 0x100
+                || (unsigned HOST_WIDE_INT) ~ INTVAL (op) < 0x100")
+    (match_operand 0 "register_operand")))
+
+;; Return 1 if OP is a constant that is the width, in bits, of an integral
+;; mode not larger than DImode.
+(define_predicate "mode_width_operand"
+  (match_code "const_int")
+{
+  HOST_WIDE_INT i = INTVAL (op);
+  return i == 8 || i == 16 || i == 32 || i == 64;
+})
+
+;; Return 1 if OP is a constant that is a mask of ones of width of an
+;; integral machine mode not larger than DImode.
+(define_predicate "mode_mask_operand"
+  (match_code "const_int,const_double")
+{
+  if (GET_CODE (op) == CONST_INT)
+    {
+      HOST_WIDE_INT value = INTVAL (op);
+
+      if (value == 0xff)
+       return 1;
+      if (value == 0xffff)
+       return 1;
+      if (value == 0xffffffff)
+       return 1;
+      if (value == -1)
+       return 1;
+    }
+  else if (HOST_BITS_PER_WIDE_INT == 32 && GET_CODE (op) == CONST_DOUBLE)
+    {
+      if (CONST_DOUBLE_LOW (op) == 0xffffffff && CONST_DOUBLE_HIGH (op) == 0)
+       return 1;
+    }
+  return 0;
+})
+
+;; Return 1 if OP is a multiple of 8 less than 64.
+(define_predicate "mul8_operand"
+  (match_code "const_int")
+{
+  unsigned HOST_WIDE_INT i = INTVAL (op);
+  return i < 64 && i % 8 == 0;
+})
+
+;; Return 1 if OP is a hard floating-point register.
+(define_predicate "hard_fp_register_operand"
+  (match_operand 0 "register_operand")
+{
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+  return REGNO_REG_CLASS (REGNO (op)) == FLOAT_REGS;
+})
+
+;; Return 1 if OP is a hard general register.
+(define_predicate "hard_int_register_operand"
+  (match_operand 0 "register_operand")
+{
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+  return REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS;
+})
+
+;; Return 1 if OP is something that can be reloaded into a register;
+;; if it is a MEM, it need not be valid.
+(define_predicate "some_operand"
+  (ior (match_code "reg,mem,const_int,const_double,const_vector,
+                   label_ref,symbol_ref,const,high")
+       (and (match_code "subreg")
+           (match_test "some_operand (SUBREG_REG (op), VOIDmode)"))))
+
+;; Likewise, but don't accept constants.
+(define_predicate "some_ni_operand"
+  (ior (match_code "reg,mem")
+       (and (match_code "subreg")
+           (match_test "some_ni_operand (SUBREG_REG (op), VOIDmode)"))))
+
+;; Return 1 if OP is a valid operand for the source of a move insn.
+(define_predicate "input_operand"
+  (match_code "label_ref,symbol_ref,const,high,reg,subreg,mem,
+              const_double,const_vector,const_int")
+{
+  switch (GET_CODE (op))
+    {
+    case LABEL_REF:
+    case SYMBOL_REF:
+    case CONST:
+      if (TARGET_EXPLICIT_RELOCS)
+       {
+         /* We don't split symbolic operands into something unintelligable
+            until after reload, but we do not wish non-small, non-global
+            symbolic operands to be reconstructed from their high/lo_sum
+            form.  */
+         return (small_symbolic_operand (op, mode)
+                 || global_symbolic_operand (op, mode)
+                 || gotdtp_symbolic_operand (op, mode)
+                 || gottp_symbolic_operand (op, mode));
+       }
+
+      /* This handles both the Windows/NT and OSF cases.  */
+      return mode == ptr_mode || mode == DImode;
+
+    case HIGH:
+      return (TARGET_EXPLICIT_RELOCS
+             && local_symbolic_operand (XEXP (op, 0), mode));
+
+    case REG:
+      return 1;
+
+    case SUBREG:
+      if (register_operand (op, mode))
+       return 1;
+      /* ... fall through ...  */
+    case MEM:
+      return ((TARGET_BWX || (mode != HImode && mode != QImode))
+             && general_operand (op, mode));
+
+    case CONST_DOUBLE:
+    case CONST_VECTOR:
+      return op == CONST0_RTX (mode);
+
+    case CONST_INT:
+      return mode == QImode || mode == HImode || add_operand (op, mode);
+
+    default:
+      abort ();
+    }
+  return 0;
+})
+
+;; Return 1 if OP is a SYMBOL_REF for a function known to be in this
+;; file, and in the same section as the current function.
+
+(define_predicate "samegp_function_operand"
+  (match_code "symbol_ref")
+{
+  /* Easy test for recursion.  */
+  if (op == XEXP (DECL_RTL (current_function_decl), 0))
+    return true;
+
+  /* Functions that are not local can be overridden, and thus may
+     not share the same gp.  */
+  if (! SYMBOL_REF_LOCAL_P (op))
+    return false;
+
+  /* If -msmall-data is in effect, assume that there is only one GP
+     for the module, and so any local symbol has this property.  We
+     need explicit relocations to be able to enforce this for symbols
+     not defined in this unit of translation, however.  */
+  if (TARGET_EXPLICIT_RELOCS && TARGET_SMALL_DATA)
+    return true;
+
+  /* Functions that are not external are defined in this UoT,
+     and thus must share the same gp.  */
+  return ! SYMBOL_REF_EXTERNAL_P (op);
+})
+
+;; Return 1 if OP is a SYMBOL_REF for which we can make a call via bsr.
+(define_predicate "direct_call_operand"
+  (match_operand 0 "samegp_function_operand")
+{
+  tree op_decl, cfun_sec, op_sec;
+
+  /* If profiling is implemented via linker tricks, we can't jump
+     to the nogp alternate entry point.  Note that current_function_profile
+     would not be correct, since that doesn't indicate if the target
+     function uses profiling.  */
+  /* ??? TARGET_PROFILING_NEEDS_GP isn't really the right test,
+     but is approximately correct for the OSF ABIs.  Don't know
+     what to do for VMS, NT, or UMK.  */
+  if (!TARGET_PROFILING_NEEDS_GP && profile_flag)
+    return false;
+
+  /* Must be a function.  In some cases folks create thunks in static
+     data structures and then make calls to them.  If we allow the
+     direct call, we'll get an error from the linker about !samegp reloc
+     against a symbol without a .prologue directive.  */
+  if (!SYMBOL_REF_FUNCTION_P (op))
+    return false;
+  
+  /* Must be "near" so that the branch is assumed to reach.  With
+     -msmall-text, this is assumed true of all local symbols.  Since
+     we've already checked samegp, locality is already assured.  */
+  if (TARGET_SMALL_TEXT)
+    return true;
+
+  /* Otherwise, a decl is "near" if it is defined in the same section.  */
+  if (flag_function_sections)
+    return false;
+
+  op_decl = SYMBOL_REF_DECL (op);
+  if (DECL_ONE_ONLY (current_function_decl)
+      || (op_decl && DECL_ONE_ONLY (op_decl)))
+    return false;
+
+  cfun_sec = DECL_SECTION_NAME (current_function_decl);
+  op_sec = op_decl ? DECL_SECTION_NAME (op_decl) : NULL;
+  return ((!cfun_sec && !op_sec)
+         || (cfun_sec && op_sec
+             && strcmp (TREE_STRING_POINTER (cfun_sec),
+                        TREE_STRING_POINTER (op_sec)) == 0));
+})
+
+;; Return 1 if OP is a valid operand for the MEM of a CALL insn.
+;;
+;; For TARGET_ABI_OSF, we want to restrict to R27 or a pseudo.
+;; For TARGET_ABI_UNICOSMK, we want to restrict to registers.
+
+(define_predicate "call_operand"
+  (if_then_else (match_code "reg")
+    (match_test "!TARGET_ABI_OSF
+                || REGNO (op) == 27 || REGNO (op) > LAST_VIRTUAL_REGISTER")
+    (and (match_test "!TARGET_ABI_UNICOSMK")
+        (match_code "symbol_ref"))))
+
+;; Return true if OP is a LABEL_REF, or SYMBOL_REF or CONST referencing
+;; a (non-tls) variable known to be defined in this file.
+(define_predicate "local_symbolic_operand"
+  (match_code "label_ref,const,symbol_ref")
+{
+  if (GET_CODE (op) == LABEL_REF)
+    return 1;
+
+  if (GET_CODE (op) == CONST
+      && GET_CODE (XEXP (op, 0)) == PLUS
+      && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
+    op = XEXP (XEXP (op, 0), 0);
+
+  if (GET_CODE (op) != SYMBOL_REF)
+    return 0;
+
+  return SYMBOL_REF_LOCAL_P (op) && !SYMBOL_REF_TLS_MODEL (op);
+})
+
+;; Return true if OP is a SYMBOL_REF or CONST referencing a variable
+;; known to be defined in this file in the small data area.
+(define_predicate "small_symbolic_operand"
+  (match_code "const,symbol_ref")
+{
+  if (! TARGET_SMALL_DATA)
+    return 0;
+
+  if (GET_CODE (op) == CONST
+      && GET_CODE (XEXP (op, 0)) == PLUS
+      && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
+    op = XEXP (XEXP (op, 0), 0);
+
+  if (GET_CODE (op) != SYMBOL_REF)
+    return 0;
+
+  /* ??? There's no encode_section_info equivalent for the rtl
+     constant pool, so SYMBOL_FLAG_SMALL never gets set.  */
+  if (CONSTANT_POOL_ADDRESS_P (op))
+    return GET_MODE_SIZE (get_pool_mode (op)) <= g_switch_value;
+
+  return (SYMBOL_REF_LOCAL_P (op)
+         && SYMBOL_REF_SMALL_P (op)
+         && SYMBOL_REF_TLS_MODEL (op) == 0);
+})
+
+;; Return true if OP is a SYMBOL_REF or CONST referencing a variable
+;; not known (or known not) to be defined in this file.
+(define_predicate "global_symbolic_operand"
+  (match_code "const,symbol_ref")
+{
+  if (GET_CODE (op) == CONST
+      && GET_CODE (XEXP (op, 0)) == PLUS
+      && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
+    op = XEXP (XEXP (op, 0), 0);
+
+  if (GET_CODE (op) != SYMBOL_REF)
+    return 0;
+
+  return !SYMBOL_REF_LOCAL_P (op) && !SYMBOL_REF_TLS_MODEL (op);
+})
+
+;; Returns 1 if OP is a symbolic operand, i.e. a symbol_ref or a label_ref,
+;; possibly with an offset.
+(define_predicate "symbolic_operand"
+  (ior (match_code "symbol_ref,label_ref")
+       (and (match_code "const")
+           (match_test "GET_CODE (XEXP (op,0)) == PLUS
+                        && GET_CODE (XEXP (XEXP (op,0), 0)) == SYMBOL_REF
+                        && GET_CODE (XEXP (XEXP (op,0), 1)) == CONST_INT"))))
+
+;; Return true if OP is valid for 16-bit DTP relative relocations.
+(define_predicate "dtp16_symbolic_operand"
+  (and (match_code "const")
+       (match_test "tls_symbolic_operand_1 (op, 16, UNSPEC_DTPREL)")))
+
+;; Return true if OP is valid for 32-bit DTP relative relocations.
+(define_predicate "dtp32_symbolic_operand"
+  (and (match_code "const")
+       (match_test "tls_symbolic_operand_1 (op, 32, UNSPEC_DTPREL)")))
+
+;; Return true if OP is valid for 64-bit DTP relative relocations.
+(define_predicate "gotdtp_symbolic_operand"
+  (and (match_code "const")
+       (match_test "tls_symbolic_operand_1 (op, 64, UNSPEC_DTPREL)")))
+
+;; Return true if OP is valid for 16-bit TP relative relocations.
+(define_predicate "tp16_symbolic_operand"
+  (and (match_code "const")
+       (match_test "tls_symbolic_operand_1 (op, 16, UNSPEC_TPREL)")))
+
+;; Return true if OP is valid for 32-bit TP relative relocations.
+(define_predicate "tp32_symbolic_operand"
+  (and (match_code "const")
+       (match_test "tls_symbolic_operand_1 (op, 32, UNSPEC_TPREL)")))
+
+;; Return true if OP is valid for 64-bit TP relative relocations.
+(define_predicate "gottp_symbolic_operand"
+  (and (match_code "const")
+       (match_test "tls_symbolic_operand_1 (op, 64, UNSPEC_TPREL)")))
+
+;; Return 1 if this memory address is a known aligned register plus
+;; a constant.  It must be a valid address.  This means that we can do
+;; this as an aligned reference plus some offset.
+;;
+;; Take into account what reload will do.  Oh god this is awful.
+;; The horrible comma-operator construct below is to prevent genrecog
+;; from thinking that this predicate accepts REG and SUBREG.  We don't
+;; use recog during reload, so pretending these codes are accepted 
+;; pessimizes things a tad.
+
+(define_predicate "aligned_memory_operand"
+  (ior (match_test "op = resolve_reload_operand (op), 0")
+       (match_code "mem"))
+{
+  rtx base;
+
+  if (MEM_ALIGN (op) >= 32)
+    return 1;
+  op = XEXP (op, 0);
+
+  /* LEGITIMIZE_RELOAD_ADDRESS creates (plus (plus reg const_hi) const_lo)
+     sorts of constructs.  Dig for the real base register.  */
+  if (reload_in_progress
+      && GET_CODE (op) == PLUS
+      && GET_CODE (XEXP (op, 0)) == PLUS)
+    base = XEXP (XEXP (op, 0), 0);
+  else
+    {
+      if (! memory_address_p (mode, op))
+       return 0;
+      base = (GET_CODE (op) == PLUS ? XEXP (op, 0) : op);
+    }
+
+  return (GET_CODE (base) == REG && REGNO_POINTER_ALIGN (REGNO (base)) >= 32);
+})
+
+;; Similar, but return 1 if OP is a MEM which is not alignable.
+
+(define_predicate "unaligned_memory_operand"
+  (ior (match_test "op = resolve_reload_operand (op), 0")
+       (match_code "mem"))
+{
+  rtx base;
+
+  if (MEM_ALIGN (op) >= 32)
+    return 0;
+  op = XEXP (op, 0);
+
+  /* LEGITIMIZE_RELOAD_ADDRESS creates (plus (plus reg const_hi) const_lo)
+     sorts of constructs.  Dig for the real base register.  */
+  if (reload_in_progress
+      && GET_CODE (op) == PLUS
+      && GET_CODE (XEXP (op, 0)) == PLUS)
+    base = XEXP (XEXP (op, 0), 0);
+  else
+    {
+      if (! memory_address_p (mode, op))
+       return 0;
+      base = (GET_CODE (op) == PLUS ? XEXP (op, 0) : op);
+    }
+
+  return (GET_CODE (base) == REG && REGNO_POINTER_ALIGN (REGNO (base)) < 32);
+})
+
+;; Return 1 if OP is any memory location.  During reload a pseudo matches.
+(define_predicate "any_memory_operand"
+  (ior (match_code "mem,reg")
+       (and (match_code "subreg")
+           (match_test "GET_CODE (SUBREG_REG (op)) == REG"))))
+
+;; Return 1 if OP is either a register or an unaligned memory location.
+(define_predicate "reg_or_unaligned_mem_operand"
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "unaligned_memory_operand")))
+
+;; Return 1 is OP is a memory location that is not a reference
+;; (using an AND) to an unaligned location.  Take into account
+;; what reload will do.
+(define_predicate "normal_memory_operand"
+  (ior (match_test "op = resolve_reload_operand (op), 0")
+       (and (match_code "mem")
+           (match_test "GET_CODE (XEXP (op, 0)) != AND"))))
+
+;; Returns 1 if OP is not an eliminable register.
+;;
+;; This exists to cure a pathological abort in the s8addq (et al) patterns,
+;;
+;;     long foo () { long t; bar(); return (long) &t * 26107; }
+;;
+;; which run afoul of a hack in reload to cure a (presumably) similar
+;; problem with lea-type instructions on other targets.  But there is
+;; one of us and many of them, so work around the problem by selectively
+;; preventing combine from making the optimization.
+
+(define_predicate "reg_not_elim_operand"
+  (match_operand 0 "register_operand")
+{
+  if (GET_CODE (op) == SUBREG)
+    op = SUBREG_REG (op);
+  return op != frame_pointer_rtx && op != arg_pointer_rtx;
+})
+
+;; Accept a register, but not a subreg of any kind.  This allows us to
+;; avoid pathological cases in reload wrt data movement common in 
+;; int->fp conversion.  */
+(define_predicate "reg_no_subreg_operand"
+  (and (match_code "reg")
+       (match_operand 0 "register_operand")))
+
+;; Return 1 if OP is a valid Alpha comparison operator for "cmp" style
+;; instructions.
+(define_predicate "alpha_comparison_operator"
+  (match_code "eq,le,lt,leu,ltu"))
+
+;; Similarly, but with swapped operands.
+(define_predicate "alpha_swapped_comparison_operator"
+  (match_code "eq,ge,gt,gtu,gtu"))
+
+;; Return 1 if OP is a valid Alpha comparison operator against zero
+;; for "bcc" style instructions.
+(define_predicate "alpha_zero_comparison_operator"
+  (match_code "eq,ne,le,lt,leu,ltu"))
+
+;; Return 1 if OP is a signed comparison operation.
+(define_predicate "signed_comparison_operator"
+  (match_code "eq,ne,le,lt,ge,gt"))
+
+;; Return 1 if OP is a valid Alpha floating point comparison operator.
+(define_predicate "alpha_fp_comparison_operator"
+  (match_code "eq,le,lt,unordered"))
+
+;; Return 1 if this is a divide or modulus operator.
+(define_predicate "divmod_operator"
+  (match_code "div,mod,udiv,umod"))
+
+;; Return 1 if this is a float->int conversion operator.
+(define_predicate "fix_operator"
+  (match_code "fix,unsigned_fix"))
+
+;; Recognize an addition operation that includes a constant.  Used to
+;; convince reload to canonize (plus (plus reg c1) c2) during register
+;; elimination.
+
+(define_predicate "addition_operation"
+  (and (match_code "plus")
+       (match_test "register_operand (XEXP (op, 0), mode)
+                   && GET_CODE (XEXP (op, 1)) == CONST_INT
+                   && CONST_OK_FOR_LETTER_P (INTVAL (XEXP (op, 1)), 'K')")))
index 833d47f907be88b4dbf2769aec0f4e3448bfccda..cdfc8f54d36a8e73abba2f1bee6987afe2e14875 100644 (file)
@@ -417,6 +417,7 @@ write_insn_preds_c (void)
 #include \"coretypes.h\"\n\
 #include \"tm.h\"\n\
 #include \"rtl.h\"\n\
+#include \"tree.h\"\n\
 #include \"tm_p.h\"\n\
 #include \"function.h\"\n\
 #include \"insn-config.h\"\n\