xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
181ad6265SDimitry Andric //===- SPIRVLegalizerInfo.cpp --- SPIR-V Legalization Rules ------*- 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 targeting of the Machinelegalizer class for SPIR-V.
1081ad6265SDimitry Andric //
1181ad6265SDimitry Andric //===----------------------------------------------------------------------===//
1281ad6265SDimitry Andric 
1381ad6265SDimitry Andric #include "SPIRVLegalizerInfo.h"
1481ad6265SDimitry Andric #include "SPIRV.h"
1581ad6265SDimitry Andric #include "SPIRVGlobalRegistry.h"
1681ad6265SDimitry Andric #include "SPIRVSubtarget.h"
1781ad6265SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
1881ad6265SDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
1981ad6265SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
2081ad6265SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
2181ad6265SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h"
2281ad6265SDimitry Andric 
2381ad6265SDimitry Andric using namespace llvm;
2481ad6265SDimitry Andric using namespace llvm::LegalizeActions;
2581ad6265SDimitry Andric using namespace llvm::LegalityPredicates;
2681ad6265SDimitry Andric 
2781ad6265SDimitry Andric static const std::set<unsigned> TypeFoldingSupportingOpcs = {
2881ad6265SDimitry Andric     TargetOpcode::G_ADD,
2981ad6265SDimitry Andric     TargetOpcode::G_FADD,
3081ad6265SDimitry Andric     TargetOpcode::G_SUB,
3181ad6265SDimitry Andric     TargetOpcode::G_FSUB,
3281ad6265SDimitry Andric     TargetOpcode::G_MUL,
3381ad6265SDimitry Andric     TargetOpcode::G_FMUL,
3481ad6265SDimitry Andric     TargetOpcode::G_SDIV,
3581ad6265SDimitry Andric     TargetOpcode::G_UDIV,
3681ad6265SDimitry Andric     TargetOpcode::G_FDIV,
3781ad6265SDimitry Andric     TargetOpcode::G_SREM,
3881ad6265SDimitry Andric     TargetOpcode::G_UREM,
3981ad6265SDimitry Andric     TargetOpcode::G_FREM,
4081ad6265SDimitry Andric     TargetOpcode::G_FNEG,
4181ad6265SDimitry Andric     TargetOpcode::G_CONSTANT,
4281ad6265SDimitry Andric     TargetOpcode::G_FCONSTANT,
4381ad6265SDimitry Andric     TargetOpcode::G_AND,
4481ad6265SDimitry Andric     TargetOpcode::G_OR,
4581ad6265SDimitry Andric     TargetOpcode::G_XOR,
4681ad6265SDimitry Andric     TargetOpcode::G_SHL,
4781ad6265SDimitry Andric     TargetOpcode::G_ASHR,
4881ad6265SDimitry Andric     TargetOpcode::G_LSHR,
4981ad6265SDimitry Andric     TargetOpcode::G_SELECT,
5081ad6265SDimitry Andric     TargetOpcode::G_EXTRACT_VECTOR_ELT,
5181ad6265SDimitry Andric };
5281ad6265SDimitry Andric 
5381ad6265SDimitry Andric bool isTypeFoldingSupported(unsigned Opcode) {
5481ad6265SDimitry Andric   return TypeFoldingSupportingOpcs.count(Opcode) > 0;
5581ad6265SDimitry Andric }
5681ad6265SDimitry Andric 
5781ad6265SDimitry Andric SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
5881ad6265SDimitry Andric   using namespace TargetOpcode;
5981ad6265SDimitry Andric 
6081ad6265SDimitry Andric   this->ST = &ST;
6181ad6265SDimitry Andric   GR = ST.getSPIRVGlobalRegistry();
6281ad6265SDimitry Andric 
6381ad6265SDimitry Andric   const LLT s1 = LLT::scalar(1);
6481ad6265SDimitry Andric   const LLT s8 = LLT::scalar(8);
6581ad6265SDimitry Andric   const LLT s16 = LLT::scalar(16);
6681ad6265SDimitry Andric   const LLT s32 = LLT::scalar(32);
6781ad6265SDimitry Andric   const LLT s64 = LLT::scalar(64);
6881ad6265SDimitry Andric 
6981ad6265SDimitry Andric   const LLT v16s64 = LLT::fixed_vector(16, 64);
7081ad6265SDimitry Andric   const LLT v16s32 = LLT::fixed_vector(16, 32);
7181ad6265SDimitry Andric   const LLT v16s16 = LLT::fixed_vector(16, 16);
7281ad6265SDimitry Andric   const LLT v16s8 = LLT::fixed_vector(16, 8);
7381ad6265SDimitry Andric   const LLT v16s1 = LLT::fixed_vector(16, 1);
7481ad6265SDimitry Andric 
7581ad6265SDimitry Andric   const LLT v8s64 = LLT::fixed_vector(8, 64);
7681ad6265SDimitry Andric   const LLT v8s32 = LLT::fixed_vector(8, 32);
7781ad6265SDimitry Andric   const LLT v8s16 = LLT::fixed_vector(8, 16);
7881ad6265SDimitry Andric   const LLT v8s8 = LLT::fixed_vector(8, 8);
7981ad6265SDimitry Andric   const LLT v8s1 = LLT::fixed_vector(8, 1);
8081ad6265SDimitry Andric 
8181ad6265SDimitry Andric   const LLT v4s64 = LLT::fixed_vector(4, 64);
8281ad6265SDimitry Andric   const LLT v4s32 = LLT::fixed_vector(4, 32);
8381ad6265SDimitry Andric   const LLT v4s16 = LLT::fixed_vector(4, 16);
8481ad6265SDimitry Andric   const LLT v4s8 = LLT::fixed_vector(4, 8);
8581ad6265SDimitry Andric   const LLT v4s1 = LLT::fixed_vector(4, 1);
8681ad6265SDimitry Andric 
8781ad6265SDimitry Andric   const LLT v3s64 = LLT::fixed_vector(3, 64);
8881ad6265SDimitry Andric   const LLT v3s32 = LLT::fixed_vector(3, 32);
8981ad6265SDimitry Andric   const LLT v3s16 = LLT::fixed_vector(3, 16);
9081ad6265SDimitry Andric   const LLT v3s8 = LLT::fixed_vector(3, 8);
9181ad6265SDimitry Andric   const LLT v3s1 = LLT::fixed_vector(3, 1);
9281ad6265SDimitry Andric 
9381ad6265SDimitry Andric   const LLT v2s64 = LLT::fixed_vector(2, 64);
9481ad6265SDimitry Andric   const LLT v2s32 = LLT::fixed_vector(2, 32);
9581ad6265SDimitry Andric   const LLT v2s16 = LLT::fixed_vector(2, 16);
9681ad6265SDimitry Andric   const LLT v2s8 = LLT::fixed_vector(2, 8);
9781ad6265SDimitry Andric   const LLT v2s1 = LLT::fixed_vector(2, 1);
9881ad6265SDimitry Andric 
9981ad6265SDimitry Andric   const unsigned PSize = ST.getPointerSize();
10081ad6265SDimitry Andric   const LLT p0 = LLT::pointer(0, PSize); // Function
10181ad6265SDimitry Andric   const LLT p1 = LLT::pointer(1, PSize); // CrossWorkgroup
10281ad6265SDimitry Andric   const LLT p2 = LLT::pointer(2, PSize); // UniformConstant
10381ad6265SDimitry Andric   const LLT p3 = LLT::pointer(3, PSize); // Workgroup
10481ad6265SDimitry Andric   const LLT p4 = LLT::pointer(4, PSize); // Generic
10581ad6265SDimitry Andric   const LLT p5 = LLT::pointer(5, PSize); // Input
10681ad6265SDimitry Andric 
10781ad6265SDimitry Andric   // TODO: remove copy-pasting here by using concatenation in some way.
10881ad6265SDimitry Andric   auto allPtrsScalarsAndVectors = {
10981ad6265SDimitry Andric       p0,    p1,    p2,    p3,    p4,    p5,    s1,     s8,     s16,
11081ad6265SDimitry Andric       s32,   s64,   v2s1,  v2s8,  v2s16, v2s32, v2s64,  v3s1,   v3s8,
11181ad6265SDimitry Andric       v3s16, v3s32, v3s64, v4s1,  v4s8,  v4s16, v4s32,  v4s64,  v8s1,
11281ad6265SDimitry Andric       v8s8,  v8s16, v8s32, v8s64, v16s1, v16s8, v16s16, v16s32, v16s64};
11381ad6265SDimitry Andric 
11481ad6265SDimitry Andric   auto allScalarsAndVectors = {
11581ad6265SDimitry Andric       s1,   s8,   s16,   s32,   s64,   v2s1,  v2s8,  v2s16,  v2s32,  v2s64,
11681ad6265SDimitry Andric       v3s1, v3s8, v3s16, v3s32, v3s64, v4s1,  v4s8,  v4s16,  v4s32,  v4s64,
11781ad6265SDimitry Andric       v8s1, v8s8, v8s16, v8s32, v8s64, v16s1, v16s8, v16s16, v16s32, v16s64};
11881ad6265SDimitry Andric 
11981ad6265SDimitry Andric   auto allIntScalarsAndVectors = {s8,    s16,   s32,   s64,    v2s8,   v2s16,
12081ad6265SDimitry Andric                                   v2s32, v2s64, v3s8,  v3s16,  v3s32,  v3s64,
12181ad6265SDimitry Andric                                   v4s8,  v4s16, v4s32, v4s64,  v8s8,   v8s16,
12281ad6265SDimitry Andric                                   v8s32, v8s64, v16s8, v16s16, v16s32, v16s64};
12381ad6265SDimitry Andric 
12481ad6265SDimitry Andric   auto allBoolScalarsAndVectors = {s1, v2s1, v3s1, v4s1, v8s1, v16s1};
12581ad6265SDimitry Andric 
12681ad6265SDimitry Andric   auto allIntScalars = {s8, s16, s32, s64};
12781ad6265SDimitry Andric 
12881ad6265SDimitry Andric   auto allFloatScalarsAndVectors = {
12981ad6265SDimitry Andric       s16,   s32,   s64,   v2s16, v2s32, v2s64, v3s16,  v3s32,  v3s64,
13081ad6265SDimitry Andric       v4s16, v4s32, v4s64, v8s16, v8s32, v8s64, v16s16, v16s32, v16s64};
13181ad6265SDimitry Andric 
13281ad6265SDimitry Andric   auto allFloatAndIntScalars = allIntScalars;
13381ad6265SDimitry Andric 
13481ad6265SDimitry Andric   auto allPtrs = {p0, p1, p2, p3, p4, p5};
13581ad6265SDimitry Andric   auto allWritablePtrs = {p0, p1, p3, p4};
13681ad6265SDimitry Andric 
13781ad6265SDimitry Andric   for (auto Opc : TypeFoldingSupportingOpcs)
13881ad6265SDimitry Andric     getActionDefinitionsBuilder(Opc).custom();
13981ad6265SDimitry Andric 
14081ad6265SDimitry Andric   getActionDefinitionsBuilder(G_GLOBAL_VALUE).alwaysLegal();
14181ad6265SDimitry Andric 
14281ad6265SDimitry Andric   // TODO: add proper rules for vectors legalization.
14381ad6265SDimitry Andric   getActionDefinitionsBuilder({G_BUILD_VECTOR, G_SHUFFLE_VECTOR}).alwaysLegal();
14481ad6265SDimitry Andric 
14581ad6265SDimitry Andric   getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE})
14681ad6265SDimitry Andric       .legalIf(all(typeInSet(0, allWritablePtrs), typeInSet(1, allPtrs)));
14781ad6265SDimitry Andric 
148bdd1243dSDimitry Andric   getActionDefinitionsBuilder(G_MEMSET).legalIf(
149bdd1243dSDimitry Andric       all(typeInSet(0, allWritablePtrs), typeInSet(1, allIntScalars)));
150bdd1243dSDimitry Andric 
15181ad6265SDimitry Andric   getActionDefinitionsBuilder(G_ADDRSPACE_CAST)
15281ad6265SDimitry Andric       .legalForCartesianProduct(allPtrs, allPtrs);
15381ad6265SDimitry Andric 
15481ad6265SDimitry Andric   getActionDefinitionsBuilder({G_LOAD, G_STORE}).legalIf(typeInSet(1, allPtrs));
15581ad6265SDimitry Andric 
15681ad6265SDimitry Andric   getActionDefinitionsBuilder(G_BITREVERSE).legalFor(allFloatScalarsAndVectors);
15781ad6265SDimitry Andric 
15881ad6265SDimitry Andric   getActionDefinitionsBuilder(G_FMA).legalFor(allFloatScalarsAndVectors);
15981ad6265SDimitry Andric 
16081ad6265SDimitry Andric   getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
16181ad6265SDimitry Andric       .legalForCartesianProduct(allIntScalarsAndVectors,
16281ad6265SDimitry Andric                                 allFloatScalarsAndVectors);
16381ad6265SDimitry Andric 
16481ad6265SDimitry Andric   getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
16581ad6265SDimitry Andric       .legalForCartesianProduct(allFloatScalarsAndVectors,
16681ad6265SDimitry Andric                                 allScalarsAndVectors);
16781ad6265SDimitry Andric 
16881ad6265SDimitry Andric   getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS})
16981ad6265SDimitry Andric       .legalFor(allIntScalarsAndVectors);
17081ad6265SDimitry Andric 
17181ad6265SDimitry Andric   getActionDefinitionsBuilder(G_CTPOP).legalForCartesianProduct(
17281ad6265SDimitry Andric       allIntScalarsAndVectors, allIntScalarsAndVectors);
17381ad6265SDimitry Andric 
17481ad6265SDimitry Andric   getActionDefinitionsBuilder(G_PHI).legalFor(allPtrsScalarsAndVectors);
17581ad6265SDimitry Andric 
17681ad6265SDimitry Andric   getActionDefinitionsBuilder(G_BITCAST).legalIf(all(
17781ad6265SDimitry Andric       typeInSet(0, allPtrsScalarsAndVectors),
17881ad6265SDimitry Andric       typeInSet(1, allPtrsScalarsAndVectors),
17981ad6265SDimitry Andric       LegalityPredicate(([=](const LegalityQuery &Query) {
18081ad6265SDimitry Andric         return Query.Types[0].getSizeInBits() == Query.Types[1].getSizeInBits();
18181ad6265SDimitry Andric       }))));
18281ad6265SDimitry Andric 
18381ad6265SDimitry Andric   getActionDefinitionsBuilder(G_IMPLICIT_DEF).alwaysLegal();
18481ad6265SDimitry Andric 
18581ad6265SDimitry Andric   getActionDefinitionsBuilder(G_INTTOPTR)
18681ad6265SDimitry Andric       .legalForCartesianProduct(allPtrs, allIntScalars);
18781ad6265SDimitry Andric   getActionDefinitionsBuilder(G_PTRTOINT)
18881ad6265SDimitry Andric       .legalForCartesianProduct(allIntScalars, allPtrs);
18981ad6265SDimitry Andric   getActionDefinitionsBuilder(G_PTR_ADD).legalForCartesianProduct(
19081ad6265SDimitry Andric       allPtrs, allIntScalars);
19181ad6265SDimitry Andric 
19281ad6265SDimitry Andric   // ST.canDirectlyComparePointers() for pointer args is supported in
19381ad6265SDimitry Andric   // legalizeCustom().
19481ad6265SDimitry Andric   getActionDefinitionsBuilder(G_ICMP).customIf(
19581ad6265SDimitry Andric       all(typeInSet(0, allBoolScalarsAndVectors),
19681ad6265SDimitry Andric           typeInSet(1, allPtrsScalarsAndVectors)));
19781ad6265SDimitry Andric 
19881ad6265SDimitry Andric   getActionDefinitionsBuilder(G_FCMP).legalIf(
19981ad6265SDimitry Andric       all(typeInSet(0, allBoolScalarsAndVectors),
20081ad6265SDimitry Andric           typeInSet(1, allFloatScalarsAndVectors)));
20181ad6265SDimitry Andric 
20281ad6265SDimitry Andric   getActionDefinitionsBuilder({G_ATOMICRMW_OR, G_ATOMICRMW_ADD, G_ATOMICRMW_AND,
20381ad6265SDimitry Andric                                G_ATOMICRMW_MAX, G_ATOMICRMW_MIN,
20481ad6265SDimitry Andric                                G_ATOMICRMW_SUB, G_ATOMICRMW_XOR,
20581ad6265SDimitry Andric                                G_ATOMICRMW_UMAX, G_ATOMICRMW_UMIN})
20681ad6265SDimitry Andric       .legalForCartesianProduct(allIntScalars, allWritablePtrs);
20781ad6265SDimitry Andric 
20881ad6265SDimitry Andric   getActionDefinitionsBuilder(G_ATOMICRMW_XCHG)
20981ad6265SDimitry Andric       .legalForCartesianProduct(allFloatAndIntScalars, allWritablePtrs);
21081ad6265SDimitry Andric 
21181ad6265SDimitry Andric   getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG_WITH_SUCCESS).lower();
21281ad6265SDimitry Andric   // TODO: add proper legalization rules.
21381ad6265SDimitry Andric   getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG).alwaysLegal();
21481ad6265SDimitry Andric 
21581ad6265SDimitry Andric   getActionDefinitionsBuilder({G_UADDO, G_USUBO, G_SMULO, G_UMULO})
21681ad6265SDimitry Andric       .alwaysLegal();
21781ad6265SDimitry Andric 
21881ad6265SDimitry Andric   // Extensions.
21981ad6265SDimitry Andric   getActionDefinitionsBuilder({G_TRUNC, G_ZEXT, G_SEXT, G_ANYEXT})
22081ad6265SDimitry Andric       .legalForCartesianProduct(allScalarsAndVectors);
22181ad6265SDimitry Andric 
22281ad6265SDimitry Andric   // FP conversions.
22381ad6265SDimitry Andric   getActionDefinitionsBuilder({G_FPTRUNC, G_FPEXT})
22481ad6265SDimitry Andric       .legalForCartesianProduct(allFloatScalarsAndVectors);
22581ad6265SDimitry Andric 
22681ad6265SDimitry Andric   // Pointer-handling.
22781ad6265SDimitry Andric   getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0});
22881ad6265SDimitry Andric 
229bdd1243dSDimitry Andric   // Control-flow. In some cases (e.g. constants) s1 may be promoted to s32.
230bdd1243dSDimitry Andric   getActionDefinitionsBuilder(G_BRCOND).legalFor({s1, s32});
23181ad6265SDimitry Andric 
2325f757f3fSDimitry Andric   // TODO: Review the target OpenCL and GLSL Extended Instruction Set specs to
2335f757f3fSDimitry Andric   // tighten these requirements. Many of these math functions are only legal on
2345f757f3fSDimitry Andric   // specific bitwidths, so they are not selectable for
2355f757f3fSDimitry Andric   // allFloatScalarsAndVectors.
23681ad6265SDimitry Andric   getActionDefinitionsBuilder({G_FPOW,
23781ad6265SDimitry Andric                                G_FEXP,
23881ad6265SDimitry Andric                                G_FEXP2,
23981ad6265SDimitry Andric                                G_FLOG,
24081ad6265SDimitry Andric                                G_FLOG2,
2415f757f3fSDimitry Andric                                G_FLOG10,
24281ad6265SDimitry Andric                                G_FABS,
24381ad6265SDimitry Andric                                G_FMINNUM,
24481ad6265SDimitry Andric                                G_FMAXNUM,
24581ad6265SDimitry Andric                                G_FCEIL,
24681ad6265SDimitry Andric                                G_FCOS,
24781ad6265SDimitry Andric                                G_FSIN,
24881ad6265SDimitry Andric                                G_FSQRT,
24981ad6265SDimitry Andric                                G_FFLOOR,
25081ad6265SDimitry Andric                                G_FRINT,
25181ad6265SDimitry Andric                                G_FNEARBYINT,
25281ad6265SDimitry Andric                                G_INTRINSIC_ROUND,
25381ad6265SDimitry Andric                                G_INTRINSIC_TRUNC,
25481ad6265SDimitry Andric                                G_FMINIMUM,
25581ad6265SDimitry Andric                                G_FMAXIMUM,
25681ad6265SDimitry Andric                                G_INTRINSIC_ROUNDEVEN})
25781ad6265SDimitry Andric       .legalFor(allFloatScalarsAndVectors);
25881ad6265SDimitry Andric 
25981ad6265SDimitry Andric   getActionDefinitionsBuilder(G_FCOPYSIGN)
26081ad6265SDimitry Andric       .legalForCartesianProduct(allFloatScalarsAndVectors,
26181ad6265SDimitry Andric                                 allFloatScalarsAndVectors);
26281ad6265SDimitry Andric 
26381ad6265SDimitry Andric   getActionDefinitionsBuilder(G_FPOWI).legalForCartesianProduct(
26481ad6265SDimitry Andric       allFloatScalarsAndVectors, allIntScalarsAndVectors);
26581ad6265SDimitry Andric 
266bdd1243dSDimitry Andric   if (ST.canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std)) {
267bdd1243dSDimitry Andric     getActionDefinitionsBuilder(
268bdd1243dSDimitry Andric         {G_CTTZ, G_CTTZ_ZERO_UNDEF, G_CTLZ, G_CTLZ_ZERO_UNDEF})
269bdd1243dSDimitry Andric         .legalForCartesianProduct(allIntScalarsAndVectors,
270bdd1243dSDimitry Andric                                   allIntScalarsAndVectors);
271bdd1243dSDimitry Andric 
272bdd1243dSDimitry Andric     // Struct return types become a single scalar, so cannot easily legalize.
273bdd1243dSDimitry Andric     getActionDefinitionsBuilder({G_SMULH, G_UMULH}).alwaysLegal();
274bdd1243dSDimitry Andric   }
275bdd1243dSDimitry Andric 
27681ad6265SDimitry Andric   getLegacyLegalizerInfo().computeTables();
27781ad6265SDimitry Andric   verify(*ST.getInstrInfo());
27881ad6265SDimitry Andric }
27981ad6265SDimitry Andric 
28081ad6265SDimitry Andric static Register convertPtrToInt(Register Reg, LLT ConvTy, SPIRVType *SpirvType,
28181ad6265SDimitry Andric                                 LegalizerHelper &Helper,
28281ad6265SDimitry Andric                                 MachineRegisterInfo &MRI,
28381ad6265SDimitry Andric                                 SPIRVGlobalRegistry *GR) {
28481ad6265SDimitry Andric   Register ConvReg = MRI.createGenericVirtualRegister(ConvTy);
28581ad6265SDimitry Andric   GR->assignSPIRVTypeToVReg(SpirvType, ConvReg, Helper.MIRBuilder.getMF());
28681ad6265SDimitry Andric   Helper.MIRBuilder.buildInstr(TargetOpcode::G_PTRTOINT)
28781ad6265SDimitry Andric       .addDef(ConvReg)
28881ad6265SDimitry Andric       .addUse(Reg);
28981ad6265SDimitry Andric   return ConvReg;
29081ad6265SDimitry Andric }
29181ad6265SDimitry Andric 
292*1db9f3b2SDimitry Andric bool SPIRVLegalizerInfo::legalizeCustom(
293*1db9f3b2SDimitry Andric     LegalizerHelper &Helper, MachineInstr &MI,
294*1db9f3b2SDimitry Andric     LostDebugLocObserver &LocObserver) const {
29581ad6265SDimitry Andric   auto Opc = MI.getOpcode();
29681ad6265SDimitry Andric   MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
29781ad6265SDimitry Andric   if (!isTypeFoldingSupported(Opc)) {
29881ad6265SDimitry Andric     assert(Opc == TargetOpcode::G_ICMP);
29981ad6265SDimitry Andric     assert(GR->getSPIRVTypeForVReg(MI.getOperand(0).getReg()));
30081ad6265SDimitry Andric     auto &Op0 = MI.getOperand(2);
30181ad6265SDimitry Andric     auto &Op1 = MI.getOperand(3);
30281ad6265SDimitry Andric     Register Reg0 = Op0.getReg();
30381ad6265SDimitry Andric     Register Reg1 = Op1.getReg();
30481ad6265SDimitry Andric     CmpInst::Predicate Cond =
30581ad6265SDimitry Andric         static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
30681ad6265SDimitry Andric     if ((!ST->canDirectlyComparePointers() ||
30781ad6265SDimitry Andric          (Cond != CmpInst::ICMP_EQ && Cond != CmpInst::ICMP_NE)) &&
30881ad6265SDimitry Andric         MRI.getType(Reg0).isPointer() && MRI.getType(Reg1).isPointer()) {
30981ad6265SDimitry Andric       LLT ConvT = LLT::scalar(ST->getPointerSize());
31081ad6265SDimitry Andric       Type *LLVMTy = IntegerType::get(MI.getMF()->getFunction().getContext(),
31181ad6265SDimitry Andric                                       ST->getPointerSize());
31281ad6265SDimitry Andric       SPIRVType *SpirvTy = GR->getOrCreateSPIRVType(LLVMTy, Helper.MIRBuilder);
31381ad6265SDimitry Andric       Op0.setReg(convertPtrToInt(Reg0, ConvT, SpirvTy, Helper, MRI, GR));
31481ad6265SDimitry Andric       Op1.setReg(convertPtrToInt(Reg1, ConvT, SpirvTy, Helper, MRI, GR));
31581ad6265SDimitry Andric     }
31681ad6265SDimitry Andric     return true;
31781ad6265SDimitry Andric   }
31881ad6265SDimitry Andric   // TODO: implement legalization for other opcodes.
31981ad6265SDimitry Andric   return true;
32081ad6265SDimitry Andric }
321