149 lines
6.1 KiB
C++
149 lines
6.1 KiB
C++
//=- SPIRVRegularizeLLVM.h - LLVM Module regularization pass -*- C++ -*-=//
|
|
//
|
|
// The LLVM/SPIR-V Translator
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
// Copyright (c) 2022 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.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SPIRV_SPIRVREGULARIZELLVM_H
|
|
#define SPIRV_SPIRVREGULARIZELLVM_H
|
|
|
|
#include "SPIRVInternal.h"
|
|
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/IR/PassManager.h"
|
|
#include "llvm/Pass.h"
|
|
|
|
namespace SPIRV {
|
|
|
|
class SPIRVRegularizeLLVMBase {
|
|
public:
|
|
SPIRVRegularizeLLVMBase() : M(nullptr), Ctx(nullptr) {}
|
|
|
|
bool runRegularizeLLVM(llvm::Module &M);
|
|
// Lower functions
|
|
bool regularize();
|
|
|
|
// SPIR-V disallows functions being entrypoints and called
|
|
// LLVM doesn't. This adds a wrapper around the entry point
|
|
// that later SPIR-V writer renames.
|
|
void addKernelEntryPoint(llvm::Module *M);
|
|
|
|
/// Some LLVM intrinsics that have no SPIR-V counterpart may be wrapped in
|
|
/// @spirv.llvm_intrinsic_* function. During reverse translation from SPIR-V
|
|
/// to LLVM IR we can detect this @spirv.llvm_intrinsic_* function and
|
|
/// replace it with @llvm.intrinsic.* back.
|
|
void lowerIntrinsicToFunction(llvm::IntrinsicInst *Intrinsic);
|
|
|
|
/// No SPIR-V counterpart for @llvm.fshl.*(@llvm.fshr.*) intrinsic. It will be
|
|
/// lowered to a newly generated @spirv.llvm_fshl_*(@spirv.llvm_fshr_*)
|
|
/// function.
|
|
///
|
|
/// Conceptually, FSHL (FSHR):
|
|
/// 1. concatenates the ints, the first one being the more significant;
|
|
/// 2. performs a left (right) shift-rotate on the resulting doubled-sized
|
|
/// int;
|
|
/// 3. returns the most (least) significant bits of the shift-rotate result,
|
|
/// the number of bits being equal to the size of the original integers.
|
|
/// If FSHL (FSHR) operates on a vector type instead, the same operations are
|
|
/// performed for each set of corresponding vector elements.
|
|
///
|
|
/// The actual implementation algorithm will be slightly different for
|
|
/// simplification purposes.
|
|
void lowerFunnelShift(llvm::IntrinsicInst *FSHIntrinsic);
|
|
|
|
void lowerUMulWithOverflow(llvm::IntrinsicInst *UMulIntrinsic);
|
|
void buildUMulWithOverflowFunc(llvm::Function *UMulFunc);
|
|
|
|
// For some cases Clang emits VectorExtractDynamic as:
|
|
// void @_Z28__spirv_VectorExtractDynamic(<Ty>* sret(<Ty>), jointMatrix, idx);
|
|
// Instead of:
|
|
// <Ty> @_Z28__spirv_VectorExtractDynamic(JointMatrix, Idx);
|
|
// And VectorInsertDynamic as:
|
|
// @_Z27__spirv_VectorInsertDynamic(jointMatrix, <Ty>* byval(<Ty>), idx);
|
|
// Instead of:
|
|
// @_Z27__spirv_VectorInsertDynamic(jointMatrix, <Ty>, idx)
|
|
// Need to add additional GEP, store and load instructions and mutate called
|
|
// function to avoid translation failures
|
|
void expandSYCLTypeUsing(llvm::Module *M);
|
|
void expandVEDWithSYCLTypeSRetArg(llvm::Function *F);
|
|
void expandVIDWithSYCLTypeByValComp(llvm::Function *F);
|
|
|
|
// It is possible that incoming LLVM IR conversion instructions convert
|
|
// floating point to non-standard integer types. Such types are not supported
|
|
// in SPIR-V. This function cleans up such code and removes occurence of
|
|
// non-standard integer types.
|
|
void cleanupConversionToNonStdIntegers(llvm::Module *M);
|
|
|
|
// According to the specification, the operands of a shift instruction must be
|
|
// a scalar/vector of integer. When LLVM-IR contains a shift instruction with
|
|
// i1 operands, they are treated as a bool. We need to extend them to i32 to
|
|
// comply with the specification. For example: "%shift = lshr i1 0, 1";
|
|
// The bit instruction should be changed to the extended version
|
|
// "%shift = lshr i32 0, 1" so the args are treated as int operands.
|
|
Value *extendBitInstBoolArg(llvm::Instruction *OldInst);
|
|
|
|
static std::string lowerLLVMIntrinsicName(llvm::IntrinsicInst *II);
|
|
static char ID;
|
|
|
|
private:
|
|
llvm::Module *M;
|
|
llvm::LLVMContext *Ctx;
|
|
};
|
|
|
|
class SPIRVRegularizeLLVMPass
|
|
: public llvm::PassInfoMixin<SPIRVRegularizeLLVMPass>,
|
|
public SPIRVRegularizeLLVMBase {
|
|
public:
|
|
llvm::PreservedAnalyses run(llvm::Module &M,
|
|
llvm::ModuleAnalysisManager &MAM) {
|
|
return runRegularizeLLVM(M) ? llvm::PreservedAnalyses::none()
|
|
: llvm::PreservedAnalyses::all();
|
|
}
|
|
|
|
static bool isRequired() { return true; }
|
|
};
|
|
|
|
class SPIRVRegularizeLLVMLegacy : public llvm::ModulePass,
|
|
public SPIRVRegularizeLLVMBase {
|
|
public:
|
|
SPIRVRegularizeLLVMLegacy() : ModulePass(ID) {
|
|
initializeSPIRVRegularizeLLVMLegacyPass(*PassRegistry::getPassRegistry());
|
|
}
|
|
|
|
bool runOnModule(llvm::Module &M) override;
|
|
|
|
static char ID;
|
|
};
|
|
|
|
} // namespace SPIRV
|
|
|
|
#endif // SPIRV_SPIRVREGULARIZELLVM_H
|