Skip to content

Commit eef06c1

Browse files
committed
[SYCL] Use file-table-tform in SYCL offload processing in clang driver.
Clang driver's design can't handily model (1) multiple inputs/outputs in the action graph. Because of that, for example, sycl-post-link tool is invoked twice - once to to split the code and produce multiple bitcode files, and secondly - to generate symbol files for the split modules. (2) "Clusters" of inputs/outputs, when subsets of inputs/outputs are associated and describe different aspects of the same data. Example of such clustering is the split module + its symbol file above. Clustering would require support both in the driver and the tools invoked in response to actions. This commit moves SYCL offload processing to the "file table concept." sycl-post-link instead of (1) being invoked n times, once per each output type requested (once for device split and once for symbol file generation) (2) outputting multiple file lists each listing outputs from the corresponding invocation above is now invoked once and produces single file table output. E.g. [Code|Symbols|Properties] a_0.bc|a_0.sym|a_0.props a_1.bc|a_1.sym|a_1.props This solves both problems - multiple input/output and clustering. Combined with the file-table-tform tool, this allows for efficent handling of multiple clusters of files (each represented as a row in the table file) in the clang driver infrastructure. For example, there is a real offload processing problem: step1. sycl-post-link outputs N clusters of files step2. "Code" file of each cluster resuilting from step1 ({a_0.bc, a_1.bc} in the example above) must undergo further transformations - translation to SPIRV and optional ahead-of-time compilation. step3. In each cluster resulting from step1 the "Code" file needs to be replaced with the result of step2 step4. All the clusters are processed by the ClangOffloadWrapper tool, which needs to know how files are distributed into clusters and what is the roles of each file in a cluster - whether it is "Code", "Symbol" or "Properties". To solve this, the following action graph is constructed in the clang driver: column:"Code" t1 -> [file-table-tform:extract column] -> t1a -> [for-each:] -> t1b llvm-spirv aot-comp t1 \ column:"Code" [file-table-tform:replace column] -> t2 -> [ClangOffloadWrapper] / t1b where t1b is ["Code"] and t2 is [Code|Symbols|Properties] a_0.bin a_0.bin|a_0.sym|a_0.props a_1.bin a_1.bin|a_1.sym|a_1.props Note that the graph does not change with growing number of clusters, neither it changes when more files are added to each cluster (e.g. a "Manifest" file). Signed-off-by: Konstantin S Bobrovsky <[email protected]>
1 parent dc8bd7d commit eef06c1

17 files changed

+621
-310
lines changed

clang/include/clang/Driver/Action.h

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "llvm/ADT/SmallVector.h"
1818
#include "llvm/ADT/StringRef.h"
1919
#include "llvm/ADT/iterator_range.h"
20+
#include <initializer_list>
2021
#include <string>
2122

2223
namespace llvm {
@@ -78,9 +79,10 @@ class Action {
7879
SYCLPostLinkJobClass,
7980
PartialLinkJobClass,
8081
BackendCompileJobClass,
82+
FileTableTformJobClass,
8183

8284
JobClassFirst = PreprocessJobClass,
83-
JobClassLast = BackendCompileJobClass
85+
JobClassLast = FileTableTformJobClass
8486
};
8587

8688
// The offloading kind determines if this action is binded to a particular
@@ -679,6 +681,13 @@ class SYCLPostLinkJobAction : public JobAction {
679681
static bool classof(const Action *A) {
680682
return A->getKind() == SYCLPostLinkJobClass;
681683
}
684+
685+
void setRTSetsSpecConstants(bool Val) { RTSetsSpecConsts = Val; }
686+
687+
bool getRTSetsSpecConstants() const { return RTSetsSpecConsts; }
688+
689+
private:
690+
bool RTSetsSpecConsts = true;
682691
};
683692

684693
class PartialLinkJobAction : public JobAction {
@@ -705,6 +714,47 @@ class BackendCompileJobAction : public JobAction {
705714
}
706715
};
707716

717+
// Represents a file table transformation action. The order of inputs to a
718+
// FileTableTformJobAction at construction time must accord with the tforms
719+
// added later - some tforms "consume" inputs. For example, "replace column"
720+
// needs another file to read the replacement column from.
721+
class FileTableTformJobAction : public JobAction {
722+
void anchor() override;
723+
724+
public:
725+
struct Tform {
726+
enum Kind { EXTRACT, EXTRACT_DROP_TITLE, REPLACE };
727+
728+
Tform() = default;
729+
Tform(Kind K, std::initializer_list<StringRef> Args) : TheKind(K) {
730+
for (auto A : Args)
731+
TheArgs.emplace_back(A.str());
732+
}
733+
734+
Kind TheKind;
735+
SmallVector<std::string, 2> TheArgs;
736+
};
737+
738+
FileTableTformJobAction(Action *Input, types::ID OutputType);
739+
FileTableTformJobAction(ActionList &Inputs, types::ID OutputType);
740+
741+
// Deletes all columns except the one with given name.
742+
void addExtractColumnTform(StringRef ColumnName, bool WithColTitle = true);
743+
744+
// Replaces a column with title <From> in this table with a column with title
745+
// <To> from another file table passed as input to this action.
746+
void addReplaceColumnTform(StringRef From, StringRef To);
747+
748+
static bool classof(const Action *A) {
749+
return A->getKind() == FileTableTformJobClass;
750+
}
751+
752+
const ArrayRef<Tform> getTforms() const { return Tforms; }
753+
754+
private:
755+
SmallVector<Tform, 2> Tforms; // transformation actions requested
756+
};
757+
708758
} // namespace driver
709759
} // namespace clang
710760

clang/include/clang/Driver/ToolChain.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ class ToolChain {
147147
mutable std::unique_ptr<Tool> SYCLPostLink;
148148
mutable std::unique_ptr<Tool> PartialLink;
149149
mutable std::unique_ptr<Tool> BackendCompiler;
150+
mutable std::unique_ptr<Tool> FileTableTform;
150151

151152
Tool *getClang() const;
152153
Tool *getFlang() const;
@@ -161,6 +162,7 @@ class ToolChain {
161162
Tool *getSYCLPostLink() const;
162163
Tool *getPartialLink() const;
163164
Tool *getBackendCompiler() const;
165+
Tool *getTableTform() const;
164166

165167
mutable std::unique_ptr<SanitizerArgs> SanitizerArguments;
166168
mutable std::unique_ptr<XRayArgs> XRayArguments;

clang/include/clang/Driver/Types.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ TYPE("spirv", SPIRV, INVALID, "spv", phases
103103
TYPE("sycl-header", SYCL_Header, INVALID, "h", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
104104
TYPE("sycl-fatbin", SYCL_FATBIN, INVALID, nullptr, phases::Compile, phases::Backend, phases::Assemble, phases::Link)
105105
TYPE("tempfilelist", Tempfilelist, INVALID, "txt", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
106-
TYPE("tempentriesfilelist", TempEntriesfilelist, INVALID, "txt", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
106+
TYPE("tempfiletable", Tempfiletable,INVALID, "table", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
107107
TYPE("tempAOCOfilelist", TempAOCOfilelist, INVALID, "txt", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
108108
TYPE("archive", Archive, INVALID, "a", phases::Compile, phases::Backend, phases::Assemble, phases::Link)
109109
TYPE("wholearchive", WholeArchive, INVALID, "a", phases::Compile, phases::Backend, phases::Assemble, phases::Link)

clang/lib/Driver/Action.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ const char *Action::getClassName(ActionClass AC) {
5353
return "partial-link";
5454
case BackendCompileJobClass:
5555
return "backend-compiler";
56+
case FileTableTformJobClass:
57+
return "file-table-tform";
5658
}
5759

5860
llvm_unreachable("invalid class");
@@ -473,3 +475,23 @@ BackendCompileJobAction::BackendCompileJobAction(ActionList &Inputs,
473475
BackendCompileJobAction::BackendCompileJobAction(Action *Input,
474476
types::ID Type)
475477
: JobAction(BackendCompileJobClass, Input, Type) {}
478+
479+
void FileTableTformJobAction::anchor() {}
480+
481+
FileTableTformJobAction::FileTableTformJobAction(Action *Input, types::ID Type)
482+
: JobAction(FileTableTformJobClass, Input, Type) {}
483+
484+
FileTableTformJobAction::FileTableTformJobAction(ActionList &Inputs,
485+
types::ID Type)
486+
: JobAction(FileTableTformJobClass, Inputs, Type) {}
487+
488+
void FileTableTformJobAction::addExtractColumnTform(StringRef ColumnName,
489+
bool WithColTitle) {
490+
auto K = WithColTitle ? Tform::EXTRACT : Tform::EXTRACT_DROP_TITLE;
491+
Tforms.emplace_back(Tform(K, {ColumnName}));
492+
}
493+
494+
void FileTableTformJobAction::addReplaceColumnTform(StringRef From,
495+
StringRef To) {
496+
Tforms.emplace_back(Tform(Tform::REPLACE, {From, To}));
497+
}

clang/lib/Driver/Compilation.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/Option/OptSpecifier.h"
2424
#include "llvm/Option/Option.h"
2525
#include "llvm/Support/FileSystem.h"
26+
#include "llvm/Support/SimpleTable.h"
2627
#include "llvm/Support/raw_ostream.h"
2728
#include <cassert>
2829
#include <fstream>
@@ -136,12 +137,29 @@ bool Compilation::CleanupFileList(const TempFileList &Files,
136137
// Temporary file lists contain files that need to be cleaned. The
137138
// file containing the information is also removed
138139
if (File.second == types::TY_Tempfilelist ||
139-
File.second == types::TY_TempEntriesfilelist) {
140-
std::ifstream ListFile(File.first);
141-
if (ListFile) {
142-
// These are temporary files and need to be removed.
140+
File.second == types::TY_Tempfiletable) {
141+
// These are temporary files and need to be removed.
142+
bool IsTable = File.second == types::TY_Tempfiletable;
143+
144+
if (IsTable) {
145+
if (llvm::sys::fs::exists(File.first)) {
146+
auto T = llvm::util::SimpleTable::read(File.first);
147+
if (!T) {
148+
Success = false;
149+
continue;
150+
}
151+
std::vector<std::string> TmpFileNames;
152+
T->get()->linearize(TmpFileNames);
153+
154+
for (const auto &TmpFileName : TmpFileNames) {
155+
if (!TmpFileName.empty())
156+
Success &= CleanupFile(TmpFileName.c_str(), IssueErrors);
157+
}
158+
}
159+
} else {
160+
std::ifstream ListFile(File.first);
143161
std::string TmpFileName;
144-
while(std::getline(ListFile, TmpFileName) && !TmpFileName.empty())
162+
while (std::getline(ListFile, TmpFileName) && !TmpFileName.empty())
145163
Success &= CleanupFile(TmpFileName.c_str(), IssueErrors);
146164
}
147165
}

0 commit comments

Comments
 (0)