diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e19ba1f4835..d10df70fff4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2014-09-25 Andi Kleen + + * config/i386/i386.c (x86_print_call_or_nop): New function. + (x86_function_profiler): Support -mnop-mcount and + -mrecord-mcount. + * config/i386/i386.opt (-mnop-mcount, -mrecord-mcount): Add + * doc/invoke.texi: Document -mnop-mcount, -mrecord-mcount. + 2014-09-25 Jan Hubicka * ipa-prop.c (ipa_intraprocedural_devirtualization): Remove. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 1aec70fe4ce..4cf4dea7b07 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -3975,6 +3975,13 @@ ix86_option_override_internal (bool main_args_p, } } +#ifndef NO_PROFILE_COUNTERS + if (flag_nop_mcount) + error ("-mnop-mcount is not compatible with this target"); +#endif + if (flag_nop_mcount && flag_pic) + error ("-mnop-mcount is not implemented for -fPIC"); + /* Accept -msseregparm only if at least SSE support is enabled. */ if (TARGET_SSEREGPARM_P (opts->x_target_flags) && ! TARGET_SSE_P (opts->x_ix86_isa_flags)) @@ -39040,6 +39047,17 @@ x86_field_alignment (tree field, int computed) return computed; } +/* Print call to TARGET to FILE. */ + +static void +x86_print_call_or_nop (FILE *file, const char *target) +{ + if (flag_nop_mcount) + fprintf (file, "1:\tnopl 0x00(%%eax,%%eax,1)\n"); /* 5 byte nop. */ + else + fprintf (file, "1:\tcall\t%s\n", target); +} + /* Output assembler code to FILE to increment profiler label # LABELNO for profiling a function entry. */ void @@ -39047,7 +39065,6 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) { const char *mcount_name = (flag_fentry ? MCOUNT_NAME_BEFORE_PROLOGUE : MCOUNT_NAME); - if (TARGET_64BIT) { #ifndef NO_PROFILE_COUNTERS @@ -39055,9 +39072,9 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) #endif if (!TARGET_PECOFF && flag_pic) - fprintf (file, "\tcall\t*%s@GOTPCREL(%%rip)\n", mcount_name); + fprintf (file, "1:\tcall\t*%s@GOTPCREL(%%rip)\n", mcount_name); else - fprintf (file, "\tcall\t%s\n", mcount_name); + x86_print_call_or_nop (file, mcount_name); } else if (flag_pic) { @@ -39065,7 +39082,7 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) fprintf (file, "\tleal\t%sP%d@GOTOFF(%%ebx),%%" PROFILE_COUNT_REGISTER "\n", LPREFIX, labelno); #endif - fprintf (file, "\tcall\t*%s@GOT(%%ebx)\n", mcount_name); + fprintf (file, "1:\tcall\t*%s@GOT(%%ebx)\n", mcount_name); } else { @@ -39073,7 +39090,14 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED) fprintf (file, "\tmovl\t$%sP%d,%%" PROFILE_COUNT_REGISTER "\n", LPREFIX, labelno); #endif - fprintf (file, "\tcall\t%s\n", mcount_name); + x86_print_call_or_nop (file, mcount_name); + } + + if (flag_record_mcount) + { + fprintf (file, "\t.section __mcount_loc, \"a\",@progbits\n"); + fprintf (file, "\t.%s 1b\n", TARGET_64BIT ? "quad" : "long"); + fprintf (file, "\t.previous\n"); } } diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index 9208b766030..acf6b375157 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -789,6 +789,15 @@ mfentry Target Report Var(flag_fentry) Init(-1) Emit profiling counter call at function entry before prologue. +mrecord-mcount +Target Report Var(flag_record_mcount) Init(0) +Generate __mcount_loc section with all mcount or __fentry__ calls. + +mnop-mcount +Target Report Var(flag_nop_mcount) Init(0) +Generate mcount/__fentry__ calls as nops. To activate they need to be +patched in. + m8bit-idiv Target Report Mask(USE_8BIT_IDIV) Save Expand 32bit/64bit integer divide into 8bit unsigned integer divide with run-time check diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index eae4ab1ac5e..0c3f4beaea9 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -692,7 +692,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} -maddress-mode=@var{mode} @gol -m32 -m64 -mx32 -m16 -mlarge-data-threshold=@var{num} @gol --msse2avx -mfentry -m8bit-idiv @gol +-msse2avx -mfentry -mrecord-mcount -mnop-mcount -m8bit-idiv @gol -mavx256-split-unaligned-load -mavx256-split-unaligned-store @gol -mstack-protector-guard=@var{guard}} @@ -15988,6 +15988,21 @@ counter call before the prologue. Note: On x86 architectures the attribute @code{ms_hook_prologue} isn't possible at the moment for @option{-mfentry} and @option{-pg}. +@item -mrecord-mcount +@itemx -mno-record-mcount +@opindex mrecord-mcount +If profiling is active (@option{-pg}), generate a __mcount_loc section +that contains pointers to each profiling call. This is useful for +automatically patching and out calls. + +@item -mnop-mcount +@itemx -mno-nop-mcount +@opindex mnop-mcount +If profiling is active (@option{-pg}), generate the calls to +the profiling functions as nops. This is useful when they +should be patched in later dynamically. This is likely only +useful together with @option{-mrecord-mcount}. + @item -m8bit-idiv @itemx -mno-8bit-idiv @opindex 8bit-idiv diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f9e2445f26b..0074c0c09a0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-09-25 Andi Kleen + + * gcc.target/i386/nop-mcount.c: New file. + * gcc.target/i386/record-mcount.c: New file. + 2014-09-25 Sandra Loosemore * gcc.dg/vect/pr56933.c: Don't specify "dg-do run" explicitly. diff --git a/gcc/testsuite/gcc.target/i386/nop-mcount.c b/gcc/testsuite/gcc.target/i386/nop-mcount.c new file mode 100644 index 00000000000..25922315604 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/nop-mcount.c @@ -0,0 +1,24 @@ +/* Test -mnop-mcount */ +/* { dg-do compile } */ +/* { dg-options "-pg -mfentry -mrecord-mcount -mnop-mcount" } */ +/* { dg-final { scan-assembler-not "__fentry__" } } */ +/* Origin: Andi Kleen */ +extern void foobar(char *); + +void func(void) +{ + foobar ("Hello world\n"); +} + +void func2(void) +{ + int i; + for (i = 0; i < 10; i++) + foobar ("Hello world"); +} + +void func3(a) +char *a; +{ + foobar("Hello world"); +} diff --git a/gcc/testsuite/gcc.target/i386/record-mcount.c b/gcc/testsuite/gcc.target/i386/record-mcount.c new file mode 100644 index 00000000000..dae413e9b0e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/record-mcount.c @@ -0,0 +1,24 @@ +/* Test -mrecord-mcount */ +/* { dg-do compile } */ +/* { dg-options "-pg -mrecord-mcount" } */ +/* { dg-final { scan-assembler "mcount_loc" } } */ +/* Origin: Andi Kleen */ +extern void foobar(char *); + +void func(void) +{ + foobar ("Hello world\n"); +} + +void func2(void) +{ + int i; + for (i = 0; i < 10; i++) + foobar ("Hello world"); +} + +void func3(a) +char *a; +{ + foobar("Hello world"); +}