diff --git a/llvm/lib/Target/SPIRV/CMakeLists.txt b/llvm/lib/Target/SPIRV/CMakeLists.txt index eab7b213756b3..79b76165cd57a 100644 --- a/llvm/lib/Target/SPIRV/CMakeLists.txt +++ b/llvm/lib/Target/SPIRV/CMakeLists.txt @@ -41,6 +41,7 @@ add_llvm_target(SPIRVCodeGen SPIRVPreLegalizerCombiner.cpp SPIRVPostLegalizer.cpp SPIRVPrepareFunctions.cpp + SPIRVPrepareGlobals.cpp SPIRVRegisterBankInfo.cpp SPIRVRegisterInfo.cpp SPIRVRegularizer.cpp diff --git a/llvm/lib/Target/SPIRV/SPIRV.h b/llvm/lib/Target/SPIRV/SPIRV.h index efd49b930aa34..fa85ee781c249 100644 --- a/llvm/lib/Target/SPIRV/SPIRV.h +++ b/llvm/lib/Target/SPIRV/SPIRV.h @@ -31,6 +31,7 @@ FunctionPass *createSPIRVPreLegalizerCombiner(); FunctionPass *createSPIRVPreLegalizerPass(); FunctionPass *createSPIRVPostLegalizerPass(); ModulePass *createSPIRVEmitIntrinsicsPass(SPIRVTargetMachine *TM); +ModulePass *createSPIRVPrepareGlobalsPass(); MachineFunctionPass *createSPIRVEmitNonSemanticDIPass(SPIRVTargetMachine *TM); InstructionSelector * createSPIRVInstructionSelector(const SPIRVTargetMachine &TM, @@ -51,6 +52,7 @@ void initializeSPIRVLegalizePointerCastPass(PassRegistry &); void initializeSPIRVRegularizerPass(PassRegistry &); void initializeSPIRVMergeRegionExitTargetsPass(PassRegistry &); void initializeSPIRVPrepareFunctionsPass(PassRegistry &); +void initializeSPIRVPrepareGlobalsPass(PassRegistry &); void initializeSPIRVStripConvergentIntrinsicsPass(PassRegistry &); void initializeSPIRVLegalizeImplicitBindingPass(PassRegistry &); } // namespace llvm diff --git a/llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp b/llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp new file mode 100644 index 0000000000000..c44c53129f1e0 --- /dev/null +++ b/llvm/lib/Target/SPIRV/SPIRVPrepareGlobals.cpp @@ -0,0 +1,68 @@ +//===-- SPIRVPrepareGlobals.cpp - Prepare IR SPIRV globals ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// The pass transforms IR globals that cannot be trivially mapped to SPIRV +// into something that is trival to lower. +// +//===----------------------------------------------------------------------===// + +#include "SPIRV.h" + +#include "llvm/IR/Module.h" + +using namespace llvm; + +namespace { + +struct SPIRVPrepareGlobals : public ModulePass { + static char ID; + SPIRVPrepareGlobals() : ModulePass(ID) {} + + StringRef getPassName() const override { + return "SPIRV prepare global variables"; + } + + bool runOnModule(Module &M) override; +}; + +bool tryExtendLLVMBitcodeMarker(GlobalVariable &Bitcode) { + assert(Bitcode.getName() == "llvm.embedded.module"); + + ArrayType *AT = cast(Bitcode.getValueType()); + if (AT->getNumElements() != 0) + return false; + + ArrayType *AT1 = ArrayType::get(AT->getElementType(), 1); + Constant *OneEltInit = Constant::getNullValue(AT1); + Bitcode.replaceInitializer(OneEltInit); + return true; +} + +bool SPIRVPrepareGlobals::runOnModule(Module &M) { + const bool IsAMD = M.getTargetTriple().getVendor() == Triple::AMD; + if (!IsAMD) + return false; + + bool Changed = false; + if (GlobalVariable *Bitcode = M.getNamedGlobal("llvm.embedded.module")) + Changed |= tryExtendLLVMBitcodeMarker(*Bitcode); + + return Changed; +} +char SPIRVPrepareGlobals::ID = 0; + +} // namespace + +INITIALIZE_PASS(SPIRVPrepareGlobals, "prepare-globals", + "SPIRV prepare global variables", false, false) + +namespace llvm { +ModulePass *createSPIRVPrepareGlobalsPass() { + return new SPIRVPrepareGlobals(); +} +} // namespace llvm diff --git a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp index 2951a4bc695e2..10bbca225b20a 100644 --- a/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVTargetMachine.cpp @@ -59,6 +59,7 @@ extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSPIRVTarget() { initializeSPIRVEmitIntrinsicsPass(PR); initializeSPIRVEmitNonSemanticDIPass(PR); initializeSPIRVPrepareFunctionsPass(PR); + initializeSPIRVPrepareGlobalsPass(PR); initializeSPIRVStripConvergentIntrinsicsPass(PR); } @@ -172,6 +173,7 @@ void SPIRVPassConfig::addIRPasses() { addPass(createSPIRVRegularizerPass()); addPass(createSPIRVPrepareFunctionsPass(TM)); + addPass(createSPIRVPrepareGlobalsPass()); } void SPIRVPassConfig::addISelPrepare() { diff --git a/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll new file mode 100644 index 0000000000000..4ffdb9b7f3c7a --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/fembed-bitcode-marker.ll @@ -0,0 +1,24 @@ +; Expanding the bitcode marker works only for AMD at the moment. +; RUN: not llc -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o - +; RUN: llc -verify-machineinstrs -mtriple=spirv64-amd-amdhsa %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -mtriple=spirv64-amd-amdhsa %s -o - -filetype=obj | spirv-val %} +; +; Verify that we lower the embedded bitcode + +@llvm.embedded.module = private addrspace(1) constant [0 x i8] zeroinitializer, section ".llvmbc", align 1 +@llvm.compiler.used = appending addrspace(1) global [1 x ptr addrspace(4)] [ptr addrspace(4) addrspacecast (ptr addrspace(1) @llvm.embedded.module to ptr addrspace(4))], section "llvm.metadata" + +; CHECK: OpName %[[#LLVM_EMBEDDED_MODULE:]] "llvm.embedded.module" +; CHECK: OpDecorate %[[#LLVM_EMBEDDED_MODULE]] Constant +; CHECK: %[[#UCHAR:]] = OpTypeInt 8 0 +; CHECK: %[[#UINT:]] = OpTypeInt 32 0 +; CHECK: %[[#ONE:]] = OpConstant %[[#UINT]] 1 +; CHECK: %[[#UCHAR_ARR_1:]] = OpTypeArray %[[#UCHAR]] %[[#ONE]] +; CHECK: %[[#UCHAR_ARR_1_PTR:]] = OpTypePointer CrossWorkgroup %[[#UCHAR_ARR_1]] +; CHECK: %[[#CONST_UCHAR_ARR_1:]] = OpConstantNull %[[#UCHAR_ARR_1]] +; CHECK: %[[#LLVM_EMBEDDED_MODULE]] = OpVariable %[[#UCHAR_ARR_1_PTR]] CrossWorkgroup %[[#CONST_UCHAR_ARR_1]] + +define spir_kernel void @foo() { +entry: + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/fembed-bitcode.ll b/llvm/test/CodeGen/SPIRV/fembed-bitcode.ll new file mode 100644 index 0000000000000..a75b44925a1ea --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/fembed-bitcode.ll @@ -0,0 +1,32 @@ +; RUN: llc -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %} +; RUN: llc -verify-machineinstrs -mtriple=spirv64-amd-amdhsa %s -o - | FileCheck %s +; RUN: %if spirv-tools %{ llc -mtriple=spirv64-amd-amdhsa %s -o - -filetype=obj | spirv-val %} +; +; Verify that we can lower the embedded module and cmdline. + +@llvm.embedded.module = private addrspace(1) constant [4 x i8] c"BC\C0\DE", section ".llvmbc", align 1 +@llvm.cmdline = private addrspace(1) constant [5 x i8] c"-cc1\00", section ".llvmcmd", align 1 +@llvm.compiler.used = appending addrspace(1) global [2 x ptr addrspace(4)] [ptr addrspace(4) addrspacecast (ptr addrspace(1) @llvm.embedded.module to ptr addrspace(4)), ptr addrspace(4) addrspacecast (ptr addrspace(1) @llvm.cmdline to ptr addrspace(4))], section "llvm.metadata" + +; CHECK: OpName %[[#LLVM_EMBEDDED_MODULE:]] "llvm.embedded.module" +; CHECK: OpName %[[#LLVM_CMDLINE:]] "llvm.cmdline" +; CHECK: OpDecorate %[[#LLVM_EMBEDDED_MODULE]] Constant +; CHECK: OpDecorate %[[#LLVM_CMDLINE]] Constant +; CHECK: %[[#UCHAR:]] = OpTypeInt 8 0 +; CHECK: %[[#UINT:]] = OpTypeInt 32 0 +; CHECK: %[[#FIVE:]] = OpConstant %[[#UINT]] 5 +; CHECK: %[[#UCHAR_ARR_5:]] = OpTypeArray %[[#UCHAR]] %[[#FIVE]] +; CHECK: %[[#FOUR:]] = OpConstant %[[#UINT]] 4 +; CHECK: %[[#UCHAR_ARR_4:]] = OpTypeArray %[[#UCHAR]] %[[#FOUR]] +; CHECK: %[[#UCHAR_ARR_5_PTR:]] = OpTypePointer CrossWorkgroup %[[#UCHAR_ARR_5]] +; CHECK: %[[#UCHAR_ARR_4_PTR:]] = OpTypePointer CrossWorkgroup %[[#UCHAR_ARR_4]] +; CHECK: %[[#CONST_UCHAR_ARR_4:]] = OpConstantComposite %[[#UCHAR_ARR_4]] +; CHECK: %[[#LLVM_EMBEDDED_MODULE]] = OpVariable %[[#UCHAR_ARR_4_PTR]] CrossWorkgroup %[[#CONST_UCHAR_ARR_4]] +; CHECK: %[[#CONST_UCHAR_ARR_5:]] = OpConstantComposite %[[#UCHAR_ARR_5]] +; CHECK: %[[#LLVM_CMDLINE]] = OpVariable %[[#UCHAR_ARR_5_PTR]] CrossWorkgroup %[[#CONST_UCHAR_ARR_5]] + +define spir_kernel void @foo() { +entry: + ret void +} diff --git a/llvm/test/CodeGen/SPIRV/llc-pipeline.ll b/llvm/test/CodeGen/SPIRV/llc-pipeline.ll index 3fff2a8a24a73..6db375445e4a3 100644 --- a/llvm/test/CodeGen/SPIRV/llc-pipeline.ll +++ b/llvm/test/CodeGen/SPIRV/llc-pipeline.ll @@ -31,6 +31,7 @@ ; SPIRV-O0-NEXT: Expand reduction intrinsics ; SPIRV-O0-NEXT: SPIR-V Regularizer ; SPIRV-O0-NEXT: SPIRV prepare functions +; SPIRV-O0-NEXT: SPIRV prepare global variables ; SPIRV-O0-NEXT: FunctionPass Manager ; SPIRV-O0-NEXT: Lower invoke and unwind, for unwindless code generators ; SPIRV-O0-NEXT: Remove unreachable blocks from the CFG @@ -130,6 +131,7 @@ ; SPIRV-Opt-NEXT: Expand reduction intrinsics ; SPIRV-Opt-NEXT: SPIR-V Regularizer ; SPIRV-Opt-NEXT: SPIRV prepare functions +; SPIRV-Opt-NEXT: SPIRV prepare global variables ; SPIRV-Opt-NEXT: FunctionPass Manager ; SPIRV-Opt-NEXT: Dominator Tree Construction ; SPIRV-Opt-NEXT: Natural Loop Information