clang  14.0.0git
AMDGPUOpenMP.cpp
Go to the documentation of this file.
1 //===- AMDGPUOpenMP.cpp - AMDGPUOpenMP ToolChain Implementation -*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "AMDGPUOpenMP.h"
10 #include "AMDGPU.h"
11 #include "CommonArgs.h"
12 #include "ToolChains/ROCm.h"
15 #include "clang/Driver/Driver.h"
17 #include "clang/Driver/InputInfo.h"
18 #include "clang/Driver/Options.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/Support/FileSystem.h"
21 #include "llvm/Support/FormatAdapters.h"
22 #include "llvm/Support/FormatVariadic.h"
23 #include "llvm/Support/Path.h"
24 
25 using namespace clang::driver;
26 using namespace clang::driver::toolchains;
27 using namespace clang::driver::tools;
28 using namespace clang;
29 using namespace llvm::opt;
30 
31 namespace {
32 
33 static const char *getOutputFileName(Compilation &C, StringRef Base,
34  const char *Postfix,
35  const char *Extension) {
36  const char *OutputFileName;
37  if (C.getDriver().isSaveTempsEnabled()) {
38  OutputFileName =
39  C.getArgs().MakeArgString(Base.str() + Postfix + "." + Extension);
40  } else {
41  std::string TmpName =
42  C.getDriver().GetTemporaryPath(Base.str() + Postfix, Extension);
43  OutputFileName = C.addTempFile(C.getArgs().MakeArgString(TmpName));
44  }
45  return OutputFileName;
46 }
47 
48 static void addLLCOptArg(const llvm::opt::ArgList &Args,
49  llvm::opt::ArgStringList &CmdArgs) {
50  if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
51  StringRef OOpt = "0";
52  if (A->getOption().matches(options::OPT_O4) ||
53  A->getOption().matches(options::OPT_Ofast))
54  OOpt = "3";
55  else if (A->getOption().matches(options::OPT_O0))
56  OOpt = "0";
57  else if (A->getOption().matches(options::OPT_O)) {
58  // Clang and opt support -Os/-Oz; llc only supports -O0, -O1, -O2 and -O3
59  // so we map -Os/-Oz to -O2.
60  // Only clang supports -Og, and maps it to -O1.
61  // We map anything else to -O2.
62  OOpt = llvm::StringSwitch<const char *>(A->getValue())
63  .Case("1", "1")
64  .Case("2", "2")
65  .Case("3", "3")
66  .Case("s", "2")
67  .Case("z", "2")
68  .Case("g", "1")
69  .Default("0");
70  }
71  CmdArgs.push_back(Args.MakeArgString("-O" + OOpt));
72  }
73 }
74 
75 static bool checkSystemForAMDGPU(const ArgList &Args, const AMDGPUToolChain &TC,
76  std::string &GPUArch) {
77  if (auto Err = TC.getSystemGPUArch(Args, GPUArch)) {
78  std::string ErrMsg =
79  llvm::formatv("{0}", llvm::fmt_consume(std::move(Err)));
80  TC.getDriver().Diag(diag::err_drv_undetermined_amdgpu_arch) << ErrMsg;
81  return false;
82  }
83 
84  return true;
85 }
86 } // namespace
87 
88 const char *AMDGCN::OpenMPLinker::constructLLVMLinkCommand(
89  const toolchains::AMDGPUOpenMPToolChain &AMDGPUOpenMPTC, Compilation &C,
90  const JobAction &JA, const InputInfoList &Inputs, const ArgList &Args,
91  StringRef SubArchName, StringRef OutputFilePrefix) const {
92  ArgStringList CmdArgs;
93 
94  for (const auto &II : Inputs)
95  if (II.isFilename())
96  CmdArgs.push_back(II.getFilename());
97 
98  if (Args.hasArg(options::OPT_l)) {
99  auto Lm = Args.getAllArgValues(options::OPT_l);
100  bool HasLibm = false;
101  for (auto &Lib : Lm) {
102  if (Lib == "m") {
103  HasLibm = true;
104  break;
105  }
106  }
107 
108  if (HasLibm) {
110  AMDGPUOpenMPTC.getCommonDeviceLibNames(Args, SubArchName.str());
111  llvm::for_each(BCLibs, [&](StringRef BCFile) {
112  CmdArgs.push_back(Args.MakeArgString(BCFile));
113  });
114  }
115  }
116 
117  AddStaticDeviceLibsLinking(C, *this, JA, Inputs, Args, CmdArgs, "amdgcn",
118  SubArchName,
119  /* bitcode SDL?*/ true,
120  /* PostClang Link? */ false);
121  // Add an intermediate output file.
122  CmdArgs.push_back("-o");
123  const char *OutputFileName =
124  getOutputFileName(C, OutputFilePrefix, "-linked", "bc");
125  CmdArgs.push_back(OutputFileName);
126  const char *Exec =
127  Args.MakeArgString(getToolChain().GetProgramPath("llvm-link"));
128  C.addCommand(std::make_unique<Command>(
129  JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs,
130  InputInfo(&JA, Args.MakeArgString(OutputFileName))));
131  return OutputFileName;
132 }
133 
134 const char *AMDGCN::OpenMPLinker::constructLlcCommand(
135  Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
136  const llvm::opt::ArgList &Args, llvm::StringRef SubArchName,
137  llvm::StringRef OutputFilePrefix, const char *InputFileName,
138  bool OutputIsAsm) const {
139  // Construct llc command.
140  ArgStringList LlcArgs;
141  // The input to llc is the output from opt.
142  LlcArgs.push_back(InputFileName);
143  // Pass optimization arg to llc.
144  addLLCOptArg(Args, LlcArgs);
145  LlcArgs.push_back("-mtriple=amdgcn-amd-amdhsa");
146  LlcArgs.push_back(Args.MakeArgString("-mcpu=" + SubArchName));
147  LlcArgs.push_back(
148  Args.MakeArgString(Twine("-filetype=") + (OutputIsAsm ? "asm" : "obj")));
149 
150  for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
151  LlcArgs.push_back(A->getValue(0));
152  }
153 
154  // Add output filename
155  LlcArgs.push_back("-o");
156  const char *LlcOutputFile =
157  getOutputFileName(C, OutputFilePrefix, "", OutputIsAsm ? "s" : "o");
158  LlcArgs.push_back(LlcOutputFile);
159  const char *Llc = Args.MakeArgString(getToolChain().GetProgramPath("llc"));
160  C.addCommand(std::make_unique<Command>(
161  JA, *this, ResponseFileSupport::AtFileCurCP(), Llc, LlcArgs, Inputs,
162  InputInfo(&JA, Args.MakeArgString(LlcOutputFile))));
163  return LlcOutputFile;
164 }
165 
166 void AMDGCN::OpenMPLinker::constructLldCommand(
167  Compilation &C, const JobAction &JA, const InputInfoList &Inputs,
168  const InputInfo &Output, const llvm::opt::ArgList &Args,
169  const char *InputFileName) const {
170  // Construct lld command.
171  // The output from ld.lld is an HSA code object file.
172  ArgStringList LldArgs{"-flavor", "gnu", "--no-undefined",
173  "-shared", "-o", Output.getFilename(),
174  InputFileName};
175 
176  const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath("lld"));
177  C.addCommand(std::make_unique<Command>(
178  JA, *this, ResponseFileSupport::AtFileCurCP(), Lld, LldArgs, Inputs,
179  InputInfo(&JA, Args.MakeArgString(Output.getFilename()))));
180 }
181 
182 // For amdgcn the inputs of the linker job are device bitcode and output is
183 // object file. It calls llvm-link, opt, llc, then lld steps.
184 void AMDGCN::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA,
185  const InputInfo &Output,
186  const InputInfoList &Inputs,
187  const ArgList &Args,
188  const char *LinkingOutput) const {
189  const ToolChain &TC = getToolChain();
190  assert(getToolChain().getTriple().isAMDGCN() && "Unsupported target");
191 
192  const toolchains::AMDGPUOpenMPToolChain &AMDGPUOpenMPTC =
193  static_cast<const toolchains::AMDGPUOpenMPToolChain &>(TC);
194 
195  std::string GPUArch = Args.getLastArgValue(options::OPT_march_EQ).str();
196  if (GPUArch.empty()) {
197  if (!checkSystemForAMDGPU(Args, AMDGPUOpenMPTC, GPUArch))
198  return;
199  }
200 
201  // Prefix for temporary file name.
202  std::string Prefix;
203  for (const auto &II : Inputs)
204  if (II.isFilename())
205  Prefix = llvm::sys::path::stem(II.getFilename()).str() + "-" + GPUArch;
206  assert(Prefix.length() && "no linker inputs are files ");
207 
208  // Each command outputs different files.
209  const char *LLVMLinkCommand = constructLLVMLinkCommand(
210  AMDGPUOpenMPTC, C, JA, Inputs, Args, GPUArch, Prefix);
211 
212  // Produce readable assembly if save-temps is enabled.
213  if (C.getDriver().isSaveTempsEnabled())
214  constructLlcCommand(C, JA, Inputs, Args, GPUArch, Prefix, LLVMLinkCommand,
215  /*OutputIsAsm=*/true);
216  const char *LlcCommand = constructLlcCommand(C, JA, Inputs, Args, GPUArch,
217  Prefix, LLVMLinkCommand);
218  constructLldCommand(C, JA, Inputs, Output, Args, LlcCommand);
219 }
220 
222  const llvm::Triple &Triple,
223  const ToolChain &HostTC,
224  const ArgList &Args)
225  : ROCMToolChain(D, Triple, Args), HostTC(HostTC) {
226  // Lookup binaries into the driver directory, this is used to
227  // discover the clang-offload-bundler executable.
228  getProgramPaths().push_back(getDriver().Dir);
229 }
230 
232  const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
233  Action::OffloadKind DeviceOffloadingKind) const {
234  HostTC.addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadingKind);
235 
236  std::string GPUArch = DriverArgs.getLastArgValue(options::OPT_march_EQ).str();
237  if (GPUArch.empty()) {
238  if (!checkSystemForAMDGPU(DriverArgs, *this, GPUArch))
239  return;
240  }
241 
242  assert(DeviceOffloadingKind == Action::OFK_OpenMP &&
243  "Only OpenMP offloading kinds are supported.");
244 
245  CC1Args.push_back("-target-cpu");
246  CC1Args.push_back(DriverArgs.MakeArgStringRef(GPUArch));
247  CC1Args.push_back("-fcuda-is-device");
248 
249  if (DriverArgs.hasArg(options::OPT_nogpulib))
250  return;
251 
252  std::string BitcodeSuffix;
253  if (DriverArgs.hasFlag(options::OPT_fopenmp_target_new_runtime,
254  options::OPT_fno_openmp_target_new_runtime, false))
255  BitcodeSuffix = "new-amdgcn-" + GPUArch;
256  else
257  BitcodeSuffix = "amdgcn-" + GPUArch;
258 
259  addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, BitcodeSuffix,
260  getTriple());
261 }
262 
263 llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs(
264  const llvm::opt::DerivedArgList &Args, StringRef BoundArch,
265  Action::OffloadKind DeviceOffloadKind) const {
266  DerivedArgList *DAL =
267  HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind);
268  if (!DAL)
269  DAL = new DerivedArgList(Args.getBaseArgs());
270 
271  const OptTable &Opts = getDriver().getOpts();
272 
273  if (DeviceOffloadKind != Action::OFK_OpenMP) {
274  for (Arg *A : Args) {
275  DAL->append(A);
276  }
277  }
278 
279  if (!BoundArch.empty()) {
280  DAL->eraseArg(options::OPT_march_EQ);
281  DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_march_EQ),
282  BoundArch);
283  }
284 
285  return DAL;
286 }
287 
289  assert(getTriple().isAMDGCN());
290  return new tools::AMDGCN::OpenMPLinker(*this);
291 }
292 
294  ArgStringList &CC1Args) const {
296 }
297 
299 AMDGPUOpenMPToolChain::GetCXXStdlibType(const ArgList &Args) const {
300  return HostTC.GetCXXStdlibType(Args);
301 }
302 
304  const ArgList &DriverArgs, ArgStringList &CC1Args) const {
305  HostTC.AddClangSystemIncludeArgs(DriverArgs, CC1Args);
306 }
307 
309  ArgStringList &CC1Args) const {
310  HostTC.AddIAMCUIncludeArgs(Args, CC1Args);
311 }
312 
314  // The AMDGPUOpenMPToolChain only supports sanitizers in the sense that it
315  // allows sanitizer arguments on the command line if they are supported by the
316  // host toolchain. The AMDGPUOpenMPToolChain will actually ignore any command
317  // line arguments for any of these "supported" sanitizers. That means that no
318  // sanitization of device code is actually supported at this time.
319  //
320  // This behavior is necessary because the host and device toolchains
321  // invocations often share the command line, so the device toolchain must
322  // tolerate flags meant only for the host toolchain.
324 }
325 
326 VersionTuple
328  const ArgList &Args) const {
329  return HostTC.computeMSVCVersion(D, Args);
330 }
clang::driver::toolchains
Definition: AIX.h:55
clang::driver::ToolChain::getProgramPaths
path_list & getProgramPaths()
Definition: ToolChain.h:262
Driver.h
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::driver::toolchains::AMDGPUOpenMPToolChain::AddIAMCUIncludeArgs
void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override
Add arguments to use MCU GCC toolchain includes.
Definition: AMDGPUOpenMP.cpp:308
clang::driver::toolchains::AMDGPUOpenMPToolChain::TranslateArgs
llvm::opt::DerivedArgList * TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const override
TranslateArgs - Create a new derived argument list for any argument translations this ToolChain may w...
Definition: AMDGPUOpenMP.cpp:263
clang::driver::ToolChain::computeMSVCVersion
virtual VersionTuple computeMSVCVersion(const Driver *D, const llvm::opt::ArgList &Args) const
On Windows, returns the MSVC compatibility version.
Definition: ToolChain.cpp:1051
AMDGPUOpenMP.h
llvm::SmallVector
Definition: LLVM.h:38
clang::driver::toolchains::AMDGPUOpenMPToolChain::GetCXXStdlibType
CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const override
Definition: AMDGPUOpenMP.cpp:299
clang::driver::tools
Definition: AIX.h:17
AttributeLangSupport::C
@ C
Definition: SemaDeclAttr.cpp:54
clang::driver::ToolChain::getDriver
const Driver & getDriver() const
Definition: ToolChain.h:221
clang::driver::ToolChain::addClangWarningOptions
virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const
Add warning options that need to be passed to cc1 for this target.
Definition: ToolChain.cpp:747
clang::driver::Driver::getOpts
const llvm::opt::OptTable & getOpts() const
Definition: Driver.h:325
clang::driver::InputInfo
InputInfo - Wrapper for information about an input source.
Definition: InputInfo.h:22
clang::driver::Action::OFK_OpenMP
@ OFK_OpenMP
Definition: Action.h:93
InputInfo.h
clang::driver::Driver::Diag
DiagnosticBuilder Diag(unsigned DiagID) const
Definition: Driver.h:112
clang::driver::tools::AddStaticDeviceLibsLinking
void AddStaticDeviceLibsLinking(Compilation &C, const Tool &T, const JobAction &JA, const InputInfoList &Inputs, const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CmdArgs, StringRef Arch, StringRef Target, bool isBitCodeSDL, bool postClangLink)
Definition: CommonArgs.cpp:1775
DiagnosticDriver.h
clang::driver::Tool
Tool - Information on a specific compilation tool.
Definition: Tool.h:32
Options.h
clang::driver::toolchains::AMDGPUOpenMPToolChain::AMDGPUOpenMPToolChain
AMDGPUOpenMPToolChain(const Driver &D, const llvm::Triple &Triple, const ToolChain &HostTC, const llvm::opt::ArgList &Args)
Definition: AMDGPUOpenMP.cpp:221
llvm::opt
Definition: DiagnosticOptions.h:19
clang::driver::toolchains::AMDGPUOpenMPToolChain::addClangWarningOptions
void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override
Add warning options that need to be passed to cc1 for this target.
Definition: AMDGPUOpenMP.cpp:293
DriverDiagnostic.h
clang::driver::ResponseFileSupport::AtFileCurCP
static constexpr ResponseFileSupport AtFileCurCP()
Definition: Job.h:92
clang::driver::ToolChain::AddClangSystemIncludeArgs
virtual void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const
Add the clang cc1 arguments for system include paths.
Definition: ToolChain.cpp:738
clang::driver::ToolChain::CXXStdlibType
CXXStdlibType
Definition: ToolChain.h:95
clang::driver::tools::AMDGCN::OpenMPLinker
Definition: AMDGPUOpenMP.h:28
clang::driver::ToolChain::getTriple
const llvm::Triple & getTriple() const
Definition: ToolChain.h:223
clang::driver::toolchains::AMDGPUOpenMPToolChain::buildLinker
Tool * buildLinker() const override
Definition: AMDGPUOpenMP.cpp:288
Base
AMDGPU.h
clang::driver::toolchains::AMDGPUOpenMPToolChain::getSupportedSanitizers
SanitizerMask getSupportedSanitizers() const override
Return sanitizers which are available in this toolchain.
Definition: AMDGPUOpenMP.cpp:313
clang::driver::tools::addOpenMPDeviceRTL
void addOpenMPDeviceRTL(const Driver &D, const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, StringRef BitcodeSuffix, const llvm::Triple &Triple)
Definition: CommonArgs.cpp:1968
clang::driver::toolchains::AMDGPUOpenMPToolChain
Definition: AMDGPUOpenMP.h:68
clang::driver::toolchains::ROCMToolChain::getCommonDeviceLibNames
llvm::SmallVector< std::string, 12 > getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs, const std::string &GPUArch) const
Definition: AMDGPU.cpp:898
clang::driver::ToolChain::getSupportedSanitizers
virtual SanitizerMask getSupportedSanitizers() const
Return sanitizers which are available in this toolchain.
Definition: ToolChain.cpp:998
ROCm.h
clang::driver::toolchains::AMDGPUOpenMPToolChain::addClangTargetOptions
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind DeviceOffloadKind) const override
Add options that need to be passed to cc1 for this target.
Definition: AMDGPUOpenMP.cpp:231
Compilation.h
clang::driver::ToolChain
ToolChain - Access to tools for a single platform.
Definition: ToolChain.h:91
clang::driver::toolchains::AMDGPUOpenMPToolChain::AddClangSystemIncludeArgs
void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override
Add the clang cc1 arguments for system include paths.
Definition: AMDGPUOpenMP.cpp:303
clang::driver::Compilation
Compilation - A set of tasks to perform for a single driver invocation.
Definition: Compilation.h:45
clang::driver::ToolChain::GetCXXStdlibType
virtual CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const
Definition: ToolChain.cpp:819
clang::driver::ToolChain::AddIAMCUIncludeArgs
virtual void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const
Add arguments to use MCU GCC toolchain includes.
Definition: ToolChain.cpp:1034
clang::driver::InputInfo::getFilename
const char * getFilename() const
Definition: InputInfo.h:83
CommonArgs.h
clang
Definition: CalledOnceCheck.h:17
clang::driver::Driver
Driver - Encapsulate logic for constructing compilation processes from a set of gcc-driver-like comma...
Definition: Driver.h:59
clang::driver::ToolChain::TranslateArgs
virtual llvm::opt::DerivedArgList * TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef BoundArch, Action::OffloadKind DeviceOffloadKind) const
TranslateArgs - Create a new derived argument list for any argument translations this ToolChain may w...
Definition: ToolChain.h:306
clang::driver::toolchains::ROCMToolChain
Definition: AMDGPU.h:131
clang::driver::ToolChain::addClangTargetOptions
virtual void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind DeviceOffloadKind) const
Add options that need to be passed to cc1 for this target.
Definition: ToolChain.cpp:743
clang::driver::toolchains::AMDGPUOpenMPToolChain::computeMSVCVersion
VersionTuple computeMSVCVersion(const Driver *D, const llvm::opt::ArgList &Args) const override
On Windows, returns the MSVC compatibility version.
Definition: AMDGPUOpenMP.cpp:327
clang::driver::Action::OffloadKind
OffloadKind
Definition: Action.h:85
clang::driver
Definition: Action.h:31
clang::driver::JobAction
Definition: Action.h:380
clang::driver::toolchains::AMDGPUToolChain::getSystemGPUArch
llvm::Error getSystemGPUArch(const llvm::opt::ArgList &Args, std::string &GPUArch) const
Uses amdgpu_arch tool to get arch of the system GPU.
Definition: AMDGPU.cpp:785
clang::driver::toolchains::AMDGPUOpenMPToolChain::HostTC
const ToolChain & HostTC
Definition: AMDGPUOpenMP.h:100
clang::SanitizerMask
Definition: Sanitizers.h:30
clang::driver::toolchains::AMDGPUToolChain
Definition: AMDGPU.h:49