@@ -2883,6 +2883,9 @@ class OffloadingActionBuilder final {
2883
2883
// / Append linker actions generated by the builder.
2884
2884
virtual void appendLinkDependences (OffloadAction::DeviceDependences &DA) {}
2885
2885
2886
+ // / Append linker actions generated by the builder.
2887
+ virtual void addDeviceLinkDependencies (OffloadDepsJobAction *DA) {}
2888
+
2886
2889
// / Initialize the builder. Return true if any initialization errors are
2887
2890
// / found.
2888
2891
virtual bool initialize () { return false ; }
@@ -3605,6 +3608,24 @@ class OffloadingActionBuilder final {
3605
3608
3606
3609
void appendLinkDependences (OffloadAction::DeviceDependences &DA) override {}
3607
3610
3611
+ void addDeviceLinkDependencies (OffloadDepsJobAction *DA) override {
3612
+ for (unsigned I = 0 ; I < ToolChains.size (); ++I) {
3613
+ // Register dependent toolchain.
3614
+ DA->registerDependentActionInfo (
3615
+ ToolChains[I], /* BoundArch=*/ StringRef (), Action::OFK_OpenMP);
3616
+
3617
+ if (!ToolChains[I]->getTriple ().isSPIR ()) {
3618
+ // Create object from the deps bitcode.
3619
+ auto *BA = C.MakeAction <BackendJobAction>(DA, types::TY_PP_Asm);
3620
+ auto *AA = C.MakeAction <AssembleJobAction>(BA, types::TY_Object);
3621
+
3622
+ // Add deps object to linker inputs.
3623
+ DeviceLinkerInputs[I].push_back (AA);
3624
+ } else
3625
+ DeviceLinkerInputs[I].push_back (DA);
3626
+ }
3627
+ }
3628
+
3608
3629
bool initialize () override {
3609
3630
// Get the OpenMP toolchains. If we don't get any, the action builder will
3610
3631
// know there is nothing to do related to OpenMP offloading.
@@ -4338,6 +4359,17 @@ class OffloadingActionBuilder final {
4338
4359
}
4339
4360
}
4340
4361
4362
+ void addDeviceLinkDependencies (OffloadDepsJobAction *DA) override {
4363
+ for (unsigned I = 0 ; I < ToolChains.size (); ++I) {
4364
+ // Register dependent toolchain.
4365
+ DA->registerDependentActionInfo (
4366
+ ToolChains[I], /* BoundArch=*/ StringRef (), Action::OFK_SYCL);
4367
+
4368
+ // Add deps output to linker inputs.
4369
+ DeviceLinkerInputs[I].push_back (DA);
4370
+ }
4371
+ }
4372
+
4341
4373
// / Initialize the GPU architecture list from arguments - this populates `GpuArchList` from
4342
4374
// / `--cuda-gpu-arch` flags. Only relevant if compiling to CUDA. Return true if any
4343
4375
// / initialization errors are found.
@@ -4741,6 +4773,32 @@ class OffloadingActionBuilder final {
4741
4773
return false ;
4742
4774
}
4743
4775
4776
+ // / Create link job from the given host inputs and feed the result to offload
4777
+ // / deps job which fetches device dependencies from the linked host image.
4778
+ // / Offload deps output is then forwarded to active device action builders so
4779
+ // / they can add it to the device linker inputs.
4780
+ void addDeviceLinkDependenciesFromHost (ActionList &LinkerInputs) {
4781
+ // Link image for reading dependencies from it.
4782
+ auto *LA = C.MakeAction <LinkJobAction>(LinkerInputs, types::TY_Image);
4783
+
4784
+ // Calculate all the offload kinds used in the current compilation.
4785
+ unsigned ActiveOffloadKinds = 0u ;
4786
+ for (auto &I : InputArgToOffloadKindMap)
4787
+ ActiveOffloadKinds |= I.second ;
4788
+
4789
+ OffloadAction::HostDependence HDep (
4790
+ *LA, *C.getSingleOffloadToolChain <Action::OFK_Host>(),
4791
+ /* BoundArch*/ nullptr , ActiveOffloadKinds);
4792
+
4793
+ auto *DA = C.MakeAction <OffloadDepsJobAction>(HDep, types::TY_LLVM_BC);
4794
+
4795
+ for (auto *SB : SpecializedBuilders) {
4796
+ if (!SB->isValid ())
4797
+ continue ;
4798
+ SB->addDeviceLinkDependencies (DA);
4799
+ }
4800
+ }
4801
+
4744
4802
void makeHostLinkAction (ActionList &LinkerInputs) {
4745
4803
// Build a list of device linking actions.
4746
4804
ActionList DeviceAL;
@@ -5065,6 +5123,11 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
5065
5123
5066
5124
OffloadBuilder.appendTopLevelLinkAction (Actions);
5067
5125
5126
+ // With static fat archives we need to create additional steps for
5127
+ // generating dependence objects for device link actions.
5128
+ if (!LinkerInputs.empty () && C.getDriver ().getOffloadStaticLibSeen ())
5129
+ OffloadBuilder.addDeviceLinkDependenciesFromHost (LinkerInputs);
5130
+
5068
5131
// Go through all of the args, and create a Linker specific argument list.
5069
5132
// When dealing with fat static archives each archive is individually
5070
5133
// unbundled.
@@ -5966,7 +6029,10 @@ InputInfo Driver::BuildJobsForActionNoCache(
5966
6029
const JobAction *JA = cast<JobAction>(A);
5967
6030
ActionList CollapsedOffloadActions;
5968
6031
5969
- ToolSelector TS (JA, *TC, C, isSaveTempsEnabled (),
6032
+ auto *DA = dyn_cast<OffloadDepsJobAction>(JA);
6033
+ const ToolChain *JATC = DA ? DA->getHostTC () : TC;
6034
+
6035
+ ToolSelector TS (JA, *JATC, C, isSaveTempsEnabled (),
5970
6036
embedBitcodeInObject () && !isUsingLTO ());
5971
6037
const Tool *T = TS.getTool (Inputs, CollapsedOffloadActions);
5972
6038
@@ -5995,8 +6061,9 @@ InputInfo Driver::BuildJobsForActionNoCache(
5995
6061
bool SubJobAtTopLevel =
5996
6062
AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A));
5997
6063
InputInfos.push_back (BuildJobsForAction (
5998
- C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs, LinkingOutput,
5999
- CachedResults, A->getOffloadingDeviceKind ()));
6064
+ C, Input, JATC, DA ? DA->getOffloadingArch () : BoundArch,
6065
+ SubJobAtTopLevel, MultipleArchs, LinkingOutput, CachedResults,
6066
+ A->getOffloadingDeviceKind ()));
6000
6067
}
6001
6068
// Check if we are in sub-work for preprocessing for host side. If so we will
6002
6069
// add another job to print information to terminal later.
@@ -6165,6 +6232,46 @@ InputInfo Driver::BuildJobsForActionNoCache(
6165
6232
" Result does not exist??" );
6166
6233
Result = CachedResults[ActionTC];
6167
6234
}
6235
+ } else if (auto *DA = dyn_cast<OffloadDepsJobAction>(JA)) {
6236
+ for (auto &DI : DA->getDependentActionsInfo ()) {
6237
+ assert (DI.DependentOffloadKind != Action::OFK_None &&
6238
+ " Deps job with no offloading" );
6239
+
6240
+ std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix (
6241
+ DI.DependentOffloadKind ,
6242
+ DI.DependentToolChain ->getTriple ().normalize (),
6243
+ /* CreatePrefixForHost=*/ true );
6244
+ auto CurI = InputInfo (
6245
+ DA,
6246
+ GetNamedOutputPath (C, *DA, BaseInput, DI.DependentBoundArch ,
6247
+ /* AtTopLevel=*/ false ,
6248
+ MultipleArchs ||
6249
+ DI.DependentOffloadKind == Action::OFK_HIP,
6250
+ OffloadingPrefix),
6251
+ BaseInput);
6252
+ // Save the result.
6253
+ UnbundlingResults.push_back (CurI);
6254
+
6255
+ // Get the unique string identifier for this dependence and cache the
6256
+ // result.
6257
+ StringRef Arch = TargetDeviceOffloadKind == Action::OFK_HIP
6258
+ ? DI.DependentOffloadKind == Action::OFK_Host
6259
+ ? StringRef ()
6260
+ : DI.DependentBoundArch
6261
+ : BoundArch;
6262
+
6263
+ CachedResults[{A, GetTriplePlusArchString (DI.DependentToolChain , Arch,
6264
+ DI.DependentOffloadKind )}] =
6265
+ CurI;
6266
+ }
6267
+
6268
+ // Now that we have all the results generated, select the one that should be
6269
+ // returned for the current depending action.
6270
+ std::pair<const Action *, std::string> ActionTC = {
6271
+ A, GetTriplePlusArchString (TC, BoundArch, TargetDeviceOffloadKind)};
6272
+ auto It = CachedResults.find (ActionTC);
6273
+ assert (It != CachedResults.end () && " Result does not exist??" );
6274
+ Result = It->second ;
6168
6275
} else if (JA->getType () == types::TY_Nothing)
6169
6276
Result = InputInfo (A, BaseInput);
6170
6277
else {
0 commit comments