Skip to content

Commit eacc876

Browse files
mdtoguchivladimirlaz
authored andcommitted
[SYCL][OpenMP] Update compilation behaviors with fat archives
Allow for compilation using multiple objects and also enable compilation from source. Initial support for compilation from fat archives only allowed the compile to be from a single object and the fat archive. These changes expand on that to allow compilation direct from source files and multiple objects. Signed-off-by: Michael D Toguchi <[email protected]>
1 parent b343f8f commit eacc876

File tree

9 files changed

+253
-73
lines changed

9 files changed

+253
-73
lines changed

clang/include/clang/Driver/Action.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ class OffloadUnbundlingJobAction final : public JobAction {
598598

599599
public:
600600
// Offloading unbundling doesn't change the type of output.
601-
OffloadUnbundlingJobAction(Action *Input);
601+
OffloadUnbundlingJobAction(ActionList &Inputs);
602602

603603
/// Register information about a dependent action.
604604
void registerDependentActionInfo(const ToolChain *TC, StringRef BoundArch,

clang/include/clang/Driver/Types.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,5 @@ TYPE("spirv", SPIRV, INVALID, "spv", "")
104104
TYPE("sycl-header", SYCL_Header, INVALID, "h", "")
105105
TYPE("sycl-fatbin", SYCL_FATBIN, INVALID, nullptr, "")
106106
TYPE("hip-fatbin", HIP_FATBIN, INVALID, "hipfb", "A")
107+
TYPE("tempfilelist", Tempfilelist, INVALID, nullptr, "")
107108
TYPE("none", Nothing, INVALID, nullptr, "u")

clang/lib/Driver/Action.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ const char *Action::getClassName(ActionClass AC) {
4242
return "clang-offload-unbundler";
4343
case OffloadWrappingJobClass:
4444
return "clang-offload-wrapper";
45+
case SPIRVTranslatorJobClass:
46+
return "llvm-spirv";
4547
}
4648

4749
llvm_unreachable("invalid class");
@@ -407,8 +409,8 @@ OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs)
407409

408410
void OffloadUnbundlingJobAction::anchor() {}
409411

410-
OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input)
411-
: JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {}
412+
OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(ActionList &Inputs)
413+
: JobAction(OffloadUnbundlingJobClass, Inputs, Inputs.back()->getType()) {}
412414

413415
void OffloadWrappingJobAction::anchor() {}
414416

clang/lib/Driver/Driver.cpp

Lines changed: 151 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2461,17 +2461,18 @@ class OffloadingActionBuilder final {
24612461
return ABRT_Inactive;
24622462

24632463
CudaDeviceActions.clear();
2464-
auto *IA = cast<InputAction>(UA->getInputs().back());
2465-
std::string FileName = IA->getInputArg().getAsString(Args);
2466-
// Check if the type of the file is the same as the action. Do not
2467-
// unbundle it if it is not. Do not unbundle .so files, for example,
2468-
// which are not object files.
2469-
if (IA->getType() == types::TY_Object &&
2470-
(!llvm::sys::path::has_extension(FileName) ||
2471-
types::lookupTypeForExtension(
2472-
llvm::sys::path::extension(FileName).drop_front()) !=
2473-
types::TY_Object))
2474-
return ABRT_Inactive;
2464+
if (auto *IA = dyn_cast<InputAction>(UA->getInputs().back())) {
2465+
std::string FileName = IA->getInputArg().getAsString(Args);
2466+
// Check if the type of the file is the same as the action. Do not
2467+
// unbundle it if it is not. Do not unbundle .so files, for example,
2468+
// which are not object files.
2469+
if (IA->getType() == types::TY_Object &&
2470+
(!llvm::sys::path::has_extension(FileName) ||
2471+
types::lookupTypeForExtension(
2472+
llvm::sys::path::extension(FileName).drop_front()) !=
2473+
types::TY_Object))
2474+
return ABRT_Inactive;
2475+
}
24752476

24762477
for (auto Arch : GpuArchList) {
24772478
CudaDeviceActions.push_back(UA);
@@ -2893,17 +2894,18 @@ class OffloadingActionBuilder final {
28932894
// If this is an unbundling action use it as is for each OpenMP toolchain.
28942895
if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) {
28952896
OpenMPDeviceActions.clear();
2896-
auto *IA = cast<InputAction>(UA->getInputs().back());
2897-
std::string FileName = IA->getInputArg().getAsString(Args);
2898-
// Check if the type of the file is the same as the action. Do not
2899-
// unbundle it if it is not. Do not unbundle .so files, for example,
2900-
// which are not object files.
2901-
if (IA->getType() == types::TY_Object &&
2902-
(!llvm::sys::path::has_extension(FileName) ||
2903-
types::lookupTypeForExtension(
2904-
llvm::sys::path::extension(FileName).drop_front()) !=
2905-
types::TY_Object))
2906-
return ABRT_Inactive;
2897+
if (auto *IA = dyn_cast<InputAction>(UA->getInputs().back())) {
2898+
std::string FileName = IA->getInputArg().getAsString(Args);
2899+
// Check if the type of the file is the same as the action. Do not
2900+
// unbundle it if it is not. Do not unbundle .so files, for example,
2901+
// which are not object files.
2902+
if (IA->getType() == types::TY_Object &&
2903+
(!llvm::sys::path::has_extension(FileName) ||
2904+
types::lookupTypeForExtension(
2905+
llvm::sys::path::extension(FileName).drop_front()) !=
2906+
types::TY_Object))
2907+
return ABRT_Inactive;
2908+
}
29072909
for (unsigned I = 0; I < ToolChains.size(); ++I) {
29082910
OpenMPDeviceActions.push_back(UA);
29092911
UA->registerDependentActionInfo(
@@ -3102,21 +3104,22 @@ class OffloadingActionBuilder final {
31023104
// If this is an unbundling action use it as is for each SYCL toolchain.
31033105
if (auto *UA = dyn_cast<OffloadUnbundlingJobAction>(HostAction)) {
31043106
SYCLDeviceActions.clear();
3105-
auto *IA = cast<InputAction>(UA->getInputs().back());
3106-
std::string FileName = IA->getInputArg().getAsString(Args);
3107-
// Check if the type of the file is the same as the action. Do not
3108-
// unbundle it if it is not. Do not unbundle .so files, for example,
3109-
// which are not object files.
3110-
if (IA->getType() == types::TY_Object &&
3111-
(!llvm::sys::path::has_extension(FileName) ||
3112-
types::lookupTypeForExtension(
3107+
if (auto *IA = dyn_cast<InputAction>(UA->getInputs().back())) {
3108+
std::string FileName = IA->getInputArg().getAsString(Args);
3109+
// Check if the type of the file is the same as the action. Do not
3110+
// unbundle it if it is not. Do not unbundle .so files, for example,
3111+
// which are not object files.
3112+
if (IA->getType() == types::TY_Object &&
3113+
(!llvm::sys::path::has_extension(FileName) ||
3114+
types::lookupTypeForExtension(
31133115
llvm::sys::path::extension(FileName).drop_front()) !=
31143116
types::TY_Object))
3115-
return ABRT_Inactive;
3117+
return ABRT_Inactive;
3118+
}
31163119
for (unsigned I = 0; I < ToolChains.size(); ++I) {
31173120
SYCLDeviceActions.push_back(UA);
31183121
UA->registerDependentActionInfo(
3119-
ToolChains[I], /*BoundArch=*/StringRef(), Action::OFK_SYCL);
3122+
ToolChains[I], /*BoundArch=*/StringRef(), Action::OFK_SYCL);
31203123
}
31213124
return ABRT_Success;
31223125
}
@@ -3373,7 +3376,8 @@ class OffloadingActionBuilder final {
33733376
/// results will be kept in this action builder. Return true if an error was
33743377
/// found.
33753378
bool addHostDependenceToDeviceActions(Action *&HostAction,
3376-
const Arg *InputArg) {
3379+
const Arg *InputArg,
3380+
DerivedArgList &Args) {
33773381
if (!IsValid)
33783382
return true;
33793383

@@ -3386,12 +3390,27 @@ class OffloadingActionBuilder final {
33863390
if (CanUseBundler && isa<InputAction>(HostAction) &&
33873391
InputArg->getOption().getKind() == llvm::opt::Option::InputClass &&
33883392
!types::isSrcFile(HostAction->getType())) {
3389-
auto UnbundlingHostAction =
3390-
C.MakeAction<OffloadUnbundlingJobAction>(HostAction);
3391-
UnbundlingHostAction->registerDependentActionInfo(
3392-
C.getSingleOffloadToolChain<Action::OFK_Host>(),
3393-
/*BoundArch=*/StringRef(), Action::OFK_Host);
3394-
HostAction = UnbundlingHostAction;
3393+
const char * InputName = InputArg->getValue();
3394+
// Do not create an unbundling action for an object when we know a fat
3395+
// static library is being used. A separate unbundling action is created
3396+
// for all objects and the fat static library.
3397+
if (!(HostAction->getType() == types::TY_Object &&
3398+
llvm::sys::path::has_extension(InputName) &&
3399+
types::lookupTypeForExtension(
3400+
llvm::sys::path::extension(InputName).drop_front()) ==
3401+
types::TY_Object &&
3402+
Args.hasArg(options::OPT_foffload_static_lib_EQ))) {
3403+
ActionList HostActionList;
3404+
HostActionList.push_back(HostAction);
3405+
if (!HostActionList.empty()) {
3406+
auto UnbundlingHostAction =
3407+
C.MakeAction<OffloadUnbundlingJobAction>(HostActionList);
3408+
UnbundlingHostAction->registerDependentActionInfo(
3409+
C.getSingleOffloadToolChain<Action::OFK_Host>(),
3410+
/*BoundArch=*/StringRef(), Action::OFK_Host);
3411+
HostAction = UnbundlingHostAction;
3412+
}
3413+
}
33953414
}
33963415

33973416
assert(HostAction && "Invalid host action!");
@@ -3423,6 +3442,43 @@ class OffloadingActionBuilder final {
34233442
return false;
34243443
}
34253444

3445+
/// Generate an action that adds a host dependence to an unbundling action.
3446+
/// The results will be kept in this action builder. Return true if an error
3447+
/// was found.
3448+
bool addHostDependenceToUnbundlingAction(Action *&HostAction,
3449+
ActionList &InputActionList,
3450+
const Arg *InputArg) {
3451+
if (!IsValid || InputActionList.empty())
3452+
return true;
3453+
3454+
auto *DeviceUnbundlingAction =
3455+
C.MakeAction<OffloadUnbundlingJobAction>(InputActionList);
3456+
DeviceUnbundlingAction->registerDependentActionInfo(
3457+
C.getSingleOffloadToolChain<Action::OFK_Host>(),
3458+
/*BoundArch=*/StringRef(), Action::OFK_Host);
3459+
HostAction = DeviceUnbundlingAction;
3460+
3461+
// Register the offload kinds that are used.
3462+
auto &OffloadKind = InputArgToOffloadKindMap[InputArg];
3463+
for (auto *SB : SpecializedBuilders) {
3464+
if (!SB->isValid())
3465+
continue;
3466+
3467+
auto RetCode = SB->addDeviceDepences(HostAction);
3468+
3469+
// Host dependences for device actions are not compatible with that same
3470+
// action being ignored.
3471+
assert(RetCode != DeviceActionBuilder::ABRT_Ignore_Host &&
3472+
"Host dependence not expected to be ignored.!");
3473+
3474+
// Unless the builder was inactive for this action, we have to record the
3475+
// offload kind because the host will have to use it.
3476+
if (RetCode != DeviceActionBuilder::ABRT_Inactive)
3477+
OffloadKind |= SB->getAssociatedOffloadKind();
3478+
}
3479+
return false;
3480+
}
3481+
34263482
/// Add the offloading top level actions that are specific for unique
34273483
/// linking situations where objects are used at only the device link
34283484
/// with no intermedate steps.
@@ -3674,7 +3730,8 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
36743730

36753731
// Use the current host action in any of the offloading actions, if
36763732
// required.
3677-
if (OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg))
3733+
if (OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg,
3734+
Args))
36783735
break;
36793736

36803737
for (SmallVectorImpl<phases::ID>::iterator i = PL.begin(), e = PL.end();
@@ -3688,6 +3745,7 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
36883745
// Add any offload action the host action depends on.
36893746
Current = OffloadBuilder.addDeviceDependencesToHostAction(
36903747
Current, InputArg, Phase, FinalPhase, PL);
3748+
36913749
if (!Current)
36923750
break;
36933751

@@ -3726,7 +3784,8 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
37263784

37273785
// Use the current host action in any of the offloading actions, if
37283786
// required.
3729-
if (OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg))
3787+
if (OffloadBuilder.addHostDependenceToDeviceActions(Current, InputArg,
3788+
Args))
37303789
break;
37313790

37323791
if (Current->getType() == types::TY_Nothing)
@@ -3743,6 +3802,43 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
37433802

37443803
OffloadBuilder.appendTopLevelLinkAction(Actions);
37453804

3805+
// When a static fat archive is provided, create a new unbundling step
3806+
// for all of the objects.
3807+
if (Args.hasArg(options::OPT_foffload_static_lib_EQ) &&
3808+
!LinkerInputs.empty()) {
3809+
ActionList UnbundlerInputs;
3810+
ActionList TempLinkerInputs;
3811+
for (const auto &LI : LinkerInputs) {
3812+
// Unbundler only handles objects.
3813+
if (auto *IA = dyn_cast<InputAction>(LI)) {
3814+
std::string FileName = IA->getInputArg().getAsString(Args);
3815+
if (IA->getType() == types::TY_Object &&
3816+
(!llvm::sys::path::has_extension(FileName) ||
3817+
types::lookupTypeForExtension(
3818+
llvm::sys::path::extension(FileName).drop_front()) !=
3819+
types::TY_Object))
3820+
// Pass the Input along to linker.
3821+
TempLinkerInputs.push_back(LI);
3822+
else
3823+
// Add to unbundler.
3824+
UnbundlerInputs.push_back(LI);
3825+
} else
3826+
UnbundlerInputs.push_back(LI);
3827+
}
3828+
LinkerInputs.clear();
3829+
if (!UnbundlerInputs.empty()) {
3830+
Action *Current;
3831+
const Arg *LastArg = Args.getLastArg(options::OPT_foffload_static_lib_EQ);
3832+
OffloadBuilder.addHostDependenceToUnbundlingAction(Current,
3833+
UnbundlerInputs, LastArg);
3834+
Current = OffloadBuilder.addDeviceDependencesToHostAction(Current,
3835+
LastArg, phases::Link, FinalPhase, PL);
3836+
LinkerInputs.push_back(Current);
3837+
}
3838+
for (const auto &TLI : TempLinkerInputs)
3839+
LinkerInputs.push_back(TLI);
3840+
}
3841+
37463842
// Add a link action if necessary.
37473843
if (!LinkerInputs.empty()) {
37483844
Action *LA = C.MakeAction<LinkJobAction>(LinkerInputs, types::TY_Image);
@@ -4495,18 +4591,30 @@ InputInfo Driver::BuildJobsForActionNoCache(
44954591
// offloading prefix, we also do that for the host file because the
44964592
// unbundling action does not change the type of the output which can
44974593
// cause a overwrite.
4498-
std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix(
4594+
InputInfo CurI;
4595+
if (C.getInputArgs().hasArg(options::OPT_foffload_static_lib_EQ) &&
4596+
UI.DependentOffloadKind != Action::OFK_Host &&
4597+
JA->getType() == types::TY_Object) {
4598+
std::string TmpFileName =
4599+
C.getDriver().GetTemporaryPath(llvm::sys::path::stem(BaseInput),
4600+
"txt");
4601+
const char *TmpFile =
4602+
C.addTempFile(C.getArgs().MakeArgString(TmpFileName));
4603+
CurI = InputInfo(types::TY_Tempfilelist, TmpFile, TmpFile);
4604+
} else {
4605+
std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix(
44994606
UI.DependentOffloadKind,
45004607
UI.DependentToolChain->getTriple().normalize(),
45014608
/*CreatePrefixForHost=*/true);
4502-
auto CurI = InputInfo(
4609+
CurI = InputInfo(
45034610
UA,
45044611
GetNamedOutputPath(C, *UA, BaseInput, UI.DependentBoundArch,
45054612
/*AtTopLevel=*/false,
45064613
MultipleArchs ||
45074614
UI.DependentOffloadKind == Action::OFK_HIP,
45084615
OffloadingPrefix),
45094616
BaseInput);
4617+
}
45104618
// Save the unbundling result.
45114619
UnbundlingResults.push_back(CurI);
45124620

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3508,6 +3508,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
35083508
bool IsWindowsMSVC = RawTriple.isWindowsMSVCEnvironment();
35093509
bool IsIAMCU = RawTriple.isOSIAMCU();
35103510
bool IsSYCLDevice = (RawTriple.getEnvironment() == llvm::Triple::SYCLDevice);
3511+
// Using just the sycldevice environment is not enough to determine usage
3512+
// of the device triple when considering fat static archives. The
3513+
// compilation path requires the host object to be fed into the partial link
3514+
// step, and being part of the SYCL tool chain causes the incorrect target.
3515+
// FIXME - Is it possible to retain host environment when on a target
3516+
// device toolchain.
3517+
bool UseSYCLTriple = IsSYCLDevice && (!IsSYCL || IsSYCLOffloadDevice);
35113518

35123519
// Adjust IsWindowsXYZ for CUDA/HIP compilations. Even when compiling in
35133520
// device mode (i.e., getToolchain().getTriple() is NVPTX/AMDGCN, not
@@ -3529,7 +3536,16 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
35293536

35303537
// Add the "effective" target triple.
35313538
CmdArgs.push_back("-triple");
3532-
CmdArgs.push_back(Args.MakeArgString(TripleStr));
3539+
if (!UseSYCLTriple && IsSYCLDevice) {
3540+
// Do not use device triple when we know the device is not SYCL
3541+
// FIXME: We override the toolchain triple in this instance to address a
3542+
// disconnect with fat static archives. We should have a cleaner way of
3543+
// using the Host environment when on a device toolchain.
3544+
std::string NormalizedTriple =
3545+
llvm::Triple(llvm::sys::getProcessTriple()).normalize();
3546+
CmdArgs.push_back(Args.MakeArgString(NormalizedTriple));
3547+
} else
3548+
CmdArgs.push_back(Args.MakeArgString(TripleStr));
35333549

35343550
if (const Arg *MJ = Args.getLastArg(options::OPT_MJ)) {
35353551
DumpCompilationDatabase(C, MJ->getValue(), TripleStr, Output, Input, Args);
@@ -3568,7 +3584,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
35683584
CmdArgs.push_back(Args.MakeArgString(NormalizedTriple));
35693585
}
35703586

3571-
if (IsSYCLDevice) {
3587+
if (UseSYCLTriple) {
35723588
// We want to compile sycl kernels.
35733589
if (types::isCXX(Input.getType()))
35743590
CmdArgs.push_back("-std=c++11");
@@ -6365,8 +6381,6 @@ void OffloadBundler::ConstructJobMultipleOutputs(
63656381
// -unbundle
63666382

63676383
ArgStringList CmdArgs;
6368-
6369-
assert(Inputs.size() == 1 && "Expecting to unbundle a single file!");
63706384
InputInfo Input = Inputs.front();
63716385
const char *TypeArg = types::getTypeTempSuffix(Input.getType());
63726386
const char *InputFileName = Input.getFilename();
@@ -6386,9 +6400,10 @@ void OffloadBundler::ConstructJobMultipleOutputs(
63866400
llvm::sys::path::stem(Input.getFilename()).str() + "-prelink", "o");
63876401
InputFileName = C.addTempFile(C.getArgs().MakeArgString(TmpName));
63886402
LinkArgs.push_back(InputFileName);
6389-
// Input files consist of fat libraries and the object to be unbundled.
6390-
LinkArgs.push_back(Input.getFilename());
6391-
for (const auto& A :
6403+
// Input files consist of fat libraries and the object(s) to be unbundled.
6404+
for (const auto &I : Inputs)
6405+
LinkArgs.push_back(I.getFilename());
6406+
for (const auto &A :
63926407
TCArgs.getAllArgValues(options::OPT_foffload_static_lib_EQ))
63936408
LinkArgs.push_back(TCArgs.MakeArgString(A));
63946409
const char *Exec = TCArgs.MakeArgString(getToolChain().GetLinkerPath());

0 commit comments

Comments
 (0)