xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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 
148*bdd1243dSDimitry Andric   getActionDefinitionsBuilder(G_MEMSET).legalIf(
149*bdd1243dSDimitry Andric       all(typeInSet(0, allWritablePtrs), typeInSet(1, allIntScalars)));
150*bdd1243dSDimitry 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 
229*bdd1243dSDimitry Andric   // Control-flow. In some cases (e.g. constants) s1 may be promoted to s32.
230*bdd1243dSDimitry Andric   getActionDefinitionsBuilder(G_BRCOND).legalFor({s1, s32});
23181ad6265SDimitry Andric 
23281ad6265SDimitry Andric   getActionDefinitionsBuilder({G_FPOW,
23381ad6265SDimitry Andric                                G_FEXP,
23481ad6265SDimitry Andric                                G_FEXP2,
23581ad6265SDimitry Andric                                G_FLOG,
23681ad6265SDimitry Andric                                G_FLOG2,
23781ad6265SDimitry Andric                                G_FABS,
23881ad6265SDimitry Andric                                G_FMINNUM,
23981ad6265SDimitry Andric                                G_FMAXNUM,
24081ad6265SDimitry Andric                                G_FCEIL,
24181ad6265SDimitry Andric                                G_FCOS,
24281ad6265SDimitry Andric                                G_FSIN,
24381ad6265SDimitry Andric                                G_FSQRT,
24481ad6265SDimitry Andric                                G_FFLOOR,
24581ad6265SDimitry Andric                                G_FRINT,
24681ad6265SDimitry Andric                                G_FNEARBYINT,
24781ad6265SDimitry Andric                                G_INTRINSIC_ROUND,
24881ad6265SDimitry Andric                                G_INTRINSIC_TRUNC,
24981ad6265SDimitry Andric                                G_FMINIMUM,
25081ad6265SDimitry Andric                                G_FMAXIMUM,
25181ad6265SDimitry Andric                                G_INTRINSIC_ROUNDEVEN})
25281ad6265SDimitry Andric       .legalFor(allFloatScalarsAndVectors);
25381ad6265SDimitry Andric 
25481ad6265SDimitry Andric   getActionDefinitionsBuilder(G_FCOPYSIGN)
25581ad6265SDimitry Andric       .legalForCartesianProduct(allFloatScalarsAndVectors,
25681ad6265SDimitry Andric                                 allFloatScalarsAndVectors);
25781ad6265SDimitry Andric 
25881ad6265SDimitry Andric   getActionDefinitionsBuilder(G_FPOWI).legalForCartesianProduct(
25981ad6265SDimitry Andric       allFloatScalarsAndVectors, allIntScalarsAndVectors);
26081ad6265SDimitry Andric 
261*bdd1243dSDimitry Andric   if (ST.canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std)) {
262*bdd1243dSDimitry Andric     getActionDefinitionsBuilder(G_FLOG10).legalFor(allFloatScalarsAndVectors);
263*bdd1243dSDimitry Andric 
264*bdd1243dSDimitry Andric     getActionDefinitionsBuilder(
265*bdd1243dSDimitry Andric         {G_CTTZ, G_CTTZ_ZERO_UNDEF, G_CTLZ, G_CTLZ_ZERO_UNDEF})
266*bdd1243dSDimitry Andric         .legalForCartesianProduct(allIntScalarsAndVectors,
267*bdd1243dSDimitry Andric                                   allIntScalarsAndVectors);
268*bdd1243dSDimitry Andric 
269*bdd1243dSDimitry Andric     // Struct return types become a single scalar, so cannot easily legalize.
270*bdd1243dSDimitry Andric     getActionDefinitionsBuilder({G_SMULH, G_UMULH}).alwaysLegal();
271*bdd1243dSDimitry Andric   }
272*bdd1243dSDimitry Andric 
27381ad6265SDimitry Andric   getLegacyLegalizerInfo().computeTables();
27481ad6265SDimitry Andric   verify(*ST.getInstrInfo());
27581ad6265SDimitry Andric }
27681ad6265SDimitry Andric 
27781ad6265SDimitry Andric static Register convertPtrToInt(Register Reg, LLT ConvTy, SPIRVType *SpirvType,
27881ad6265SDimitry Andric                                 LegalizerHelper &Helper,
27981ad6265SDimitry Andric                                 MachineRegisterInfo &MRI,
28081ad6265SDimitry Andric                                 SPIRVGlobalRegistry *GR) {
28181ad6265SDimitry Andric   Register ConvReg = MRI.createGenericVirtualRegister(ConvTy);
28281ad6265SDimitry Andric   GR->assignSPIRVTypeToVReg(SpirvType, ConvReg, Helper.MIRBuilder.getMF());
28381ad6265SDimitry Andric   Helper.MIRBuilder.buildInstr(TargetOpcode::G_PTRTOINT)
28481ad6265SDimitry Andric       .addDef(ConvReg)
28581ad6265SDimitry Andric       .addUse(Reg);
28681ad6265SDimitry Andric   return ConvReg;
28781ad6265SDimitry Andric }
28881ad6265SDimitry Andric 
28981ad6265SDimitry Andric bool SPIRVLegalizerInfo::legalizeCustom(LegalizerHelper &Helper,
29081ad6265SDimitry Andric                                         MachineInstr &MI) const {
29181ad6265SDimitry Andric   auto Opc = MI.getOpcode();
29281ad6265SDimitry Andric   MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
29381ad6265SDimitry Andric   if (!isTypeFoldingSupported(Opc)) {
29481ad6265SDimitry Andric     assert(Opc == TargetOpcode::G_ICMP);
29581ad6265SDimitry Andric     assert(GR->getSPIRVTypeForVReg(MI.getOperand(0).getReg()));
29681ad6265SDimitry Andric     auto &Op0 = MI.getOperand(2);
29781ad6265SDimitry Andric     auto &Op1 = MI.getOperand(3);
29881ad6265SDimitry Andric     Register Reg0 = Op0.getReg();
29981ad6265SDimitry Andric     Register Reg1 = Op1.getReg();
30081ad6265SDimitry Andric     CmpInst::Predicate Cond =
30181ad6265SDimitry Andric         static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
30281ad6265SDimitry Andric     if ((!ST->canDirectlyComparePointers() ||
30381ad6265SDimitry Andric          (Cond != CmpInst::ICMP_EQ && Cond != CmpInst::ICMP_NE)) &&
30481ad6265SDimitry Andric         MRI.getType(Reg0).isPointer() && MRI.getType(Reg1).isPointer()) {
30581ad6265SDimitry Andric       LLT ConvT = LLT::scalar(ST->getPointerSize());
30681ad6265SDimitry Andric       Type *LLVMTy = IntegerType::get(MI.getMF()->getFunction().getContext(),
30781ad6265SDimitry Andric                                       ST->getPointerSize());
30881ad6265SDimitry Andric       SPIRVType *SpirvTy = GR->getOrCreateSPIRVType(LLVMTy, Helper.MIRBuilder);
30981ad6265SDimitry Andric       Op0.setReg(convertPtrToInt(Reg0, ConvT, SpirvTy, Helper, MRI, GR));
31081ad6265SDimitry Andric       Op1.setReg(convertPtrToInt(Reg1, ConvT, SpirvTy, Helper, MRI, GR));
31181ad6265SDimitry Andric     }
31281ad6265SDimitry Andric     return true;
31381ad6265SDimitry Andric   }
31481ad6265SDimitry Andric   // TODO: implement legalization for other opcodes.
31581ad6265SDimitry Andric   return true;
31681ad6265SDimitry Andric }
317