28  return [IsExtendedInts, TypeIdx](
const LegalityQuery &Query) {
 
   29    const LLT Ty = Query.Types[TypeIdx];
 
   30    return IsExtendedInts && Ty.isValid() && Ty.isScalar();
 
 
   76  const unsigned PSize = ST.getPointerSize();
 
   92  auto allPtrsScalarsAndVectors = {
 
   93      p0,    p1,    p2,    p3,     p4,     p5,    p6,    p7,    p8,
 
   94      p10,   p11,   p12,   s1,     s8,     s16,   s32,   s64,   v2s1,
 
   95      v2s8,  v2s16, v2s32, v2s64,  v3s1,   v3s8,  v3s16, v3s32, v3s64,
 
   96      v4s1,  v4s8,  v4s16, v4s32,  v4s64,  v8s1,  v8s8,  v8s16, v8s32,
 
   97      v8s64, v16s1, v16s8, v16s16, v16s32, v16s64};
 
   99  auto allVectors = {v2s1,  v2s8,   v2s16,  v2s32, v2s64, v3s1,  v3s8,
 
  100                     v3s16, v3s32,  v3s64,  v4s1,  v4s8,  v4s16, v4s32,
 
  101                     v4s64, v8s1,   v8s8,   v8s16, v8s32, v8s64, v16s1,
 
  102                     v16s8, v16s16, v16s32, v16s64};
 
  104  auto allScalarsAndVectors = {
 
  105      s1,   s8,   s16,   s32,   s64,   v2s1,  v2s8,  v2s16,  v2s32,  v2s64,
 
  106      v3s1, v3s8, v3s16, v3s32, v3s64, v4s1,  v4s8,  v4s16,  v4s32,  v4s64,
 
  107      v8s1, v8s8, v8s16, v8s32, v8s64, v16s1, v16s8, v16s16, v16s32, v16s64};
 
  109  auto allIntScalarsAndVectors = {s8,    s16,   s32,   s64,    v2s8,   v2s16,
 
  110                                  v2s32, v2s64, v3s8,  v3s16,  v3s32,  v3s64,
 
  111                                  v4s8,  v4s16, v4s32, v4s64,  v8s8,   v8s16,
 
  112                                  v8s32, v8s64, v16s8, v16s16, v16s32, v16s64};
 
  114  auto allBoolScalarsAndVectors = {s1, v2s1, v3s1, v4s1, v8s1, v16s1};
 
  116  auto allIntScalars = {s8, s16, s32, s64};
 
  118  auto allFloatScalars = {s16, s32, s64};
 
  120  auto allFloatScalarsAndVectors = {
 
  121      s16,   s32,   s64,   v2s16, v2s32, v2s64, v3s16,  v3s32,  v3s64,
 
  122      v4s16, v4s32, v4s64, v8s16, v8s32, v8s64, v16s16, v16s32, v16s64};
 
  124  auto allFloatAndIntScalarsAndPtrs = {s8, s16, s32, s64, p0, p1,  p2,  p3,
 
  125                                       p4, p5,  p6,  p7,  p8, p10, p11, p12};
 
  127  auto allPtrs = {p0, p1, p2, p3, p4, p5, p6, p7, p8, p10, p11, p12};
 
  129  bool IsExtendedInts =
 
  131          SPIRV::Extension::SPV_INTEL_arbitrary_precision_integers) ||
 
  132      ST.canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions) ||
 
  133      ST.canUseExtension(SPIRV::Extension::SPV_INTEL_int4);
 
  134  auto extendedScalarsAndVectors =
 
  136        const LLT Ty = Query.Types[0];
 
  137        return IsExtendedInts && Ty.isValid() && !Ty.isPointerOrPointerVector();
 
  139  auto extendedScalarsAndVectorsProduct = [IsExtendedInts](
 
  141    const LLT Ty1 = Query.Types[0], Ty2 = Query.Types[1];
 
  142    return IsExtendedInts && Ty1.
isValid() && Ty2.isValid() &&
 
  145  auto extendedPtrsScalarsAndVectors =
 
  147        const LLT Ty = Query.Types[0];
 
  148        return IsExtendedInts && Ty.isValid();
 
  158      {G_BUILD_VECTOR, G_SHUFFLE_VECTOR, G_SPLAT_VECTOR})
 
  163      {G_VECREDUCE_SMIN, G_VECREDUCE_SMAX, G_VECREDUCE_UMIN, G_VECREDUCE_UMAX,
 
  164       G_VECREDUCE_ADD, G_VECREDUCE_MUL, G_VECREDUCE_FMUL, G_VECREDUCE_FMIN,
 
  165       G_VECREDUCE_FMAX, G_VECREDUCE_FMINIMUM, G_VECREDUCE_FMAXIMUM,
 
  166       G_VECREDUCE_OR, G_VECREDUCE_AND, G_VECREDUCE_XOR})
 
  167      .legalFor(allVectors)
 
  191                               G_BITREVERSE, G_SADDSAT, G_UADDSAT, G_SSUBSAT,
 
  192                               G_USUBSAT, G_SCMP, G_UCMP})
 
  193      .legalFor(allIntScalarsAndVectors)
 
  194      .
legalIf(extendedScalarsAndVectors);
 
  197      .legalFor(allFloatScalarsAndVectors);
 
  203      .legalForCartesianProduct(allIntScalarsAndVectors,
 
  204                                allFloatScalarsAndVectors);
 
  207      .legalForCartesianProduct(allIntScalarsAndVectors,
 
  208                                allFloatScalarsAndVectors);
 
  211      .legalForCartesianProduct(allFloatScalarsAndVectors,
 
  212                                allScalarsAndVectors);
 
  216      .
legalIf(extendedScalarsAndVectorsProduct);
 
  220      .legalForCartesianProduct(allScalarsAndVectors)
 
  221      .
legalIf(extendedScalarsAndVectorsProduct);
 
  225      .
legalIf(extendedPtrsScalarsAndVectors);
 
  229          typeInSet(1, allPtrsScalarsAndVectors)));
 
  252          typeInSet(1, allPtrsScalarsAndVectors)));
 
  256          typeInSet(1, allFloatScalarsAndVectors)));
 
  259                               G_ATOMICRMW_MAX, G_ATOMICRMW_MIN,
 
  260                               G_ATOMICRMW_SUB, G_ATOMICRMW_XOR,
 
  261                               G_ATOMICRMW_UMAX, G_ATOMICRMW_UMIN})
 
  262      .legalForCartesianProduct(allIntScalars, allPtrs);
 
  265      {G_ATOMICRMW_FADD, G_ATOMICRMW_FSUB, G_ATOMICRMW_FMIN, G_ATOMICRMW_FMAX})
 
  266      .legalForCartesianProduct(allFloatScalars, allPtrs);
 
  276      {G_UADDO, G_SADDO, G_USUBO, G_SSUBO, G_UMULO, G_SMULO})
 
  280      .legalForCartesianProduct(allFloatScalarsAndVectors,
 
  281                                allIntScalarsAndVectors);
 
  285      .legalForCartesianProduct(allFloatScalarsAndVectors);
 
  294      allFloatScalarsAndVectors, {s32, v2s32, v3s32, v4s32, v8s32, v16s32});
 
  330                               G_INTRINSIC_ROUNDEVEN})
 
  331      .legalFor(allFloatScalarsAndVectors);
 
  335                                allFloatScalarsAndVectors);
 
  338      allFloatScalarsAndVectors, allIntScalarsAndVectors);
 
  340  if (ST.canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std)) {
 
  342        {G_CTTZ, G_CTTZ_ZERO_UNDEF, G_CTLZ, G_CTLZ_ZERO_UNDEF})
 
  343        .legalForCartesianProduct(allIntScalarsAndVectors,
 
  344                                  allIntScalarsAndVectors);
 
  353  verify(*ST.getInstrInfo());
 
 
  360  Register ConvReg = 
MRI.createGenericVirtualRegister(ConvTy);
 
 
  373  switch (
MI.getOpcode()) {
 
  377  case TargetOpcode::G_IS_FPCLASS:
 
  378    return legalizeIsFPClass(Helper, 
MI, LocObserver);
 
  379  case TargetOpcode::G_ICMP: {
 
  380    assert(GR->getSPIRVTypeForVReg(
MI.getOperand(0).getReg()));
 
  381    auto &Op0 = 
MI.getOperand(2);
 
  382    auto &Op1 = 
MI.getOperand(3);
 
  387    if ((!ST->canDirectlyComparePointers() ||
 
  389        MRI.getType(Reg0).isPointer() && 
MRI.getType(Reg1).isPointer()) {
 
  392                                      ST->getPointerSize());
 
  393      SPIRVType *SpirvTy = GR->getOrCreateSPIRVType(
 
  394          LLVMTy, Helper.
MIRBuilder, SPIRV::AccessQualifier::ReadWrite, 
true);
 
 
  406bool SPIRVLegalizerInfo::legalizeIsFPClass(
 
  409  auto [DstReg, DstTy, SrcReg, SrcTy] = 
MI.getFirst2RegLLTs();
 
  413  auto &MF = MIRBuilder.
getMF();
 
  418  if (DstTy.isVector())
 
  421      LLVMDstTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
 
  424  unsigned BitSize = SrcTy.getScalarSizeInBits();
 
  429  if (SrcTy.isVector()) {
 
  430    IntTy = 
LLT::vector(SrcTy.getElementCount(), IntTy);
 
  434      LLVMIntTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite,
 
  438  LLT DstTyCopy = DstTy;
 
  443    LLT MITy = 
MRI.getType(
MI.getReg(0));
 
  444    assert((MITy == IntTy || MITy == DstTyCopy) &&
 
  445           "Unexpected LLT type while lowering G_IS_FPCLASS");
 
  446    auto *SPVTy = MITy == IntTy ? SPIRVIntTy : SPIRVDstTy;
 
  452  const auto buildSPIRVConstant = [&](LLT Ty, 
auto &&
C) -> MachineInstrBuilder {
 
  454      return assignSPIRVTy(MIRBuilder.buildConstant(Ty, 
C));
 
  456    assert((Ty == IntTy || Ty == DstTyCopy) &&
 
  457           "Unexpected LLT type while lowering constant for G_IS_FPCLASS");
 
  458    SPIRVType *VecEltTy = GR->getOrCreateSPIRVType(
 
  459        (Ty == IntTy ? LLVMIntTy : LLVMDstTy)->getScalarType(), MIRBuilder,
 
  460        SPIRV::AccessQualifier::ReadWrite,
 
  462    GR->assignSPIRVTypeToVReg(VecEltTy, ScalarC.getReg(0), MF);
 
  463    return assignSPIRVTy(MIRBuilder.buildSplatBuildVector(Ty, ScalarC));
 
  467    MIRBuilder.buildCopy(DstReg, buildSPIRVConstant(DstTy, 0));
 
  468    MI.eraseFromParent();
 
  472    MIRBuilder.buildCopy(DstReg, buildSPIRVConstant(DstTy, 1));
 
  473    MI.eraseFromParent();
 
  481  Register ResVReg = 
MRI.createGenericVirtualRegister(IntTy);
 
  482  MRI.setRegClass(ResVReg, GR->getRegClass(SPIRVIntTy));
 
  483  GR->assignSPIRVTypeToVReg(SPIRVIntTy, ResVReg, Helper.
MIRBuilder.
getMF());
 
  484  auto AsInt = MIRBuilder.buildInstr(SPIRV::OpBitcast)
 
  486                   .addUse(GR->getSPIRVTypeID(SPIRVIntTy))
 
  488  AsInt = assignSPIRVTy(std::move(AsInt));
 
  500  auto SignBitC = buildSPIRVConstant(IntTy, SignBit);
 
  501  auto ValueMaskC = buildSPIRVConstant(IntTy, ValueMask);
 
  502  auto InfC = buildSPIRVConstant(IntTy, Inf);
 
  503  auto ExpMaskC = buildSPIRVConstant(IntTy, ExpMask);
 
  504  auto ZeroC = buildSPIRVConstant(IntTy, 0);
 
  506  auto Abs = assignSPIRVTy(MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC));
 
  507  auto Sign = assignSPIRVTy(
 
  510  auto Res = buildSPIRVConstant(DstTy, 0);
 
  512  const auto appendToRes = [&](MachineInstrBuilder &&ToAppend) {
 
  514        MIRBuilder.buildOr(DstTyCopy, Res, assignSPIRVTy(std::move(ToAppend))));
 
  527    Mask &= ~fcPosFinite;
 
  531                                                  DstTy, Abs, ExpMaskC));
 
  532    appendToRes(MIRBuilder.buildAnd(DstTy, Cmp, Sign));
 
  533    Mask &= ~fcNegFinite;
 
  541      auto ExpBits = assignSPIRVTy(MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC));
 
  544      Mask &= ~PartialCheck;
 
  553    else if (PartialCheck == 
fcZero)
 
  565    auto OneC = buildSPIRVConstant(IntTy, 1);
 
  566    auto VMinusOne = MIRBuilder.buildSub(IntTy, V, OneC);
 
  567    auto SubnormalRes = assignSPIRVTy(
 
  569                             buildSPIRVConstant(IntTy, AllOneMantissa)));
 
  571      SubnormalRes = MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
 
  572    appendToRes(std::move(SubnormalRes));
 
  579    else if (PartialCheck == 
fcInf)
 
  584      auto NegInfC = buildSPIRVConstant(IntTy, NegInf);
 
  591    auto InfWithQnanBitC =
 
  592        buildSPIRVConstant(IntTy, std::move(Inf) | QNaNBitMask);
 
  593    if (PartialCheck == 
fcNan) {
 
  597    } 
else if (PartialCheck == 
fcQNan) {
 
  604      auto IsNan = assignSPIRVTy(
 
  606      auto IsNotQnan = assignSPIRVTy(MIRBuilder.buildICmp(
 
  608      appendToRes(MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
 
  615    APInt ExpLSB = ExpMask & ~(ExpMask.
shl(1));
 
  616    auto ExpMinusOne = assignSPIRVTy(
 
  617        MIRBuilder.buildSub(IntTy, Abs, buildSPIRVConstant(IntTy, ExpLSB)));
 
  618    APInt MaxExpMinusOne = std::move(ExpMask) - ExpLSB;
 
  619    auto NormalRes = assignSPIRVTy(
 
  621                             buildSPIRVConstant(IntTy, MaxExpMinusOne)));
 
  623      NormalRes = MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
 
  625      auto PosSign = assignSPIRVTy(MIRBuilder.buildXor(
 
  626          DstTy, Sign, buildSPIRVConstant(DstTy, InversionMask)));
 
  627      NormalRes = MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
 
  629    appendToRes(std::move(NormalRes));
 
  632  MIRBuilder.buildCopy(DstReg, Res);
 
  633  MI.eraseFromParent();
 
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void scalarize(Instruction *I, SmallVectorImpl< Instruction * > &Worklist)
This file declares the MachineIRBuilder class.
Promote Memory to Register
const SmallVectorImpl< MachineOperand > & Cond
static Register convertPtrToInt(Register Reg, LLT ConvTy, SPIRVType *SpvType, LegalizerHelper &Helper, MachineRegisterInfo &MRI, SPIRVGlobalRegistry *GR)
LegalityPredicate typeOfExtendedScalars(unsigned TypeIdx, bool IsExtendedInts)
APInt bitcastToAPInt() const
static APFloat getLargest(const fltSemantics &Sem, bool Negative=false)
Returns the largest finite number in the given semantics.
static APFloat getInf(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Infinity.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
static APInt getSignMask(unsigned BitWidth)
Get the SignMask for a specific bit width.
unsigned getActiveBits() const
Compute the number of active bits in the value.
static APInt getSignedMaxValue(unsigned numBits)
Gets maximum signed value of APInt for a specific bit width.
APInt shl(unsigned shiftAmt) const
Left-shift function.
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ ICMP_UGE
unsigned greater or equal
@ ICMP_UGT
unsigned greater than
@ ICMP_ULT
unsigned less than
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
static constexpr LLT vector(ElementCount EC, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isValid() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
constexpr bool isPointerOrPointerVector() const
constexpr bool isFixedVector() const
Returns true if the LLT is a fixed vector.
constexpr LLT getScalarType() const
LLVM_ABI void computeTables()
Compute any ancillary tables needed to quickly decide how an operation should be handled.
LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)
The instruction is legal when type index 0 is any type in the given list.
LegalizeRuleSet & lower()
The instruction is lowered.
LegalizeRuleSet & custom()
Unconditionally custom lower.
LegalizeRuleSet & alwaysLegal()
LegalizeRuleSet & customIf(LegalityPredicate Predicate)
LegalizeRuleSet & scalarize(unsigned TypeIdx)
LegalizeRuleSet & legalForCartesianProduct(std::initializer_list< LLT > Types)
The instruction is legal when type indexes 0 and 1 are both in the given list.
LegalizeRuleSet & legalIf(LegalityPredicate Predicate)
The instruction is legal if predicate is true.
MachineIRBuilder & MIRBuilder
Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
const LegacyLegalizerInfo & getLegacyLegalizerInfo() const
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineFunction & getMF()
Getter for the function we currently build.
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)
SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)
const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const
SPIRVLegalizerInfo(const SPIRVSubtarget &ST)
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override
Called for instructions with the Custom LegalizationAction.
SPIRVGlobalRegistry * getSPIRVGlobalRegistry() const
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list< LLT > TypesInit)
True iff the given type index is one of the specified types.
Predicate all(Predicate P0, Predicate P1)
True iff P0 and P1 are true.
Invariant opcodes: All instruction sets have these as their low opcodes.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
std::function< bool(const LegalityQuery &)> LegalityPredicate
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
const MachineInstr SPIRVType
const std::set< unsigned > & getTypeFoldingSupportedOpcodes()
The LegalityQuery object bundles together all the information that's needed to decide whether a given...