https://gcc.gnu.org/g:a7fe8f83bf89704e278c1db30f51d6bb26bf0e69

commit r16-3565-ga7fe8f83bf89704e278c1db30f51d6bb26bf0e69
Author: Kito Cheng <kito.ch...@sifive.com>
Date:   Thu Jul 10 15:28:30 2025 +0800

    RISC-V: Always register vector built-in functions during LTO [PR110812]
    
    Previously, vector built-in functions were not properly registered during
    the LTO pipeline, causing link failures when vector intrinsics were used
    in LTO builds with mixed architecture options.  This patch ensures all
    vector built-in functions are always registered during LTO compilation.
    
    The key changes include:
    - Moving pragma intrinsic flag manipulation from riscv-c.cc to
      riscv-vector-builtins.cc for better encapsulation
    - Registering all vector built-in functions regardless of current ISA
      extensions, deferring the actual extension checking to expansion time
    - Adding proper support for built-in type registration during LTO
    
    This approach is safe because we already perform extension requirement
    checking at expansion time.  The trade-off is a slight increase in
    bootstrap time for LTO builds due to registering more built-in functions.
    
            PR target/110812
    
    gcc/ChangeLog:
    
            * config/riscv/riscv-c.cc (pragma_intrinsic_flags): Remove struct.
            (riscv_pragma_intrinsic_flags_pollute): Remove function.
            (riscv_pragma_intrinsic_flags_restore): Remove function.
            (riscv_pragma_intrinsic): Simplify to only call 
handle_pragma_vector.
            * config/riscv/riscv-vector-builtins.cc (pragma_intrinsic_flags):
            Move struct definition here from riscv-c.cc.
            (riscv_pragma_intrinsic_flags_pollute): Move and adapt from
            riscv-c.cc, add zvfbfmin, zvfhmin and vector_elen_bf_16 support.
            (riscv_pragma_intrinsic_flags_restore): Move from riscv-c.cc.
            (rvv_switcher::rvv_switcher): Add pollute_flags parameter to
            control flag manipulation.
            (rvv_switcher::~rvv_switcher): Restore flags conditionally.
            (register_builtin_types): Use rvv_switcher without polluting flags.
            (get_required_extensions): Remove function.
            (check_required_extensions): Simplify to only check type validity.
            (function_instance::function_returns_void_p): Move implementation
            from header.
            (function_builder::add_function): Register placeholder for LTO.
            (init_builtins): Simplify and handle LTO case.
            (reinit_builtins): Remove function.
            (handle_pragma_vector): Remove extension checking.
            * config/riscv/riscv-vector-builtins.h
            (function_instance::function_returns_void_p): Add declaration.
            (function_call_info::function_returns_void_p): Remove inline
            implementation.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/lto/pr110812_0.c: New test.
            * gcc.target/riscv/lto/pr110812_1.c: New test.
            * gcc.target/riscv/lto/riscv-lto.exp: New test driver.
            * gcc.target/riscv/lto/riscv_vector.h: New header wrapper.

Diff:
---
 gcc/config/riscv/riscv-c.cc                       |  84 ---------
 gcc/config/riscv/riscv-vector-builtins.cc         | 211 ++++++++++++----------
 gcc/config/riscv/riscv-vector-builtins.h          |  10 +-
 gcc/testsuite/gcc.target/riscv/lto/pr110812_0.c   |   9 +
 gcc/testsuite/gcc.target/riscv/lto/pr110812_1.c   |   9 +
 gcc/testsuite/gcc.target/riscv/lto/riscv-lto.exp  |  61 +++++++
 gcc/testsuite/gcc.target/riscv/lto/riscv_vector.h |  11 ++
 7 files changed, 211 insertions(+), 184 deletions(-)

diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc
index d2c0af359550..4fc052817824 100644
--- a/gcc/config/riscv/riscv-c.cc
+++ b/gcc/config/riscv/riscv-c.cc
@@ -34,77 +34,6 @@ along with GCC; see the file COPYING3.  If not see
 
 #define builtin_define(TXT) cpp_define (pfile, TXT)
 
-struct pragma_intrinsic_flags
-{
-  int intrinsic_riscv_isa_flags;
-
-  int intrinsic_riscv_vector_elen_flags;
-  int intrinsic_riscv_zvl_subext;
-  int intrinsic_riscv_zvb_subext;
-  int intrinsic_riscv_zvk_subext;
-};
-
-static void
-riscv_pragma_intrinsic_flags_pollute (struct pragma_intrinsic_flags *flags)
-{
-  flags->intrinsic_riscv_isa_flags = riscv_isa_flags;
-  flags->intrinsic_riscv_vector_elen_flags = riscv_vector_elen_flags;
-  flags->intrinsic_riscv_zvl_subext = riscv_zvl_subext;
-  flags->intrinsic_riscv_zvb_subext = riscv_zvb_subext;
-  flags->intrinsic_riscv_zvk_subext = riscv_zvk_subext;
-
-  riscv_isa_flags = riscv_isa_flags
-    | MASK_VECTOR;
-
-  riscv_zvl_subext = riscv_zvl_subext
-    | MASK_ZVL32B
-    | MASK_ZVL64B
-    | MASK_ZVL128B
-    | MASK_ZVL256B
-    | MASK_ZVL512B
-    | MASK_ZVL1024B
-    | MASK_ZVL2048B
-    | MASK_ZVL4096B;
-
-  riscv_vector_elen_flags = riscv_vector_elen_flags
-    | MASK_VECTOR_ELEN_32
-    | MASK_VECTOR_ELEN_64
-    | MASK_VECTOR_ELEN_FP_16
-    | MASK_VECTOR_ELEN_FP_32
-    | MASK_VECTOR_ELEN_FP_64;
-
-  riscv_zvb_subext = riscv_zvb_subext
-    | MASK_ZVBB
-    | MASK_ZVBC
-    | MASK_ZVKB;
-
-  riscv_zvk_subext = riscv_zvk_subext
-    | MASK_ZVKG
-    | MASK_ZVKNED
-    | MASK_ZVKNHA
-    | MASK_ZVKNHB
-    | MASK_ZVKSED
-    | MASK_ZVKSH
-    | MASK_ZVKN
-    | MASK_ZVKNC
-    | MASK_ZVKNG
-    | MASK_ZVKS
-    | MASK_ZVKSC
-    | MASK_ZVKSG
-    | MASK_ZVKT;
-}
-
-static void
-riscv_pragma_intrinsic_flags_restore (struct pragma_intrinsic_flags *flags)
-{
-  riscv_isa_flags = flags->intrinsic_riscv_isa_flags;
-
-  riscv_vector_elen_flags = flags->intrinsic_riscv_vector_elen_flags;
-  riscv_zvl_subext = flags->intrinsic_riscv_zvl_subext;
-  riscv_zvb_subext = flags->intrinsic_riscv_zvb_subext;
-  riscv_zvk_subext = flags->intrinsic_riscv_zvk_subext;
-}
-
 static int
 riscv_ext_version_value (unsigned major, unsigned minor)
 {
@@ -278,20 +207,7 @@ riscv_pragma_intrinsic (cpp_reader *)
       || strcmp (name, "xtheadvector") == 0
       || strcmp (name, "xsfvcp") == 0)
     {
-      struct pragma_intrinsic_flags backup_flags;
-
-      riscv_pragma_intrinsic_flags_pollute (&backup_flags);
-
-      riscv_option_override ();
-      init_adjust_machine_modes ();
-      riscv_vector::reinit_builtins ();
       riscv_vector::handle_pragma_vector ();
-
-      riscv_pragma_intrinsic_flags_restore (&backup_flags);
-
-      /* Re-initialize after the flags are restored.  */
-      riscv_option_override ();
-      init_adjust_machine_modes ();
     }
   else
     error ("unknown %<#pragma riscv intrinsic%> option %qs", name);
diff --git a/gcc/config/riscv/riscv-vector-builtins.cc 
b/gcc/config/riscv/riscv-vector-builtins.cc
index 0db7549fc5ca..00a81578567d 100644
--- a/gcc/config/riscv/riscv-vector-builtins.cc
+++ b/gcc/config/riscv/riscv-vector-builtins.cc
@@ -3474,6 +3474,71 @@ static hash_table<registered_function_hasher> 
*function_table;
 static hash_table<non_overloaded_registered_function_hasher>
   *non_overloaded_function_table;
 
+struct pragma_intrinsic_flags
+{
+  int intrinsic_riscv_isa_flags;
+  int intrinsic_riscv_base_subext;
+
+  int intrinsic_riscv_vector_elen_flags;
+  int intrinsic_riscv_zvl_subext;
+  int intrinsic_riscv_zvf_subext;
+};
+
+static void
+riscv_pragma_intrinsic_flags_pollute (struct pragma_intrinsic_flags *flags)
+{
+  /* We already defer the required extension checking to expantion time, so we
+     only need to pollute those flags that might affect the type registration.
+
+     e.g. zvfbmin and zvfhmin are required to define the vector bf16 and f16,
+         and VECTOR_ELEN* also required for vector interger and floating
+         type.  */
+  flags->intrinsic_riscv_isa_flags = riscv_isa_flags;
+  flags->intrinsic_riscv_base_subext = riscv_base_subext;
+  flags->intrinsic_riscv_vector_elen_flags = riscv_vector_elen_flags;
+  flags->intrinsic_riscv_zvl_subext = riscv_zvl_subext;
+  flags->intrinsic_riscv_zvf_subext = riscv_zvf_subext;
+
+  riscv_zvf_subext = riscv_zvf_subext
+    | MASK_ZVFBFMIN
+    | MASK_ZVFHMIN;
+
+  riscv_isa_flags = riscv_isa_flags
+    | MASK_VECTOR;
+
+  riscv_base_subext = riscv_base_subext
+    | MASK_MUL;
+
+  riscv_zvl_subext = riscv_zvl_subext
+    | MASK_ZVL32B
+    | MASK_ZVL64B
+    | MASK_ZVL128B
+    | MASK_ZVL256B
+    | MASK_ZVL512B
+    | MASK_ZVL1024B
+    | MASK_ZVL2048B
+    | MASK_ZVL4096B;
+
+  riscv_vector_elen_flags = riscv_vector_elen_flags
+    | MASK_VECTOR_ELEN_32
+    | MASK_VECTOR_ELEN_64
+    | MASK_VECTOR_ELEN_FP_16
+    | MASK_VECTOR_ELEN_FP_32
+    | MASK_VECTOR_ELEN_FP_64
+    | MASK_VECTOR_ELEN_BF_16;
+}
+
+static void
+riscv_pragma_intrinsic_flags_restore (struct pragma_intrinsic_flags *flags)
+{
+  riscv_isa_flags = flags->intrinsic_riscv_isa_flags;
+  riscv_base_subext = flags->intrinsic_riscv_base_subext;
+
+  riscv_vector_elen_flags = flags->intrinsic_riscv_vector_elen_flags;
+  riscv_zvl_subext = flags->intrinsic_riscv_zvl_subext;
+  riscv_zvf_subext = flags->intrinsic_riscv_zvf_subext;
+}
+
 /* RAII class for enabling enough RVV features to define the built-in
    types and implement the riscv_vector.h pragma.
 
@@ -3486,21 +3551,42 @@ static 
hash_table<non_overloaded_registered_function_hasher>
 class rvv_switcher
 {
 public:
-  rvv_switcher ();
+  rvv_switcher (bool pollute_flags = true);
   ~rvv_switcher ();
 
 private:
   bool m_old_have_regs_of_mode[MAX_MACHINE_MODE];
+  struct pragma_intrinsic_flags backup_flags;
+  bool m_pollute_flags;
 };
 
-rvv_switcher::rvv_switcher ()
+static void
+register_builtin_types_on_null ();
+
+rvv_switcher::rvv_switcher (bool pollute_flags)
+  : m_pollute_flags (pollute_flags)
 {
+  if (m_pollute_flags)
+    {
+      riscv_pragma_intrinsic_flags_pollute (&backup_flags);
+      riscv_option_override ();
+    }
+
   /* Set have_regs_of_mode before targetm.init_builtins ().  */
   memcpy (m_old_have_regs_of_mode, have_regs_of_mode,
          sizeof (have_regs_of_mode));
   for (int i = 0; i < NUM_MACHINE_MODES; ++i)
     if (riscv_v_ext_vector_mode_p ((machine_mode) i))
       have_regs_of_mode[i] = true;
+
+  /* Not necessary to adjust mode and register type if we don't pollute
+     flags.  */
+  if (m_pollute_flags)
+    {
+      init_adjust_machine_modes ();
+
+      register_builtin_types_on_null ();
+    }
 }
 
 rvv_switcher::~rvv_switcher ()
@@ -3508,6 +3594,15 @@ rvv_switcher::~rvv_switcher ()
   /* Recover back have_regs_of_mode.  */
   memcpy (have_regs_of_mode, m_old_have_regs_of_mode,
          sizeof (have_regs_of_mode));
+
+  if (m_pollute_flags)
+    {
+      riscv_pragma_intrinsic_flags_restore (&backup_flags);
+
+      /* Re-initialize after the flags are restored.  */
+      riscv_option_override ();
+      init_adjust_machine_modes ();
+    }
 }
 
 /* Add attribute NAME to ATTRS.  */
@@ -3664,26 +3759,10 @@ register_tuple_type (vector_type_index type, 
vector_type_index subpart_type,
 static void
 register_builtin_types ()
 {
-  /* Get type node from get_typenode_from_name to prevent we have different 
type
-     node define in different target libraries, e.g. int32_t defined as
-     `long` in RV32/newlib-stdint, but `int` for RV32/glibc-stdint.h.
-     NOTE: uint[16|32|64]_type_node already defined in tree.h.  */
-  tree int8_type_node = get_typenode_from_name (INT8_TYPE);
-  tree uint8_type_node = get_typenode_from_name (UINT8_TYPE);
-  tree int16_type_node = get_typenode_from_name (INT16_TYPE);
-  tree int32_type_node = get_typenode_from_name (INT32_TYPE);
-  tree int64_type_node = get_typenode_from_name (INT64_TYPE);
-
-  machine_mode mode;
-#define DEF_RVV_TYPE(NAME, NCHARS, ABI_NAME, SCALAR_TYPE, VECTOR_MODE,         
\
-                    ARGS...)                                                  \
-  mode = VECTOR_MODE##mode;                                                    
\
-  register_builtin_type (VECTOR_TYPE_##NAME, SCALAR_TYPE##_type_node, mode);
-#define DEF_RVV_TUPLE_TYPE(NAME, NCHARS, ABI_NAME, SUBPART_TYPE, SCALAR_TYPE,  
\
-                          NF, VECTOR_SUFFIX)                                  \
-  register_tuple_type (VECTOR_TYPE_##NAME, VECTOR_TYPE_##SUBPART_TYPE,         
\
-                      SCALAR_TYPE##_type_node, NF);
-#include "riscv-vector-builtins.def"
+  /* Don't pollute flags at this stage to make sure we only register type with
+     what we want so far, we will register all type if necessary later.   */
+  rvv_switcher rvv (/* pollute_flags */ false);
+  register_builtin_types_on_null ();
 }
 
 /* Similar as register_builtin_types but perform the registration if and
@@ -3795,25 +3874,15 @@ required_extensions_p (enum rvv_base_type type)
   gcc_unreachable ();
 }
 
-static uint64_t
-get_required_extensions (vector_type_index type_idx)
-{
-  for (unsigned int i = 0; all_ops[i].index != NUM_VECTOR_TYPES; i++)
-    if (type_idx == all_ops[i].index)
-      return all_ops[i].required_extensions;
-  for (unsigned int i = 0; b_ops[i].index != NUM_VECTOR_TYPES; i++)
-    if (type_idx == b_ops[i].index)
-      return b_ops[i].required_extensions;
-  gcc_unreachable ();
-}
-
 /* Check whether all the RVV_REQUIRE_* values in REQUIRED_EXTENSIONS are
-   enabled.  */
+   enabled.
+   TODO: We defer the required extensions to expantion time, this function is
+        only doing the legality now, and we may rename this function and moving
+        to another layer.  */
 static bool
 check_required_extensions (const function_instance &instance)
 {
   rvv_type_info type_info = instance.type;
-  uint64_t required_extensions = type_info.required_extensions;
   const rvv_op_info *op_info = instance.op_info;
 
   if (required_extensions_p (op_info->ret.base_type))
@@ -3822,48 +3891,18 @@ check_required_extensions (const function_instance 
&instance)
        = op_info->ret.get_function_type_index (type_info.index);
       if (ret_type_idx == NUM_VECTOR_TYPES)
        return false;
-      required_extensions |= get_required_extensions (ret_type_idx);
     }
 
   for (unsigned i = 0; op_info->args[i].base_type != NUM_BASE_TYPES; ++i)
     {
       if (!required_extensions_p (op_info->args[i].base_type))
        continue;
-
       enum vector_type_index vector_type
        = op_info->args[i].get_function_type_index (type_info.index);
       if (vector_type == NUM_VECTOR_TYPES)
        return false;
-      required_extensions |= get_required_extensions (vector_type);
-
-      /* According to RVV ISA, EEW=64 index of indexed loads/stores require
-        XLEN = 64.  */
-      if (op_info->args[i].base_type == RVV_BASE_eew64_index)
-       required_extensions |= RVV_REQUIRE_RV64BIT;
     }
 
-  uint64_t isa_flags = 0;
-
-  if (TARGET_VECTOR_ELEN_BF_16)
-    isa_flags |= RVV_REQUIRE_ELEN_BF_16;
-  if (TARGET_VECTOR_ELEN_FP_16)
-    isa_flags |= RVV_REQUIRE_ELEN_FP_16;
-  if (TARGET_VECTOR_ELEN_FP_32)
-    isa_flags |= RVV_REQUIRE_ELEN_FP_32;
-  if (TARGET_VECTOR_ELEN_FP_64)
-    isa_flags |= RVV_REQUIRE_ELEN_FP_64;
-  if (TARGET_VECTOR_ELEN_64)
-    isa_flags |= RVV_REQUIRE_ELEN_64;
-  if (TARGET_64BIT)
-    isa_flags |= RVV_REQUIRE_RV64BIT;
-  if (TARGET_FULL_V)
-    isa_flags |= RVV_REQUIRE_FULL_V;
-  if (TARGET_MIN_VLEN > 32)
-    isa_flags |= RVV_REQUIRE_MIN_VLEN_64;
-
-  uint64_t missing_extensions = required_extensions & ~isa_flags;
-  if (missing_extensions != 0)
-    return false;
   return true;
 }
 
@@ -4044,6 +4083,12 @@ function_instance::get_return_type () const
   return op_info->ret.get_tree_type (type.index);
 }
 
+bool
+function_instance::function_returns_void_p () const
+{
+  return get_return_type () == void_type_node;
+}
+
 tree
 function_instance::get_arg_type (unsigned opno) const
 {
@@ -4316,7 +4361,7 @@ function_builder::add_function (const function_instance 
&instance,
      nodes and remove the target hook. For now, however, we need to appease the
      validation and return a non-NULL, non-error_mark_node node, so we
      arbitrarily choose integer_zero_node.  */
-  tree decl = placeholder_p
+  tree decl = placeholder_p || in_lto_p
                ? integer_zero_node
                : simulate_builtin_function_decl (input_location, name, fntype,
                                                  code, NULL, attrs);
@@ -5094,28 +5139,15 @@ builtin_type_p (const_tree type)
 void
 init_builtins ()
 {
-  rvv_switcher rvv;
-  if (!TARGET_VECTOR)
-    return;
-  register_builtin_types ();
-  if (in_lto_p)
-    handle_pragma_vector ();
-}
-
-/* Reinitialize builtins similar to init_builtins,  but only the null
-   builtin types will be registered.  */
-void
-reinit_builtins ()
-{
-  rvv_switcher rvv;
-
-  if (!TARGET_VECTOR)
-    return;
-
-  register_builtin_types_on_null ();
-
   if (in_lto_p)
+    /* "pragma vector" will register type during the process. */
     handle_pragma_vector ();
+  else
+    {
+      if (!TARGET_VECTOR)
+       return;
+      register_builtin_types ();
+    }
 }
 
 /* Implement TARGET_VERIFY_TYPE_CONTEXT for RVV types.  */
@@ -5281,10 +5313,7 @@ handle_pragma_vector ()
   function_table = new hash_table<registered_function_hasher> (1023);
   function_builder builder;
   for (unsigned int i = 0; i < ARRAY_SIZE (function_groups); ++i)
-  {
-    if (function_groups[i].match (function_groups[i].required_extensions))
-      builder.register_function_group (function_groups[i]);
-  }
+    builder.register_function_group (function_groups[i]);
 }
 
 /* Return the function decl with RVV function subcode CODE, or error_mark_node
diff --git a/gcc/config/riscv/riscv-vector-builtins.h 
b/gcc/config/riscv/riscv-vector-builtins.h
index 86d81154db93..12a07a195c9e 100644
--- a/gcc/config/riscv/riscv-vector-builtins.h
+++ b/gcc/config/riscv/riscv-vector-builtins.h
@@ -377,6 +377,7 @@ public:
   bool any_type_float_p () const;
 
   tree get_return_type () const;
+  bool function_returns_void_p () const;
   tree get_arg_type (unsigned opno) const;
 
   /* The properties of the function.  (The explicit "enum"s are required
@@ -432,8 +433,6 @@ class function_call_info : public function_instance
 public:
   function_call_info (location_t, const function_instance &, tree);
 
-  bool function_returns_void_p ();
-
   /* The location of the call.  */
   location_t location;
 
@@ -441,13 +440,6 @@ public:
   tree fndecl;
 };
 
-/* Return true if the function has no return value.  */
-inline bool
-function_call_info::function_returns_void_p ()
-{
-  return TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
-}
-
 /* A class for folding a gimple function call.  */
 class gimple_folder : public function_call_info
 {
diff --git a/gcc/testsuite/gcc.target/riscv/lto/pr110812_0.c 
b/gcc/testsuite/gcc.target/riscv/lto/pr110812_0.c
new file mode 100644
index 000000000000..a2f70928b162
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/lto/pr110812_0.c
@@ -0,0 +1,9 @@
+/* { dg-lto-do link } */
+/* { dg-lto-options { { -flto -march=rv64gc -mabi=lp64d } } } */
+/* { dg-extra-ld-options "-nostdlib" } */
+
+void foo();
+
+int _start(){
+    foo();
+}
diff --git a/gcc/testsuite/gcc.target/riscv/lto/pr110812_1.c 
b/gcc/testsuite/gcc.target/riscv/lto/pr110812_1.c
new file mode 100644
index 000000000000..34d7cbbbcbbb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/lto/pr110812_1.c
@@ -0,0 +1,9 @@
+/* { dg-options { -flto -march=rv64gcv -mabi=lp64d } } */
+
+#include "riscv_vector.h"
+uint8_t *x, *y;
+void foo () {
+   int vl = __riscv_vsetvl_e8m8 (100);
+   vint8m8_t a = __riscv_vle8_v_i8m8 (x, 100);
+   __riscv_vse8_v_i8m8 (y, a, 100);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/lto/riscv-lto.exp 
b/gcc/testsuite/gcc.target/riscv/lto/riscv-lto.exp
new file mode 100644
index 000000000000..459cb766ac0a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/lto/riscv-lto.exp
@@ -0,0 +1,61 @@
+# Copyright (C) 2025 Free Software Foundation, Inc.
+
+# This program 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 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Exit immediately if this isn't an RISC-V target.
+if ![istarget riscv*-*-*] then {
+  return
+}
+
+# Test link-time optimization across multiple files.
+#
+# Programs are broken into multiple files.  Each one is compiled
+# separately with LTO information.  The final executable is generated
+# by collecting all the generated object files using regular LTO or WHOPR.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+# Load procedures from common libraries.
+load_lib standard.exp
+load_lib gcc.exp
+
+# Load the language-independent compabibility support procedures.
+load_lib lto.exp
+
+# If LTO has not been enabled, bail.
+if { ![check_effective_target_lto] } {
+    return
+}
+
+gcc_init
+lto_init no-mathlib
+
+# Define an identifier for use with this suite to avoid name conflicts
+# with other lto tests running at the same time.
+set sid "c_lto"
+
+# Main loop.
+foreach src [lsort [find $srcdir/$subdir *_0.c]] {
+    # If we're only testing specific files and this isn't one of them, skip it.
+    if ![runtest_file_p $runtests $src] then {
+       continue
+    }
+
+    lto-execute $src $sid
+}
+
+lto_finish
diff --git a/gcc/testsuite/gcc.target/riscv/lto/riscv_vector.h 
b/gcc/testsuite/gcc.target/riscv/lto/riscv_vector.h
new file mode 100644
index 000000000000..fbb4858fc867
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/lto/riscv_vector.h
@@ -0,0 +1,11 @@
+/* Wrapper of riscv_vector.h, prevent riscv_vector.h including stdint.h from
+   C library, that might cause problem on testing RV32 related testcase when
+   we disable multilib.  */
+#ifndef _RISCV_VECTOR_WRAP_H
+
+#define _GCC_WRAP_STDINT_H
+#include "stdint-gcc.h"
+#include_next <riscv_vector.h>
+#define _RISCV_VECTOR_WRAP_H
+
+#endif

Reply via email to