Skip to content

Commit 830619e

Browse files
committed
- When doing nested split of a module, the entry point is now limited to
the entry points of the source module. This fixes SYCL/SpecConstants/2020/non_native/multiple-targets.cpp test failure. - Make internal interfaces more convenient and consistent by passing ModuleDesc instead of Module + entry points + properties. - Fix call graph traversal by detecting cases when a CallInst uses a function not as a callee (call target), but otherwise.
1 parent 9c1e483 commit 830619e

File tree

4 files changed

+110
-105
lines changed

4 files changed

+110
-105
lines changed

llvm/lib/SYCLLowerIR/ESIMD/ESIMDUtils.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ void traverseCallgraphUp(llvm::Function *F, CallGraphNodeAction ActionF,
2222
// Update all callers as well.
2323
for (auto It = CurF->use_begin(); It != CurF->use_end(); It++) {
2424
auto FCall = It->getUser();
25+
auto ErrMsg =
26+
llvm::Twine(__FILE__ " ") +
27+
"Function use other than call detected while traversing call\n"
28+
"graph up to a kernel";
2529
if (!isa<CallInst>(FCall)) {
2630
// A use other than a call is met...
2731
if (ErrorOnNonCallUse) {
2832
// ... non-call is an error - report
29-
llvm::report_fatal_error(
30-
llvm::Twine(__FILE__ " ") +
31-
"Function use other than call detected while traversing call\n"
32-
"graph up to a kernel");
33+
llvm::report_fatal_error(ErrMsg);
3334
} else {
3435
// ... non-call is OK - add using function to the worklist
3536
if (auto *I = dyn_cast<Instruction>(FCall)) {
@@ -41,10 +42,17 @@ void traverseCallgraphUp(llvm::Function *F, CallGraphNodeAction ActionF,
4142
}
4243
}
4344
} else {
44-
auto FCaller = cast<CallInst>(FCall)->getFunction();
45+
auto *CI = cast<CallInst>(FCall);
4546

46-
if (!FunctionsVisited.count(FCaller)) {
47-
Worklist.push_back(FCaller);
47+
if ((CI->getCalledFunction() != CurF) && ErrorOnNonCallUse) {
48+
// CurF is used in a call, but not as the callee.
49+
llvm::report_fatal_error(ErrMsg);
50+
} else {
51+
auto FCaller = CI->getFunction();
52+
53+
if (!FunctionsVisited.count(FCaller)) {
54+
Worklist.push_back(FCaller);
55+
}
4856
}
4957
}
5058
}

llvm/tools/sycl-post-link/ModuleSplitter.cpp

Lines changed: 67 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -135,35 +135,28 @@ bool isESIMDFunction(const Function &F) {
135135

136136
// This function makes one or two groups depending on kernel types (SYCL, ESIMD)
137137
EntryPointGroupVec
138-
groupEntryPointsByKernelType(const Module &M, bool EmitOnlyKernelsAsEntryPoints,
139-
EntryPointVec *AllowedEntriesVec,
140-
EntryPointGroup::Properties BlueprintProps) {
141-
SmallPtrSet<const Function *, 32> AllowedEntries;
142-
143-
if (AllowedEntriesVec) {
144-
std::copy(AllowedEntriesVec->begin(), AllowedEntriesVec->end(),
145-
std::inserter(AllowedEntries, AllowedEntries.end()));
146-
}
138+
groupEntryPointsByKernelType(const ModuleDesc &MD,
139+
bool EmitOnlyKernelsAsEntryPoints) {
140+
const Module &M = MD.getModule();
147141
EntryPointGroupVec EntryPointGroups{};
148-
std::map<StringRef, EntryPointVec> EntryPointMap;
142+
std::map<StringRef, EntryPointSet> EntryPointMap;
149143

150144
// Only process module entry points:
151145
for (const auto &F : M.functions()) {
152-
if (!isEntryPoint(F, EmitOnlyKernelsAsEntryPoints))
153-
continue;
154-
if (AllowedEntriesVec && (AllowedEntries.find(&F) == AllowedEntries.end()))
146+
if (!isEntryPoint(F, EmitOnlyKernelsAsEntryPoints) ||
147+
!MD.isEntryPointCandidate(F))
155148
continue;
156149

157150
if (isESIMDFunction(F))
158-
EntryPointMap[ESIMD_SCOPE_NAME].push_back(&F);
151+
EntryPointMap[ESIMD_SCOPE_NAME].insert(&F);
159152
else
160-
EntryPointMap[SYCL_SCOPE_NAME].push_back(&F);
153+
EntryPointMap[SYCL_SCOPE_NAME].insert(&F);
161154
}
162155

163156
if (!EntryPointMap.empty()) {
164157
for (auto &EPG : EntryPointMap) {
165-
EntryPointGroups.emplace_back(
166-
EntryPointGroup{EPG.first, std::move(EPG.second), BlueprintProps});
158+
EntryPointGroups.emplace_back(EntryPointGroup{
159+
EPG.first, std::move(EPG.second), MD.getEntryPointGroup().Props});
167160
EntryPointGroup &G = EntryPointGroups.back();
168161

169162
if (G.GroupId == ESIMD_SCOPE_NAME) {
@@ -175,7 +168,8 @@ groupEntryPointsByKernelType(const Module &M, bool EmitOnlyKernelsAsEntryPoints,
175168
}
176169
} else {
177170
// No entry points met, record this.
178-
EntryPointGroups.emplace_back(EntryPointGroup{SYCL_SCOPE_NAME, {}});
171+
EntryPointGroups.emplace_back(
172+
EntryPointGroup{SYCL_SCOPE_NAME, EntryPointSet{}});
179173
EntryPointGroup &G = EntryPointGroups.back();
180174
G.Props.HasESIMD = SyclEsimdSplitStatus::SYCL_ONLY;
181175
}
@@ -189,22 +183,23 @@ groupEntryPointsByKernelType(const Module &M, bool EmitOnlyKernelsAsEntryPoints,
189183
// which contains pairs of group id and entry points for that group. Each such
190184
// group along with IR it depends on (globals, functions from its call graph,
191185
// ...) will constitute a separate module.
192-
EntryPointGroupVec
193-
groupEntryPointsByScope(const Module &M, EntryPointsGroupScope EntryScope,
194-
bool EmitOnlyKernelsAsEntryPoints,
195-
EntryPointGroup::Properties BlueprintProps) {
186+
EntryPointGroupVec groupEntryPointsByScope(const ModuleDesc &MD,
187+
EntryPointsGroupScope EntryScope,
188+
bool EmitOnlyKernelsAsEntryPoints) {
196189
EntryPointGroupVec EntryPointGroups{};
197190
// Use MapVector for deterministic order of traversal (helps tests).
198-
MapVector<StringRef, EntryPointVec> EntryPointMap;
191+
MapVector<StringRef, EntryPointSet> EntryPointMap;
192+
const Module &M = MD.getModule();
199193

200194
// Only process module entry points:
201195
for (const auto &F : M.functions()) {
202-
if (!isEntryPoint(F, EmitOnlyKernelsAsEntryPoints))
196+
if (!isEntryPoint(F, EmitOnlyKernelsAsEntryPoints) ||
197+
!MD.isEntryPointCandidate(F))
203198
continue;
204199

205200
switch (EntryScope) {
206201
case Scope_PerKernel:
207-
EntryPointMap[F.getName()].push_back(&F);
202+
EntryPointMap[F.getName()].insert(&F);
208203
break;
209204

210205
case Scope_PerModule: {
@@ -218,55 +213,59 @@ groupEntryPointsByScope(const Module &M, EntryPointsGroupScope EntryScope,
218213

219214
Attribute Id = F.getFnAttribute(ATTR_SYCL_MODULE_ID);
220215
StringRef Val = Id.getValueAsString();
221-
EntryPointMap[Val].push_back(&F);
216+
EntryPointMap[Val].insert(&F);
222217
break;
223218
}
224219

225220
case Scope_Global:
226221
// the map key is not significant here
227-
EntryPointMap[GLOBAL_SCOPE_NAME].push_back(&F);
222+
EntryPointMap[GLOBAL_SCOPE_NAME].insert(&F);
228223
break;
229224
}
230225
}
231226

232227
if (!EntryPointMap.empty()) {
233228
EntryPointGroups.reserve(EntryPointMap.size());
234229
for (auto &EPG : EntryPointMap) {
235-
EntryPointGroups.emplace_back(
236-
EntryPointGroup{EPG.first, std::move(EPG.second), BlueprintProps});
230+
EntryPointGroups.emplace_back(EntryPointGroup{
231+
EPG.first, std::move(EPG.second), MD.getEntryPointGroup().Props});
237232
EntryPointGroup &G = EntryPointGroups.back();
238233
G.Props.Scope = EntryScope;
239234
}
240235
} else {
241236
// No entry points met, record this.
242-
EntryPointGroups.push_back({GLOBAL_SCOPE_NAME, {}});
237+
EntryPointGroups.emplace_back(
238+
EntryPointGroup{GLOBAL_SCOPE_NAME, EntryPointSet{}});
243239
}
244240
return EntryPointGroups;
245241
}
246242

247243
template <class EntryPoinGroupFunc>
248-
EntryPointGroupVec groupEntryPointsByAttribute(
249-
const Module &M, StringRef AttrName, bool EmitOnlyKernelsAsEntryPoints,
250-
EntryPoinGroupFunc F, EntryPointGroup::Properties BlueprintProps) {
244+
EntryPointGroupVec
245+
groupEntryPointsByAttribute(const ModuleDesc &MD, StringRef AttrName,
246+
bool EmitOnlyKernelsAsEntryPoints,
247+
EntryPoinGroupFunc F) {
251248
EntryPointGroupVec EntryPointGroups{};
252-
std::map<StringRef, EntryPointVec> EntryPointMap;
249+
std::map<StringRef, EntryPointSet> EntryPointMap;
250+
const Module &M = MD.getModule();
253251

254252
// Only process module entry points:
255253
for (const auto &F : M.functions()) {
256-
if (!isEntryPoint(F, EmitOnlyKernelsAsEntryPoints)) {
254+
if (!isEntryPoint(F, EmitOnlyKernelsAsEntryPoints) ||
255+
!MD.isEntryPointCandidate(F)) {
257256
continue;
258257
}
259258
if (F.hasFnAttribute(AttrName)) {
260-
EntryPointMap[AttrName].push_back(&F);
259+
EntryPointMap[AttrName].insert(&F);
261260
} else {
262-
EntryPointMap[""].push_back(&F);
261+
EntryPointMap[""].insert(&F);
263262
}
264263
}
265264
if (!EntryPointMap.empty()) {
266265
EntryPointGroups.reserve(EntryPointMap.size());
267266
for (auto &EPG : EntryPointMap) {
268-
EntryPointGroups.emplace_back(
269-
EntryPointGroup{EPG.first, std::move(EPG.second), BlueprintProps});
267+
EntryPointGroups.emplace_back(EntryPointGroup{
268+
EPG.first, std::move(EPG.second), MD.getEntryPointGroup().Props});
270269
F(EntryPointGroups.back());
271270
}
272271
} else {
@@ -354,12 +353,11 @@ ModuleDesc extractSubModule(const ModuleDesc &MD,
354353
std::unique_ptr<Module> SubM = CloneModule(
355354
M, VMap, [&](const GlobalValue *GV) { return GVs.count(GV); });
356355
// Replace entry points with cloned ones.
357-
EntryPointVec NewEPs;
358-
const EntryPointVec &EPs = ModuleEntryPoints.Functions;
359-
NewEPs.reserve(EPs.size());
360-
std::transform(
361-
EPs.cbegin(), EPs.cend(), std::inserter(NewEPs, NewEPs.end()),
362-
[&VMap](const Function *F) { return cast<Function>(VMap[F]); });
356+
EntryPointSet NewEPs;
357+
const EntryPointSet &EPs = ModuleEntryPoints.Functions;
358+
std::for_each(EPs.begin(), EPs.end(), [&](const Function *F) {
359+
NewEPs.insert(cast<Function>(VMap[F]));
360+
});
363361
ModuleEntryPoints.Functions = std::move(NewEPs);
364362
return ModuleDesc{std::move(SubM), std::move(ModuleEntryPoints), MD.Props};
365363
}
@@ -416,11 +414,9 @@ namespace llvm {
416414
namespace module_split {
417415

418416
std::unique_ptr<ModuleSplitterBase>
419-
getSplitterByKernelType(ModuleDesc &&MD, bool EmitOnlyKernelsAsEntryPoints,
420-
EntryPointVec *AllowedEntries) {
421-
EntryPointGroupVec Groups = groupEntryPointsByKernelType(
422-
MD.getModule(), EmitOnlyKernelsAsEntryPoints, AllowedEntries,
423-
MD.getEntryPointGroup().Props);
417+
getSplitterByKernelType(ModuleDesc &&MD, bool EmitOnlyKernelsAsEntryPoints) {
418+
EntryPointGroupVec Groups =
419+
groupEntryPointsByKernelType(MD, EmitOnlyKernelsAsEntryPoints);
424420
bool DoSplit = (Groups.size() > 1);
425421

426422
if (DoSplit)
@@ -435,9 +431,8 @@ getSplitterByMode(ModuleDesc &&MD, IRSplitMode Mode,
435431
bool EmitOnlyKernelsAsEntryPoints) {
436432
EntryPointsGroupScope Scope =
437433
selectDeviceCodeGroupScope(MD.getModule(), Mode, AutoSplitIsGlobalScope);
438-
EntryPointGroupVec Groups = groupEntryPointsByScope(
439-
MD.getModule(), Scope, EmitOnlyKernelsAsEntryPoints,
440-
MD.getEntryPointGroup().Props);
434+
EntryPointGroupVec Groups =
435+
groupEntryPointsByScope(MD, Scope, EmitOnlyKernelsAsEntryPoints);
441436
assert(!Groups.empty() && "At least one group is expected");
442437
bool DoSplit = (Mode != SPLIT_NONE &&
443438
(Groups.size() > 1 || !Groups.cbegin()->Functions.empty()));
@@ -526,7 +521,7 @@ void tab(int N) {
526521
}
527522
}
528523

529-
void dumpEntryPoints(const EntryPointVec &C, const char *msg, int Tab) {
524+
void dumpEntryPoints(const EntryPointSet &C, const char *msg, int Tab) {
530525
tab(Tab);
531526
llvm::errs() << "ENTRY POINTS"
532527
<< " " << msg << " {\n";
@@ -565,8 +560,8 @@ void ModuleDesc::renameDuplicatesOf(const Module &MA, StringRef Suff) {
565560
Module &MB = getModule();
566561
#ifndef NDEBUG
567562
DenseSet<StringRef> EntryNamesB;
568-
auto It0 = entries().cbegin();
569-
auto It1 = entries().cend();
563+
const auto It0 = entries().begin();
564+
const auto It1 = entries().end();
570565
std::for_each(It0, It1,
571566
[&](const Function *F) { EntryNamesB.insert(F->getName()); });
572567
#endif // NDEBUG
@@ -640,52 +635,47 @@ void ModuleDesc::dump() const {
640635

641636
void EntryPointGroup::saveNames(std::vector<std::string> &Dest) const {
642637
Dest.reserve(Dest.size() + Functions.size());
643-
std::transform(Functions.cbegin(), Functions.cend(),
638+
std::transform(Functions.begin(), Functions.end(),
644639
std::inserter(Dest, Dest.end()),
645640
[](const Function *F) { return F->getName().str(); });
646641
}
647642

648643
void EntryPointGroup::rebuildFromNames(const std::vector<std::string> &Names,
649644
const Module &M) {
650645
Functions.clear();
651-
Functions.reserve(Names.size());
652646
auto It0 = Names.cbegin();
653647
auto It1 = Names.cend();
654-
std::transform(It0, It1, std::inserter(Functions, Functions.begin()),
655-
[&M](const std::string &Name) {
656-
const Function *F = M.getFunction(Name);
657-
assert(F && "entry point lost");
658-
return F;
659-
});
648+
std::for_each(It0, It1, [&](const std::string &Name) {
649+
const Function *F = M.getFunction(Name);
650+
assert(F && "entry point lost");
651+
Functions.insert(F);
652+
});
660653
}
661654

662655
void EntryPointGroup::rebuild(const Module &M) {
663656
if (Functions.size() == 0) {
664657
return;
665658
}
666-
EntryPointVec NewFunctions;
667-
NewFunctions.reserve(Functions.size());
668-
auto It0 = Functions.cbegin();
669-
auto It1 = Functions.cend();
670-
std::transform(It0, It1, std::inserter(NewFunctions, NewFunctions.begin()),
671-
[&M](const Function *F) {
672-
Function *NewF = M.getFunction(F->getName());
673-
assert(NewF && "entry point lost");
674-
return NewF;
675-
});
659+
EntryPointSet NewFunctions;
660+
const auto It0 = Functions.begin();
661+
const auto It1 = Functions.end();
662+
std::for_each(It0, It1, [&](const Function *F) {
663+
Function *NewF = M.getFunction(F->getName());
664+
assert(NewF && "entry point lost");
665+
NewFunctions.insert(NewF);
666+
});
676667
Functions = std::move(NewFunctions);
677668
}
678669

679670
std::unique_ptr<ModuleSplitterBase>
680671
getESIMDDoubleGRFSplitter(ModuleDesc &&MD, bool EmitOnlyKernelsAsEntryPoints) {
681672
EntryPointGroupVec Groups = groupEntryPointsByAttribute(
682-
MD.getModule(), ATTR_DOUBLE_GRF, EmitOnlyKernelsAsEntryPoints,
673+
MD, ATTR_DOUBLE_GRF, EmitOnlyKernelsAsEntryPoints,
683674
[](EntryPointGroup &G) {
684675
if (G.GroupId == ATTR_DOUBLE_GRF) {
685676
G.Props.UsesDoubleGRF = true;
686677
}
687-
},
688-
MD.getEntryPointGroup().Props);
678+
});
689679
assert(!Groups.empty() && "At least one group is expected");
690680
assert(Groups.size() <= 2 && "At most 2 groups are expected");
691681

0 commit comments

Comments
 (0)