Skip to content

Commit cf10351

Browse files
[DAE][SYCL] Emit MD instead of updating integration header (#2258)
Removed DAE from standard optimization pipeline We cannot run DAE in ESIMD cntext since the pointers to SPIR kernel functions are saved in !genx.kernels metadata. Because of that I removed DAE pass from the standard pipeline and put it in the place that is specific for SYCL passes and guarded it under a new temporary option: '-fenable-sycl-dae'. This option is only used until other parts of the solution are not in place.
1 parent 1a71a4a commit cf10351

16 files changed

+34
-181
lines changed

clang/include/clang/Basic/LangOptions.def

+1
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ LANGOPT(SYCLUnnamedLambda , 1, 0, "Allow unnamed lambda SYCL kernels")
251251
LANGOPT(SYCLVersion , 32, 0, "Version of the SYCL standard used")
252252
LANGOPT(DeclareSPIRVBuiltins, 1, 0, "Declare SPIR-V builtin functions")
253253
LANGOPT(SYCLExplicitSIMD , 1, 0, "SYCL compilation with explicit SIMD extension")
254+
LANGOPT(EnableDAEInSpirKernels , 1, 0, "Enable Dead Argument Elimination in SPIR kernels")
254255

255256
LANGOPT(HIPUseNewLaunchAPI, 1, 0, "Use new kernel launching API for HIP")
256257

clang/include/clang/Driver/Options.td

+2
Original file line numberDiff line numberDiff line change
@@ -4455,6 +4455,8 @@ def fsycl_std_layout_kernel_params: Flag<["-"], "fsycl-std-layout-kernel-params"
44554455
def fsycl_allow_func_ptr : Flag<["-"], "fsycl-allow-func-ptr">,
44564456
HelpText<"Allow function pointers in SYCL device.">;
44574457
def fno_sycl_allow_func_ptr : Flag<["-"], "fno-sycl-allow-func-ptr">;
4458+
def fenable_sycl_dae : Flag<["-"], "fenable-sycl-dae">,
4459+
HelpText<"Enable Dead Argument Elimination in SPIR kernels">;
44584460

44594461
} // let Flags = [CC1Option]
44604462

clang/lib/CodeGen/BackendUtil.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,15 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,
918918
if (LangOpts.SYCLIsDevice && CodeGenOpts.DisableLLVMPasses)
919919
PerModulePasses.add(createDeadCodeEliminationPass());
920920

921+
// Eliminate dead arguments from SPIR kernels in SYCL environment.
922+
// 1. Run DAE when LLVM optimizations are applied as well.
923+
// 2. We cannot run DAE for ESIMD since the pointers to SPIR kernel
924+
// functions are saved in !genx.kernels metadata.
925+
// 3. DAE pass temporary guarded under option.
926+
if (LangOpts.SYCLIsDevice && !CodeGenOpts.DisableLLVMPasses &&
927+
!LangOpts.SYCLExplicitSIMD && LangOpts.EnableDAEInSpirKernels)
928+
PerModulePasses.add(createDeadArgEliminationSYCLPass());
929+
921930
if (LangOpts.SYCLIsDevice && LangOpts.SYCLExplicitSIMD)
922931
PerModulePasses.add(createGenXSPIRVWriterAdaptorPass());
923932

clang/lib/Frontend/CompilerInvocation.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -2596,6 +2596,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
25962596
}
25972597
}
25982598
Opts.SYCLExplicitSIMD = Args.hasArg(options::OPT_fsycl_esimd);
2599+
Opts.EnableDAEInSpirKernels = Args.hasArg(options::OPT_fenable_sycl_dae);
25992600
}
26002601

26012602
Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header);

llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp

+11-85
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
#include "llvm/InitializePasses.h"
4242
#include "llvm/Pass.h"
4343
#include "llvm/Support/Casting.h"
44-
#include "llvm/Support/CommandLine.h"
4544
#include "llvm/Support/Debug.h"
4645
#include "llvm/Support/raw_ostream.h"
4746
#include "llvm/Transforms/IPO.h"
@@ -55,11 +54,6 @@ using namespace llvm;
5554

5655
#define DEBUG_TYPE "deadargelim"
5756

58-
static cl::opt<std::string>
59-
IntegrationHeaderFileName("integr-header-file",
60-
cl::desc("Path to integration header file"),
61-
cl::value_desc("filename"), cl::Hidden);
62-
6357
STATISTIC(NumArgumentsEliminated, "Number of unread args removed");
6458
STATISTIC(NumRetValsEliminated , "Number of unused return values removed");
6559
STATISTIC(NumArgumentsReplacedWithUndef,
@@ -760,78 +754,6 @@ void DeadArgumentEliminationPass::PropagateLiveness(const RetOrArg &RA) {
760754
Uses.erase(Begin, I);
761755
}
762756

763-
// Update kernel arguments table inside the integration header.
764-
// For example:
765-
// static constexpr const bool param_omit_table[] = {
766-
// // OMIT_TABLE_BEGIN
767-
// // kernel_name_1
768-
// false, false, // <= update to true if the argument is dead
769-
// // kernel_name_2
770-
// false, false,
771-
// // OMIT_TABLE_END
772-
// };
773-
// TODO: batch changes to multiple SPIR kernels and do one bulk update.
774-
constexpr StringLiteral OMIT_TABLE_BEGIN("// OMIT_TABLE_BEGIN");
775-
constexpr StringLiteral OMIT_TABLE_END("// OMIT_TABLE_END");
776-
static void updateIntegrationHeader(StringRef SpirKernelName,
777-
const ArrayRef<bool> &ArgAlive) {
778-
ErrorOr<std::unique_ptr<MemoryBuffer>> IntHeaderBuffer =
779-
MemoryBuffer::getFile(IntegrationHeaderFileName);
780-
781-
if (!IntHeaderBuffer)
782-
report_fatal_error("unable to read integration header file '" +
783-
IntegrationHeaderFileName +
784-
"': " + IntHeaderBuffer.getError().message());
785-
786-
// 1. Find the region between OMIT_TABLE_BEGIN and OMIT_TABLE_END
787-
StringRef IntHeader((*IntHeaderBuffer)->getBuffer());
788-
if (!IntHeader.contains(OMIT_TABLE_BEGIN))
789-
report_fatal_error(OMIT_TABLE_BEGIN +
790-
" marker not found in integration header");
791-
if (!IntHeader.contains(OMIT_TABLE_END))
792-
report_fatal_error(OMIT_TABLE_END +
793-
" marker not found in integration header");
794-
795-
size_t BeginRegionPos =
796-
IntHeader.find(OMIT_TABLE_BEGIN) + OMIT_TABLE_BEGIN.size();
797-
size_t EndRegionPos = IntHeader.find(OMIT_TABLE_END);
798-
799-
StringRef OmitArgTable = IntHeader.slice(BeginRegionPos, EndRegionPos);
800-
801-
// 2. Find the line that corresponds to the SPIR kernel
802-
if (!OmitArgTable.contains(SpirKernelName))
803-
report_fatal_error(
804-
"Argument table not found in integration header for function '" +
805-
SpirKernelName + "'");
806-
807-
size_t BeginLinePos =
808-
OmitArgTable.find(SpirKernelName) + SpirKernelName.size();
809-
size_t EndLinePos = OmitArgTable.find("//", BeginLinePos);
810-
811-
StringRef OmitArgLine = OmitArgTable.slice(BeginLinePos, EndLinePos);
812-
813-
size_t LineLeftTrim = OmitArgLine.size() - OmitArgLine.ltrim().size();
814-
size_t LineRightTrim = OmitArgLine.size() - OmitArgLine.rtrim().size();
815-
816-
// 3. Construct new file contents and replace only that string.
817-
std::string NewIntHeader;
818-
NewIntHeader +=
819-
IntHeader.take_front(BeginRegionPos + BeginLinePos + LineLeftTrim);
820-
for (auto &AliveArg : ArgAlive)
821-
NewIntHeader += AliveArg ? "false, " : "true, ";
822-
NewIntHeader += IntHeader.drop_front(BeginRegionPos + BeginLinePos +
823-
OmitArgLine.size() - LineRightTrim);
824-
825-
// 4. Flush the string into the file.
826-
std::error_code EC;
827-
raw_fd_ostream File(IntegrationHeaderFileName, EC, sys::fs::F_Text);
828-
829-
if (EC)
830-
report_fatal_error("Cannot open integration header for writing.");
831-
832-
File << NewIntHeader;
833-
}
834-
835757
// RemoveDeadStuffFromFunction - Remove any arguments and return values from F
836758
// that are not in LiveValues. Transform the function and all of the callees of
837759
// the function to not have these arguments and return values.
@@ -875,8 +797,17 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) {
875797
}
876798
}
877799

878-
if (CheckSpirKernels)
879-
updateIntegrationHeader(F->getName(), ArgAlive);
800+
if (CheckSpirKernels) {
801+
SmallVector<Metadata *, 10> MDOmitArgs;
802+
auto MDOmitArgTrue = llvm::ConstantAsMetadata::get(
803+
ConstantInt::get(Type::getInt1Ty(F->getContext()), 1));
804+
auto MDOmitArgFalse = llvm::ConstantAsMetadata::get(
805+
ConstantInt::get(Type::getInt1Ty(F->getContext()), 0));
806+
for (auto &AliveArg : ArgAlive)
807+
MDOmitArgs.push_back(AliveArg ? MDOmitArgFalse : MDOmitArgTrue);
808+
F->setMetadata("spir_kernel_omit_args",
809+
llvm::MDNode::get(F->getContext(), MDOmitArgs));
810+
}
880811

881812
// Find out the new return value.
882813
Type *RetTy = FTy->getReturnType();
@@ -1193,11 +1124,6 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) {
11931124

11941125
PreservedAnalyses DeadArgumentEliminationPass::run(Module &M,
11951126
ModuleAnalysisManager &) {
1196-
// Integration header file must be provided for
1197-
// DAE to work on SPIR kernels.
1198-
if (CheckSpirKernels && !IntegrationHeaderFileName.getNumOccurrences())
1199-
return PreservedAnalyses::all();
1200-
12011127
bool Changed = false;
12021128

12031129
// First pass: Do a simple check to see if any functions can have their "..."

llvm/lib/Transforms/IPO/PassManagerBuilder.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,6 @@ void PassManagerBuilder::populateModulePassManager(
680680
if (RunInliner) {
681681
MPM.add(createGlobalOptimizerPass());
682682
MPM.add(createGlobalDCEPass());
683-
MPM.add(createDeadArgEliminationSYCLPass());
684683
}
685684

686685
// If we are planning to perform ThinLTO later, let's not bloat the code with

llvm/test/Other/opt-O2-pipeline.ll

-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,6 @@
193193
; CHECK-NEXT: Branch Probability Analysis
194194
; CHECK-NEXT: Block Frequency Analysis
195195
; CHECK-NEXT: Dead Global Elimination
196-
; CHECK-NEXT: Dead Argument Elimination for SPIR kernels in SYCL environment
197196
; CHECK-NEXT: CallGraph Construction
198197
; CHECK-NEXT: Globals Alias Analysis
199198
; CHECK-NEXT: FunctionPass Manager

llvm/test/Other/opt-O3-pipeline-enable-matrix.ll

-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,6 @@
198198
; CHECK-NEXT: Branch Probability Analysis
199199
; CHECK-NEXT: Block Frequency Analysis
200200
; CHECK-NEXT: Dead Global Elimination
201-
; CHECK-NEXT: Dead Argument Elimination for SPIR kernels in SYCL environment
202201
; CHECK-NEXT: CallGraph Construction
203202
; CHECK-NEXT: Globals Alias Analysis
204203
; CHECK-NEXT: FunctionPass Manager

llvm/test/Other/opt-O3-pipeline.ll

-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,6 @@
198198
; CHECK-NEXT: Branch Probability Analysis
199199
; CHECK-NEXT: Block Frequency Analysis
200200
; CHECK-NEXT: Dead Global Elimination
201-
; CHECK-NEXT: Dead Argument Elimination for SPIR kernels in SYCL environment
202201
; CHECK-NEXT: CallGraph Construction
203202
; CHECK-NEXT: Globals Alias Analysis
204203
; CHECK-NEXT: FunctionPass Manager

llvm/test/Other/opt-Os-pipeline.ll

-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,6 @@
179179
; CHECK-NEXT: Branch Probability Analysis
180180
; CHECK-NEXT: Block Frequency Analysis
181181
; CHECK-NEXT: Dead Global Elimination
182-
; CHECK-NEXT: Dead Argument Elimination for SPIR kernels in SYCL environment
183182
; CHECK-NEXT: CallGraph Construction
184183
; CHECK-NEXT: Globals Alias Analysis
185184
; CHECK-NEXT: FunctionPass Manager

llvm/test/Transforms/DeadArgElim/sycl-kernels-neg5.ll renamed to llvm/test/Transforms/DeadArgElim/sycl-kernels-neg.ll

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
; RUN: opt < %s -deadargelim-sycl -S | FileCheck %s
44

55
; This test ensures dead arguments are not eliminated
6-
; from a global function that is not a SYCL kernel.
6+
; from a global function that is not a SPIR kernel.
7+
8+
; CHECK-NOT: !spir_kernel_omit_args
79

810
target triple = "spir64-unknown-unknown-sycldevice"
911

llvm/test/Transforms/DeadArgElim/sycl-kernels-neg1.ll

-17
This file was deleted.

llvm/test/Transforms/DeadArgElim/sycl-kernels-neg2.ll

-13
This file was deleted.

llvm/test/Transforms/DeadArgElim/sycl-kernels-neg3.ll

-16
This file was deleted.

llvm/test/Transforms/DeadArgElim/sycl-kernels-neg4.ll

-18
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
2-
; RUN: echo 'some code we want to preserve' > %t-int_header.h
3-
; RUN: echo 'static constexpr const bool param_omit_table[] = {' >> %t-int_header.h
4-
; RUN: echo ' // OMIT_TABLE_BEGIN' >> %t-int_header.h
5-
; RUN: echo ' // SpirKernel1' >> %t-int_header.h
6-
; RUN: echo ' false, false,' >> %t-int_header.h
7-
; RUN: echo ' // SpirKernel2' >> %t-int_header.h
8-
; RUN: echo ' false, false,' >> %t-int_header.h
9-
; RUN: echo ' // OMIT_TABLE_END' >> %t-int_header.h
10-
; RUN: echo '};' >> %t-int_header.h
11-
; RUN: echo 'some code we want to preserve' >> %t-int_header.h
122
; RUN: opt < %s -deadargelim -S | FileCheck %s --check-prefixes=CHECK
13-
; RUN: opt < %s -deadargelim-sycl -S -integr-header-file %t-int_header.h | FileCheck %s --check-prefixes=CHECK-SYCL
14-
; RUN: cat %t-int_header.h | FileCheck %s --check-prefixes=CHECK-INT-HEADER
3+
; RUN: opt < %s -deadargelim-sycl -S | FileCheck %s --check-prefixes=CHECK-SYCL
154

165
; This test checks eliminating dead arguments
176
; from SPIR kernel functions in SYCL environment.
@@ -25,10 +14,10 @@ define weak_odr spir_kernel void @SpirKernel1(float %arg1, float %arg2) {
2514
; CHECK-NEXT: ret void
2615
;
2716
; CHECK-SYCL-LABEL: define {{[^@]+}}@SpirKernel1
28-
; CHECK-SYCL-SAME: (float [[ARG1:%.*]])
17+
; CHECK-SYCL-SAME: (float [[ARG1:%.*]]) !spir_kernel_omit_args ![[KERN_ARGS1:[0-9]]]
2918
; CHECK-SYCL-NEXT: call void @foo(float [[ARG1]])
3019
; CHECK-SYCL-NEXT: ret void
31-
;
20+
3221
call void @foo(float %arg1)
3322
ret void
3423
}
@@ -40,23 +29,15 @@ define weak_odr spir_kernel void @SpirKernel2(float %arg1, float %arg2) {
4029
; CHECK-NEXT: ret void
4130
;
4231
; CHECK-SYCL-LABEL: define {{[^@]+}}@SpirKernel2
43-
; CHECK-SYCL-SAME: (float [[ARG2:%.*]])
32+
; CHECK-SYCL-SAME: (float [[ARG2:%.*]]) !spir_kernel_omit_args ![[KERN_ARGS2:[0-9]]]
4433
; CHECK-SYCL-NEXT: call void @foo(float [[ARG2]])
4534
; CHECK-SYCL-NEXT: ret void
46-
;
35+
4736
call void @foo(float %arg2)
4837
ret void
4938
}
5039

51-
; CHECK-INT-HEADER: some code we want to preserve
52-
; CHECK-INT-HEADER: static constexpr const bool param_omit_table[] = {
53-
; CHECK-INT-HEADER: // OMIT_TABLE_BEGIN
54-
; CHECK-INT-HEADER: // SpirKernel1
55-
; CHECK-INT-HEADER: false, true,
56-
; CHECK-INT-HEADER: // SpirKernel2
57-
; CHECK-INT-HEADER: true, false,
58-
; CHECK-INT-HEADER: // OMIT_TABLE_END
59-
; CHECK-INT-HEADER: };
60-
; CHECK-INT-HEADER: some code we want to preserve
40+
; CHECK-SYCL: ![[KERN_ARGS1]] = !{i1 false, i1 true}
41+
; CHECK-SYCL: ![[KERN_ARGS2]] = !{i1 true, i1 false}
6142

6243
declare void @foo(float %arg)

0 commit comments

Comments
 (0)