xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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