Index: gcc/gcc/config/i386/cygming.h
===================================================================
--- gcc.orig/gcc/config/i386/cygming.h	2010-07-18 12:15:00.061060600 +0200
+++ gcc/gcc/config/i386/cygming.h	2010-07-18 13:35:41.901998000 +0200
@@ -39,6 +39,13 @@ along with GCC; see the file COPYING3.
 #undef DEFAULT_ABI
 #define DEFAULT_ABI (TARGET_64BIT ? MS_ABI : SYSV_ABI)
 
+/* Choose the correct profiler mcount name.  */
+#undef MCOUNT_NAME
+#define MCOUNT_NAME "_mcount"
+
+#undef MCOUNT_NAME_BEFORE_PROLOGUE
+#define MCOUNT_NAME_BEFORE_PROLOGUE "_mcount_top"
+
 #if ! defined (USE_MINGW64_LEADING_UNDERSCORES)
 #undef USER_LABEL_PREFIX
 #define USER_LABEL_PREFIX (TARGET_64BIT ? "" : "_")
@@ -327,7 +334,7 @@ do {						\
 
 #undef PROFILE_HOOK
 #define PROFILE_HOOK(LABEL)						\
-  if (MAIN_NAME_P (DECL_NAME (current_function_decl)))			\
+  if (!flag_fentry && MAIN_NAME_P (DECL_NAME (current_function_decl)))	\
     {									\
       emit_call_insn (gen_rtx_CALL (VOIDmode,				\
 	gen_rtx_MEM (FUNCTION_MODE,					\
@@ -335,6 +342,13 @@ do {						\
 	const0_rtx));							\
     }
 
+#undef PROFILE_HOOK_BEFORE_PROFILE
+#define PROFILE_HOOK_BEFORE_PROFILE(FILE, LABEL)			\
+  if (flag_fentry && MAIN_NAME_P (DECL_NAME (current_function_decl)))	\
+    {									\
+      fprintf ((FILE), "\tcall\t%s_monstartup\n", user_label_prefix);	\
+    }
+
 /* Java Native Interface (JNI) methods on Win32 are invoked using the
    stdcall calling convention.  */
 #undef MODIFY_JNI_METHOD_CALL
Index: gcc/gcc/config/i386/i386.c
===================================================================
--- gcc.orig/gcc/config/i386/i386.c	2010-07-18 12:15:00.062060600 +0200
+++ gcc/gcc/config/i386/i386.c	2010-07-18 13:34:31.547974000 +0200
@@ -2768,6 +2768,15 @@ software_prefetching_beneficial_p (void)
     }
 }
 
+/* Return true, if profiling code should be emitted before
+   prologue. Otherwise it returns false.
+   Note: For x86 with "hotfix" it is sorried.  */
+static bool
+ix86_profile_before_prologue (void)
+{
+  return flag_fentry != 0;
+}
+
 /* Function that is callable from the debugger to print the current
    options.  */
 void
@@ -3671,6 +3680,34 @@ override_options (bool main_args_p)
     target_flags |= MASK_CLD & ~target_flags_explicit;
 #endif
 
+  {
+    int default_profile_top_flag = 0;
+    int only_default = 1;
+    bool force_default_profile_top_flag = (!TARGET_64BIT && flag_pic);
+
+#if defined(PROFILE_BEFORE_PROLOGUE)
+    default_profile_top_flag = (force_default_profile_top_flag ? 0 : 1);
+#endif
+#if defined(MCOUNT_NAME) && defined(MCOUNT_NAME_BEFORE_PROLOGUE)
+    only_default = 0;
+#endif
+
+    if (flag_fentry == -1)
+      flag_fentry = default_profile_top_flag;
+    if (flag_fentry != 0 && force_default_profile_top_flag)
+      {
+	sorry ("-mfentry isn't support for x86 in combination with -fpic");
+	flag_fentry = 0;
+      }
+    else if (flag_fentry != default_profile_top_flag && only_default)
+      {
+        if (!default_profile_top_flag)
+          sorry ("-mfentry isn't supported for this target");
+        else
+          sorry ("-mno-fentry isn't supported for this target");
+	flag_fentry = default_profile_top_flag;
+      }
+  }
   /* Save the initial options in case the user does function specific options */
   if (main_args_p)
     target_option_default_node = target_option_current_node
@@ -4841,7 +4878,7 @@ ix86_function_regparm (const_tree type,
   if (decl
       && TREE_CODE (decl) == FUNCTION_DECL
       && optimize
-      && !profile_flag)
+      && !(profile_flag && !flag_fentry))
     {
       /* FIXME: remove this CONST_CAST when cgraph.[ch] is constified.  */
       struct cgraph_local_info *i = cgraph_local_info (CONST_CAST_TREE (decl));
@@ -4913,7 +4950,8 @@ ix86_function_sseregparm (const_tree typ
 
   /* For local functions, pass up to SSE_REGPARM_MAX SFmode
      (and DFmode for SSE2) arguments in SSE registers.  */
-  if (decl && TARGET_SSE_MATH && optimize && !profile_flag)
+  if (decl && TARGET_SSE_MATH && optimize
+      && !(profile_flag && !flag_fentry))
     {
       /* FIXME: remove this CONST_CAST when cgraph.[ch] is constified.  */
       struct cgraph_local_info *i = cgraph_local_info (CONST_CAST_TREE(decl));
@@ -7878,7 +7916,7 @@ ix86_frame_pointer_required (void)
 	  || ix86_current_function_calls_tls_descriptor))
     return true;
 
-  if (crtl->profile)
+  if (crtl->profile && !flag_fentry)
     return true;
 
   return false;
@@ -8146,7 +8184,8 @@ gen_push (rtx arg)
 static unsigned int
 ix86_select_alt_pic_regnum (void)
 {
-  if (current_function_is_leaf && !crtl->profile
+  if (current_function_is_leaf
+      && !crtl->profile
       && !ix86_current_function_calls_tls_descriptor)
     {
       int i, drap;
@@ -9194,6 +9233,11 @@ ix86_expand_prologue (void)
     {
       rtx push, mov;
 
+      /* Check if profiling is active and we shall use profiling before
+         prologue variant. If so sorry.  */
+      if (crtl->profile && flag_fentry != 0)
+        sorry ("ms_hook_prologue attribute isn't compatible with -mfentry for 32-bit");
+
       /* Make sure the function starts with
 	 8b ff     movl.s %edi,%edi (emited by ix86_asm_output_function_label)
 	 55        push   %ebp
@@ -9483,7 +9527,7 @@ ix86_expand_prologue (void)
      when mcount needs it.  Blockage to avoid call movement across mcount
      call is emitted in generic code after the NOTE_INSN_PROLOGUE_END
      note.  */
-  if (crtl->profile && pic_reg_used)
+  if (crtl->profile && !flag_fentry && pic_reg_used)
     emit_insn (gen_prologue_use (pic_offset_table_rtx));
 
   if (crtl->drap_reg && !crtl->stack_realign_needed)
@@ -27285,11 +27329,30 @@ x86_field_alignment (tree field, int com
   return computed;
 }
 
+#if !defined(MCOUNT_NAME) && !defined(MCOUNT_NAME_BEFORE_PROLOGUE)
+#error MCOUNT_NAME ,and/or MCOUNT_NAME_BEFORE_PROLOGUE have to be define
+#endif
+
+/* Make sure both are getting defined.  */
+#ifndef MCOUNT_NAME
+#define MCOUNT_NAME MCOUNT_NAME_BEFORE_PROLOGUE
+#endif
+#ifndef MCOUNT_NAME_BEFORE_PROLOGUE
+#define MCOUNT_NAME_BEFORE_PROLOGUE MCOUNT_NAME
+#endif
+
 /* Output assembler code to FILE to increment profiler label # LABELNO
    for profiling a function entry.  */
 void
 x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
 {
+  const char *mcount_name = (flag_fentry ? MCOUNT_NAME_BEFORE_PROLOGUE
+					 : MCOUNT_NAME);
+
+#ifdef PROFILE_HOOK_BEFORE_PROFILE
+  PROFILE_HOOK_BEFORE_PROFILE (file, labelno);
+#endif
+
   if (TARGET_64BIT)
     {
 #ifndef NO_PROFILE_COUNTERS
@@ -27297,9 +27360,9 @@ x86_function_profiler (FILE *file, int l
 #endif
 
       if (DEFAULT_ABI == SYSV_ABI && flag_pic)
-	fputs ("\tcall\t*" MCOUNT_NAME "@GOTPCREL(%rip)\n", file);
+	fprintf (file, "\tcall\t*%s@GOTPCREL(%%rip)\n", mcount_name);
       else
-	fputs ("\tcall\t" MCOUNT_NAME "\n", file);
+	fprintf (file, "\tcall\t%s\n", mcount_name);
     }
   else if (flag_pic)
     {
@@ -27307,7 +27370,7 @@ x86_function_profiler (FILE *file, int l
       fprintf (file, "\tleal\t%sP%d@GOTOFF(%%ebx),%%" PROFILE_COUNT_REGISTER "\n",
 	       LPREFIX, labelno);
 #endif
-      fputs ("\tcall\t*" MCOUNT_NAME "@GOT(%ebx)\n", file);
+      fprintf (file, "\tcall\t*%s@GOT(%%ebx)\n", mcount_name);
     }
   else
     {
@@ -27315,7 +27378,7 @@ x86_function_profiler (FILE *file, int l
       fprintf (file, "\tmovl\t$%sP%d,%%" PROFILE_COUNT_REGISTER "\n",
 	       LPREFIX, labelno);
 #endif
-      fputs ("\tcall\t" MCOUNT_NAME "\n", file);
+      fprintf (file, "\tcall\t%s\n", mcount_name);
     }
 }
 
@@ -31363,6 +31426,9 @@ ix86_enum_va_list (int idx, const char *
 #define TARGET_ASM_ALIGNED_DI_OP ASM_QUAD
 #endif
 
+#undef TARGET_PROFILE_BEFORE_PROLOGUE
+#define TARGET_PROFILE_BEFORE_PROLOGUE ix86_profile_before_prologue
+
 #undef TARGET_ASM_UNALIGNED_HI_OP
 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
 #undef TARGET_ASM_UNALIGNED_SI_OP
Index: gcc/gcc/config/i386/i386.opt
===================================================================
--- gcc.orig/gcc/config/i386/i386.opt	2010-07-18 12:15:00.078060600 +0200
+++ gcc/gcc/config/i386/i386.opt	2010-07-18 13:34:31.568974000 +0200
@@ -375,3 +375,7 @@ Support RDRND built-in functions and cod
 mf16c
 Target Report Mask(ISA_F16C) Var(ix86_isa_flags) VarExists Save
 Support F16C built-in functions and code generation
+
+mfentry
+Target Report Var(flag_fentry) Init(-1)
+Emit profiling counter call at function entry before prologue.
Index: gcc/gcc/doc/invoke.texi
===================================================================
--- gcc.orig/gcc/doc/invoke.texi	2010-07-18 12:15:00.081060600 +0200
+++ gcc/gcc/doc/invoke.texi	2010-07-18 13:34:31.591974000 +0200
@@ -601,7 +601,7 @@ Objective-C and Objective-C++ Dialects}.
 -momit-leaf-frame-pointer  -mno-red-zone -mno-tls-direct-seg-refs @gol
 -mcmodel=@var{code-model} -mabi=@var{name} @gol
 -m32  -m64 -mlarge-data-threshold=@var{num} @gol
--msse2avx}
+-msse2avx -mfentry}
 
 @emph{IA-64 Options}
 @gccoptlist{-mbig-endian  -mlittle-endian  -mgnu-as  -mgnu-ld  -mno-pic @gol
@@ -12466,6 +12466,14 @@ For systems that use GNU libc, the defau
 @opindex msse2avx
 Specify that the assembler should encode SSE instructions with VEX
 prefix.  The option @option{-mavx} turns this on by default.
+
+@item -mfentry
+@itemx -mno-fentry
+@opindex mfentry
+If profiling is active @option{-pg} put the profiling
+counter call before prologue.
+Note: On x86 architectures the attribute @code{ms_hook_prologue}
+isn't possible at the moment for @option{-mfentry} and @option{-pg}.
 @end table
 
 These @samp{-m} switches are supported in addition to the above
Index: gcc/gcc/doc/tm.texi
===================================================================
--- gcc.orig/gcc/doc/tm.texi	2010-07-18 12:15:00.082060600 +0200
+++ gcc/gcc/doc/tm.texi	2010-07-18 12:25:33.157271600 +0200
@@ -7101,6 +7101,13 @@ Contains the value true if the target pl
 ``small data'' into a separate section.  The default value is false.
 @end deftypevr
 
+@deftypefn {Target Hook} bool TARGET_PROFILE_BEFORE_PROLOGUE (void)
+It returns true if target wants profile code emitted before prologue.
+
+The default version of this hook use the target macro
+@code{PROFILE_BEFORE_PROLOGUE}.
+@end deftypefn
+
 @deftypefn {Target Hook} bool TARGET_BINDS_LOCAL_P (const_tree @var{exp})
 Returns true if @var{exp} names an object for which name resolution
 rules must resolve to the current ``module'' (dynamic shared library
Index: gcc/gcc/doc/tm.texi.in
===================================================================
--- gcc.orig/gcc/doc/tm.texi.in	2010-07-18 12:15:00.089060600 +0200
+++ gcc/gcc/doc/tm.texi.in	2010-07-18 12:25:33.163271900 +0200
@@ -7101,6 +7101,8 @@ Contains the value true if the target pl
 ``small data'' into a separate section.  The default value is false.
 @end deftypevr
 
+@hook TARGET_PROFILE_BEFORE_PROLOGUE
+
 @hook TARGET_BINDS_LOCAL_P
 Returns true if @var{exp} names an object for which name resolution
 rules must resolve to the current ``module'' (dynamic shared library
Index: gcc/gcc/final.c
===================================================================
--- gcc.orig/gcc/final.c	2010-07-18 12:15:00.090060600 +0200
+++ gcc/gcc/final.c	2010-07-18 12:25:33.167272200 +0200
@@ -1546,10 +1546,8 @@ final_start_function (rtx first ATTRIBUT
 
   /* The Sun386i and perhaps other machines don't work right
      if the profiling code comes after the prologue.  */
-#ifdef PROFILE_BEFORE_PROLOGUE
-  if (crtl->profile)
+  if (targetm.profile_before_prologue () && crtl->profile)
     profile_function (file);
-#endif /* PROFILE_BEFORE_PROLOGUE */
 
 #if defined (DWARF2_UNWIND_INFO) && defined (HAVE_prologue)
   if (dwarf2out_do_frame ())
@@ -1591,10 +1589,8 @@ final_start_function (rtx first ATTRIBUT
 static void
 profile_after_prologue (FILE *file ATTRIBUTE_UNUSED)
 {
-#ifndef PROFILE_BEFORE_PROLOGUE
-  if (crtl->profile)
+  if (!targetm.profile_before_prologue () && crtl->profile)
     profile_function (file);
-#endif /* not PROFILE_BEFORE_PROLOGUE */
 }
 
 static void
Index: gcc/gcc/function.c
===================================================================
--- gcc.orig/gcc/function.c	2010-07-18 12:15:00.091060600 +0200
+++ gcc/gcc/function.c	2010-07-18 12:25:33.172272400 +0200
@@ -5179,13 +5179,11 @@ thread_prologue_and_epilogue_insns (void
       record_insns (seq, NULL, &prologue_insn_hash);
       emit_note (NOTE_INSN_PROLOGUE_END);
 
-#ifndef PROFILE_BEFORE_PROLOGUE
       /* Ensure that instructions are not moved into the prologue when
 	 profiling is on.  The call to the profiling routine can be
 	 emitted within the live range of a call-clobbered register.  */
-      if (crtl->profile)
+      if (!targetm.profile_before_prologue () && crtl->profile)
         emit_insn (gen_blockage ());
-#endif
 
       seq = get_insns ();
       end_sequence ();
Index: gcc/gcc/target.def
===================================================================
--- gcc.orig/gcc/target.def	2010-07-18 12:15:00.093060600 +0200
+++ gcc/gcc/target.def	2010-07-18 12:25:33.175272600 +0200
@@ -1218,6 +1218,15 @@ DEFHOOK
  bool, (const_tree exp),
  default_binds_local_p)
 
+/* Check if profiling code is before or after prologue.  */
+DEFHOOK
+(profile_before_prologue,
+ "It returns true if target wants profile code emitted before prologue.\n\n\
+The default version of this hook use the target macro\n\
+@code{PROFILE_BEFORE_PROLOGUE}.",
+ bool, (void),
+ default_profile_before_prologue)
+
 /* Modify and return the identifier of a DECL's external name,
    originally identified by ID, as required by the target,
    (eg, append @nn to windows32 stdcall function names).
Index: gcc/gcc/targhooks.c
===================================================================
--- gcc.orig/gcc/targhooks.c	2010-07-18 12:15:00.094060600 +0200
+++ gcc/gcc/targhooks.c	2010-07-18 12:25:33.177272700 +0200
@@ -1197,4 +1197,14 @@ default_register_move_cost (enum machine
 #endif
 }
 
+bool
+default_profile_before_prologue (void)
+{
+#ifndef PROFILE_BEFORE_PROLOGUE
+  return false;
+#else
+  return true;
+#endif
+}
+
 #include "gt-targhooks.h"
Index: gcc/gcc/targhooks.h
===================================================================
--- gcc.orig/gcc/targhooks.h	2010-07-18 12:15:00.110060600 +0200
+++ gcc/gcc/targhooks.h	2010-07-18 12:25:33.180272900 +0200
@@ -150,3 +150,4 @@ extern int default_memory_move_cost (enu
 extern int default_register_move_cost (enum machine_mode, reg_class_t,
 				       reg_class_t);
 
+extern bool default_profile_before_prologue (void);
