OSDN Git Service

* collect2.c (main): In AIX specific computations for vector
[pf3gnuchains/gcc-fork.git] / gcc / targhooks.c
index d619ae5..2b4fd27 100644 (file)
@@ -1,5 +1,5 @@
 /* Default target hook functions.
-   Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009
+   Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -56,16 +56,21 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "expr.h"
 #include "output.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
 #include "function.h"
 #include "target.h"
 #include "tm_p.h"
 #include "target-def.h"
 #include "ggc.h"
 #include "hard-reg-set.h"
+#include "regs.h"
 #include "reload.h"
 #include "optabs.h"
 #include "recog.h"
+#include "intl.h"
+#include "opts.h"
+#include "tree-flow.h"
+#include "tree-ssa-alias.h"
 
 
 bool
@@ -119,7 +124,7 @@ default_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
                               const_tree funtype ATTRIBUTE_UNUSED,
                               int for_return ATTRIBUTE_UNUSED)
 {
-  if (for_return == 2)
+  if (type != NULL_TREE && for_return == 2)
     return promote_mode (type, mode, punsignedp);
   return mode;
 }
@@ -165,7 +170,7 @@ default_expand_builtin_saveregs (void)
 }
 
 void
-default_setup_incoming_varargs (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+default_setup_incoming_varargs (cumulative_args_t ca ATTRIBUTE_UNUSED,
                                enum machine_mode mode ATTRIBUTE_UNUSED,
                                tree type ATTRIBUTE_UNUSED,
                                int *pretend_arg_size ATTRIBUTE_UNUSED,
@@ -184,13 +189,13 @@ default_builtin_setjmp_frame_value (void)
 /* Generic hook that takes a CUMULATIVE_ARGS pointer and returns false.  */
 
 bool
-hook_bool_CUMULATIVE_ARGS_false (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED)
+hook_bool_CUMULATIVE_ARGS_false (cumulative_args_t ca ATTRIBUTE_UNUSED)
 {
   return false;
 }
 
 bool
-default_pretend_outgoing_varargs_named (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED)
+default_pretend_outgoing_varargs_named (cumulative_args_t ca ATTRIBUTE_UNUSED)
 {
   return (targetm.calls.setup_incoming_varargs
          != default_setup_incoming_varargs);
@@ -248,7 +253,7 @@ default_mode_rep_extended (enum machine_mode mode ATTRIBUTE_UNUSED,
 /* Generic hook that takes a CUMULATIVE_ARGS pointer and returns true.  */
 
 bool
-hook_bool_CUMULATIVE_ARGS_true (CUMULATIVE_ARGS * a ATTRIBUTE_UNUSED)
+hook_bool_CUMULATIVE_ARGS_true (cumulative_args_t a ATTRIBUTE_UNUSED)
 {
   return true;
 }
@@ -297,7 +302,7 @@ default_cxx_get_cookie_size (tree type)
    of the TARGET_PASS_BY_REFERENCE hook uses just MUST_PASS_IN_STACK.  */
 
 bool
-hook_pass_by_reference_must_pass_in_stack (CUMULATIVE_ARGS *c ATTRIBUTE_UNUSED,
+hook_pass_by_reference_must_pass_in_stack (cumulative_args_t c ATTRIBUTE_UNUSED,
        enum machine_mode mode ATTRIBUTE_UNUSED, const_tree type ATTRIBUTE_UNUSED,
        bool named_arg ATTRIBUTE_UNUSED)
 {
@@ -308,21 +313,62 @@ hook_pass_by_reference_must_pass_in_stack (CUMULATIVE_ARGS *c ATTRIBUTE_UNUSED,
    version of the hook is true for all named arguments.  */
 
 bool
-hook_callee_copies_named (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+hook_callee_copies_named (cumulative_args_t ca ATTRIBUTE_UNUSED,
                          enum machine_mode mode ATTRIBUTE_UNUSED,
                          const_tree type ATTRIBUTE_UNUSED, bool named)
 {
   return named;
 }
 
-/* Emit any directives required to unwind this instruction.  */
+/* Emit to STREAM the assembler syntax for insn operand X.  */
 
 void
-default_unwind_emit (FILE * stream ATTRIBUTE_UNUSED,
-                    rtx insn ATTRIBUTE_UNUSED)
+default_print_operand (FILE *stream ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
+                      int code ATTRIBUTE_UNUSED)
 {
-  /* Should never happen.  */
+#ifdef PRINT_OPERAND
+  PRINT_OPERAND (stream, x, code);
+#else
+  gcc_unreachable ();
+#endif
+}
+
+/* Emit to STREAM the assembler syntax for an insn operand whose memory
+   address is X.  */
+
+void
+default_print_operand_address (FILE *stream ATTRIBUTE_UNUSED,
+                              rtx x ATTRIBUTE_UNUSED)
+{
+#ifdef PRINT_OPERAND_ADDRESS
+  PRINT_OPERAND_ADDRESS (stream, x);
+#else
   gcc_unreachable ();
+#endif
+}
+
+/* Return true if CODE is a valid punctuation character for the
+   `print_operand' hook.  */
+
+bool
+default_print_operand_punct_valid_p (unsigned char code ATTRIBUTE_UNUSED)
+{
+#ifdef PRINT_OPERAND_PUNCT_VALID_P
+  return PRINT_OPERAND_PUNCT_VALID_P (code);
+#else
+  return false;
+#endif
+}
+
+/* The default implementation of TARGET_MANGLE_ASSEMBLER_NAME.  */
+tree
+default_mangle_assembler_name (const char *name ATTRIBUTE_UNUSED)
+{
+  const char *skipped = name + (*name == '*' ? 1 : 0);
+  const char *stripped = targetm.strip_name_encoding (skipped);
+  if (*name != '*' && user_label_prefix[0])
+    stripped = ACONCAT ((user_label_prefix, stripped, NULL));
+  return get_identifier (stripped);
 }
 
 /* True if MODE is valid for the target.  By "valid", we mean able to
@@ -378,6 +424,19 @@ default_scalar_mode_supported_p (enum machine_mode mode)
     }
 }
 
+/* Make some target macros useable by target-independent code.  */
+bool
+targhook_words_big_endian (void)
+{
+  return !!WORDS_BIG_ENDIAN;
+}
+
+bool
+targhook_float_words_big_endian (void)
+{
+  return !!FLOAT_WORDS_BIG_ENDIAN;
+}
+
 /* True if the target supports decimal floating point.  */
 
 bool
@@ -419,7 +478,7 @@ default_invalid_within_doloop (const_rtx insn)
 /* Mapping of builtin functions to vectorized variants.  */
 
 tree
-default_builtin_vectorized_function (unsigned int fn ATTRIBUTE_UNUSED,
+default_builtin_vectorized_function (tree fndecl ATTRIBUTE_UNUSED,
                                     tree type_out ATTRIBUTE_UNUSED,
                                     tree type_in ATTRIBUTE_UNUSED)
 {
@@ -430,11 +489,45 @@ default_builtin_vectorized_function (unsigned int fn ATTRIBUTE_UNUSED,
 
 tree
 default_builtin_vectorized_conversion (unsigned int code ATTRIBUTE_UNUSED,
-                                      tree type ATTRIBUTE_UNUSED)
+                                      tree dest_type ATTRIBUTE_UNUSED,
+                                      tree src_type ATTRIBUTE_UNUSED)
 {
   return NULL_TREE;
 }
 
+/* Default vectorizer cost model values.  */
+
+int
+default_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
+                                    tree vectype ATTRIBUTE_UNUSED,
+                                    int misalign ATTRIBUTE_UNUSED)
+{
+  switch (type_of_cost)
+    {
+      case scalar_stmt:
+      case scalar_load:
+      case scalar_store:
+      case vector_stmt:
+      case vector_load:
+      case vector_store:
+      case vec_to_scalar:
+      case scalar_to_vec:
+      case cond_branch_not_taken:
+      case vec_perm:
+        return 1;
+
+      case unaligned_load:
+      case unaligned_store:
+        return 2;
+
+      case cond_branch_taken:
+        return 3;
+
+      default:
+        gcc_unreachable ();
+    }
+}
+
 /* Reciprocal.  */
 
 tree
@@ -447,7 +540,7 @@ default_builtin_reciprocal (unsigned int fn ATTRIBUTE_UNUSED,
 
 bool
 hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false (
-       CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+       cumulative_args_t ca ATTRIBUTE_UNUSED,
        enum machine_mode mode ATTRIBUTE_UNUSED,
        const_tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
 {
@@ -456,7 +549,7 @@ hook_bool_CUMULATIVE_ARGS_mode_tree_bool_false (
 
 bool
 hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true (
-       CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+       cumulative_args_t ca ATTRIBUTE_UNUSED,
        enum machine_mode mode ATTRIBUTE_UNUSED,
        const_tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
 {
@@ -465,7 +558,7 @@ hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true (
 
 int
 hook_int_CUMULATIVE_ARGS_mode_tree_bool_0 (
-       CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+       cumulative_args_t ca ATTRIBUTE_UNUSED,
        enum machine_mode mode ATTRIBUTE_UNUSED,
        tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
 {
@@ -473,6 +566,47 @@ hook_int_CUMULATIVE_ARGS_mode_tree_bool_0 (
 }
 
 void
+default_function_arg_advance (cumulative_args_t ca ATTRIBUTE_UNUSED,
+                             enum machine_mode mode ATTRIBUTE_UNUSED,
+                             const_tree type ATTRIBUTE_UNUSED,
+                             bool named ATTRIBUTE_UNUSED)
+{
+  gcc_unreachable ();
+}
+
+rtx
+default_function_arg (cumulative_args_t ca ATTRIBUTE_UNUSED,
+                     enum machine_mode mode ATTRIBUTE_UNUSED,
+                     const_tree type ATTRIBUTE_UNUSED,
+                     bool named ATTRIBUTE_UNUSED)
+{
+  gcc_unreachable ();
+}
+
+rtx
+default_function_incoming_arg (cumulative_args_t ca ATTRIBUTE_UNUSED,
+                              enum machine_mode mode ATTRIBUTE_UNUSED,
+                              const_tree type ATTRIBUTE_UNUSED,
+                              bool named ATTRIBUTE_UNUSED)
+{
+  gcc_unreachable ();
+}
+
+unsigned int
+default_function_arg_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
+                              const_tree type ATTRIBUTE_UNUSED)
+{
+  return PARM_BOUNDARY;
+}
+
+unsigned int
+default_function_arg_round_boundary (enum machine_mode mode ATTRIBUTE_UNUSED,
+                                    const_tree type ATTRIBUTE_UNUSED)
+{
+  return PARM_BOUNDARY;
+}
+
+void
 hook_void_bitmap (bitmap regs ATTRIBUTE_UNUSED)
 {
 }
@@ -498,6 +632,8 @@ default_stack_protect_guard (void)
 
   if (t == NULL)
     {
+      rtx x;
+
       t = build_decl (UNKNOWN_LOCATION,
                      VAR_DECL, get_identifier ("__stack_chk_guard"),
                      ptr_type_node);
@@ -509,6 +645,11 @@ default_stack_protect_guard (void)
       DECL_ARTIFICIAL (t) = 1;
       DECL_IGNORED_P (t) = 1;
 
+      /* Do not share RTL as the declaration is visible outside of
+        current function.  */
+      x = DECL_RTL (t);
+      RTX_FLAG (x, used) = 1;
+
       stack_chk_guard_decl = t;
     }
 
@@ -595,11 +736,6 @@ default_function_value (const_tree ret_type ATTRIBUTE_UNUSED,
       && !DECL_P (fn_decl_or_type))
     fn_decl_or_type = NULL;
 
-#ifdef FUNCTION_OUTGOING_VALUE
-  if (outgoing)
-    return FUNCTION_OUTGOING_VALUE (ret_type, fn_decl_or_type);
-#endif
-
 #ifdef FUNCTION_VALUE
   return FUNCTION_VALUE (ret_type, fn_decl_or_type);
 #else
@@ -618,6 +754,18 @@ default_libcall_value (enum machine_mode mode ATTRIBUTE_UNUSED,
 #endif
 }
 
+/* The default hook for TARGET_FUNCTION_VALUE_REGNO_P.  */
+
+bool
+default_function_value_regno_p (const unsigned int regno ATTRIBUTE_UNUSED)
+{
+#ifdef FUNCTION_VALUE_REGNO_P
+  return FUNCTION_VALUE_REGNO_P (regno);
+#else
+  gcc_unreachable ();
+#endif
+}
+
 rtx
 default_internal_arg_pointer (void)
 {
@@ -671,28 +819,28 @@ default_trampoline_init (rtx ARG_UNUSED (m_tramp), tree ARG_UNUSED (t_func),
   sorry ("nested function trampolines not supported on this target");
 }
 
-enum reg_class
-default_branch_target_register_class (void)
+int
+default_return_pops_args (tree fundecl ATTRIBUTE_UNUSED,
+                         tree funtype ATTRIBUTE_UNUSED,
+                         int size ATTRIBUTE_UNUSED)
 {
-  return NO_REGS;
+  return 0;
 }
 
-#ifdef IRA_COVER_CLASSES
-const enum reg_class *
-default_ira_cover_classes (void)
+reg_class_t
+default_branch_target_register_class (void)
 {
-  static enum reg_class classes[] = IRA_COVER_CLASSES;
-  return classes;
+  return NO_REGS;
 }
-#endif
 
-enum reg_class
+reg_class_t
 default_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
-                         enum reg_class reload_class ATTRIBUTE_UNUSED,
+                         reg_class_t reload_class_i ATTRIBUTE_UNUSED,
                          enum machine_mode reload_mode ATTRIBUTE_UNUSED,
                          secondary_reload_info *sri)
 {
   enum reg_class rclass = NO_REGS;
+  enum reg_class reload_class = (enum reg_class) reload_class_i;
 
   if (sri->prev_sri && sri->prev_sri->t_icode != CODE_FOR_nothing)
     {
@@ -709,12 +857,12 @@ default_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
 #endif
   if (rclass != NO_REGS)
     {
-      enum insn_code icode = (in_p ? reload_in_optab[(int) reload_mode]
-                             : reload_out_optab[(int) reload_mode]);
+      enum insn_code icode
+       = direct_optab_handler (in_p ? reload_in_optab : reload_out_optab,
+                               reload_mode);
 
       if (icode != CODE_FOR_nothing
-         && insn_data[(int) icode].operand[in_p].predicate
-         && ! insn_data[(int) icode].operand[in_p].predicate (x, reload_mode))
+         && !insn_operand_matches (icode, in_p, x))
        icode = CODE_FOR_nothing;
       else if (icode != CODE_FOR_nothing)
        {
@@ -774,14 +922,6 @@ default_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
   return rclass;
 }
 
-bool
-default_handle_c_option (size_t code ATTRIBUTE_UNUSED,
-                        const char *arg ATTRIBUTE_UNUSED,
-                        int value ATTRIBUTE_UNUSED)
-{
-  return false;
-}
-
 /* By default, if flag_pic is true, then neither local nor global relocs
    should be placed in readonly memory.  */
 
@@ -826,11 +966,29 @@ default_builtin_support_vector_misalignment (enum machine_mode mode,
                                             bool is_packed
                                             ATTRIBUTE_UNUSED)
 {
-  if (optab_handler (movmisalign_optab, mode)->insn_code != CODE_FOR_nothing)
+  if (optab_handler (movmisalign_optab, mode) != CODE_FOR_nothing)
     return true;
   return false;
 }
 
+/* By default, only attempt to parallelize bitwise operations, and
+   possibly adds/subtracts using bit-twiddling.  */
+
+enum machine_mode
+default_preferred_simd_mode (enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+  return word_mode;
+}
+
+/* By default only the size derived from the preferred vector mode
+   is tried.  */
+
+unsigned int
+default_autovectorize_vector_sizes (void)
+{
+  return 0;
+}
+
 /* Determine whether or not a pointer mode is valid. Assume defaults
    of ptr_mode or Pmode - can be overridden.  */
 bool
@@ -839,6 +997,33 @@ default_valid_pointer_mode (enum machine_mode mode)
   return (mode == ptr_mode || mode == Pmode);
 }
 
+/* Determine whether the memory reference specified by REF may alias
+   the C libraries errno location.  */
+bool
+default_ref_may_alias_errno (ao_ref *ref)
+{
+  tree base = ao_ref_base (ref);
+  /* The default implementation assumes the errno location is
+     a declaration of type int or is always accessed via a
+     pointer to int.  We assume that accesses to errno are
+     not deliberately obfuscated (even in conforming ways).  */
+  if (TYPE_UNSIGNED (TREE_TYPE (base))
+      || TYPE_MODE (TREE_TYPE (base)) != TYPE_MODE (integer_type_node))
+    return false;
+  /* The default implementation assumes an errno location
+     declaration is never defined in the current compilation unit.  */
+  if (DECL_P (base)
+      && !TREE_STATIC (base))
+    return true;
+  else if (TREE_CODE (base) == MEM_REF
+          && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME)
+    {
+      struct ptr_info_def *pi = SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0));
+      return !pi || pi->pt.anything || pi->pt.nonlocal;
+    }
+  return false;
+}
+
 /* Return the mode for a pointer to a given ADDRSPACE, defaulting to ptr_mode
    for the generic address space only.  */
 
@@ -938,6 +1123,26 @@ default_hard_regno_scratch_ok (unsigned int regno ATTRIBUTE_UNUSED)
   return true;
 }
 
+/* The default implementation of TARGET_MODE_DEPENDENT_ADDRESS_P.  */
+
+bool
+default_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED)
+{
+#ifdef GO_IF_MODE_DEPENDENT_ADDRESS
+
+  GO_IF_MODE_DEPENDENT_ADDRESS (CONST_CAST_RTX (addr), win);
+  return false;
+  /* Label `win' might (not) be used via GO_IF_MODE_DEPENDENT_ADDRESS.  */
+ win: ATTRIBUTE_UNUSED_LABEL
+  return true;
+
+#else
+
+  return false;
+
+#endif
+}
+
 bool
 default_target_option_valid_attribute_p (tree ARG_UNUSED (fndecl),
                                         tree ARG_UNUSED (name),
@@ -976,9 +1181,10 @@ default_target_can_inline_p (tree caller, tree callee)
   else if (!caller_opts)
     ret = false;
 
-  /* If both caller and callee have attributes, assume that if the pointer is
-     different, the the two functions have different target options since
-     build_target_option_node uses a hash table for the options.  */
+  /* If both caller and callee have attributes, assume that if the
+     pointer is different, the two functions have different target
+     options since build_target_option_node uses a hash table for the
+     options.  */
   else
     ret = (callee_opts == caller_opts);
 
@@ -1008,4 +1214,238 @@ default_have_conditional_execution (void)
 #endif
 }
 
+tree
+default_builtin_tm_load_store (tree ARG_UNUSED (type))
+{
+  return NULL_TREE;
+}
+
+/* Compute cost of moving registers to/from memory.  */
+
+int
+default_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+                         reg_class_t rclass ATTRIBUTE_UNUSED,
+                         bool in ATTRIBUTE_UNUSED)
+{
+#ifndef MEMORY_MOVE_COST
+    return (4 + memory_move_secondary_cost (mode, (enum reg_class) rclass, in));
+#else
+    return MEMORY_MOVE_COST (mode, (enum reg_class) rclass, in);
+#endif
+}
+
+/* Compute cost of moving data from a register of class FROM to one of
+   TO, using MODE.  */
+
+int
+default_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+                            reg_class_t from ATTRIBUTE_UNUSED,
+                            reg_class_t to ATTRIBUTE_UNUSED)
+{
+#ifndef REGISTER_MOVE_COST
+  return 2;
+#else
+  return REGISTER_MOVE_COST (mode, (enum reg_class) from, (enum reg_class) to);
+#endif
+}
+
+bool
+default_profile_before_prologue (void)
+{
+#ifdef PROFILE_BEFORE_PROLOGUE
+  return true;
+#else
+  return false;
+#endif
+}
+
+/* The default implementation of TARGET_PREFERRED_RELOAD_CLASS.  */
+
+reg_class_t
+default_preferred_reload_class (rtx x ATTRIBUTE_UNUSED,
+                               reg_class_t rclass)
+{
+#ifdef PREFERRED_RELOAD_CLASS 
+  return (reg_class_t) PREFERRED_RELOAD_CLASS (x, (enum reg_class) rclass);
+#else
+  return rclass;
+#endif
+}
+
+/* The default implementation of TARGET_OUTPUT_PREFERRED_RELOAD_CLASS.  */
+
+reg_class_t
+default_preferred_output_reload_class (rtx x ATTRIBUTE_UNUSED,
+                                      reg_class_t rclass)
+{
+  return rclass;
+}
+
+/* The default implementation of TARGET_PREFERRED_RENAME_CLASS.  */
+reg_class_t
+default_preferred_rename_class (reg_class_t rclass ATTRIBUTE_UNUSED)
+{
+  return NO_REGS;
+}
+
+/* The default implementation of TARGET_CLASS_LIKELY_SPILLED_P.  */
+
+bool
+default_class_likely_spilled_p (reg_class_t rclass)
+{
+  return (reg_class_size[(int) rclass] == 1);
+}
+
+/* The default implementation of TARGET_CLASS_MAX_NREGS.  */
+
+unsigned char
+default_class_max_nregs (reg_class_t rclass ATTRIBUTE_UNUSED,
+                        enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+#ifdef CLASS_MAX_NREGS
+  return (unsigned char) CLASS_MAX_NREGS ((enum reg_class) rclass, mode);
+#else
+  return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
+#endif
+}
+
+/* Determine the debugging unwind mechanism for the target.  */
+
+enum unwind_info_type
+default_debug_unwind_info (void)
+{
+  /* If the target wants to force the use of dwarf2 unwind info, let it.  */
+  /* ??? Change all users to the hook, then poison this.  */
+#ifdef DWARF2_FRAME_INFO
+  if (DWARF2_FRAME_INFO)
+    return UI_DWARF2;
+#endif
+
+  /* Otherwise, only turn it on if dwarf2 debugging is enabled.  */
+#ifdef DWARF2_DEBUGGING_INFO
+  if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
+    return UI_DWARF2;
+#endif
+
+  return UI_NONE;
+}
+
+/* To be used by targets where reg_raw_mode doesn't return the right
+   mode for registers used in apply_builtin_return and apply_builtin_arg.  */
+
+enum machine_mode
+default_get_reg_raw_mode(int regno)
+{
+  return reg_raw_mode[regno];
+}
+
+/* Return true if the state of option OPTION should be stored in PCH files
+   and checked by default_pch_valid_p.  Store the option's current state
+   in STATE if so.  */
+
+static inline bool
+option_affects_pch_p (int option, struct cl_option_state *state)
+{
+  if ((cl_options[option].flags & CL_TARGET) == 0)
+    return false;
+  if (option_flag_var (option, &global_options) == &target_flags)
+    if (targetm.check_pch_target_flags)
+      return false;
+  return get_option_state (&global_options, option, state);
+}
+
+/* Default version of get_pch_validity.
+   By default, every flag difference is fatal; that will be mostly right for
+   most targets, but completely right for very few.  */
+
+void *
+default_get_pch_validity (size_t *sz)
+{
+  struct cl_option_state state;
+  size_t i;
+  char *result, *r;
+
+  *sz = 2;
+  if (targetm.check_pch_target_flags)
+    *sz += sizeof (target_flags);
+  for (i = 0; i < cl_options_count; i++)
+    if (option_affects_pch_p (i, &state))
+      *sz += state.size;
+
+  result = r = XNEWVEC (char, *sz);
+  r[0] = flag_pic;
+  r[1] = flag_pie;
+  r += 2;
+  if (targetm.check_pch_target_flags)
+    {
+      memcpy (r, &target_flags, sizeof (target_flags));
+      r += sizeof (target_flags);
+    }
+
+  for (i = 0; i < cl_options_count; i++)
+    if (option_affects_pch_p (i, &state))
+      {
+       memcpy (r, state.data, state.size);
+       r += state.size;
+      }
+
+  return result;
+}
+
+/* Return a message which says that a PCH file was created with a different
+   setting of OPTION.  */
+
+static const char *
+pch_option_mismatch (const char *option)
+{
+  char *r;
+
+  asprintf (&r, _("created and used with differing settings of '%s'"), option);
+  if (r == NULL)
+    return _("out of memory");
+  return r;
+}
+
+/* Default version of pch_valid_p.  */
+
+const char *
+default_pch_valid_p (const void *data_p, size_t len)
+{
+  struct cl_option_state state;
+  const char *data = (const char *)data_p;
+  size_t i;
+
+  /* -fpic and -fpie also usually make a PCH invalid.  */
+  if (data[0] != flag_pic)
+    return _("created and used with different settings of -fpic");
+  if (data[1] != flag_pie)
+    return _("created and used with different settings of -fpie");
+  data += 2;
+
+  /* Check target_flags.  */
+  if (targetm.check_pch_target_flags)
+    {
+      int tf;
+      const char *r;
+
+      memcpy (&tf, data, sizeof (target_flags));
+      data += sizeof (target_flags);
+      len -= sizeof (target_flags);
+      r = targetm.check_pch_target_flags (tf);
+      if (r != NULL)
+       return r;
+    }
+
+  for (i = 0; i < cl_options_count; i++)
+    if (option_affects_pch_p (i, &state))
+      {
+       if (memcmp (data, state.data, state.size) != 0)
+         return pch_option_mismatch (cl_options[i].opt_text);
+       data += state.size;
+       len -= state.size;
+      }
+
+  return NULL;
+}
+
 #include "gt-targhooks.h"