This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH ARM] RFC: PR69770 -mlong-calls does not affect calls to __gnu_mcount_nc generated by -pg


When compiling with -mlong-calls and -pg, calls to the __gnu_mcount_nc
function are not generated as long calls.

This is encountered when building an allyesconfig Linux kernel because
the Linux build system generates very large sections by partial
linking a large number of object files. This causes link failures,
which don't go away with -mlong-calls due to this bug. (However, with
this patch linking still fails due to calls in inline asm)

For example:

    extern void g(void);
    int f() { g(); return 0; }

compiles to:

        push    {r4, lr}
        push    {lr}
        bl      __gnu_mcount_nc    ;// not a long call
        ldr     r3, .L2
        blx     r3                 ;// a long call to g()
        mov     r0, #0
        pop     {r4, pc}

The call to __gnu_mcount_nc is generated from ARM_FUNCTION_PROFILER in
config/arm/bpabi.h.

For targets without MOVW/MOVT, the long call sequence requires a load
from the literal pool, and it is too late to set up a literal pool
entry from within ARM_FUNCTION_PROFILER. My approach to fix this is to
modify the prologue generation to load the address of __gnu_mcount_nc
into ip, so that it is ready when the call is generated.

This patch only implements the fix for ARM and Thumb-2. A similar fix
is possible for Thumb-1, but requires more slightly complex changes to
the prologue generation to make sure there is a low register
available.

This feels like a bit of a hack to me, so ideas for a cleaner solution
are welcome, if none, is this acceptable for trunk now, or should it
wait until GCC 7?
From 34993396a43fcfc263db5b02b2d1837c490f52ad Mon Sep 17 00:00:00 2001
From: Charles Baylis <charles.baylis@linaro.org>
Date: Thu, 11 Feb 2016 18:07:00 +0000
Subject: [PATCH] [ARM] PR69770 fix -mlong-calls with -pg

gcc/ChangeLog:

2016-02-12  Charles Baylis  <charles.baylis@linaro.org>

	* config/arm/arm.c (arm_expand_prologue): Load address of
	__gnu_mcount_nc in r12 if profiling and long calls are enabled.
        * config/arm/bpabi.h (ARM_FUNCTION_PROFILER): Emit long call to
	__gnu_mcount_nc long calls are enabled.
	(ARM_FUNCTION_PROFILER_SUPPORTS_LONG_CALLS): New define.

gcc/testsuite/ChangeLog:

2016-02-12  Charles Baylis  <charles.baylis@linaro.org>

        * gcc.target/arm/pr69770.c: New test.

Change-Id: I4c639a5edf32fa8c67324d37faee1cb4ddd57a5c

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 27aecf7..9ce9a58 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -21739,6 +21739,15 @@ arm_expand_prologue (void)
       arm_load_pic_register (mask);
     }
 
+  if (crtl->profile && TARGET_LONG_CALLS
+      && ARM_FUNCTION_PROFILER_SUPPORTS_LONG_CALLS)
+    {
+      rtx tmp = gen_rtx_SET (gen_rtx_REG (SImode, IP_REGNUM),
+			     gen_rtx_SYMBOL_REF (Pmode, "__gnu_mcount_nc"));
+      emit_insn (tmp);
+      emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, IP_REGNUM)));
+    }
+
   /* If we are profiling, make sure no instructions are scheduled before
      the call to mcount.  Similarly if the user has requested no
      scheduling in the prolog.  Similarly if we want non-call exceptions
diff --git a/gcc/config/arm/bpabi.h b/gcc/config/arm/bpabi.h
index 82128ef..b734a24 100644
--- a/gcc/config/arm/bpabi.h
+++ b/gcc/config/arm/bpabi.h
@@ -173,11 +173,21 @@
 
 #undef  NO_PROFILE_COUNTERS
 #define NO_PROFILE_COUNTERS 1
+#undef  ARM_FUNCTION_PROFILER_SUPPORTS_LONG_CALLS
+#define ARM_FUNCTION_PROFILER_SUPPORTS_LONG_CALLS 1
 #undef  ARM_FUNCTION_PROFILER
 #define ARM_FUNCTION_PROFILER(STREAM, LABELNO)  			\
 {									\
-  fprintf (STREAM, "\tpush\t{lr}\n");					\
-  fprintf (STREAM, "\tbl\t__gnu_mcount_nc\n");				\
+  if (TARGET_LONG_CALLS && TARGET_32BIT)				\
+  { 									\
+    fprintf (STREAM, "\tpush\t{lr}\n");					\
+    /* arm_expand_prolog() has already set up ip to contain the */	\
+    /* address of __gnu_mcount_nc.  */					\
+    fprintf (STREAM, "\tblx\tip\n");					\
+  } else {								\
+    fprintf (STREAM, "\tpush\t{lr}\n");					\
+    fprintf (STREAM, "\tbl\t__gnu_mcount_nc\n");			\
+  }									\
 }
 
 #undef SUBTARGET_FRAME_POINTER_REQUIRED
diff --git a/gcc/testsuite/gcc.target/arm/pr69770.c b/gcc/testsuite/gcc.target/arm/pr69770.c
new file mode 100644
index 0000000..61e5c6d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr69770.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-pg -mlong-calls" } */
+
+extern void g(void);
+
+int f() { g(); return 0; }
+
+/* { dg-final { scan-assembler-not "bl\[ \t\]+__gnu_mcount_nc" } } */
+/* { dg-final { scan-assembler "__gnu_mcount_nc" } } */
-- 
1.9.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]