* [PATCH] m68k: Add LTO support
@ 2026-03-11 9:30 Daniel Palmer
2026-03-12 7:40 ` Yao Zi
2026-03-13 16:56 ` Kuan-Wei Chiu
0 siblings, 2 replies; 4+ messages in thread
From: Daniel Palmer @ 2026-03-11 9:30 UTC (permalink / raw)
To: visitorckw, angelo; +Cc: u-boot, Daniel Palmer
Most m68k retro/homebrew machines will have limited flash/RAM
so having LTO working would be nice.
Not many changes are need really. Most of this is copy/paste
from the ARM32 version.
The major change is that the direct register usage of d7 for gd
needs to be hidden so that when LTO passes over everything it
doesn't see multiple instances of d7.
Signed-off-by: Daniel Palmer <daniel@thingy.jp>
---
This is another patch from my vault that I have been using
on various classic m68k machines for ages. I haven't tested
it with coldfire though.
arch/Kconfig | 1 +
arch/m68k/config.mk | 11 +++++++++--
arch/m68k/cpu/m680x0/cpu.c | 2 +-
arch/m68k/include/asm/global_data.h | 19 +++++++++++++++++++
arch/m68k/lib/ashldi3.c | 1 +
arch/m68k/lib/lshrdi3.c | 1 +
arch/m68k/lib/muldi3.c | 1 +
common/board_r.c | 4 ++--
common/init/board_init.c | 2 +-
9 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/arch/Kconfig b/arch/Kconfig
index 4af0da2485fb..488de442f557 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -112,6 +112,7 @@ config ARM
config M68K
bool "M68000 architecture"
+ select ARCH_SUPPORTS_LTO
select HAVE_PRIVATE_LIBGCC
select USE_PRIVATE_LIBGCC
select SYS_BOOT_GET_CMDLINE
diff --git a/arch/m68k/config.mk b/arch/m68k/config.mk
index 458953f97122..1be46adda966 100644
--- a/arch/m68k/config.mk
+++ b/arch/m68k/config.mk
@@ -8,9 +8,16 @@ ifneq ($(CONFIG_M680x0),y)
PLATFORM_CPPFLAGS += -fPIC
endif
KBUILD_LDFLAGS += -n -pie
-PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections
PLATFORM_RELFLAGS += -ffixed-d7
ifneq ($(CONFIG_M680x0),y)
PLATFORM_RELFLAGS += -msep-data
endif
-LDFLAGS_FINAL += --gc-sections -pie
+LDFLAGS_FINAL += -pie
+
+ifneq ($(LTO_ENABLE)$(CONFIG_USE_PRIVATE_LIBGCC),yy)
+LDFLAGS_FINAL += --gc-sections
+endif
+
+ifneq ($(LTO_ENABLE),y)
+PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections
+endif
diff --git a/arch/m68k/cpu/m680x0/cpu.c b/arch/m68k/cpu/m680x0/cpu.c
index f60b932c7dd4..3f87076b8c3d 100644
--- a/arch/m68k/cpu/m680x0/cpu.c
+++ b/arch/m68k/cpu/m680x0/cpu.c
@@ -24,7 +24,7 @@ void m68k_virt_init_reserve(ulong base)
for (i = 0; i < sizeof(*gd_ptr); i++)
p[i] = 0;
- gd = gd_ptr;
+ arch_setup_gd(gd);
gd->malloc_base = base + sizeof(*gd_ptr);
}
diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
index aea2ccabe083..9150ed4ab466 100644
--- a/arch/m68k/include/asm/global_data.h
+++ b/arch/m68k/include/asm/global_data.h
@@ -32,6 +32,25 @@ struct arch_global_data {
#include <asm-generic/global_data.h>
+#if defined(LTO_ENABLE)
+/* If LTO is enabled we have to hide d7 to avoid multiple symbol declarations */
+#define DECLARE_GLOBAL_DATA_PTR
+#define gd get_gd()
+
+static inline gd_t *get_gd(void)
+{
+ gd_t *gd_ptr;
+
+ __asm__ volatile("move.l %%d7, %0\n" : "=r" (gd_ptr));
+
+ return gd_ptr;
+}
+#else
#define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("d7")
+#endif
+static inline void arch_setup_gd(gd_t *new_gd)
+{
+ __asm__ volatile("move.l %0, %%d7\n" : : "r" (new_gd));
+}
#endif /* __ASM_GBL_DATA_H */
diff --git a/arch/m68k/lib/ashldi3.c b/arch/m68k/lib/ashldi3.c
index 9a4bc676bf4c..82bd9113ecbf 100644
--- a/arch/m68k/lib/ashldi3.c
+++ b/arch/m68k/lib/ashldi3.c
@@ -21,6 +21,7 @@ typedef union
DItype ll;
} DIunion;
+DItype __ashldi3 (DItype u, word_type b) __attribute__((used));
DItype __ashldi3 (DItype u, word_type b)
{
DIunion w;
diff --git a/arch/m68k/lib/lshrdi3.c b/arch/m68k/lib/lshrdi3.c
index e639e676a269..691d503d7313 100644
--- a/arch/m68k/lib/lshrdi3.c
+++ b/arch/m68k/lib/lshrdi3.c
@@ -21,6 +21,7 @@ typedef union
DItype ll;
} DIunion;
+DItype __lshrdi3 (DItype u, word_type b) __attribute__((used));
DItype __lshrdi3 (DItype u, word_type b)
{
DIunion w;
diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c
index c42ca1d753e5..53d674701531 100644
--- a/arch/m68k/lib/muldi3.c
+++ b/arch/m68k/lib/muldi3.c
@@ -54,6 +54,7 @@ typedef union
DItype ll;
} DIunion;
+DItype __muldi3 (DItype u, DItype v) __attribute__((used));
DItype __muldi3 (DItype u, DItype v)
{
DIunion w;
diff --git a/common/board_r.c b/common/board_r.c
index 76f9fc090fbe..58eb69005468 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -800,12 +800,12 @@ void board_init_r(gd_t *new_gd, ulong dest_addr)
* TODO(sjg@chromium.org): Consider doing this for all archs, or
* dropping the new_gd parameter.
*/
- if (CONFIG_IS_ENABLED(X86_64) && !IS_ENABLED(CONFIG_EFI_APP))
+ if ((CONFIG_IS_ENABLED(X86_64) && !IS_ENABLED(CONFIG_EFI_APP)) || CONFIG_IS_ENABLED(M68K))
arch_setup_gd(new_gd);
#if defined(CONFIG_RISCV)
set_gd(new_gd);
-#elif !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
+#elif !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64) && !defined(CONFIG_M68K)
gd = new_gd;
#endif
gd->flags &= ~GD_FLG_LOG_READY;
diff --git a/common/init/board_init.c b/common/init/board_init.c
index 2a6f39f51adb..c56b33e7be7c 100644
--- a/common/init/board_init.c
+++ b/common/init/board_init.c
@@ -17,7 +17,7 @@ DECLARE_GLOBAL_DATA_PTR;
* Unfortunately x86, ARM and RISC-V can't compile this code as gd is defined
* as macro and cannot be assigned.
*/
-#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_RISCV)
+#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_RISCV) && !defined(CONFIG_M68K)
__weak void arch_setup_gd(struct global_data *gd_ptr)
{
gd = gd_ptr;
--
2.51.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] m68k: Add LTO support
2026-03-11 9:30 [PATCH] m68k: Add LTO support Daniel Palmer
@ 2026-03-12 7:40 ` Yao Zi
2026-03-13 16:56 ` Kuan-Wei Chiu
1 sibling, 0 replies; 4+ messages in thread
From: Yao Zi @ 2026-03-12 7:40 UTC (permalink / raw)
To: Daniel Palmer, visitorckw, angelo; +Cc: u-boot
On Wed, Mar 11, 2026 at 06:30:48PM +0900, Daniel Palmer wrote:
> Most m68k retro/homebrew machines will have limited flash/RAM
> so having LTO working would be nice.
>
> Not many changes are need really. Most of this is copy/paste
> from the ARM32 version.
>
> The major change is that the direct register usage of d7 for gd
> needs to be hidden so that when LTO passes over everything it
> doesn't see multiple instances of d7.
>
> Signed-off-by: Daniel Palmer <daniel@thingy.jp>
> ---
>
> This is another patch from my vault that I have been using
> on various classic m68k machines for ages. I haven't tested
> it with coldfire though.
>
> arch/Kconfig | 1 +
> arch/m68k/config.mk | 11 +++++++++--
> arch/m68k/cpu/m680x0/cpu.c | 2 +-
> arch/m68k/include/asm/global_data.h | 19 +++++++++++++++++++
> arch/m68k/lib/ashldi3.c | 1 +
> arch/m68k/lib/lshrdi3.c | 1 +
> arch/m68k/lib/muldi3.c | 1 +
> common/board_r.c | 4 ++--
> common/init/board_init.c | 2 +-
> 9 files changed, 36 insertions(+), 6 deletions(-)
...
> diff --git a/common/init/board_init.c b/common/init/board_init.c
> index 2a6f39f51adb..c56b33e7be7c 100644
> --- a/common/init/board_init.c
> +++ b/common/init/board_init.c
> @@ -17,7 +17,7 @@ DECLARE_GLOBAL_DATA_PTR;
> * Unfortunately x86, ARM and RISC-V can't compile this code as gd is defined
> * as macro and cannot be assigned.
This comment should probably be updated as well to reflect the code
behavior :)
> */
> -#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_RISCV)
> +#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_RISCV) && !defined(CONFIG_M68K)
> __weak void arch_setup_gd(struct global_data *gd_ptr)
> {
> gd = gd_ptr;
> --
> 2.51.0
>
Regards,
Yao Zi
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] m68k: Add LTO support
2026-03-11 9:30 [PATCH] m68k: Add LTO support Daniel Palmer
2026-03-12 7:40 ` Yao Zi
@ 2026-03-13 16:56 ` Kuan-Wei Chiu
2026-03-15 8:36 ` Daniel Palmer
1 sibling, 1 reply; 4+ messages in thread
From: Kuan-Wei Chiu @ 2026-03-13 16:56 UTC (permalink / raw)
To: Daniel Palmer; +Cc: angelo, u-boot
Hi Daniel,
On Wed, Mar 11, 2026 at 06:30:48PM +0900, Daniel Palmer wrote:
> Most m68k retro/homebrew machines will have limited flash/RAM
> so having LTO working would be nice.
>
> Not many changes are need really. Most of this is copy/paste
> from the ARM32 version.
>
> The major change is that the direct register usage of d7 for gd
> needs to be hidden so that when LTO passes over everything it
> doesn't see multiple instances of d7.
>
> Signed-off-by: Daniel Palmer <daniel@thingy.jp>
> ---
>
> This is another patch from my vault that I have been using
> on various classic m68k machines for ages. I haven't tested
> it with coldfire though.
>
> arch/Kconfig | 1 +
> arch/m68k/config.mk | 11 +++++++++--
> arch/m68k/cpu/m680x0/cpu.c | 2 +-
> arch/m68k/include/asm/global_data.h | 19 +++++++++++++++++++
> arch/m68k/lib/ashldi3.c | 1 +
> arch/m68k/lib/lshrdi3.c | 1 +
> arch/m68k/lib/muldi3.c | 1 +
> common/board_r.c | 4 ++--
> common/init/board_init.c | 2 +-
> 9 files changed, 36 insertions(+), 6 deletions(-)
>
> diff --git a/arch/Kconfig b/arch/Kconfig
> index 4af0da2485fb..488de442f557 100644
> --- a/arch/Kconfig
> +++ b/arch/Kconfig
> @@ -112,6 +112,7 @@ config ARM
>
> config M68K
> bool "M68000 architecture"
> + select ARCH_SUPPORTS_LTO
> select HAVE_PRIVATE_LIBGCC
> select USE_PRIVATE_LIBGCC
> select SYS_BOOT_GET_CMDLINE
> diff --git a/arch/m68k/config.mk b/arch/m68k/config.mk
> index 458953f97122..1be46adda966 100644
> --- a/arch/m68k/config.mk
> +++ b/arch/m68k/config.mk
> @@ -8,9 +8,16 @@ ifneq ($(CONFIG_M680x0),y)
> PLATFORM_CPPFLAGS += -fPIC
> endif
> KBUILD_LDFLAGS += -n -pie
> -PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections
> PLATFORM_RELFLAGS += -ffixed-d7
> ifneq ($(CONFIG_M680x0),y)
> PLATFORM_RELFLAGS += -msep-data
> endif
> -LDFLAGS_FINAL += --gc-sections -pie
> +LDFLAGS_FINAL += -pie
> +
> +ifneq ($(LTO_ENABLE)$(CONFIG_USE_PRIVATE_LIBGCC),yy)
> +LDFLAGS_FINAL += --gc-sections
> +endif
Maybe add a comment saying why we must drop --gc-sections when both LTO
and private libgcc are enabled?
> +
> +ifneq ($(LTO_ENABLE),y)
> +PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections
> +endif
> diff --git a/arch/m68k/cpu/m680x0/cpu.c b/arch/m68k/cpu/m680x0/cpu.c
> index f60b932c7dd4..3f87076b8c3d 100644
> --- a/arch/m68k/cpu/m680x0/cpu.c
> +++ b/arch/m68k/cpu/m680x0/cpu.c
> @@ -24,7 +24,7 @@ void m68k_virt_init_reserve(ulong base)
> for (i = 0; i < sizeof(*gd_ptr); i++)
> p[i] = 0;
>
> - gd = gd_ptr;
> + arch_setup_gd(gd);
I guess you mean arch_setup_gd(gd_ptr) here?
>
> gd->malloc_base = base + sizeof(*gd_ptr);
> }
> diff --git a/arch/m68k/include/asm/global_data.h b/arch/m68k/include/asm/global_data.h
> index aea2ccabe083..9150ed4ab466 100644
> --- a/arch/m68k/include/asm/global_data.h
> +++ b/arch/m68k/include/asm/global_data.h
> @@ -32,6 +32,25 @@ struct arch_global_data {
>
> #include <asm-generic/global_data.h>
>
> +#if defined(LTO_ENABLE)
> +/* If LTO is enabled we have to hide d7 to avoid multiple symbol declarations */
> +#define DECLARE_GLOBAL_DATA_PTR
> +#define gd get_gd()
> +
> +static inline gd_t *get_gd(void)
> +{
> + gd_t *gd_ptr;
> +
> + __asm__ volatile("move.l %%d7, %0\n" : "=r" (gd_ptr));
> +
> + return gd_ptr;
> +}
> +#else
> #define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("d7")
> +#endif
> +static inline void arch_setup_gd(gd_t *new_gd)
> +{
> + __asm__ volatile("move.l %0, %%d7\n" : : "r" (new_gd));
> +}
>
> #endif /* __ASM_GBL_DATA_H */
> diff --git a/arch/m68k/lib/ashldi3.c b/arch/m68k/lib/ashldi3.c
> index 9a4bc676bf4c..82bd9113ecbf 100644
> --- a/arch/m68k/lib/ashldi3.c
> +++ b/arch/m68k/lib/ashldi3.c
> @@ -21,6 +21,7 @@ typedef union
> DItype ll;
> } DIunion;
>
> +DItype __ashldi3 (DItype u, word_type b) __attribute__((used));
We have __used in linux/compiler.h, which I think is preferred over raw
__attribute__((used)).
Regards,
Kuan-Wei
> DItype __ashldi3 (DItype u, word_type b)
> {
> DIunion w;
> diff --git a/arch/m68k/lib/lshrdi3.c b/arch/m68k/lib/lshrdi3.c
> index e639e676a269..691d503d7313 100644
> --- a/arch/m68k/lib/lshrdi3.c
> +++ b/arch/m68k/lib/lshrdi3.c
> @@ -21,6 +21,7 @@ typedef union
> DItype ll;
> } DIunion;
>
> +DItype __lshrdi3 (DItype u, word_type b) __attribute__((used));
> DItype __lshrdi3 (DItype u, word_type b)
> {
> DIunion w;
> diff --git a/arch/m68k/lib/muldi3.c b/arch/m68k/lib/muldi3.c
> index c42ca1d753e5..53d674701531 100644
> --- a/arch/m68k/lib/muldi3.c
> +++ b/arch/m68k/lib/muldi3.c
> @@ -54,6 +54,7 @@ typedef union
> DItype ll;
> } DIunion;
>
> +DItype __muldi3 (DItype u, DItype v) __attribute__((used));
> DItype __muldi3 (DItype u, DItype v)
> {
> DIunion w;
> diff --git a/common/board_r.c b/common/board_r.c
> index 76f9fc090fbe..58eb69005468 100644
> --- a/common/board_r.c
> +++ b/common/board_r.c
> @@ -800,12 +800,12 @@ void board_init_r(gd_t *new_gd, ulong dest_addr)
> * TODO(sjg@chromium.org): Consider doing this for all archs, or
> * dropping the new_gd parameter.
> */
> - if (CONFIG_IS_ENABLED(X86_64) && !IS_ENABLED(CONFIG_EFI_APP))
> + if ((CONFIG_IS_ENABLED(X86_64) && !IS_ENABLED(CONFIG_EFI_APP)) || CONFIG_IS_ENABLED(M68K))
> arch_setup_gd(new_gd);
>
> #if defined(CONFIG_RISCV)
> set_gd(new_gd);
> -#elif !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64)
> +#elif !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_ARM64) && !defined(CONFIG_M68K)
> gd = new_gd;
> #endif
> gd->flags &= ~GD_FLG_LOG_READY;
> diff --git a/common/init/board_init.c b/common/init/board_init.c
> index 2a6f39f51adb..c56b33e7be7c 100644
> --- a/common/init/board_init.c
> +++ b/common/init/board_init.c
> @@ -17,7 +17,7 @@ DECLARE_GLOBAL_DATA_PTR;
> * Unfortunately x86, ARM and RISC-V can't compile this code as gd is defined
> * as macro and cannot be assigned.
> */
> -#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_RISCV)
> +#if !defined(CONFIG_X86) && !defined(CONFIG_ARM) && !defined(CONFIG_RISCV) && !defined(CONFIG_M68K)
> __weak void arch_setup_gd(struct global_data *gd_ptr)
> {
> gd = gd_ptr;
> --
> 2.51.0
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] m68k: Add LTO support
2026-03-13 16:56 ` Kuan-Wei Chiu
@ 2026-03-15 8:36 ` Daniel Palmer
0 siblings, 0 replies; 4+ messages in thread
From: Daniel Palmer @ 2026-03-15 8:36 UTC (permalink / raw)
To: Kuan-Wei Chiu; +Cc: angelo, u-boot
Hi Kuan-Wei,
On Sat, 14 Mar 2026 at 01:56, Kuan-Wei Chiu <visitorckw@gmail.com> wrote:
> > +ifneq ($(LTO_ENABLE)$(CONFIG_USE_PRIVATE_LIBGCC),yy)
> > +LDFLAGS_FINAL += --gc-sections
> > +endif
>
> Maybe add a comment saying why we must drop --gc-sections when both LTO
> and private libgcc are enabled?
mm I'm not sure actually, I think we always have private libgcc. I
don't think a comment is needed because --gc-sections doesn't make
sense with LTO as far as I know because LTO will cause unneeded stuff
to get dropped either way.
Other issues noted. I'll fix and send a v2 after a little bit.
Cheers,
Daniel
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-03-15 8:36 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-11 9:30 [PATCH] m68k: Add LTO support Daniel Palmer
2026-03-12 7:40 ` Yao Zi
2026-03-13 16:56 ` Kuan-Wei Chiu
2026-03-15 8:36 ` Daniel Palmer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox