Skip to content

Commit 317a0fe

Browse files
committed
[Driver][CodeGen] Properly handle -fsplit-machine-functions for fatbinary compilation.
When building a fatbinary, the driver invokes the compiler multiple times with different "--target". (For example, with "-x cuda --cuda-gpu-arch=sm_70" flags, clang will be invoded twice, once with --target=x86_64_...., once with --target=sm_70) If we use -fsplit-machine-functions or -fno-split-machine-functions for such invocation, the driver reports an error. This CL changes the behavior so: - "-fsplit-machine-functions" is now passed to all targets, for non-X86 targets, the flag is a NOOP and causes a warning. - "-fno-split-machine-functions" now negates -fsplit-machine-functions (if -fno-split-machine-functions appears after any -fsplit-machine-functions) for any target triple, previously, it causes an error. - "-fsplit-machine-functions -Xarch_device -fno-split-machine-functions" enables MFS on host but disables MFS for GPUS without warnings/errors. - "-Xarch_host -fsplit-machine-functions" enables MFS on host but disables MFS for GPUS without warnings/errors. Reviewed by: xur, dhoekwater Differential Revision: https://reviews.llvm.org/D157750
1 parent 2f3fe3e commit 317a0fe

File tree

10 files changed

+127
-8
lines changed

10 files changed

+127
-8
lines changed

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,10 @@ def warn_drv_fjmc_for_elf_only : Warning<
693693
"-fjmc works only for ELF; option ignored">,
694694
InGroup<OptionIgnored>;
695695

696+
def warn_drv_for_elf_only : Warning<
697+
"'%0' works only for ELF; option ignored">,
698+
InGroup<OptionIgnored>;
699+
696700
def warn_target_override_arm64ec : Warning<
697701
"/arm64EC has been overridden by specified target: %0; option ignored">,
698702
InGroup<OptionIgnored>;

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5870,14 +5870,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
58705870

58715871
if (Arg *A = Args.getLastArg(options::OPT_fsplit_machine_functions,
58725872
options::OPT_fno_split_machine_functions)) {
5873-
// This codegen pass is only available on x86-elf targets.
5874-
if (Triple.isX86() && Triple.isOSBinFormatELF()) {
5875-
if (A->getOption().matches(options::OPT_fsplit_machine_functions))
5873+
if (A->getOption().matches(options::OPT_fsplit_machine_functions)) {
5874+
// This codegen pass is only available on elf targets.
5875+
if (Triple.isOSBinFormatELF())
58765876
A->render(Args, CmdArgs);
5877-
} else {
5878-
D.Diag(diag::err_drv_unsupported_opt_for_target)
5879-
<< A->getAsString(Args) << TripleStr;
5877+
else
5878+
D.Diag(diag::warn_drv_for_elf_only) << A->getAsString(Args);
58805879
}
5880+
// Do not issue warnings for -fno-split-machine-functions even it is not
5881+
// on ELF.
58815882
}
58825883

58835884
Args.AddLastArg(CmdArgs, options::OPT_finstrument_functions,
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// REQUIRES: system-linux
2+
// REQUIRES: x86-registered-target
3+
// REQUIRES: nvptx-registered-target
4+
// REQUIRES: shell
5+
6+
// Check that -fsplit-machine-functions is passed to both x86 and cuda
7+
// compilation and does not cause driver error.
8+
// RUN: %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -nogpuinc \
9+
// RUN: --cuda-gpu-arch=sm_70 -x cuda -fsplit-machine-functions -S %s 2>&1 \
10+
// RUN: | FileCheck %s --check-prefix=MFS1
11+
// MFS1: "-target-cpu" "x86-64"{{.*}}"-fsplit-machine-functions"
12+
// MFS1: "-target-cpu" "sm_70"{{.*}}"-fsplit-machine-functions"
13+
14+
// Check that -fsplit-machine-functions is passed to cuda and it
15+
// causes a warning.
16+
// RUN: %clang --target=x86_64-unknown-linux-gnu -nogpulib -nogpuinc \
17+
// RUN: --cuda-gpu-arch=sm_70 -x cuda -fsplit-machine-functions -S %s 2>&1 \
18+
// RUN: | FileCheck %s --check-prefix=MFS2
19+
// MFS2: warning: -fsplit-machine-functions is not valid for nvptx
20+
21+
// Check that -Xarch_host -fsplit-machine-functions is passed only to
22+
// native compilation.
23+
// RUN: %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -nogpuinc \
24+
// RUN: --cuda-gpu-arch=sm_70 -x cuda -Xarch_host \
25+
// RUN: -fsplit-machine-functions -S %s \
26+
// RUN: 2>&1 | FileCheck %s --check-prefix=MFS3
27+
// MFS3: "-target-cpu" "x86-64"{{.*}}"-fsplit-machine-functions"
28+
// MFS3-NOT: "-target-cpu" "sm_70"{{.*}}"-fsplit-machine-functions"
29+
30+
// Check that -Xarch_host -fsplit-machine-functions does not cause any warning.
31+
// RUN: %clang --target=x86_64-unknown-linux-gnu -nogpulib -nogpuinc \
32+
// RUN --cuda-gpu-arch=sm_70 -x cuda -Xarch_host \
33+
// RUN -fsplit-machine-functions -S %s || { echo \
34+
// RUN "warning: -fsplit-machine-functions is not valid for" ; } \
35+
// RUN 2>&1 | FileCheck %s --check-prefix=MFS4
36+
// MFS4-NOT: warning: -fsplit-machine-functions is not valid for
37+
38+
// Check that -Xarch_device -fsplit-machine-functions does cause the warning.
39+
// RUN: %clang --target=x86_64-unknown-linux-gnu -nogpulib -nogpuinc \
40+
// RUN: --cuda-gpu-arch=sm_70 -x cuda -Xarch_device \
41+
// RUN: -fsplit-machine-functions -S %s 2>&1 | \
42+
// RUN: FileCheck %s --check-prefix=MFS5
43+
// MFS5: warning: -fsplit-machine-functions is not valid for
44+
45+
// Check that -fsplit-machine-functions -Xarch_device
46+
// -fno-split-machine-functions only passes MFS to x86
47+
// RUN: %clang -### --target=x86_64-unknown-linux-gnu -nogpulib -nogpuinc \
48+
// RUN: --cuda-gpu-arch=sm_70 -x cuda -fsplit-machine-functions \
49+
// RUN: -Xarch_device -fno-split-machine-functions -S %s \
50+
// RUN: 2>&1 | FileCheck %s --check-prefix=MFS6
51+
// MFS6: "-target-cpu" "x86-64"{{.*}}"-fsplit-machine-functions"
52+
// MFS6-NOT: "-target-cpu" "sm_70"{{.*}}"-fsplit-machine-functions"
53+
54+
// Check that -fsplit-machine-functions -Xarch_device
55+
// -fno-split-machine-functions has no warnings
56+
// RUN: %clang --target=x86_64-unknown-linux-gnu -nogpulib -nogpuinc \
57+
// RUN: --cuda-gpu-arch=sm_70 -x cuda -fsplit-machine-functions \
58+
// RUN: -Xarch_device -fno-split-machine-functions -S %s \
59+
// RUN: || { echo "warning: -fsplit-machine-functions is not valid for"; } \
60+
// RUN: 2>&1 | FileCheck %s --check-prefix=MFS7
61+
// MFS7-NOT: warning: -fsplit-machine-functions is not valid for
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// RUN: %clang -### -target x86_64 -fprofile-use=default.profdata -fsplit-machine-functions %s -c 2>&1 | FileCheck -check-prefix=CHECK-OPT %s
22
// RUN: %clang -### -target x86_64 -fsplit-machine-functions %s -c 2>&1 | FileCheck -check-prefix=CHECK-OPT %s
33
// RUN: %clang -### -target x86_64 -fprofile-use=default.profdata -fsplit-machine-functions -fno-split-machine-functions %s -c 2>&1 | FileCheck -check-prefix=CHECK-NOOPT %s
4-
// RUN: not %clang -c -target arm-unknown-linux -fsplit-machine-functions %s 2>&1 | FileCheck -check-prefix=CHECK-TRIPLE %s
4+
// RUN: %clang -c -target arm-unknown-linux -fsplit-machine-functions %s 2>&1 | FileCheck -check-prefix=CHECK-TRIPLE %s
55

66
// CHECK-OPT: "-fsplit-machine-functions"
77
// CHECK-NOOPT-NOT: "-fsplit-machine-functions"
8-
// CHECK-TRIPLE: error: unsupported option '-fsplit-machine-functions' for target
8+
// CHECK-TRIPLE: warning: -fsplit-machine-functions is not valid for arm

clang/test/Driver/fsplit-machine-functions2.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
// Test the mix of -fsplit-machine-functions and -fno-split-machine-functions
88
// RUN: %clang -### -target x86_64-unknown-linux -flto -fsplit-machine-functions -fno-split-machine-functions %s 2>&1 | FileCheck %s -check-prefix=CHECK-NOPASS
99
// RUN: %clang -### -target x86_64-unknown-linux -flto -fno-split-machine-functions -fsplit-machine-functions %s 2>&1 | FileCheck %s -check-prefix=CHECK-PASS
10+
// Check that for non-X86, passing no-split-machine-functions does not cause error.
11+
// RUN: %clang -### -target aarch64-unknown-linux -flto -fsplit-machine-functions -fno-split-machine-functions %s 2>&1 | FileCheck %s -check-prefix=CHECK-NOPASS2
1012

1113
// CHECK-PASS: "-plugin-opt=-split-machine-functions"
1214
// CHECK-NOPASS-NOT: "-plugin-opt=-split-machine-functions"
15+
// CHECK-NOPASS2-NOT: "-plugin-opt=-split-machine-functions"

llvm/include/llvm/IR/DiagnosticInfo.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ enum DiagnosticKind {
8686
DK_SrcMgr,
8787
DK_DontCall,
8888
DK_MisExpect,
89+
DK_MachineFunctionSplit,
8990
DK_FirstPluginKind // Must be last value to work with
9091
// getNextAvailablePluginDiagnosticKind
9192
};
@@ -1117,6 +1118,20 @@ class DiagnosticInfoDontCall : public DiagnosticInfo {
11171118
}
11181119
};
11191120

1121+
class DiagnosticInfoMachineFunctionSplit : public DiagnosticInfo {
1122+
StringRef TargetTriple;
1123+
1124+
public:
1125+
DiagnosticInfoMachineFunctionSplit(StringRef TargetTriple,
1126+
DiagnosticSeverity DS)
1127+
: DiagnosticInfo(DK_MachineFunctionSplit, DS),
1128+
TargetTriple(TargetTriple) {}
1129+
void print(DiagnosticPrinter &DP) const override;
1130+
static bool classof(const DiagnosticInfo *DI) {
1131+
return DI->getKind() == DK_MachineFunctionSplit;
1132+
}
1133+
};
1134+
11201135
} // end namespace llvm
11211136

11221137
#endif // LLVM_IR_DIAGNOSTICINFO_H

llvm/lib/CodeGen/MachineFunctionSplitter.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@
3535
#include "llvm/CodeGen/MachineFunctionPass.h"
3636
#include "llvm/CodeGen/MachineModuleInfo.h"
3737
#include "llvm/CodeGen/Passes.h"
38+
#include "llvm/IR/DiagnosticInfo.h"
3839
#include "llvm/IR/Function.h"
3940
#include "llvm/InitializePasses.h"
4041
#include "llvm/Support/CommandLine.h"
42+
#include "llvm/TargetParser/Triple.h"
4143
#include <optional>
4244

4345
using namespace llvm;
@@ -82,6 +84,13 @@ class MachineFunctionSplitter : public MachineFunctionPass {
8284
void getAnalysisUsage(AnalysisUsage &AU) const override;
8385

8486
bool runOnMachineFunction(MachineFunction &F) override;
87+
88+
bool doInitialization(Module &) override;
89+
90+
static bool isSupportedTriple(const Triple &T) { return T.isX86(); }
91+
92+
private:
93+
bool UnsupportedTriple = false;
8594
};
8695
} // end anonymous namespace
8796

@@ -127,7 +136,20 @@ static bool isColdBlock(const MachineBasicBlock &MBB,
127136
return (*Count < ColdCountThreshold);
128137
}
129138

139+
bool MachineFunctionSplitter::doInitialization(Module &M) {
140+
StringRef T = M.getTargetTriple();
141+
if (!isSupportedTriple(Triple(T))) {
142+
UnsupportedTriple = true;
143+
M.getContext().diagnose(
144+
DiagnosticInfoMachineFunctionSplit(T, DS_Warning));
145+
return false;
146+
}
147+
return MachineFunctionPass::doInitialization(M);
148+
}
149+
130150
bool MachineFunctionSplitter::runOnMachineFunction(MachineFunction &MF) {
151+
if (UnsupportedTriple)
152+
return false;
131153
// We target functions with profile data. Static information in the form
132154
// of exception handling code may be split to cold if user passes the
133155
// mfs-split-ehcode flag.

llvm/lib/IR/DiagnosticInfo.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,3 +449,7 @@ void DiagnosticInfoDontCall::print(DiagnosticPrinter &DP) const {
449449
if (!getNote().empty())
450450
DP << ": " << getNote();
451451
}
452+
453+
void DiagnosticInfoMachineFunctionSplit::print(DiagnosticPrinter &DP) const {
454+
DP << "-fsplit-machine-functions is not valid for " << TargetTriple;
455+
}
135 Bytes
Binary file not shown.

llvm/test/CodeGen/Generic/machine-function-splitter.ll

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@
1010
; RUN: sed 's/InstrProf/SampleProfile/g' %s > %t.ll
1111
; RUN: llc < %t.ll -mtriple=x86_64-unknown-linux-gnu -split-machine-functions | FileCheck %s --check-prefix=FSAFDO-MFS
1212
; RUN: llc < %t.ll -mtriple=x86_64-unknown-linux-gnu -split-machine-functions | FileCheck %s --check-prefix=FSAFDO-MFS2
13+
; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -debug-pass=Structure -fs-profile-file=%S/Inputs/fsloader-mfs.afdo -enable-fs-discriminator=true -improved-fs-discriminator=true -split-machine-functions 2>&1 | FileCheck %s --check-prefix=MFS_ON
14+
; RUN: llc < %s -mtriple=aarch64-unknown-linux-gnu -debug-pass=Structure -fs-profile-file=%S/Inputs/fsloader-mfs.afdo -enable-fs-discriminator=true -improved-fs-discriminator=true -split-machine-functions 2>&1 | FileCheck %s --check-prefix=MFS_OFF
15+
16+
;; Check that MFS is on for X86 targets.
17+
; MFS_ON: Machine Function Splitter Transformation
18+
; MFS_ON_NO: warning: -fsplit-machine-functions is not valid for
19+
;; Check that MFS is not on for non-X86 targets.
20+
; MFS_OFF: warning: -fsplit-machine-functions is not valid for
21+
; MFS_OFF_NO: Machine Function Splitter Transformation
1322

1423
define void @foo1(i1 zeroext %0) nounwind !prof !14 !section_prefix !15 {
1524
;; Check that cold block is moved to .text.split.

0 commit comments

Comments
 (0)