Skip to content

Commit

Permalink
Add pass plugin for in-tree build with shared libs (#2290)
Browse files Browse the repository at this point in the history
The plugin registers llvm-spirv passes to llvm pass manager and enables
LIT test for llvm-spirv passes using opt tool.
  • Loading branch information
wenju-he authored Jan 10, 2024
1 parent 4db768c commit 346b4cd
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/SPIRV/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ set(SRC_LIST
SPIRVUtil.cpp
SPIRVWriter.cpp
SPIRVWriterPass.cpp
PassPlugin.cpp
PreprocessMetadata.cpp
libSPIRV/SPIRVBasicBlock.cpp
libSPIRV/SPIRVDebug.cpp
Expand Down
135 changes: 135 additions & 0 deletions lib/SPIRV/PassPlugin.cpp
Original file line number Diff line number Diff line change
@@ -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<PassBuilder::PipelineElement>) {
if (Name.equals("spirv-lower-bitcast")) {
PM.addPass(
SPIRVLowerBitCastToNonStandardTypePass(TranslatorOpts{}));
return true;
}
return false;
});
PB.registerPipelineParsingCallback(
[](StringRef Name, ModulePassManager &PM,
ArrayRef<PassBuilder::PipelineElement>) {
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-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-lower-sadd-with-overflow")) {
PM.addPass(SPIRVLowerSaddWithOverflowPass());
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;
});
}};
}

} // namespace

extern "C" LLVM_ATTRIBUTE_WEAK ::llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo() {
return getSPIRVPluginInfo();
}
7 changes: 7 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -96,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)


Expand Down
11 changes: 11 additions & 0 deletions test/lit.cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions test/lit.site.cfg.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -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@"
Expand Down
10 changes: 10 additions & 0 deletions test/pass-plugin-opt.ll
Original file line number Diff line number Diff line change
@@ -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"

0 comments on commit 346b4cd

Please sign in to comment.