From 362f53709a1bd2390e3b71f0ffc49c46098e2f30 Mon Sep 17 00:00:00 2001 From: Wenju He Date: Mon, 8 Jan 2024 09:51:50 +0800 Subject: [PATCH 1/4] Add pass plugin for in-tree build with shared libs The plugin registers llvm-spirv passes to llvm pass manager and enables LIT test for llvm-spirv passes using opt tool. --- lib/SPIRV/CMakeLists.txt | 1 + lib/SPIRV/PassPlugin.cpp | 135 +++++++++++++++++++++++++++++++++++++++ test/CMakeLists.txt | 2 + test/lit.cfg.py | 11 ++++ test/lit.site.cfg.py.in | 2 + test/pass-plugin-opt.ll | 10 +++ 6 files changed, 161 insertions(+) create mode 100644 lib/SPIRV/PassPlugin.cpp create mode 100644 test/pass-plugin-opt.ll diff --git a/lib/SPIRV/CMakeLists.txt b/lib/SPIRV/CMakeLists.txt index 31f13f9849..c88335ad04 100644 --- a/lib/SPIRV/CMakeLists.txt +++ b/lib/SPIRV/CMakeLists.txt @@ -26,6 +26,7 @@ set(SRC_LIST SPIRVUtil.cpp SPIRVWriter.cpp SPIRVWriterPass.cpp + PassPlugin.cpp PreprocessMetadata.cpp libSPIRV/SPIRVBasicBlock.cpp libSPIRV/SPIRVDebug.cpp diff --git a/lib/SPIRV/PassPlugin.cpp b/lib/SPIRV/PassPlugin.cpp new file mode 100644 index 0000000000..334d7061e8 --- /dev/null +++ b/lib/SPIRV/PassPlugin.cpp @@ -0,0 +1,135 @@ +//===- PassPlugin.cpp - Register SPIRV passes as plugin -------------------===// +// +// The LLVM/SPIR-V Translator +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +// Copyright (c) 2024 The Khronos Group Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal with the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimers. +// Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimers in the documentation +// and/or other materials provided with the distribution. +// Neither the names of The Khronos Group, nor the names of its +// contributors may be used to endorse or promote products derived from this +// Software without specific prior written permission. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH +// THE SOFTWARE. +// +//===----------------------------------------------------------------------===// +// +// This file implements pass plugin to register llvm-spirv passes for opt tool. +// +//===----------------------------------------------------------------------===// + +#include "OCLToSPIRV.h" +#include "PreprocessMetadata.h" +#include "SPIRVLowerBitCastToNonStandardType.h" +#include "SPIRVLowerBool.h" +#include "SPIRVLowerConstExpr.h" +#include "SPIRVLowerMemmove.h" +#include "SPIRVLowerOCLBlocks.h" +#include "SPIRVLowerSaddWithOverflow.h" +#include "SPIRVRegularizeLLVM.h" +#include "SPIRVToOCL.h" +#include "SPIRVWriter.h" + +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Passes/PassPlugin.h" + +using namespace llvm; + +namespace { + +PassPluginLibraryInfo getSPIRVPluginInfo() { + return { + LLVM_PLUGIN_API_VERSION, "SPIRV", LLVM_VERSION_STRING, + [](PassBuilder &PB) { + PB.registerAnalysisRegistrationCallback([](ModuleAnalysisManager &AM) { + AM.registerPass([] { return OCLTypeToSPIRVPass(); }); + }); + PB.registerPipelineParsingCallback( + [](StringRef Name, FunctionPassManager &PM, + ArrayRef) { + if (Name.equals("spirv-lower-bitcast")) { + PM.addPass( + SPIRVLowerBitCastToNonStandardTypePass(TranslatorOpts{})); + return true; + } + return false; + }); + PB.registerPipelineParsingCallback( + [](StringRef Name, ModulePassManager &PM, + ArrayRef) { + if (Name.equals("ocl-to-spirv")) { + PM.addPass(OCLToSPIRVPass()); + return true; + } + if (Name.equals("llvm-to-spirv")) { + SPIRV::TranslatorOpts DefaultOpts; + DefaultOpts.enableAllExtensions(); + SPIRVModule *BM = SPIRVModule::createSPIRVModule(DefaultOpts); + PM.addPass(LLVMToSPIRVPass(BM)); + return true; + } + if (Name.equals("process-metadata")) { + PM.addPass(PreprocessMetadataPass()); + return true; + } + if (Name.equals("spirv-lower-bool")) { + PM.addPass(SPIRVLowerBoolPass()); + return true; + } + if (Name.equals("spirv-lower-sadd-with-overflow")) { + PM.addPass(SPIRVLowerSaddWithOverflowPass()); + return true; + } + if (Name.equals("spirv-lower-constexpr")) { + PM.addPass(SPIRVLowerConstExprPass()); + return true; + } + if (Name.equals("spirv-lower-memmove")) { + PM.addPass(SPIRVLowerMemmovePass()); + return true; + } + if (Name.equals("spirv-lower-ocl-blocks")) { + PM.addPass(SPIRVLowerOCLBlocksPass()); + return true; + } + if (Name.equals("spirv-regularize-llvm")) { + PM.addPass(SPIRVRegularizeLLVMPass()); + return true; + } + if (Name.equals("spirv-to-ocl12")) { + PM.addPass(SPIRVToOCL12Pass()); + return true; + } + if (Name.equals("spirv-to-ocl20")) { + PM.addPass(SPIRVToOCL20Pass()); + return true; + } + return false; + }); + }}; +} + +} + +extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo +llvmGetPassPluginInfo() { + return getSPIRVPluginInfo(); +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 355baffb82..29f09f6e20 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,5 +1,7 @@ llvm_canonicalize_cmake_booleans(SPIRV_SKIP_CLANG_BUILD) llvm_canonicalize_cmake_booleans(SPIRV_SKIP_DEBUG_INFO_TESTS) +llvm_canonicalize_cmake_booleans(LLVM_BUILD_SHARED_LIBS) +llvm_canonicalize_cmake_booleans(LLVM_SPIRV_BUILD_EXTERNAL) # required by lit.site.cfg.py.in get_target_property(LLVM_SPIRV_DIR llvm-spirv BINARY_DIR) diff --git a/test/lit.cfg.py b/test/lit.cfg.py index fd8d3f94c8..3184a81526 100644 --- a/test/lit.cfg.py +++ b/test/lit.cfg.py @@ -76,6 +76,17 @@ else: config.substitutions.append(('spirv-val', ':')) +if not config.llvm_spirv_build_external and config.llvm_build_shared_libs: + config.available_features.add('pass-plugin') + config.substitutions.append( + ( + "%load_spirv_lib", + "-load-pass-plugin={}/libLLVMSPIRVLib{}".format( + config.llvm_shlib_dir, config.llvm_plugin_ext + ), + ) + ) + llvm_config.with_system_environment('LD_LIBRARY_PATH') if using_spirv_tools: llvm_config.with_environment('LD_LIBRARY_PATH', config.spirv_tools_lib_dir, append_path=True) diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in index fdc4f43190..cc32160814 100644 --- a/test/lit.site.cfg.py.in +++ b/test/lit.site.cfg.py.in @@ -10,6 +10,8 @@ config.llvm_spirv_lib_dir = "@LLVM_SPIRV_LIB_DIR@" config.llvm_libs_dir = "@LLVM_LIBS_DIR@" config.llvm_shlib_dir = "@SHLIBDIR@" config.llvm_plugin_ext = "@LLVM_PLUGIN_EXT@" +config.llvm_build_shared_libs = @LLVM_BUILD_SHARED_LIBS@ +config.llvm_spirv_build_external = @LLVM_SPIRV_BUILD_EXTERNAL@ config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" config.host_triple = "@LLVM_HOST_TRIPLE@" config.target_triple = "@LLVM_TARGET_TRIPLE@" diff --git a/test/pass-plugin-opt.ll b/test/pass-plugin-opt.ll new file mode 100644 index 0000000000..24c3397900 --- /dev/null +++ b/test/pass-plugin-opt.ll @@ -0,0 +1,10 @@ +; REQUIRES: pass-plugin +; UNSUPPORTED: target={{.*windows.*}} + +; RUN: opt %load_spirv_lib -passes=llvm-to-spirv -disable-output -debug-pass-manager %s 2>&1 | FileCheck %s + +; CHECK: Running pass: SPIRV::LLVMToSPIRVPass +; CHECK: Running analysis: SPIRV::OCLTypeToSPIRVPass + +target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024" +target triple = "spir64-unknown-unknown" From f0cbbe5b17a3e481f27909e030b8aaf2528462c8 Mon Sep 17 00:00:00 2001 From: Wenju He Date: Mon, 8 Jan 2024 09:56:34 +0800 Subject: [PATCH 2/4] clang-format --- lib/SPIRV/PassPlugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/SPIRV/PassPlugin.cpp b/lib/SPIRV/PassPlugin.cpp index 334d7061e8..ae7929f1e0 100644 --- a/lib/SPIRV/PassPlugin.cpp +++ b/lib/SPIRV/PassPlugin.cpp @@ -127,7 +127,7 @@ PassPluginLibraryInfo getSPIRVPluginInfo() { }}; } -} +} // namespace extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo llvmGetPassPluginInfo() { From 8b9ded28a76fc012cb8b2ed06d641a138d015d17 Mon Sep 17 00:00:00 2001 From: Wenju He Date: Mon, 8 Jan 2024 11:35:50 +0800 Subject: [PATCH 3/4] add opt to LLVM_SPIRV_TEST_DEPS --- test/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 29f09f6e20..8d6a9264ba 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -98,6 +98,11 @@ if(NOT LLVM_SPIRV_BUILD_EXTERNAL) llvm-readobj ) endif(NOT SPIRV_SKIP_DEBUG_INFO_TESTS) + if(LLVM_BUILD_SHARED_LIBS) + list(APPEND LLVM_SPIRV_TEST_DEPS + opt + ) + endif() endif(NOT LLVM_SPIRV_BUILD_EXTERNAL) From a97796ef1a3d06e7619388d134f545238d6c95c9 Mon Sep 17 00:00:00 2001 From: Wenju He Date: Mon, 8 Jan 2024 12:02:30 +0800 Subject: [PATCH 4/4] sort by pass name --- lib/SPIRV/PassPlugin.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/SPIRV/PassPlugin.cpp b/lib/SPIRV/PassPlugin.cpp index ae7929f1e0..119bce8629 100644 --- a/lib/SPIRV/PassPlugin.cpp +++ b/lib/SPIRV/PassPlugin.cpp @@ -94,10 +94,6 @@ PassPluginLibraryInfo getSPIRVPluginInfo() { PM.addPass(SPIRVLowerBoolPass()); return true; } - if (Name.equals("spirv-lower-sadd-with-overflow")) { - PM.addPass(SPIRVLowerSaddWithOverflowPass()); - return true; - } if (Name.equals("spirv-lower-constexpr")) { PM.addPass(SPIRVLowerConstExprPass()); return true; @@ -110,6 +106,10 @@ PassPluginLibraryInfo getSPIRVPluginInfo() { PM.addPass(SPIRVLowerOCLBlocksPass()); return true; } + if (Name.equals("spirv-lower-sadd-with-overflow")) { + PM.addPass(SPIRVLowerSaddWithOverflowPass()); + return true; + } if (Name.equals("spirv-regularize-llvm")) { PM.addPass(SPIRVRegularizeLLVMPass()); return true;