xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVSubtarget.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
181ad6265SDimitry Andric //===-- SPIRVSubtarget.cpp - SPIR-V Subtarget Information ------*- C++ -*--===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric //
981ad6265SDimitry Andric // This file implements the SPIR-V specific subclass of TargetSubtargetInfo.
1081ad6265SDimitry Andric //
1181ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1281ad6265SDimitry Andric 
1381ad6265SDimitry Andric #include "SPIRVSubtarget.h"
1481ad6265SDimitry Andric #include "SPIRV.h"
15*0fca6ea1SDimitry Andric #include "SPIRVCommandLine.h"
1681ad6265SDimitry Andric #include "SPIRVGlobalRegistry.h"
1781ad6265SDimitry Andric #include "SPIRVLegalizerInfo.h"
1881ad6265SDimitry Andric #include "SPIRVRegisterBankInfo.h"
1981ad6265SDimitry Andric #include "SPIRVTargetMachine.h"
2081ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h"
2106c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h"
2281ad6265SDimitry Andric 
2381ad6265SDimitry Andric using namespace llvm;
2481ad6265SDimitry Andric 
2581ad6265SDimitry Andric #define DEBUG_TYPE "spirv-subtarget"
2681ad6265SDimitry Andric 
2781ad6265SDimitry Andric #define GET_SUBTARGETINFO_TARGET_DESC
2881ad6265SDimitry Andric #define GET_SUBTARGETINFO_CTOR
2981ad6265SDimitry Andric #include "SPIRVGenSubtargetInfo.inc"
3081ad6265SDimitry Andric 
31*0fca6ea1SDimitry Andric static cl::opt<bool>
32*0fca6ea1SDimitry Andric     SPVTranslatorCompat("translator-compatibility-mode",
33*0fca6ea1SDimitry Andric                         cl::desc("SPIR-V Translator compatibility mode"),
34*0fca6ea1SDimitry Andric                         cl::Optional, cl::init(false));
35*0fca6ea1SDimitry Andric 
36*0fca6ea1SDimitry Andric static cl::opt<std::set<SPIRV::Extension::Extension>, false,
37*0fca6ea1SDimitry Andric                SPIRVExtensionsParser>
38*0fca6ea1SDimitry Andric     Extensions("spirv-ext",
39*0fca6ea1SDimitry Andric                cl::desc("Specify list of enabled SPIR-V extensions"));
405f757f3fSDimitry Andric 
4181ad6265SDimitry Andric // Compare version numbers, but allow 0 to mean unspecified.
42*0fca6ea1SDimitry Andric static bool isAtLeastVer(VersionTuple Target, VersionTuple VerToCompareTo) {
43*0fca6ea1SDimitry Andric   return Target.empty() || Target >= VerToCompareTo;
4481ad6265SDimitry Andric }
4581ad6265SDimitry Andric 
4681ad6265SDimitry Andric SPIRVSubtarget::SPIRVSubtarget(const Triple &TT, const std::string &CPU,
4781ad6265SDimitry Andric                                const std::string &FS,
4881ad6265SDimitry Andric                                const SPIRVTargetMachine &TM)
4981ad6265SDimitry Andric     : SPIRVGenSubtargetInfo(TT, CPU, /*TuneCPU=*/CPU, FS),
50*0fca6ea1SDimitry Andric       PointerSize(TM.getPointerSizeInBits(/* AS= */ 0)), InstrInfo(),
515f757f3fSDimitry Andric       FrameLowering(initSubtargetDependencies(CPU, FS)), TLInfo(TM, *this),
525f757f3fSDimitry Andric       TargetTriple(TT) {
53*0fca6ea1SDimitry Andric   switch (TT.getSubArch()) {
54*0fca6ea1SDimitry Andric   case Triple::SPIRVSubArch_v10:
55*0fca6ea1SDimitry Andric     SPIRVVersion = VersionTuple(1, 0);
56*0fca6ea1SDimitry Andric     break;
57*0fca6ea1SDimitry Andric   case Triple::SPIRVSubArch_v11:
58*0fca6ea1SDimitry Andric     SPIRVVersion = VersionTuple(1, 1);
59*0fca6ea1SDimitry Andric     break;
60*0fca6ea1SDimitry Andric   case Triple::SPIRVSubArch_v12:
61*0fca6ea1SDimitry Andric     SPIRVVersion = VersionTuple(1, 2);
62*0fca6ea1SDimitry Andric     break;
63*0fca6ea1SDimitry Andric   case Triple::SPIRVSubArch_v13:
64*0fca6ea1SDimitry Andric     SPIRVVersion = VersionTuple(1, 3);
65*0fca6ea1SDimitry Andric     break;
66*0fca6ea1SDimitry Andric   case Triple::SPIRVSubArch_v14:
67*0fca6ea1SDimitry Andric   default:
68*0fca6ea1SDimitry Andric     SPIRVVersion = VersionTuple(1, 4);
69*0fca6ea1SDimitry Andric     break;
70*0fca6ea1SDimitry Andric   case Triple::SPIRVSubArch_v15:
71*0fca6ea1SDimitry Andric     SPIRVVersion = VersionTuple(1, 5);
72*0fca6ea1SDimitry Andric     break;
73*0fca6ea1SDimitry Andric   case Triple::SPIRVSubArch_v16:
74*0fca6ea1SDimitry Andric     SPIRVVersion = VersionTuple(1, 6);
75*0fca6ea1SDimitry Andric     break;
76*0fca6ea1SDimitry Andric   }
77*0fca6ea1SDimitry Andric   OpenCLVersion = VersionTuple(2, 2);
78*0fca6ea1SDimitry Andric 
79bdd1243dSDimitry Andric   // The order of initialization is important.
80bdd1243dSDimitry Andric   initAvailableExtensions();
81bdd1243dSDimitry Andric   initAvailableExtInstSets();
82bdd1243dSDimitry Andric 
8381ad6265SDimitry Andric   GR = std::make_unique<SPIRVGlobalRegistry>(PointerSize);
84fcaf7f86SDimitry Andric   CallLoweringInfo = std::make_unique<SPIRVCallLowering>(TLInfo, GR.get());
85*0fca6ea1SDimitry Andric   InlineAsmInfo = std::make_unique<SPIRVInlineAsmLowering>(TLInfo);
8681ad6265SDimitry Andric   Legalizer = std::make_unique<SPIRVLegalizerInfo>(*this);
8781ad6265SDimitry Andric   RegBankInfo = std::make_unique<SPIRVRegisterBankInfo>();
8881ad6265SDimitry Andric   InstSelector.reset(
8981ad6265SDimitry Andric       createSPIRVInstructionSelector(TM, *this, *RegBankInfo.get()));
9081ad6265SDimitry Andric }
9181ad6265SDimitry Andric 
9281ad6265SDimitry Andric SPIRVSubtarget &SPIRVSubtarget::initSubtargetDependencies(StringRef CPU,
9381ad6265SDimitry Andric                                                           StringRef FS) {
9481ad6265SDimitry Andric   ParseSubtargetFeatures(CPU, /*TuneCPU=*/CPU, FS);
9581ad6265SDimitry Andric   return *this;
9681ad6265SDimitry Andric }
9781ad6265SDimitry Andric 
98bdd1243dSDimitry Andric bool SPIRVSubtarget::canUseExtension(SPIRV::Extension::Extension E) const {
99bdd1243dSDimitry Andric   return AvailableExtensions.contains(E);
100bdd1243dSDimitry Andric }
101bdd1243dSDimitry Andric 
102bdd1243dSDimitry Andric bool SPIRVSubtarget::canUseExtInstSet(
103bdd1243dSDimitry Andric     SPIRV::InstructionSet::InstructionSet E) const {
104bdd1243dSDimitry Andric   return AvailableExtInstSets.contains(E);
105bdd1243dSDimitry Andric }
106bdd1243dSDimitry Andric 
107*0fca6ea1SDimitry Andric bool SPIRVSubtarget::isAtLeastSPIRVVer(VersionTuple VerToCompareTo) const {
108bdd1243dSDimitry Andric   return isAtLeastVer(SPIRVVersion, VerToCompareTo);
109bdd1243dSDimitry Andric }
110bdd1243dSDimitry Andric 
111*0fca6ea1SDimitry Andric bool SPIRVSubtarget::isAtLeastOpenCLVer(VersionTuple VerToCompareTo) const {
1125f757f3fSDimitry Andric   if (!isOpenCLEnv())
1135f757f3fSDimitry Andric     return false;
114bdd1243dSDimitry Andric   return isAtLeastVer(OpenCLVersion, VerToCompareTo);
115bdd1243dSDimitry Andric }
116bdd1243dSDimitry Andric 
11781ad6265SDimitry Andric // If the SPIR-V version is >= 1.4 we can call OpPtrEqual and OpPtrNotEqual.
118*0fca6ea1SDimitry Andric // In SPIR-V Translator compatibility mode this feature is not available.
11981ad6265SDimitry Andric bool SPIRVSubtarget::canDirectlyComparePointers() const {
120*0fca6ea1SDimitry Andric   return !SPVTranslatorCompat && isAtLeastVer(SPIRVVersion, VersionTuple(1, 4));
12181ad6265SDimitry Andric }
122bdd1243dSDimitry Andric 
123bdd1243dSDimitry Andric void SPIRVSubtarget::initAvailableExtensions() {
124bdd1243dSDimitry Andric   AvailableExtensions.clear();
125bdd1243dSDimitry Andric   if (!isOpenCLEnv())
126bdd1243dSDimitry Andric     return;
1275f757f3fSDimitry Andric 
128*0fca6ea1SDimitry Andric   AvailableExtensions.insert(Extensions.begin(), Extensions.end());
129bdd1243dSDimitry Andric }
130bdd1243dSDimitry Andric 
131bdd1243dSDimitry Andric // TODO: use command line args for this rather than just defaults.
132bdd1243dSDimitry Andric // Must have called initAvailableExtensions first.
133bdd1243dSDimitry Andric void SPIRVSubtarget::initAvailableExtInstSets() {
134bdd1243dSDimitry Andric   AvailableExtInstSets.clear();
135bdd1243dSDimitry Andric   if (!isOpenCLEnv())
136bdd1243dSDimitry Andric     AvailableExtInstSets.insert(SPIRV::InstructionSet::GLSL_std_450);
137bdd1243dSDimitry Andric   else
138bdd1243dSDimitry Andric     AvailableExtInstSets.insert(SPIRV::InstructionSet::OpenCL_std);
139bdd1243dSDimitry Andric 
140bdd1243dSDimitry Andric   // Handle extended instruction sets from extensions.
141bdd1243dSDimitry Andric   if (canUseExtension(
142bdd1243dSDimitry Andric           SPIRV::Extension::SPV_AMD_shader_trinary_minmax_extension)) {
143bdd1243dSDimitry Andric     AvailableExtInstSets.insert(
144bdd1243dSDimitry Andric         SPIRV::InstructionSet::SPV_AMD_shader_trinary_minmax);
145bdd1243dSDimitry Andric   }
146bdd1243dSDimitry Andric }
147