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 105*0fca6ea1SDimitry Andric const LLT p5 = 106*0fca6ea1SDimitry Andric LLT::pointer(5, PSize); // Input, SPV_INTEL_usm_storage_classes (Device) 107*0fca6ea1SDimitry Andric const LLT p6 = LLT::pointer(6, PSize); // SPV_INTEL_usm_storage_classes (Host) 10881ad6265SDimitry Andric 10981ad6265SDimitry Andric // TODO: remove copy-pasting here by using concatenation in some way. 11081ad6265SDimitry Andric auto allPtrsScalarsAndVectors = { 111*0fca6ea1SDimitry Andric p0, p1, p2, p3, p4, p5, p6, s1, s8, s16, 112*0fca6ea1SDimitry Andric s32, s64, v2s1, v2s8, v2s16, v2s32, v2s64, v3s1, v3s8, v3s16, 113*0fca6ea1SDimitry Andric v3s32, v3s64, v4s1, v4s8, v4s16, v4s32, v4s64, v8s1, v8s8, v8s16, 114*0fca6ea1SDimitry Andric v8s32, v8s64, v16s1, v16s8, v16s16, v16s32, v16s64}; 115*0fca6ea1SDimitry Andric 116*0fca6ea1SDimitry Andric auto allVectors = {v2s1, v2s8, v2s16, v2s32, v2s64, v3s1, v3s8, 117*0fca6ea1SDimitry Andric v3s16, v3s32, v3s64, v4s1, v4s8, v4s16, v4s32, 118*0fca6ea1SDimitry Andric v4s64, v8s1, v8s8, v8s16, v8s32, v8s64, v16s1, 119*0fca6ea1SDimitry Andric v16s8, v16s16, v16s32, v16s64}; 12081ad6265SDimitry Andric 12181ad6265SDimitry Andric auto allScalarsAndVectors = { 12281ad6265SDimitry Andric s1, s8, s16, s32, s64, v2s1, v2s8, v2s16, v2s32, v2s64, 12381ad6265SDimitry Andric v3s1, v3s8, v3s16, v3s32, v3s64, v4s1, v4s8, v4s16, v4s32, v4s64, 12481ad6265SDimitry Andric v8s1, v8s8, v8s16, v8s32, v8s64, v16s1, v16s8, v16s16, v16s32, v16s64}; 12581ad6265SDimitry Andric 12681ad6265SDimitry Andric auto allIntScalarsAndVectors = {s8, s16, s32, s64, v2s8, v2s16, 12781ad6265SDimitry Andric v2s32, v2s64, v3s8, v3s16, v3s32, v3s64, 12881ad6265SDimitry Andric v4s8, v4s16, v4s32, v4s64, v8s8, v8s16, 12981ad6265SDimitry Andric v8s32, v8s64, v16s8, v16s16, v16s32, v16s64}; 13081ad6265SDimitry Andric 13181ad6265SDimitry Andric auto allBoolScalarsAndVectors = {s1, v2s1, v3s1, v4s1, v8s1, v16s1}; 13281ad6265SDimitry Andric 13381ad6265SDimitry Andric auto allIntScalars = {s8, s16, s32, s64}; 13481ad6265SDimitry Andric 135*0fca6ea1SDimitry Andric auto allFloatScalars = {s16, s32, s64}; 136*0fca6ea1SDimitry Andric 13781ad6265SDimitry Andric auto allFloatScalarsAndVectors = { 13881ad6265SDimitry Andric s16, s32, s64, v2s16, v2s32, v2s64, v3s16, v3s32, v3s64, 13981ad6265SDimitry Andric v4s16, v4s32, v4s64, v8s16, v8s32, v8s64, v16s16, v16s32, v16s64}; 14081ad6265SDimitry Andric 141*0fca6ea1SDimitry Andric auto allFloatAndIntScalarsAndPtrs = {s8, s16, s32, s64, p0, p1, 142*0fca6ea1SDimitry Andric p2, p3, p4, p5, p6}; 14381ad6265SDimitry Andric 144*0fca6ea1SDimitry Andric auto allPtrs = {p0, p1, p2, p3, p4, p5, p6}; 145*0fca6ea1SDimitry Andric auto allWritablePtrs = {p0, p1, p3, p4, p5, p6}; 14681ad6265SDimitry Andric 14781ad6265SDimitry Andric for (auto Opc : TypeFoldingSupportingOpcs) 14881ad6265SDimitry Andric getActionDefinitionsBuilder(Opc).custom(); 14981ad6265SDimitry Andric 15081ad6265SDimitry Andric getActionDefinitionsBuilder(G_GLOBAL_VALUE).alwaysLegal(); 15181ad6265SDimitry Andric 15281ad6265SDimitry Andric // TODO: add proper rules for vectors legalization. 153*0fca6ea1SDimitry Andric getActionDefinitionsBuilder( 154*0fca6ea1SDimitry Andric {G_BUILD_VECTOR, G_SHUFFLE_VECTOR, G_SPLAT_VECTOR}) 155*0fca6ea1SDimitry Andric .alwaysLegal(); 156*0fca6ea1SDimitry Andric 157*0fca6ea1SDimitry Andric // Vector Reduction Operations 158*0fca6ea1SDimitry Andric getActionDefinitionsBuilder( 159*0fca6ea1SDimitry Andric {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX, 160*0fca6ea1SDimitry Andric G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FMUL, G_VECREDUCE_FMIN, 161*0fca6ea1SDimitry Andric G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM, G_VECREDUCE_FMAXIMUM, 162*0fca6ea1SDimitry Andric G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR}) 163*0fca6ea1SDimitry Andric .legalFor(allVectors) 164*0fca6ea1SDimitry Andric .scalarize(1) 165*0fca6ea1SDimitry Andric .lower(); 166*0fca6ea1SDimitry Andric 167*0fca6ea1SDimitry Andric getActionDefinitionsBuilder({G_VECREDUCE_SEQ_FADD, G_VECREDUCE_SEQ_FMUL}) 168*0fca6ea1SDimitry Andric .scalarize(2) 169*0fca6ea1SDimitry Andric .lower(); 170*0fca6ea1SDimitry Andric 171*0fca6ea1SDimitry Andric // Merge/Unmerge 172*0fca6ea1SDimitry Andric // TODO: add proper legalization rules. 173*0fca6ea1SDimitry Andric getActionDefinitionsBuilder(G_UNMERGE_VALUES).alwaysLegal(); 17481ad6265SDimitry Andric 17581ad6265SDimitry Andric getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE}) 17681ad6265SDimitry Andric .legalIf(all(typeInSet(0, allWritablePtrs), typeInSet(1, allPtrs))); 17781ad6265SDimitry Andric 178bdd1243dSDimitry Andric getActionDefinitionsBuilder(G_MEMSET).legalIf( 179bdd1243dSDimitry Andric all(typeInSet(0, allWritablePtrs), typeInSet(1, allIntScalars))); 180bdd1243dSDimitry Andric 18181ad6265SDimitry Andric getActionDefinitionsBuilder(G_ADDRSPACE_CAST) 18281ad6265SDimitry Andric .legalForCartesianProduct(allPtrs, allPtrs); 18381ad6265SDimitry Andric 18481ad6265SDimitry Andric getActionDefinitionsBuilder({G_LOAD, G_STORE}).legalIf(typeInSet(1, allPtrs)); 18581ad6265SDimitry Andric 186*0fca6ea1SDimitry Andric getActionDefinitionsBuilder(G_BITREVERSE).legalFor(allIntScalarsAndVectors); 18781ad6265SDimitry Andric 18881ad6265SDimitry Andric getActionDefinitionsBuilder(G_FMA).legalFor(allFloatScalarsAndVectors); 18981ad6265SDimitry Andric 19081ad6265SDimitry Andric getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI}) 19181ad6265SDimitry Andric .legalForCartesianProduct(allIntScalarsAndVectors, 19281ad6265SDimitry Andric allFloatScalarsAndVectors); 19381ad6265SDimitry Andric 19481ad6265SDimitry Andric getActionDefinitionsBuilder({G_SITOFP, G_UITOFP}) 19581ad6265SDimitry Andric .legalForCartesianProduct(allFloatScalarsAndVectors, 19681ad6265SDimitry Andric allScalarsAndVectors); 19781ad6265SDimitry Andric 19881ad6265SDimitry Andric getActionDefinitionsBuilder({G_SMIN, G_SMAX, G_UMIN, G_UMAX, G_ABS}) 19981ad6265SDimitry Andric .legalFor(allIntScalarsAndVectors); 20081ad6265SDimitry Andric 20181ad6265SDimitry Andric getActionDefinitionsBuilder(G_CTPOP).legalForCartesianProduct( 20281ad6265SDimitry Andric allIntScalarsAndVectors, allIntScalarsAndVectors); 20381ad6265SDimitry Andric 20481ad6265SDimitry Andric getActionDefinitionsBuilder(G_PHI).legalFor(allPtrsScalarsAndVectors); 20581ad6265SDimitry Andric 206*0fca6ea1SDimitry Andric getActionDefinitionsBuilder(G_BITCAST).legalIf( 207*0fca6ea1SDimitry Andric all(typeInSet(0, allPtrsScalarsAndVectors), 208*0fca6ea1SDimitry Andric typeInSet(1, allPtrsScalarsAndVectors))); 20981ad6265SDimitry Andric 210*0fca6ea1SDimitry Andric getActionDefinitionsBuilder({G_IMPLICIT_DEF, G_FREEZE}).alwaysLegal(); 211*0fca6ea1SDimitry Andric 212*0fca6ea1SDimitry Andric getActionDefinitionsBuilder({G_STACKSAVE, G_STACKRESTORE}).alwaysLegal(); 21381ad6265SDimitry Andric 21481ad6265SDimitry Andric getActionDefinitionsBuilder(G_INTTOPTR) 21581ad6265SDimitry Andric .legalForCartesianProduct(allPtrs, allIntScalars); 21681ad6265SDimitry Andric getActionDefinitionsBuilder(G_PTRTOINT) 21781ad6265SDimitry Andric .legalForCartesianProduct(allIntScalars, allPtrs); 21881ad6265SDimitry Andric getActionDefinitionsBuilder(G_PTR_ADD).legalForCartesianProduct( 21981ad6265SDimitry Andric allPtrs, allIntScalars); 22081ad6265SDimitry Andric 22181ad6265SDimitry Andric // ST.canDirectlyComparePointers() for pointer args is supported in 22281ad6265SDimitry Andric // legalizeCustom(). 22381ad6265SDimitry Andric getActionDefinitionsBuilder(G_ICMP).customIf( 22481ad6265SDimitry Andric all(typeInSet(0, allBoolScalarsAndVectors), 22581ad6265SDimitry Andric typeInSet(1, allPtrsScalarsAndVectors))); 22681ad6265SDimitry Andric 22781ad6265SDimitry Andric getActionDefinitionsBuilder(G_FCMP).legalIf( 22881ad6265SDimitry Andric all(typeInSet(0, allBoolScalarsAndVectors), 22981ad6265SDimitry Andric typeInSet(1, allFloatScalarsAndVectors))); 23081ad6265SDimitry Andric 23181ad6265SDimitry Andric getActionDefinitionsBuilder({G_ATOMICRMW_OR, G_ATOMICRMW_ADD, G_ATOMICRMW_AND, 23281ad6265SDimitry Andric G_ATOMICRMW_MAX, G_ATOMICRMW_MIN, 23381ad6265SDimitry Andric G_ATOMICRMW_SUB, G_ATOMICRMW_XOR, 23481ad6265SDimitry Andric G_ATOMICRMW_UMAX, G_ATOMICRMW_UMIN}) 23581ad6265SDimitry Andric .legalForCartesianProduct(allIntScalars, allWritablePtrs); 23681ad6265SDimitry Andric 237*0fca6ea1SDimitry Andric getActionDefinitionsBuilder( 238*0fca6ea1SDimitry Andric {G_ATOMICRMW_FADD, G_ATOMICRMW_FSUB, G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX}) 239*0fca6ea1SDimitry Andric .legalForCartesianProduct(allFloatScalars, allWritablePtrs); 240*0fca6ea1SDimitry Andric 24181ad6265SDimitry Andric getActionDefinitionsBuilder(G_ATOMICRMW_XCHG) 242*0fca6ea1SDimitry Andric .legalForCartesianProduct(allFloatAndIntScalarsAndPtrs, allWritablePtrs); 24381ad6265SDimitry Andric 24481ad6265SDimitry Andric getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG_WITH_SUCCESS).lower(); 24581ad6265SDimitry Andric // TODO: add proper legalization rules. 24681ad6265SDimitry Andric getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG).alwaysLegal(); 24781ad6265SDimitry Andric 24881ad6265SDimitry Andric getActionDefinitionsBuilder({G_UADDO, G_USUBO, G_SMULO, G_UMULO}) 24981ad6265SDimitry Andric .alwaysLegal(); 25081ad6265SDimitry Andric 25181ad6265SDimitry Andric // Extensions. 25281ad6265SDimitry Andric getActionDefinitionsBuilder({G_TRUNC, G_ZEXT, G_SEXT, G_ANYEXT}) 25381ad6265SDimitry Andric .legalForCartesianProduct(allScalarsAndVectors); 25481ad6265SDimitry Andric 25581ad6265SDimitry Andric // FP conversions. 25681ad6265SDimitry Andric getActionDefinitionsBuilder({G_FPTRUNC, G_FPEXT}) 25781ad6265SDimitry Andric .legalForCartesianProduct(allFloatScalarsAndVectors); 25881ad6265SDimitry Andric 25981ad6265SDimitry Andric // Pointer-handling. 26081ad6265SDimitry Andric getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0}); 26181ad6265SDimitry Andric 262bdd1243dSDimitry Andric // Control-flow. In some cases (e.g. constants) s1 may be promoted to s32. 263bdd1243dSDimitry Andric getActionDefinitionsBuilder(G_BRCOND).legalFor({s1, s32}); 26481ad6265SDimitry Andric 2655f757f3fSDimitry Andric // TODO: Review the target OpenCL and GLSL Extended Instruction Set specs to 2665f757f3fSDimitry Andric // tighten these requirements. Many of these math functions are only legal on 2675f757f3fSDimitry Andric // specific bitwidths, so they are not selectable for 2685f757f3fSDimitry Andric // allFloatScalarsAndVectors. 26981ad6265SDimitry Andric getActionDefinitionsBuilder({G_FPOW, 27081ad6265SDimitry Andric G_FEXP, 27181ad6265SDimitry Andric G_FEXP2, 27281ad6265SDimitry Andric G_FLOG, 27381ad6265SDimitry Andric G_FLOG2, 2745f757f3fSDimitry Andric G_FLOG10, 27581ad6265SDimitry Andric G_FABS, 27681ad6265SDimitry Andric G_FMINNUM, 27781ad6265SDimitry Andric G_FMAXNUM, 27881ad6265SDimitry Andric G_FCEIL, 27981ad6265SDimitry Andric G_FCOS, 28081ad6265SDimitry Andric G_FSIN, 281*0fca6ea1SDimitry Andric G_FTAN, 282*0fca6ea1SDimitry Andric G_FACOS, 283*0fca6ea1SDimitry Andric G_FASIN, 284*0fca6ea1SDimitry Andric G_FATAN, 285*0fca6ea1SDimitry Andric G_FCOSH, 286*0fca6ea1SDimitry Andric G_FSINH, 287*0fca6ea1SDimitry Andric G_FTANH, 28881ad6265SDimitry Andric G_FSQRT, 28981ad6265SDimitry Andric G_FFLOOR, 29081ad6265SDimitry Andric G_FRINT, 29181ad6265SDimitry Andric G_FNEARBYINT, 29281ad6265SDimitry Andric G_INTRINSIC_ROUND, 29381ad6265SDimitry Andric G_INTRINSIC_TRUNC, 29481ad6265SDimitry Andric G_FMINIMUM, 29581ad6265SDimitry Andric G_FMAXIMUM, 29681ad6265SDimitry Andric G_INTRINSIC_ROUNDEVEN}) 29781ad6265SDimitry Andric .legalFor(allFloatScalarsAndVectors); 29881ad6265SDimitry Andric 29981ad6265SDimitry Andric getActionDefinitionsBuilder(G_FCOPYSIGN) 30081ad6265SDimitry Andric .legalForCartesianProduct(allFloatScalarsAndVectors, 30181ad6265SDimitry Andric allFloatScalarsAndVectors); 30281ad6265SDimitry Andric 30381ad6265SDimitry Andric getActionDefinitionsBuilder(G_FPOWI).legalForCartesianProduct( 30481ad6265SDimitry Andric allFloatScalarsAndVectors, allIntScalarsAndVectors); 30581ad6265SDimitry Andric 306bdd1243dSDimitry Andric if (ST.canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std)) { 307bdd1243dSDimitry Andric getActionDefinitionsBuilder( 308bdd1243dSDimitry Andric {G_CTTZ, G_CTTZ_ZERO_UNDEF, G_CTLZ, G_CTLZ_ZERO_UNDEF}) 309bdd1243dSDimitry Andric .legalForCartesianProduct(allIntScalarsAndVectors, 310bdd1243dSDimitry Andric allIntScalarsAndVectors); 311bdd1243dSDimitry Andric 312bdd1243dSDimitry Andric // Struct return types become a single scalar, so cannot easily legalize. 313bdd1243dSDimitry Andric getActionDefinitionsBuilder({G_SMULH, G_UMULH}).alwaysLegal(); 314*0fca6ea1SDimitry Andric 315*0fca6ea1SDimitry Andric // supported saturation arithmetic 316*0fca6ea1SDimitry Andric getActionDefinitionsBuilder({G_SADDSAT, G_UADDSAT, G_SSUBSAT, G_USUBSAT}) 317*0fca6ea1SDimitry Andric .legalFor(allIntScalarsAndVectors); 318bdd1243dSDimitry Andric } 319bdd1243dSDimitry Andric 32081ad6265SDimitry Andric getLegacyLegalizerInfo().computeTables(); 32181ad6265SDimitry Andric verify(*ST.getInstrInfo()); 32281ad6265SDimitry Andric } 32381ad6265SDimitry Andric 32481ad6265SDimitry Andric static Register convertPtrToInt(Register Reg, LLT ConvTy, SPIRVType *SpirvType, 32581ad6265SDimitry Andric LegalizerHelper &Helper, 32681ad6265SDimitry Andric MachineRegisterInfo &MRI, 32781ad6265SDimitry Andric SPIRVGlobalRegistry *GR) { 32881ad6265SDimitry Andric Register ConvReg = MRI.createGenericVirtualRegister(ConvTy); 32981ad6265SDimitry Andric GR->assignSPIRVTypeToVReg(SpirvType, ConvReg, Helper.MIRBuilder.getMF()); 33081ad6265SDimitry Andric Helper.MIRBuilder.buildInstr(TargetOpcode::G_PTRTOINT) 33181ad6265SDimitry Andric .addDef(ConvReg) 33281ad6265SDimitry Andric .addUse(Reg); 33381ad6265SDimitry Andric return ConvReg; 33481ad6265SDimitry Andric } 33581ad6265SDimitry Andric 3361db9f3b2SDimitry Andric bool SPIRVLegalizerInfo::legalizeCustom( 3371db9f3b2SDimitry Andric LegalizerHelper &Helper, MachineInstr &MI, 3381db9f3b2SDimitry Andric LostDebugLocObserver &LocObserver) const { 33981ad6265SDimitry Andric auto Opc = MI.getOpcode(); 34081ad6265SDimitry Andric MachineRegisterInfo &MRI = MI.getMF()->getRegInfo(); 34181ad6265SDimitry Andric if (!isTypeFoldingSupported(Opc)) { 34281ad6265SDimitry Andric assert(Opc == TargetOpcode::G_ICMP); 34381ad6265SDimitry Andric assert(GR->getSPIRVTypeForVReg(MI.getOperand(0).getReg())); 34481ad6265SDimitry Andric auto &Op0 = MI.getOperand(2); 34581ad6265SDimitry Andric auto &Op1 = MI.getOperand(3); 34681ad6265SDimitry Andric Register Reg0 = Op0.getReg(); 34781ad6265SDimitry Andric Register Reg1 = Op1.getReg(); 34881ad6265SDimitry Andric CmpInst::Predicate Cond = 34981ad6265SDimitry Andric static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()); 35081ad6265SDimitry Andric if ((!ST->canDirectlyComparePointers() || 35181ad6265SDimitry Andric (Cond != CmpInst::ICMP_EQ && Cond != CmpInst::ICMP_NE)) && 35281ad6265SDimitry Andric MRI.getType(Reg0).isPointer() && MRI.getType(Reg1).isPointer()) { 35381ad6265SDimitry Andric LLT ConvT = LLT::scalar(ST->getPointerSize()); 35481ad6265SDimitry Andric Type *LLVMTy = IntegerType::get(MI.getMF()->getFunction().getContext(), 35581ad6265SDimitry Andric ST->getPointerSize()); 35681ad6265SDimitry Andric SPIRVType *SpirvTy = GR->getOrCreateSPIRVType(LLVMTy, Helper.MIRBuilder); 35781ad6265SDimitry Andric Op0.setReg(convertPtrToInt(Reg0, ConvT, SpirvTy, Helper, MRI, GR)); 35881ad6265SDimitry Andric Op1.setReg(convertPtrToInt(Reg1, ConvT, SpirvTy, Helper, MRI, GR)); 35981ad6265SDimitry Andric } 36081ad6265SDimitry Andric return true; 36181ad6265SDimitry Andric } 36281ad6265SDimitry Andric // TODO: implement legalization for other opcodes. 36381ad6265SDimitry Andric return true; 36481ad6265SDimitry Andric } 365