diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index b43902ff8a551..aad9a4a1a65ae 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -120,6 +120,7 @@ void initializeCostModelAnalysisPass(PassRegistry&); void initializeCrossDSOCFIPass(PassRegistry&); void initializeDAEPass(PassRegistry&); void initializeDAHPass(PassRegistry&); +void initializeDAESYCLPass(PassRegistry&); void initializeDCELegacyPassPass(PassRegistry&); void initializeDSELegacyPassPass(PassRegistry&); void initializeDataFlowSanitizerPass(PassRegistry&); diff --git a/llvm/include/llvm/LinkAllPasses.h b/llvm/include/llvm/LinkAllPasses.h index c50459347643d..125195faf829d 100644 --- a/llvm/include/llvm/LinkAllPasses.h +++ b/llvm/include/llvm/LinkAllPasses.h @@ -95,6 +95,7 @@ namespace { (void) llvm::createControlHeightReductionLegacyPass(); (void) llvm::createCostModelAnalysisPass(); (void) llvm::createDeadArgEliminationPass(); + (void) llvm::createDeadArgEliminationSYCLPass(); (void) llvm::createDeadCodeEliminationPass(); (void) llvm::createDeadInstEliminationPass(); (void) llvm::createDeadStoreEliminationPass(); diff --git a/llvm/include/llvm/Transforms/IPO.h b/llvm/include/llvm/Transforms/IPO.h index 28e454d3b0fc7..efae3cbd13421 100644 --- a/llvm/include/llvm/Transforms/IPO.h +++ b/llvm/include/llvm/Transforms/IPO.h @@ -144,6 +144,9 @@ ModulePass *createDeadArgEliminationPass(); /// bugpoint. ModulePass *createDeadArgHackingPass(); +/// DeadArgumentElimination pass for SYCL kernel functions +ModulePass *createDeadArgEliminationSYCLPass(); + //===----------------------------------------------------------------------===// /// createArgumentPromotionPass - This pass promotes "by reference" arguments to /// be passed by value if the number of elements passed is smaller or diff --git a/llvm/include/llvm/Transforms/IPO/DeadArgumentElimination.h b/llvm/include/llvm/Transforms/IPO/DeadArgumentElimination.h index 73797bc10017c..f4a71618e53e0 100644 --- a/llvm/include/llvm/Transforms/IPO/DeadArgumentElimination.h +++ b/llvm/include/llvm/Transforms/IPO/DeadArgumentElimination.h @@ -73,8 +73,10 @@ class DeadArgumentEliminationPass /// thus become dead in the end. enum Liveness { Live, MaybeLive }; - DeadArgumentEliminationPass(bool ShouldHackArguments_ = false) - : ShouldHackArguments(ShouldHackArguments_) {} + DeadArgumentEliminationPass(bool ShouldHackArguments_ = false, + bool CheckSpirKernels_ = false) + : ShouldHackArguments(ShouldHackArguments_), + CheckSpirKernels(CheckSpirKernels_) {} PreservedAnalyses run(Module &M, ModuleAnalysisManager &); @@ -121,6 +123,10 @@ class DeadArgumentEliminationPass /// (used only by bugpoint). bool ShouldHackArguments = false; + /// This allows to eliminate dead arguments in SPIR kernel functions with + /// external linkage in SYCL environment + bool CheckSpirKernels = false; + private: Liveness MarkIfNotLive(RetOrArg Use, UseVector &MaybeLiveUses); Liveness SurveyUse(const Use *U, UseVector &MaybeLiveUses, diff --git a/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp b/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp index af5f72f6b6365..d3a924f6f000a 100644 --- a/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -41,6 +41,7 @@ #include "llvm/InitializePasses.h" #include "llvm/Pass.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/IPO.h" @@ -54,6 +55,11 @@ using namespace llvm; #define DEBUG_TYPE "deadargelim" +static cl::opt + IntegrationHeaderFileName("integr-header-file", + cl::desc("Path to integration header file"), + cl::value_desc("filename"), cl::Hidden); + STATISTIC(NumArgumentsEliminated, "Number of unread args removed"); STATISTIC(NumRetValsEliminated , "Number of unused return values removed"); STATISTIC(NumArgumentsReplacedWithUndef, @@ -77,13 +83,15 @@ namespace { bool runOnModule(Module &M) override { if (skipModule(M)) return false; - DeadArgumentEliminationPass DAEP(ShouldHackArguments()); + DeadArgumentEliminationPass DAEP(ShouldHackArguments(), + CheckSpirKernels()); ModuleAnalysisManager DummyMAM; PreservedAnalyses PA = DAEP.run(M, DummyMAM); return !PA.areAllPreserved(); } virtual bool ShouldHackArguments() const { return false; } + virtual bool CheckSpirKernels() const { return false; } }; } // end anonymous namespace @@ -103,6 +111,7 @@ namespace { DAH() : DAE(ID) {} bool ShouldHackArguments() const override { return true; } + bool CheckSpirKernels() const override { return false; } }; } // end anonymous namespace @@ -113,12 +122,42 @@ INITIALIZE_PASS(DAH, "deadarghaX0r", "Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)", false, false) +namespace { + +/// DAESYCL - DeadArgumentElimination pass for SPIR kernel functions even +/// if they are external. +struct DAESYCL : public DAE { + static char ID; + + DAESYCL() : DAE(ID) { + initializeDAESYCLPass(*PassRegistry::getPassRegistry()); + } + + StringRef getPassName() const override { + return "Dead Argument Elimination for SPIR kernels in SYCL environment"; + } + + bool ShouldHackArguments() const override { return false; } + bool CheckSpirKernels() const override { return true; } +}; + +} // end anonymous namespace + +char DAESYCL::ID = 0; + +INITIALIZE_PASS( + DAESYCL, "deadargelim-sycl", + "Dead Argument Elimination for SPIR kernels in SYCL environment", false, + false) + /// createDeadArgEliminationPass - This pass removes arguments from functions /// which are not used by the body of the function. ModulePass *llvm::createDeadArgEliminationPass() { return new DAE(); } ModulePass *llvm::createDeadArgHackingPass() { return new DAH(); } +ModulePass *llvm::createDeadArgEliminationSYCLPass() { return new DAESYCL(); } + /// DeleteDeadVarargs - If this is an function that takes a ... list, and if /// llvm.vastart is never called, the varargs list is dead for the function. bool DeadArgumentEliminationPass::DeleteDeadVarargs(Function &Fn) { @@ -535,7 +574,14 @@ void DeadArgumentEliminationPass::SurveyFunction(const Function &F) { << " has musttail calls\n"); } - if (!F.hasLocalLinkage() && (!ShouldHackArguments || F.isIntrinsic())) { + // We can't modify arguments if the function is not local + // but we can do so for SPIR kernel function in SYCL environment. + bool FuncIsSpirKernel = + CheckSpirKernels && + StringRef(F.getParent()->getTargetTriple()).contains("sycldevice") && + F.getCallingConv() == CallingConv::SPIR_KERNEL; + bool FuncIsLive = !F.hasLocalLinkage() && !FuncIsSpirKernel; + if (FuncIsLive && (!ShouldHackArguments || F.isIntrinsic())) { MarkLive(F); return; } @@ -714,6 +760,78 @@ void DeadArgumentEliminationPass::PropagateLiveness(const RetOrArg &RA) { Uses.erase(Begin, I); } +// Update kernel arguments table inside the integration header. +// For example: +// static constexpr const bool param_omit_table[] = { +// // OMIT_TABLE_BEGIN +// // kernel_name_1 +// false, false, // <= update to true if the argument is dead +// // kernel_name_2 +// false, false, +// // OMIT_TABLE_END +// }; +// TODO: batch changes to multiple SPIR kernels and do one bulk update. +constexpr StringLiteral OMIT_TABLE_BEGIN("// OMIT_TABLE_BEGIN"); +constexpr StringLiteral OMIT_TABLE_END("// OMIT_TABLE_END"); +static void updateIntegrationHeader(StringRef SpirKernelName, + const ArrayRef &ArgAlive) { + ErrorOr> IntHeaderBuffer = + MemoryBuffer::getFile(IntegrationHeaderFileName); + + if (!IntHeaderBuffer) + report_fatal_error("unable to read integration header file '" + + IntegrationHeaderFileName + + "': " + IntHeaderBuffer.getError().message()); + + // 1. Find the region between OMIT_TABLE_BEGIN and OMIT_TABLE_END + StringRef IntHeader((*IntHeaderBuffer)->getBuffer()); + if (!IntHeader.contains(OMIT_TABLE_BEGIN)) + report_fatal_error(OMIT_TABLE_BEGIN + + " marker not found in integration header"); + if (!IntHeader.contains(OMIT_TABLE_END)) + report_fatal_error(OMIT_TABLE_END + + " marker not found in integration header"); + + size_t BeginRegionPos = + IntHeader.find(OMIT_TABLE_BEGIN) + OMIT_TABLE_BEGIN.size(); + size_t EndRegionPos = IntHeader.find(OMIT_TABLE_END); + + StringRef OmitArgTable = IntHeader.slice(BeginRegionPos, EndRegionPos); + + // 2. Find the line that corresponds to the SPIR kernel + if (!OmitArgTable.contains(SpirKernelName)) + report_fatal_error( + "Argument table not found in integration header for function '" + + SpirKernelName + "'"); + + size_t BeginLinePos = + OmitArgTable.find(SpirKernelName) + SpirKernelName.size(); + size_t EndLinePos = OmitArgTable.find("//", BeginLinePos); + + StringRef OmitArgLine = OmitArgTable.slice(BeginLinePos, EndLinePos); + + size_t LineLeftTrim = OmitArgLine.size() - OmitArgLine.ltrim().size(); + size_t LineRightTrim = OmitArgLine.size() - OmitArgLine.rtrim().size(); + + // 3. Construct new file contents and replace only that string. + std::string NewIntHeader; + NewIntHeader += + IntHeader.take_front(BeginRegionPos + BeginLinePos + LineLeftTrim); + for (auto &AliveArg : ArgAlive) + NewIntHeader += AliveArg ? "false, " : "true, "; + NewIntHeader += IntHeader.drop_front(BeginRegionPos + BeginLinePos + + OmitArgLine.size() - LineRightTrim); + + // 4. Flush the string into the file. + std::error_code EC; + raw_fd_ostream File(IntegrationHeaderFileName, EC, sys::fs::F_Text); + + if (EC) + report_fatal_error("Cannot open integration header for writing."); + + File << NewIntHeader; +} + // RemoveDeadStuffFromFunction - Remove any arguments and return values from F // that are not in LiveValues. Transform the function and all of the callees of // the function to not have these arguments and return values. @@ -757,6 +875,9 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) { } } + if (CheckSpirKernels) + updateIntegrationHeader(F->getName(), ArgAlive); + // Find out the new return value. Type *RetTy = FTy->getReturnType(); Type *NRetTy = nullptr; @@ -1072,6 +1193,11 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) { PreservedAnalyses DeadArgumentEliminationPass::run(Module &M, ModuleAnalysisManager &) { + // Integration header file must be provided for + // DAE to work on SPIR kernels. + if (CheckSpirKernels && !IntegrationHeaderFileName.getNumOccurrences()) + return PreservedAnalyses::all(); + bool Changed = false; // First pass: Do a simple check to see if any functions can have their "..." diff --git a/llvm/lib/Transforms/IPO/IPO.cpp b/llvm/lib/Transforms/IPO/IPO.cpp index d37b9236380d4..c0e237aded7eb 100644 --- a/llvm/lib/Transforms/IPO/IPO.cpp +++ b/llvm/lib/Transforms/IPO/IPO.cpp @@ -30,6 +30,7 @@ void llvm::initializeIPO(PassRegistry &Registry) { initializeCrossDSOCFIPass(Registry); initializeDAEPass(Registry); initializeDAHPass(Registry); + initializeDAESYCLPass(Registry); initializeForceFunctionAttrsLegacyPassPass(Registry); initializeGlobalDCELegacyPassPass(Registry); initializeGlobalOptLegacyPassPass(Registry); diff --git a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp index c045c277706b3..3384ef51fb9e4 100644 --- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -680,6 +680,7 @@ void PassManagerBuilder::populateModulePassManager( if (RunInliner) { MPM.add(createGlobalOptimizerPass()); MPM.add(createGlobalDCEPass()); + MPM.add(createDeadArgEliminationSYCLPass()); } // If we are planning to perform ThinLTO later, let's not bloat the code with diff --git a/llvm/test/Other/opt-O2-pipeline.ll b/llvm/test/Other/opt-O2-pipeline.ll index 56f85d0fb9a8c..dfc3087d60dae 100644 --- a/llvm/test/Other/opt-O2-pipeline.ll +++ b/llvm/test/Other/opt-O2-pipeline.ll @@ -193,6 +193,7 @@ ; CHECK-NEXT: Branch Probability Analysis ; CHECK-NEXT: Block Frequency Analysis ; CHECK-NEXT: Dead Global Elimination +; CHECK-NEXT: Dead Argument Elimination for SPIR kernels in SYCL environment ; CHECK-NEXT: CallGraph Construction ; CHECK-NEXT: Globals Alias Analysis ; CHECK-NEXT: FunctionPass Manager diff --git a/llvm/test/Other/opt-O3-pipeline-enable-matrix.ll b/llvm/test/Other/opt-O3-pipeline-enable-matrix.ll index a0b7a8f5e1e3d..10a03d5e47850 100644 --- a/llvm/test/Other/opt-O3-pipeline-enable-matrix.ll +++ b/llvm/test/Other/opt-O3-pipeline-enable-matrix.ll @@ -198,6 +198,7 @@ ; CHECK-NEXT: Branch Probability Analysis ; CHECK-NEXT: Block Frequency Analysis ; CHECK-NEXT: Dead Global Elimination +; CHECK-NEXT: Dead Argument Elimination for SPIR kernels in SYCL environment ; CHECK-NEXT: CallGraph Construction ; CHECK-NEXT: Globals Alias Analysis ; CHECK-NEXT: FunctionPass Manager diff --git a/llvm/test/Other/opt-O3-pipeline.ll b/llvm/test/Other/opt-O3-pipeline.ll index 942f7d9dfead5..c4d18357690bd 100644 --- a/llvm/test/Other/opt-O3-pipeline.ll +++ b/llvm/test/Other/opt-O3-pipeline.ll @@ -198,6 +198,7 @@ ; CHECK-NEXT: Branch Probability Analysis ; CHECK-NEXT: Block Frequency Analysis ; CHECK-NEXT: Dead Global Elimination +; CHECK-NEXT: Dead Argument Elimination for SPIR kernels in SYCL environment ; CHECK-NEXT: CallGraph Construction ; CHECK-NEXT: Globals Alias Analysis ; CHECK-NEXT: FunctionPass Manager diff --git a/llvm/test/Other/opt-Os-pipeline.ll b/llvm/test/Other/opt-Os-pipeline.ll index d975cc48b629c..31806bc173006 100644 --- a/llvm/test/Other/opt-Os-pipeline.ll +++ b/llvm/test/Other/opt-Os-pipeline.ll @@ -179,6 +179,7 @@ ; CHECK-NEXT: Branch Probability Analysis ; CHECK-NEXT: Block Frequency Analysis ; CHECK-NEXT: Dead Global Elimination +; CHECK-NEXT: Dead Argument Elimination for SPIR kernels in SYCL environment ; CHECK-NEXT: CallGraph Construction ; CHECK-NEXT: Globals Alias Analysis ; CHECK-NEXT: FunctionPass Manager diff --git a/llvm/test/Transforms/DeadArgElim/sycl-kernels-neg1.ll b/llvm/test/Transforms/DeadArgElim/sycl-kernels-neg1.ll new file mode 100644 index 0000000000000..55199ccdda687 --- /dev/null +++ b/llvm/test/Transforms/DeadArgElim/sycl-kernels-neg1.ll @@ -0,0 +1,17 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature +; RUN: opt < %s -deadargelim-sycl -S | FileCheck %s +; Skip DAE if the path to the integration header is not specified. + +target triple = "spir64-unknown-unknown-sycldevice" + +define weak_odr spir_kernel void @NegativeSpirKernel(float %arg1, float %arg2) { +; CHECK-LABEL: define {{[^@]+}}@NegativeSpirKernel +; CHECK-SAME: (float [[ARG1:%.*]], float [[ARG2:%.*]]) +; CHECK-NEXT: call void @foo(float [[ARG1]]) +; CHECK-NEXT: ret void +; + call void @foo(float %arg1) + ret void +} + +declare void @foo(float %arg) diff --git a/llvm/test/Transforms/DeadArgElim/sycl-kernels-neg2.ll b/llvm/test/Transforms/DeadArgElim/sycl-kernels-neg2.ll new file mode 100644 index 0000000000000..1c67c9a53dd04 --- /dev/null +++ b/llvm/test/Transforms/DeadArgElim/sycl-kernels-neg2.ll @@ -0,0 +1,13 @@ +; RUN: touch %t-int_header.h +; RUN: not --crash opt < %s -deadargelim-sycl -S -integr-header-file %t-bad_file.h + +; Path to the integration header is wrong. + +target triple = "spir64-unknown-unknown-sycldevice" + +define weak_odr spir_kernel void @NegativeSpirKernel(float %arg1, float %arg2) { + call void @foo(float %arg1) + ret void +} + +declare void @foo(float %arg) diff --git a/llvm/test/Transforms/DeadArgElim/sycl-kernels-neg3.ll b/llvm/test/Transforms/DeadArgElim/sycl-kernels-neg3.ll new file mode 100644 index 0000000000000..2a1f8189269ae --- /dev/null +++ b/llvm/test/Transforms/DeadArgElim/sycl-kernels-neg3.ll @@ -0,0 +1,16 @@ +; RUN: echo 'static constexpr const bool param_omit_table[] = {' > %t-int_header.h +; RUN: echo ' // NegativeSpirKernel' >> %t-int_header.h +; RUN: echo ' false, false,' >> %t-int_header.h +; RUN: echo '};' >> %t-int_header.h +; RUN: not --crash opt < %s -deadargelim-sycl -S -integr-header-file %t-int_header.h + +; No OMIT_TABLE markers in the integration header. + +target triple = "spir64-unknown-unknown-sycldevice" + +define weak_odr spir_kernel void @NegativeSpirKernel(float %arg1, float %arg2) { + call void @foo(float %arg1) + ret void +} + +declare void @foo(float %arg) diff --git a/llvm/test/Transforms/DeadArgElim/sycl-kernels-neg4.ll b/llvm/test/Transforms/DeadArgElim/sycl-kernels-neg4.ll new file mode 100644 index 0000000000000..21412ac5a4bfe --- /dev/null +++ b/llvm/test/Transforms/DeadArgElim/sycl-kernels-neg4.ll @@ -0,0 +1,18 @@ +; RUN: echo 'static constexpr const bool param_omit_table[] = {' > %t-int_header.h +; RUN: echo ' // OMIT_TABLE_BEGIN' >> %t-int_header.h +; RUN: echo ' // WrongKernelName' >> %t-int_header.h +; RUN: echo ' false, false,' >> %t-int_header.h +; RUN: echo ' // OMIT_TABLE_END' >> %t-int_header.h +; RUN: echo '};' >> %t-int_header.h +; RUN: not --crash opt < %s -deadargelim-sycl -S -integr-header-file %t-int_header.h + +; Wrong kernel name in the integration header. + +target triple = "spir64-unknown-unknown-sycldevice" + +define weak_odr spir_kernel void @NegativeSpirKernel(float %arg1, float %arg2) { + call void @foo(float %arg1) + ret void +} + +declare void @foo(float %arg) diff --git a/llvm/test/Transforms/DeadArgElim/sycl-kernels-neg5.ll b/llvm/test/Transforms/DeadArgElim/sycl-kernels-neg5.ll new file mode 100644 index 0000000000000..915241aec9489 --- /dev/null +++ b/llvm/test/Transforms/DeadArgElim/sycl-kernels-neg5.ll @@ -0,0 +1,20 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature +; RUN: opt < %s -deadargelim -S | FileCheck %s +; RUN: opt < %s -deadargelim-sycl -S | FileCheck %s + +; This test ensures dead arguments are not eliminated +; from a global function that is not a SYCL kernel. + +target triple = "spir64-unknown-unknown-sycldevice" + +define weak_odr void @NotASpirKernel(float %arg1, float %arg2) { +; CHECK-LABEL: define {{[^@]+}}@NotASpirKernel +; CHECK-SAME: (float [[ARG1:%.*]], float [[ARG2:%.*]]) +; CHECK-NEXT: call void @foo(float [[ARG1]]) +; CHECK-NEXT: ret void +; + call void @foo(float %arg1) + ret void +} + +declare void @foo(float %arg) diff --git a/llvm/test/Transforms/DeadArgElim/sycl-kernels.ll b/llvm/test/Transforms/DeadArgElim/sycl-kernels.ll new file mode 100644 index 0000000000000..5cd5019554734 --- /dev/null +++ b/llvm/test/Transforms/DeadArgElim/sycl-kernels.ll @@ -0,0 +1,62 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature +; RUN: echo 'some code we want to preserve' > %t-int_header.h +; RUN: echo 'static constexpr const bool param_omit_table[] = {' >> %t-int_header.h +; RUN: echo ' // OMIT_TABLE_BEGIN' >> %t-int_header.h +; RUN: echo ' // SpirKernel1' >> %t-int_header.h +; RUN: echo ' false, false,' >> %t-int_header.h +; RUN: echo ' // SpirKernel2' >> %t-int_header.h +; RUN: echo ' false, false,' >> %t-int_header.h +; RUN: echo ' // OMIT_TABLE_END' >> %t-int_header.h +; RUN: echo '};' >> %t-int_header.h +; RUN: echo 'some code we want to preserve' >> %t-int_header.h +; RUN: opt < %s -deadargelim -S | FileCheck %s --check-prefixes=CHECK +; RUN: opt < %s -deadargelim-sycl -S -integr-header-file %t-int_header.h | FileCheck %s --check-prefixes=CHECK-SYCL +; RUN: cat %t-int_header.h | FileCheck %s --check-prefixes=CHECK-INT-HEADER + +; This test checks eliminating dead arguments +; from SPIR kernel functions in SYCL environment. + +target triple = "spir64-unknown-unknown-sycldevice" + +define weak_odr spir_kernel void @SpirKernel1(float %arg1, float %arg2) { +; CHECK-LABEL: define {{[^@]+}}@SpirKernel1 +; CHECK-SAME: (float [[ARG1:%.*]], float [[ARG2:%.*]]) +; CHECK-NEXT: call void @foo(float [[ARG1]]) +; CHECK-NEXT: ret void +; +; CHECK-SYCL-LABEL: define {{[^@]+}}@SpirKernel1 +; CHECK-SYCL-SAME: (float [[ARG1:%.*]]) +; CHECK-SYCL-NEXT: call void @foo(float [[ARG1]]) +; CHECK-SYCL-NEXT: ret void +; + call void @foo(float %arg1) + ret void +} + +define weak_odr spir_kernel void @SpirKernel2(float %arg1, float %arg2) { +; CHECK-LABEL: define {{[^@]+}}@SpirKernel2 +; CHECK-SAME: (float [[ARG1:%.*]], float [[ARG2:%.*]]) +; CHECK-NEXT: call void @foo(float [[ARG2]]) +; CHECK-NEXT: ret void +; +; CHECK-SYCL-LABEL: define {{[^@]+}}@SpirKernel2 +; CHECK-SYCL-SAME: (float [[ARG2:%.*]]) +; CHECK-SYCL-NEXT: call void @foo(float [[ARG2]]) +; CHECK-SYCL-NEXT: ret void +; + call void @foo(float %arg2) + ret void +} + +; CHECK-INT-HEADER: some code we want to preserve +; CHECK-INT-HEADER: static constexpr const bool param_omit_table[] = { +; CHECK-INT-HEADER: // OMIT_TABLE_BEGIN +; CHECK-INT-HEADER: // SpirKernel1 +; CHECK-INT-HEADER: false, true, +; CHECK-INT-HEADER: // SpirKernel2 +; CHECK-INT-HEADER: true, false, +; CHECK-INT-HEADER: // OMIT_TABLE_END +; CHECK-INT-HEADER: }; +; CHECK-INT-HEADER: some code we want to preserve + +declare void @foo(float %arg)