[clang] [llvm] [MFS] Implement -fsplit-machine-functions for Mach-O (ARM64) (PR #179449)
Anton Bikineev via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 4 01:44:37 PST 2026
https://github.com/AntonBikineev updated https://github.com/llvm/llvm-project/pull/179449
>From f78957614bd40c37c17c6bc18372a94b5709b7f6 Mon Sep 17 00:00:00 2001
From: Anton Bikineev <bikineev at chromium.org>
Date: Tue, 3 Feb 2026 12:54:36 +0100
Subject: [PATCH] [MFS] Implement -fsplit-machine-functions for Mach-O (ARM64)
This patch enables machine function splitting for Mach-O targets on
x86 and AArch64.
1. Driver: Allow -fsplit-machine-functions for Mach-O triples.
2. ObjectFile: Implement getSectionForMachineBasicBlock for Mach-O to
place cold blocks into the __TEXT,__text_cold section.
3. AArch64: Relax isFunctionSafeToSplit for Mach-O targets as they
typically do not use a red zone and branch relaxation is handled
by the linker.
Added backend test to verify the implementation. Driver test was omitted
due to environment issues with llvm-profdata.
---
clang/include/clang/Options/Options.td | 2 +-
clang/lib/Driver/ToolChains/Clang.cpp | 6 ++--
.../CodeGen/TargetLoweringObjectFileImpl.h | 9 ++++++
.../CodeGen/TargetLoweringObjectFileImpl.cpp | 20 ++++++++++++
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 3 +-
.../AArch64/split-machine-functions-macho.ll | 31 +++++++++++++++++++
6 files changed, 67 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/split-machine-functions-macho.ll
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 5ecb516c2cf68..2137d5c22065e 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4704,7 +4704,7 @@ defm split_machine_functions: BoolFOption<"split-machine-functions",
CodeGenOpts<"SplitMachineFunctions">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Enable">,
NegFlag<SetFalse, [], [ClangOption], "Disable">,
- BothFlags<[], [ClangOption], " late function splitting using profile information (x86 and aarch64 ELF)">>;
+ BothFlags<[], [ClangOption], " late function splitting using profile information (x86 and aarch64 ELF/Mach-O)">>;
defm partition_static_data_sections: BoolFOption<"partition-static-data-sections",
CodeGenOpts<"PartitionStaticDataSections">, DefaultFalse,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 0293b04217673..6a171c3d4cfc7 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6237,8 +6237,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (Arg *A = Args.getLastArg(options::OPT_fsplit_machine_functions,
options::OPT_fno_split_machine_functions)) {
if (!A->getOption().matches(options::OPT_fno_split_machine_functions)) {
- // This codegen pass is only available on x86 and AArch64 ELF targets.
- if ((Triple.isX86() || Triple.isAArch64()) && Triple.isOSBinFormatELF())
+ // This codegen pass is only available on x86 and AArch64 ELF and Mach-O
+ // targets.
+ if ((Triple.isX86() || Triple.isAArch64()) &&
+ (Triple.isOSBinFormatELF() || Triple.isOSBinFormatMachO()))
A->render(Args, CmdArgs);
else
D.Diag(diag::err_drv_unsupported_opt_for_target)
diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
index 9f271dd502b24..eddb788bbebfa 100644
--- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -178,6 +178,15 @@ class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile {
const TargetMachine &TM) const override;
MCSection *getSectionForCommandLines() const override;
+
+ MCSection *
+ getSectionForMachineBasicBlock(const Function &F,
+ const MachineBasicBlock &MBB,
+ const TargetMachine &TM) const override;
+
+ MCSection *
+ getUniqueSectionForFunction(const Function &F,
+ const TargetMachine &TM) const override;
};
class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile {
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index fac0a17d4c0da..c2bbe54323f1c 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -1493,6 +1493,26 @@ MCSection *TargetLoweringObjectFileMachO::getSectionForCommandLines() const {
SectionKind::getReadOnly());
}
+MCSection *TargetLoweringObjectFileMachO::getSectionForMachineBasicBlock(
+ const Function &F, const MachineBasicBlock &MBB,
+ const TargetMachine &TM) const {
+ assert(MBB.isBeginSection() && "Basic block does not start a section!");
+
+ if (MBB.getSectionID() == MBBSectionID::ColdSectionID) {
+ return getContext().getMachOSection("__TEXT", "__text_cold",
+ MachO::S_REGULAR |
+ MachO::S_ATTR_PURE_INSTRUCTIONS,
+ SectionKind::getText());
+ }
+
+ return SectionForGlobal(&F, TM);
+}
+
+MCSection *TargetLoweringObjectFileMachO::getUniqueSectionForFunction(
+ const Function &F, const TargetMachine &TM) const {
+ return SectionForGlobal(&F, TM);
+}
+
const MCExpr *TargetLoweringObjectFileMachO::getTTypeGlobalReference(
const GlobalValue *GV, unsigned Encoding, const TargetMachine &TM,
MachineModuleInfo *MMI, MCStreamer &Streamer) const {
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 1775e3de8c8c5..ff952d2c4c99c 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -11105,7 +11105,8 @@ bool AArch64InstrInfo::isFunctionSafeToSplit(const MachineFunction &MF) const {
// a red zone. This is because relaxing a cross-section branch may require
// incrementing the stack pointer to spill a register, which would overwrite
// the red zone.
- if (MF.getInfo<AArch64FunctionInfo>()->hasRedZone().value_or(true))
+ if (MF.getInfo<AArch64FunctionInfo>()->hasRedZone().value_or(
+ !MF.getSubtarget<AArch64Subtarget>().isTargetMachO()))
return false;
return TargetInstrInfo::isFunctionSafeToSplit(MF);
diff --git a/llvm/test/CodeGen/AArch64/split-machine-functions-macho.ll b/llvm/test/CodeGen/AArch64/split-machine-functions-macho.ll
new file mode 100644
index 0000000000000..0dcea60f158cf
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/split-machine-functions-macho.ll
@@ -0,0 +1,31 @@
+; RUN: llc < %s -mtriple=arm64-apple-macos -split-machine-functions | FileCheck %s
+
+define void @foo(i1 %cond) !prof !0 {
+entry:
+ br i1 %cond, label %hot, label %cold, !prof !1
+hot:
+ call void @bar()
+ ret void
+cold:
+ call void @baz()
+ ret void
+}
+
+declare void @bar()
+declare void @baz()
+
+!0 = !{!"function_entry_count", i64 1000}
+!1 = !{!"branch_weights", i32 1000, i32 0}
+
+; CHECK: .section __TEXT,__text,regular,pure_instructions
+; CHECK: _foo:
+; CHECK: tbz w0, #0, [[TRAMPOLINE:LBB0_[0-9]+]]
+; CHECK: bl _bar
+; CHECK: ret
+; CHECK: [[TRAMPOLINE]]:
+; CHECK: b foo.cold
+
+; CHECK: .section __TEXT,__text_cold,regular,pure_instructions
+; CHECK: foo.cold:
+; CHECK: bl _baz
+; CHECK: ret
More information about the cfe-commits
mailing list