---
 gcc/cif-code.def                           | 12 ++++++++++++
 gcc/common.opt                             | 16 ++++++++++++++++
 gcc/doc/invoke.texi                        | 15 ++++++++++++++-
 gcc/flag-types.h                           |  7 +++++++
 gcc/ipa-inline.c                           | 12 ++++++++++++
 gcc/testsuite/gcc.dg/inline_visibility_1.c | 22 ++++++++++++++++++++++
 gcc/testsuite/gcc.dg/inline_visibility_2.c | 22 ++++++++++++++++++++++
 7 files changed, 105 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/inline_visibility_1.c
 create mode 100644 gcc/testsuite/gcc.dg/inline_visibility_2.c

diff --git a/gcc/cif-code.def b/gcc/cif-code.def
index 19a7621..9e8bd4e 100644
--- a/gcc/cif-code.def
+++ b/gcc/cif-code.def
@@ -132,6 +132,18 @@ DEFCIFCODE(USES_COMDAT_LOCAL, CIF_FINAL_ERROR,
 DEFCIFCODE(ATTRIBUTE_MISMATCH, CIF_FINAL_ERROR,
 	   N_("function attribute mismatch"))
 
+/* We can't inline because the user requests only inlining static function 
+   but the function is external visible.  */
+DEFCIFCODE(FUNCTION_EXTERN, CIF_FINAL_ERROR,
+	   N_("function is external visible when the user requests only"
+	      " inlining static"))
+
+/* We can't inline because the user requests only inlining external function 
+   but the function is static.  */
+DEFCIFCODE(FUNCTION_STATIC, CIF_FINAL_ERROR,
+	   N_("function is static when the user requests only inlining"
+	      " external"))
+
 /* We proved that the call is unreachable.  */
 DEFCIFCODE(UNREACHABLE, CIF_FINAL_ERROR,
 	   N_("unreachable"))
diff --git a/gcc/common.opt b/gcc/common.opt
index ebc3ef4..a3e754c 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1633,6 +1633,22 @@ finline-atomics
 Common Report Var(flag_inline_atomics) Init(1) Optimization
 Inline __atomic operations when a lock free instruction sequence is available.
 
+finline-visibility=
+Common Joined RejectNegative Enum(inline_visibility) Var(flag_inline_visibility) Init(INLINE_VISIBILITY_ALL) Optimization
+-finline-visibility=[all|extern|static]   Set the eligible visibility of function for inlining.
+
+Enum
+Name(inline_visibility) Type(enum inline_visibility) UnknownError(unknown Inline Visibility %qs)
+
+EnumValue
+Enum(inline_visibility) String(all) Value(INLINE_VISIBILITY_ALL)
+
+EnumValue
+Enum(inline_visibility) String(extern) Value(INLINE_VISIBILITY_EXTERN)
+
+EnumValue
+Enum(inline_visibility) String(static) Value(INLINE_VISIBILITY_STATIC)
+
 fcf-protection
 Common RejectNegative Alias(fcf-protection=,full)
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 8ac29fd..61c0c64 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -407,7 +407,8 @@ Objective-C and Objective-C++ Dialects}.
 -fgcse-sm  -fhoist-adjacent-loads  -fif-conversion @gol
 -fif-conversion2  -findirect-inlining @gol
 -finline-functions  -finline-functions-called-once  -finline-limit=@var{n} @gol
--finline-small-functions  -fipa-cp  -fipa-cp-clone @gol
+-finline-visibility=@r{[}all@r{|}extern@r{|}static@r{]} @gol
+-finline-small-functions -fipa-cp  -fipa-cp-clone @gol
 -fipa-bit-cp -fipa-vrp @gol
 -fipa-pta  -fipa-profile  -fipa-pure-const  -fipa-reference  -fipa-icf @gol
 -fira-algorithm=@var{algorithm} @gol
@@ -8060,6 +8061,18 @@ having large chains of nested wrapper functions.
 
 Enabled by default.
 
+@item -finline-visibility=@r{[}all@r{|}extern@r{|}static@r{]}
+@opindex finline-visibility
+By default, GCC inlines functions without considering their visibility. This
+flag allows finer control of inlining based on their visibility.
+
+The value @code{extern} tells the compiler to only inline functions with
+external visibility. The value @code{static} tells the compiler to only 
+inline functions with static visibility. The value @code{all} tells the 
+compilers to inline functions without condidering their visibility.
+
+The default value of @option{-finline-visibility} is @code{all}.
+
 @item -fipa-sra
 @opindex fipa-sra
 Perform interprocedural scalar replacement of aggregates, removal of
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index 500f663..777b060 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -336,6 +336,13 @@ enum gfc_convert
   GFC_FLAG_CONVERT_LITTLE
 };
 
+/* Inline Visibility values -finline-visibility=.  */
+enum inline_visibility
+{
+  INLINE_VISIBILITY_STATIC = 0,
+  INLINE_VISIBILITY_EXTERN = 1,
+  INLINE_VISIBILITY_ALL = 2
+};
 
 /* Control-Flow Protection values.  */
 enum cf_protection_level
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 0257885..88e61e3 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -376,6 +376,18 @@ can_inline_edge_p (struct cgraph_edge *e, bool report,
       e->inline_failed = CIF_ATTRIBUTE_MISMATCH;
       inlinable = false;
     }
+  else if (callee->externally_visible 
+	   && flag_inline_visibility == INLINE_VISIBILITY_STATIC)
+    {
+      e->inline_failed = CIF_FUNCTION_EXTERN;
+      inlinable = false;
+    }
+  else if (!callee->externally_visible 
+	   && flag_inline_visibility == INLINE_VISIBILITY_EXTERN)
+    {
+      e->inline_failed = CIF_FUNCTION_STATIC;
+      inlinable = false;
+    }
   if (!inlinable && report)
     report_inline_failed_reason (e);
   return inlinable;
diff --git a/gcc/testsuite/gcc.dg/inline_visibility_1.c b/gcc/testsuite/gcc.dg/inline_visibility_1.c
new file mode 100644
index 0000000..6f68f97
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/inline_visibility_1.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -finline-visibility=extern -fdump-tree-einline" } */
+
+extern int sum, n, m;
+
+int foo (int a)
+{
+  return a + n;
+}
+
+static int bar (int b) 
+{
+  return b * m;
+}
+
+int main()
+{
+  sum = foo (m) + bar (n); 
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "not inlinable: main/2 -> bar/1, function is static when the user requests only inlining external"  "einline" } } */
diff --git a/gcc/testsuite/gcc.dg/inline_visibility_2.c b/gcc/testsuite/gcc.dg/inline_visibility_2.c
new file mode 100644
index 0000000..74cc2c9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/inline_visibility_2.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -finline-visibility=static -fdump-tree-einline" } */
+
+extern int sum, n, m;
+
+int foo (int a)
+{
+  return a + n;
+}
+
+static int bar (int b)
+{
+  return b * m;
+}
+
+int main()
+{
+  sum = foo (m) + bar (n); 
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "not inlinable: main/2 -> foo/0, function is external visible when the user requests only inlining static"  "einline" } } */
-- 
1.9.1
