llvm-project/llvm/lib/Target/SPIRV/SPIRVSubtarget.h
Marcos Maronas b1703ad38d
[SPIRV] Change how to detect OpenCL/Vulkan Env and update tests accordingly. (#129689)
A new test added for spirv-friendly builtins for
SPV_KHR_bit_instructions unveiled that current mechanism to detect
whether SPIRV Backend is in OpenCL environment or Vulkan environment was
not good enough. This PR updates how to detect the environment and all
the tests accordingly.

*UPDATE*: the new approach is having a new member in `SPIRVSubtarget` to
represent the environment. It can be either OpenCL, Kernel or Unknown.
If the triple is explicit, we can directly set it at the creation of the
`SPIRVSubtarget`, otherwise we just leave it unknown until we find other
information that can help us set the environment. For now, the only
other information we use to set the environment is `hlsl.shader`
attribute at `SPIRV::ExecutionModel::ExecutionModel
getExecutionModel(const SPIRVSubtarget &STI, const Function &F)`. Going
forward we should consider also specific instructions that are
Kernel-exclusive or Shader-exclusive.

---------

Co-authored-by: marcos.maronas <mmaronas@smtp.igk.intel.com>
2025-06-03 09:50:23 -04:00

162 lines
5.9 KiB
C++

//===-- SPIRVSubtarget.h - SPIR-V Subtarget Information --------*- 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
//
//===----------------------------------------------------------------------===//
//
// This file declares the SPIR-V specific subclass of TargetSubtargetInfo.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_SPIRV_SPIRVSUBTARGET_H
#define LLVM_LIB_TARGET_SPIRV_SPIRVSUBTARGET_H
#include "SPIRVCallLowering.h"
#include "SPIRVFrameLowering.h"
#include "SPIRVISelLowering.h"
#include "SPIRVInlineAsmLowering.h"
#include "SPIRVInstrInfo.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/TargetParser/Triple.h"
#define GET_SUBTARGETINFO_HEADER
#include "SPIRVGenSubtargetInfo.inc"
namespace llvm {
class StringRef;
class SPIRVTargetMachine;
class SPIRVSubtarget : public SPIRVGenSubtargetInfo {
public:
// Enum for the SPIR-V environment: Kernel, Shader or Unknown.
enum SPIRVEnvType { Kernel, Shader, Unknown };
private:
const unsigned PointerSize;
VersionTuple SPIRVVersion;
VersionTuple OpenCLVersion;
SmallSet<SPIRV::Extension::Extension, 4> AvailableExtensions;
SmallSet<SPIRV::InstructionSet::InstructionSet, 4> AvailableExtInstSets;
std::unique_ptr<SPIRVGlobalRegistry> GR;
SPIRVInstrInfo InstrInfo;
SPIRVFrameLowering FrameLowering;
SPIRVTargetLowering TLInfo;
Triple TargetTriple;
SPIRVEnvType Env;
// GlobalISel related APIs.
std::unique_ptr<CallLowering> CallLoweringInfo;
std::unique_ptr<RegisterBankInfo> RegBankInfo;
std::unique_ptr<LegalizerInfo> Legalizer;
std::unique_ptr<InstructionSelector> InstSelector;
std::unique_ptr<InlineAsmLowering> InlineAsmInfo;
// TODO: Initialise the available extensions, extended instruction sets
// based on the environment settings.
void initAvailableExtInstSets();
void accountForAMDShaderTrinaryMinmax();
public:
// This constructor initializes the data members to match that
// of the specified triple.
SPIRVSubtarget(const Triple &TT, const std::string &CPU,
const std::string &FS, const SPIRVTargetMachine &TM);
SPIRVSubtarget &initSubtargetDependencies(StringRef CPU, StringRef FS);
void initAvailableExtensions(
const std::set<SPIRV::Extension::Extension> &AllowedExtIds);
// Parses features string setting specified subtarget options.
// The definition of this function is auto generated by tblgen.
void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
unsigned getPointerSize() const { return PointerSize; }
unsigned getBound() const { return GR->getBound(); }
bool canDirectlyComparePointers() const;
void setEnv(SPIRVEnvType E) {
if (E == Unknown)
report_fatal_error("Unknown environment is not allowed.");
if (Env != Unknown)
report_fatal_error("Environment is already set.");
Env = E;
}
SPIRVEnvType getEnv() const { return Env; }
bool isKernel() const { return getEnv() == Kernel; }
bool isShader() const { return getEnv() == Shader; }
bool isLogicalSPIRV() const {
return TargetTriple.getArch() == Triple::spirv;
}
bool isPhysicalSPIRV() const {
return TargetTriple.getArch() == Triple::spirv32 ||
TargetTriple.getArch() == Triple::spirv64;
}
const std::string &getTargetTripleAsStr() const { return TargetTriple.str(); }
VersionTuple getSPIRVVersion() const { return SPIRVVersion; };
bool isAtLeastSPIRVVer(VersionTuple VerToCompareTo) const;
bool isAtLeastOpenCLVer(VersionTuple VerToCompareTo) const;
// TODO: implement command line args or other ways to determine this.
bool hasOpenCLFullProfile() const { return true; }
bool hasOpenCLImageSupport() const { return true; }
const SmallSet<SPIRV::Extension::Extension, 4> &
getAllAvailableExtensions() const {
return AvailableExtensions;
}
bool canUseExtension(SPIRV::Extension::Extension E) const;
bool canUseExtInstSet(SPIRV::InstructionSet::InstructionSet E) const;
SPIRV::InstructionSet::InstructionSet getPreferredInstructionSet() const;
SPIRVGlobalRegistry *getSPIRVGlobalRegistry() const { return GR.get(); }
const CallLowering *getCallLowering() const override {
return CallLoweringInfo.get();
}
const RegisterBankInfo *getRegBankInfo() const override {
return RegBankInfo.get();
}
const LegalizerInfo *getLegalizerInfo() const override {
return Legalizer.get();
}
InstructionSelector *getInstructionSelector() const override {
return InstSelector.get();
}
const InlineAsmLowering *getInlineAsmLowering() const override {
return InlineAsmInfo.get();
}
const SPIRVInstrInfo *getInstrInfo() const override { return &InstrInfo; }
const SPIRVFrameLowering *getFrameLowering() const override {
return &FrameLowering;
}
const SPIRVTargetLowering *getTargetLowering() const override {
return &TLInfo;
}
const SPIRVRegisterInfo *getRegisterInfo() const override {
return &InstrInfo.getRegisterInfo();
}
static bool classof(const TargetSubtargetInfo *ST) {
return ST->getTargetTriple().isSPIRV();
}
static constexpr unsigned MaxLegalAddressSpace = 6;
// Adds known SPIR-V extensions to the global list of allowed extensions that
// SPIRVSubtarget module owns as
// cl::opt<std::set<SPIRV::Extension::Extension>, ...> global variable.
static void
addExtensionsToClOpt(const std::set<SPIRV::Extension::Extension> &AllowList);
};
} // namespace llvm
#endif // LLVM_LIB_TARGET_SPIRV_SPIRVSUBTARGET_H