LLVM: lib/Target/SPIRV/SPIRVBuiltins.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

20#include "llvm/IR/IntrinsicsSPIRV.h"

21#include

22#include

23#include

24

25#define DEBUG_TYPE "spirv-builtins"

26

27namespace llvm {

29#define GET_BuiltinGroup_DECL

30#include "SPIRVGenTables.inc"

31

34 InstructionSet::InstructionSet Set;

38};

39

40#define GET_DemangledBuiltins_DECL

41#define GET_DemangledBuiltins_IMPL

42

60

63 InstructionSet::InstructionSet Set;

65};

66

67#define GET_NativeBuiltins_DECL

68#define GET_NativeBuiltins_IMPL

69

85

86#define GET_GroupBuiltins_DECL

87#define GET_GroupBuiltins_IMPL

88

96

97#define GET_IntelSubgroupsBuiltins_DECL

98#define GET_IntelSubgroupsBuiltins_IMPL

99

104

105#define GET_AtomicFloatingBuiltins_DECL

106#define GET_AtomicFloatingBuiltins_IMPL

112

113#define GET_GroupUniformBuiltins_DECL

114#define GET_GroupUniformBuiltins_IMPL

115

118 InstructionSet::InstructionSet Set;

120};

121

123#define GET_GetBuiltins_DECL

124#define GET_GetBuiltins_IMPL

125

128 InstructionSet::InstructionSet Set;

130};

131

132#define GET_ImageQueryBuiltins_DECL

133#define GET_ImageQueryBuiltins_IMPL

134

140

141#define GET_IntegerDotProductBuiltins_DECL

142#define GET_IntegerDotProductBuiltins_IMPL

143

146 InstructionSet::InstructionSet Set;

153};

154

157 InstructionSet::InstructionSet Set;

162};

163

165#define GET_ConvertBuiltins_DECL

166#define GET_ConvertBuiltins_IMPL

167

168using namespace InstructionSet;

169#define GET_VectorLoadStoreBuiltins_DECL

170#define GET_VectorLoadStoreBuiltins_IMPL

171

172#define GET_CLMemoryScope_DECL

173#define GET_CLSamplerAddressingMode_DECL

174#define GET_CLMemoryFenceFlags_DECL

175#define GET_ExtendedBuiltins_DECL

176#include "SPIRVGenTables.inc"

177}

178

179

180

181

182

183

185

188 StringRef PassPrefix = "(anonymous namespace)::";

189 std::string BuiltinName;

190

191 if (DemangledCall.starts_with(PassPrefix))

192 BuiltinName = DemangledCall.substr(PassPrefix.size());

193 else

194 BuiltinName = DemangledCall;

195

196

197 BuiltinName = BuiltinName.substr(0, BuiltinName.find('('));

198

199

200 if (BuiltinName.rfind("__spirv_ocl_", 0) == 0)

201 BuiltinName = BuiltinName.substr(12);

202

203

204

205

206 std::size_t Pos1 = BuiltinName.rfind('<');

207 if (Pos1 != std:🧵:npos && BuiltinName.back() == '>') {

208 std::size_t Pos2 = BuiltinName.rfind(' ', Pos1);

209 if (Pos2 == std:🧵:npos)

210 Pos2 = 0;

211 else

212 ++Pos2;

213 BuiltinName = BuiltinName.substr(Pos2, Pos1 - Pos2);

214 BuiltinName = BuiltinName.substr(BuiltinName.find_last_of(' ') + 1);

215 }

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241 static const std::regex SpvWithR(

242 "(__spirv_(ImageSampleExplicitLod|ImageRead|ImageWrite|ImageQuerySizeLod|"

243 "UDotKHR|"

244 "SDotKHR|SUDotKHR|SDotAccSatKHR|UDotAccSatKHR|SUDotAccSatKHR|"

245 "ReadClockKHR|SubgroupBlockReadINTEL|SubgroupImageBlockReadINTEL|"

246 "SubgroupImageMediaBlockReadINTEL|SubgroupImageMediaBlockWriteINTEL|"

247 "Convert|Round|"

248 "UConvert|SConvert|FConvert|SatConvert)[^_]*)(_R[^_]*_?(\\w+)?.*)?");

249 std::smatch Match;

250 if (std::regex_match(BuiltinName, Match, SpvWithR) && Match.size() > 1) {

251 std::ssub_match SubMatch;

252 if (DecorationId && Match.size() > 3) {

253 SubMatch = Match[4];

255 }

256 SubMatch = Match[1];

257 BuiltinName = SubMatch.str();

258 }

259

260 return BuiltinName;

261}

262}

263

264

265

266

267

268

269

270

271

272

273

274static std::unique_ptr

276 SPIRV::InstructionSet::InstructionSet Set,

280

283 DemangledCall.slice(DemangledCall.find('(') + 1, DemangledCall.find(')'));

284 BuiltinArgs.split(BuiltinArgumentTypes, ',', -1, false);

285

286

287

289 if ((Builtin = SPIRV::lookupBuiltin(BuiltinName, Set)))

290 return std::make_uniqueSPIRV::IncomingCall(

291 BuiltinName, Builtin, ReturnRegister, ReturnType, Arguments);

292

293

294

295

296 if (BuiltinArgumentTypes.size() >= 1) {

297 char FirstArgumentType = BuiltinArgumentTypes[0][0];

298

299

300 std::string Prefix;

301

302 switch (FirstArgumentType) {

303

304 case 'u':

305 if (Set == SPIRV::InstructionSet::OpenCL_std)

306 Prefix = "u_";

307 else if (Set == SPIRV::InstructionSet::GLSL_std_450)

308 Prefix = "u";

309 break;

310

311 case 'c':

312 case 's':

313 case 'i':

314 case 'l':

315 if (Set == SPIRV::InstructionSet::OpenCL_std)

316 Prefix = "s_";

317 else if (Set == SPIRV::InstructionSet::GLSL_std_450)

318 Prefix = "s";

319 break;

320

321 case 'f':

322 case 'd':

323 case 'h':

324 if (Set == SPIRV::InstructionSet::OpenCL_std ||

325 Set == SPIRV::InstructionSet::GLSL_std_450)

326 Prefix = "f";

327 break;

328 }

329

330

331 if (!Prefix.empty() &&

332 (Builtin = SPIRV::lookupBuiltin(Prefix + BuiltinName, Set)))

333 return std::make_uniqueSPIRV::IncomingCall(

334 BuiltinName, Builtin, ReturnRegister, ReturnType, Arguments);

335

336

337

338

339 std::string Suffix;

340

341 switch (FirstArgumentType) {

342

343 case 'u':

344 Suffix = "u";

345 break;

346

347 case 'c':

348 case 's':

349 case 'i':

350 case 'l':

351 Suffix = "s";

352 break;

353

354 case 'f':

355 case 'd':

356 case 'h':

357 Suffix = "f";

358 break;

359 }

360

361

362 if (!Suffix.empty() &&

363 (Builtin = SPIRV::lookupBuiltin(BuiltinName + Suffix, Set)))

364 return std::make_uniqueSPIRV::IncomingCall(

365 BuiltinName, Builtin, ReturnRegister, ReturnType, Arguments);

366 }

367

368

369 return nullptr;

370}

371

374

375

376

377

378

380 assert(MI->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST &&

381 MI->getOperand(1).isReg());

382 Register BitcastReg = MI->getOperand(1).getReg();

383 MachineInstr *BitcastMI = MRI->getUniqueVRegDef(BitcastReg);

388 return ValueMI;

389}

390

391

392

393

396 assert(DefMI->getOpcode() == TargetOpcode::G_CONSTANT &&

397 DefMI->getOperand(1).isCImm());

398 return DefMI->getOperand(1).getCImm()->getValue().getZExtValue();

399}

400

401

402

405 if (!NextMI)

406 return nullptr;

407 if (isSpvIntrinsic(*NextMI, Intrinsic::spv_assign_name))

408 if ((NextMI = NextMI->getNextNode()) == nullptr)

409 return nullptr;

410 Register ValueReg = MI->getOperand(0).getReg();

411 if ((isSpvIntrinsic(*NextMI, Intrinsic::spv_assign_type) &&

412 isSpvIntrinsic(*NextMI, Intrinsic::spv_assign_ptr_type)) ||

414 return nullptr;

416 assert(Ty && "Type is expected");

417 return Ty;

418}

419

422

423

424

425

426

428 if (MI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE)

429 return MI->getOperand(1).getGlobal()->getType();

431 "Blocks in OpenCL C must be traceable to allocation site");

433}

434

435

436

437

438

439

440

441

442

443static std::tuple<Register, SPIRVType *>

448

449 if (ResultType->getOpcode() == SPIRV::OpTypeVector) {

450 unsigned VectorElements = ResultType->getOperand(2).getImm();

452 MIRBuilder, true);

456 } else {

458 }

459

464 return std::make_tuple(ResultRegister, BoolType);

465}

466

467

468

473 Register TrueConst, FalseConst;

474

475 if (ReturnType->getOpcode() == SPIRV::OpTypeVector) {

478 TrueConst =

481 } else {

482 TrueConst = GR->buildConstantInt(1, MIRBuilder, ReturnType, true);

483 FalseConst = GR->buildConstantInt(0, MIRBuilder, ReturnType, true);

484 }

485

486 return MIRBuilder.buildSelect(ReturnRegister, SourceRegister, TrueConst,

487 FalseConst);

488}

489

490

491

496 if (!DestinationReg.isValid())

498

499

501 MIRBuilder.buildLoad(DestinationReg, PtrRegister, PtrInfo, Align());

502 return DestinationReg;

503}

504

505

506

511 const std::optionalSPIRV::LinkageType::LinkageType &LinkageTy = {

512 SPIRV::LinkageType::Import}) {

516 NewRegister,

520 VariableType, MIRBuilder, SPIRV::StorageClass::Input);

522

523

526 SPIRV::StorageClass::Input, nullptr, isConst, LinkageTy,

527 MIRBuilder, false);

528

529

531 buildLoadInst(VariableType, Variable, MIRBuilder, GR, LLType, Reg);

532 MIRBuilder.getMRI()->setType(LoadedRegister, LLType);

533 return LoadedRegister;

534}

535

536

537

541

542

543static SPIRV::MemorySemantics::MemorySemantics

545 switch (MemOrder) {

546 case std::memory_order_relaxed:

547 return SPIRV::MemorySemantics::None;

548 case std::memory_order_acquire:

549 return SPIRV::MemorySemantics::Acquire;

550 case std::memory_order_release:

551 return SPIRV::MemorySemantics::Release;

552 case std::memory_order_acq_rel:

553 return SPIRV::MemorySemantics::AcquireRelease;

554 case std::memory_order_seq_cst:

555 return SPIRV::MemorySemantics::SequentiallyConsistent;

556 default:

558 }

559}

560

561static SPIRV::Scope::Scope getSPIRVScope(SPIRV::CLMemoryScope ClScope) {

562 switch (ClScope) {

563 case SPIRV::CLMemoryScope::memory_scope_work_item:

564 return SPIRV::Scope::Invocation;

565 case SPIRV::CLMemoryScope::memory_scope_work_group:

566 return SPIRV::Scope::Workgroup;

567 case SPIRV::CLMemoryScope::memory_scope_device:

568 return SPIRV::Scope::Device;

569 case SPIRV::CLMemoryScope::memory_scope_all_svm_devices:

570 return SPIRV::Scope::CrossDevice;

571 case SPIRV::CLMemoryScope::memory_scope_sub_group:

572 return SPIRV::Scope::Subgroup;

573 }

575}

576

583

585 SPIRV::Scope::Scope Scope,

589 if (CLScopeRegister.isValid()) {

590 auto CLScope =

591 static_castSPIRV::CLMemoryScope\(getIConstVal(CLScopeRegister, MRI));

593

594 if (CLScope == static_cast<unsigned>(Scope)) {

595 MRI->setRegClass(CLScopeRegister, &SPIRV::iIDRegClass);

596 return CLScopeRegister;

597 }

598 }

600}

601

604 if (MRI->getRegClassOrNull(Reg))

605 return;

607 MRI->setRegClass(Reg,

608 SpvType ? GR->getRegClass(SpvType) : &SPIRV::iIDRegClass);

609}

610

612 Register PtrRegister, unsigned &Semantics,

615 if (SemanticsRegister.isValid()) {

617 std::memory_order Order =

618 static_caststd::memory\_order\(getIConstVal(SemanticsRegister, MRI));

619 Semantics =

622 if (static_cast<unsigned>(Order) == Semantics) {

623 MRI->setRegClass(SemanticsRegister, &SPIRV::iIDRegClass);

624 return SemanticsRegister;

625 }

626 }

628}

629

634 auto MIB = MIRBuilder.buildInstr(Opcode);

637 unsigned Sz = Call->Arguments.size() - ImmArgs.size();

638 for (unsigned i = 0; i < Sz; ++i)

639 MIB.addUse(Call->Arguments[i]);

640 for (uint32_t ImmArg : ImmArgs)

641 MIB.addImm(ImmArg);

642 return true;

643}

644

645

648 if (Call->isSpirvOp())

650

651 assert(Call->Arguments.size() == 2 &&

652 "Need 2 arguments for atomic init translation");

653 MIRBuilder.buildInstr(SPIRV::OpStore)

656 return true;

657}

658

659

664 if (Call->isSpirvOp())

666

668

669

670

672 Call->Arguments.size() > 1

673 ? Call->Arguments[1]

676 if (Call->Arguments.size() > 2) {

677

678 MemSemanticsReg = Call->Arguments[2];

679 } else {

680 int Semantics =

681 SPIRV::MemorySemantics::SequentiallyConsistent |

684 }

685

686 MIRBuilder.buildInstr(SPIRV::OpAtomicLoad)

690 .addUse(ScopeRegister)

691 .addUse(MemSemanticsReg);

692 return true;

693}

694

695

699 if (Call->isSpirvOp())

702

706 int Semantics =

707 SPIRV::MemorySemantics::SequentiallyConsistent |

710 MIRBuilder.buildInstr(SPIRV::OpAtomicStore)

712 .addUse(ScopeRegister)

713 .addUse(MemSemanticsReg)

715 return true;

716}

717

718

722 if (Call->isSpirvOp())

725

726 bool IsCmpxchg = Call->Builtin->Name.contains("cmpxchg");

728

729 Register ObjectPtr = Call->Arguments[0];

730 Register ExpectedArg = Call->Arguments[1];

731 Register Desired = Call->Arguments[2];

733 LLT DesiredLLT = MRI->getType(Desired);

734

736 SPIRV::OpTypePointer);

738 (void)ExpectedType;

739 assert(IsCmpxchg ? ExpectedType == SPIRV::OpTypeInt

740 : ExpectedType == SPIRV::OpTypePointer);

742

745 auto StorageClass = static_castSPIRV::StorageClass::StorageClass\(

748

752 IsCmpxchg

753 ? SPIRV::MemorySemantics::None

754 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;

756 IsCmpxchg

757 ? SPIRV::MemorySemantics::None

758 : SPIRV::MemorySemantics::SequentiallyConsistent | MemSemStorage;

759 if (Call->Arguments.size() >= 4) {

760 assert(Call->Arguments.size() >= 5 &&

761 "Need 5+ args for explicit atomic cmpxchg");

762 auto MemOrdEq =

764 auto MemOrdNeq =

768 if (static_cast<unsigned>(MemOrdEq) == MemSemEqual)

769 MemSemEqualReg = Call->Arguments[3];

770 if (static_cast<unsigned>(MemOrdNeq) == MemSemEqual)

771 MemSemUnequalReg = Call->Arguments[4];

772 }

773 if (!MemSemEqualReg.isValid())

775 if (!MemSemUnequalReg.isValid())

777

779 auto Scope = IsCmpxchg ? SPIRV::Scope::Workgroup : SPIRV::Scope::Device;

780 if (Call->Arguments.size() >= 6) {

781 assert(Call->Arguments.size() == 6 &&

782 "Extra args for explicit atomic cmpxchg");

783 auto ClScope = static_castSPIRV::CLMemoryScope\(

786 if (ClScope == static_cast<unsigned>(Scope))

787 ScopeReg = Call->Arguments[5];

788 }

791

793 ? ExpectedArg

794 : buildLoadInst(SpvDesiredTy, ExpectedArg, MIRBuilder,

797 Register Tmp = !IsCmpxchg ? MRI->createGenericVirtualRegister(DesiredLLT)

798 : Call->ReturnRegister;

799 if (MRI->getRegClassOrNull(Tmp))

800 MRI->setRegClass(Tmp, GR->getRegClass(SpvDesiredTy));

802

808 .addUse(MemSemEqualReg)

809 .addUse(MemSemUnequalReg)

812 if (!IsCmpxchg) {

815 }

816 return true;

817}

818

819

823 if (Call->isSpirvOp())

826

829 Call->Arguments.size() >= 4 ? Call->Arguments[3] : Register();

830

831 assert(Call->Arguments.size() <= 4 &&

832 "Too many args for explicit atomic RMW");

833 ScopeRegister = buildScopeReg(ScopeRegister, SPIRV::Scope::Workgroup,

834 MIRBuilder, GR, MRI);

835

837 unsigned Semantics = SPIRV::MemorySemantics::None;

839 Call->Arguments.size() >= 3 ? Call->Arguments[2] : Register();

841 Semantics, MIRBuilder, GR);

844

845 if (Call->ReturnType->getOpcode() == SPIRV::OpTypeFloat) {

846 if (Opcode == SPIRV::OpAtomicIAdd) {

847 Opcode = SPIRV::OpAtomicFAddEXT;

848 } else if (Opcode == SPIRV::OpAtomicISub) {

849

850

851 Opcode = SPIRV::OpAtomicFAddEXT;

853 MRI->createGenericVirtualRegister(MRI->getType(ValueReg));

856 MIRBuilder.getMF());

857 MIRBuilder.buildInstr(TargetOpcode::G_FNEG)

860 updateRegType(NegValueReg, nullptr, Call->ReturnType, GR, MIRBuilder,

862 ValueReg = NegValueReg;

863 }

864 }

867 .addUse(ValueTypeReg)

869 .addUse(ScopeRegister)

870 .addUse(MemSemanticsReg)

872 return true;

873}

874

875

877 unsigned Opcode,

880 assert(Call->Arguments.size() == 4 &&

881 "Wrong number of atomic floating-type builtin");

884 Register MemSemanticsReg = Call->Arguments[2];

891 .addUse(MemSemanticsReg)

893 return true;

894}

895

896

897

901 bool IsSet = Opcode == SPIRV::OpAtomicFlagTestAndSet;

903 if (Call->isSpirvOp())

905 IsSet ? TypeReg : Register(0));

906

909 unsigned Semantics = SPIRV::MemorySemantics::SequentiallyConsistent;

911 Call->Arguments.size() >= 2 ? Call->Arguments[1] : Register();

913 Semantics, MIRBuilder, GR);

914

915 assert((Opcode != SPIRV::OpAtomicFlagClear ||

916 (Semantics != SPIRV::MemorySemantics::Acquire &&

917 Semantics != SPIRV::MemorySemantics::AcquireRelease)) &&

918 "Invalid memory order argument!");

919

921 Call->Arguments.size() >= 3 ? Call->Arguments[2] : Register();

922 ScopeRegister =

923 buildScopeReg(ScopeRegister, SPIRV::Scope::Device, MIRBuilder, GR, MRI);

924

925 auto MIB = MIRBuilder.buildInstr(Opcode);

926 if (IsSet)

928

929 MIB.addUse(PtrRegister).addUse(ScopeRegister).addUse(MemSemanticsReg);

930 return true;

931}

932

933

934

939 const auto *ST =

941 if ((Opcode == SPIRV::OpControlBarrierArriveINTEL ||

942 Opcode == SPIRV::OpControlBarrierWaitINTEL) &&

943 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_split_barrier)) {

944 std::string DiagMsg = std::string(Builtin->Name) +

945 ": the builtin requires the following SPIR-V "

946 "extension: SPV_INTEL_split_barrier";

948 }

949

950 if (Call->isSpirvOp())

952

955 unsigned MemSemantics = SPIRV::MemorySemantics::None;

956

957 if (MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE)

958 MemSemantics |= SPIRV::MemorySemantics::WorkgroupMemory;

959

960 if (MemFlags & SPIRV::CLK_GLOBAL_MEM_FENCE)

961 MemSemantics |= SPIRV::MemorySemantics::CrossWorkgroupMemory;

962

963 if (MemFlags & SPIRV::CLK_IMAGE_MEM_FENCE)

964 MemSemantics |= SPIRV::MemorySemantics::ImageMemory;

965

966 if (Opcode == SPIRV::OpMemoryBarrier)

969 MemSemantics;

970 else if (Opcode == SPIRV::OpControlBarrierArriveINTEL)

971 MemSemantics |= SPIRV::MemorySemantics::Release;

972 else if (Opcode == SPIRV::OpControlBarrierWaitINTEL)

973 MemSemantics |= SPIRV::MemorySemantics::Acquire;

974 else

975 MemSemantics |= SPIRV::MemorySemantics::SequentiallyConsistent;

976

978 MemFlags == MemSemantics

979 ? Call->Arguments[0]

982 SPIRV::Scope::Scope Scope = SPIRV::Scope::Workgroup;

983 SPIRV::Scope::Scope MemScope = Scope;

984 if (Call->Arguments.size() >= 2) {

986 ((Opcode != SPIRV::OpMemoryBarrier && Call->Arguments.size() == 2) ||

987 (Opcode == SPIRV::OpMemoryBarrier && Call->Arguments.size() == 3)) &&

988 "Extra args for explicitly scoped barrier");

989 Register ScopeArg = (Opcode == SPIRV::OpMemoryBarrier) ? Call->Arguments[2]

990 : Call->Arguments[1];

991 SPIRV::CLMemoryScope CLScope =

992 static_castSPIRV::CLMemoryScope\(getIConstVal(ScopeArg, MRI));

994 if (!(MemFlags & SPIRV::CLK_LOCAL_MEM_FENCE) ||

995 (Opcode == SPIRV::OpMemoryBarrier))

996 Scope = MemScope;

997 if (CLScope == static_cast<unsigned>(Scope))

998 ScopeReg = Call->Arguments[1];

999 }

1000

1001 if (!ScopeReg.isValid())

1003

1005 if (Opcode != SPIRV::OpMemoryBarrier)

1007 MIB.addUse(MemSemanticsReg);

1008 return true;

1009}

1010

1011

1013 unsigned Opcode,

1017 const auto *ST =

1018 static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());

1019 if ((Opcode == SPIRV::OpBitFieldInsert ||

1020 Opcode == SPIRV::OpBitFieldSExtract ||

1021 Opcode == SPIRV::OpBitFieldUExtract || Opcode == SPIRV::OpBitReverse) &&

1022 !ST->canUseExtension(SPIRV::Extension::SPV_KHR_bit_instructions)) {

1023 std::string DiagMsg = std::string(Builtin->Name) +

1024 ": the builtin requires the following SPIR-V "

1025 "extension: SPV_KHR_bit_instructions";

1027 }

1028

1029

1030 if (Call->isSpirvOp())

1033

1034 auto MIB = MIRBuilder.buildInstr(Opcode)

1037 for (unsigned i = 0; i < Call->Arguments.size(); ++i)

1039

1040 return true;

1041}

1042

1043

1045 unsigned Opcode,

1048

1049 if (Call->isSpirvOp())

1052

1057

1058 return true;

1059}

1060

1061

1065

1066 if (Call->isSpirvOp())

1069

1070 auto MIB = MIRBuilder.buildInstr(Opcode)

1073 for (unsigned i = 0; i < Call->Arguments.size(); ++i)

1075

1076 return true;

1077}

1078

1079

1081 unsigned Opcode,

1084

1085 if (Call->isSpirvOp())

1087

1088 auto MIB = MIRBuilder.buildInstr(Opcode)

1091 for (unsigned i = 0; i < Call->Arguments.size(); ++i)

1093

1094 return true;

1095}

1096

1100 switch (Opcode) {

1101 case SPIRV::OpCommitReadPipe:

1102 case SPIRV::OpCommitWritePipe:

1104 case SPIRV::OpGroupCommitReadPipe:

1105 case SPIRV::OpGroupCommitWritePipe:

1106 case SPIRV::OpGroupReserveReadPipePackets:

1107 case SPIRV::OpGroupReserveWritePipePackets: {

1111 MRI->setRegClass(ScopeConstReg, &SPIRV::iIDRegClass);

1113 MIB = MIRBuilder.buildInstr(Opcode);

1114

1115 if (Opcode == SPIRV::OpGroupReserveReadPipePackets ||

1116 Opcode == SPIRV::OpGroupReserveWritePipePackets)

1119

1120 MIB.addUse(ScopeConstReg);

1121 for (unsigned int i = 0; i < Call->Arguments.size(); ++i)

1123

1124 return true;

1125 }

1126 default:

1129 }

1130}

1131

1133 switch (dim) {

1134 case SPIRV::Dim::DIM_1D:

1135 case SPIRV::Dim::DIM_Buffer:

1136 return 1;

1137 case SPIRV::Dim::DIM_2D:

1138 case SPIRV::Dim::DIM_Cube:

1139 case SPIRV::Dim::DIM_Rect:

1140 return 2;

1141 case SPIRV::Dim::DIM_3D:

1142 return 3;

1143 default:

1145 }

1146}

1147

1148

1151 auto dim = static_castSPIRV::Dim::Dim\(imgType->getOperand(2).getImm());

1154 return arrayed ? numComps + 1 : numComps;

1155}

1156

1157

1158

1159

1160

1164

1167 SPIRV::lookupExtendedBuiltin(Builtin->Name, Builtin->Set)->Number;

1168

1169

1170

1174 if (ST.canUseExtension(SPIRV::Extension::SPV_KHR_float_controls2) &&

1175 (Number == SPIRV::OpenCLExtInst::fmin_common ||

1176 Number == SPIRV::OpenCLExtInst::fmax_common)) {

1177 Number = (Number == SPIRV::OpenCLExtInst::fmin_common)

1178 ? SPIRV::OpenCLExtInst::fmin

1179 : SPIRV::OpenCLExtInst::fmax;

1180 }

1181

1182

1183 auto MIB =

1184 MIRBuilder.buildInstr(SPIRV::OpExtInst)

1187 .addImm(static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))

1189

1193 if (OrigNumber == SPIRV::OpenCLExtInst::fmin_common ||

1194 OrigNumber == SPIRV::OpenCLExtInst::fmax_common) {

1195

1198 }

1199 return true;

1200}

1201

1205

1207 unsigned Opcode =

1208 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

1209

1212 std::tie(CompareRegister, RelationType) =

1214

1215

1216 auto MIB = MIRBuilder.buildInstr(Opcode)

1217 .addDef(CompareRegister)

1219

1222

1223

1224 return buildSelectInst(MIRBuilder, Call->ReturnRegister, CompareRegister,

1225 Call->ReturnType, GR);

1226}

1227

1233 SPIRV::lookupGroupBuiltin(Builtin->Name);

1234

1236 if (Call->isSpirvOp()) {

1239 if (GroupBuiltin->Opcode ==

1240 SPIRV::OpSubgroupMatrixMultiplyAccumulateINTEL &&

1241 Call->Arguments.size() > 4)

1245 }

1246

1247

1250 if (MI || MI->getOpcode() != TargetOpcode::G_CONSTANT)

1252 "Group Operation parameter must be an integer constant");

1253 uint64_t GrpOp = MI->getOperand(1).getCImm()->getValue().getZExtValue();

1260 for (unsigned i = 2; i < Call->Arguments.size(); ++i)

1262 return true;

1263 }

1264

1270 if (!BoolRegType)

1273 if (ArgInstruction->getOpcode() == TargetOpcode::G_CONSTANT) {

1274 if (BoolRegType->getOpcode() != SPIRV::OpTypeBool)

1276 BoolType, true);

1277 } else {

1278 if (BoolRegType->getOpcode() == SPIRV::OpTypeInt) {

1279 Arg0 = MRI->createGenericVirtualRegister(LLT::scalar(1));

1280 MRI->setRegClass(Arg0, &SPIRV::iIDRegClass);

1285 updateRegType(Arg0, nullptr, BoolType, GR, MIRBuilder,

1287 } else if (BoolRegType->getOpcode() != SPIRV::OpTypeBool) {

1289 }

1290

1291 }

1292 }

1293

1294 Register GroupResultRegister = Call->ReturnRegister;

1296

1297

1298

1299 const bool HasBoolReturnTy =

1303

1304 if (HasBoolReturnTy)

1305 std::tie(GroupResultRegister, GroupResultType) =

1307

1308 auto Scope = Builtin->Name.starts_with("sub_group") ? SPIRV::Scope::Subgroup

1309 : SPIRV::Scope::Workgroup;

1311

1313 if (GroupBuiltin->Opcode == SPIRV::OpGroupBroadcast &&

1314 Call->Arguments.size() > 2) {

1315

1316

1317

1318

1319

1322 if (!ElemType || ElemType->getOpcode() != SPIRV::OpTypeInt)

1324 unsigned VecLen = Call->Arguments.size() - 1;

1325 VecReg = MRI->createGenericVirtualRegister(

1327 MRI->setRegClass(VecReg, &SPIRV::vIDRegClass);

1331 auto MIB =

1332 MIRBuilder.buildInstr(TargetOpcode::G_BUILD_VECTOR).addDef(VecReg);

1333 for (unsigned i = 1; i < Call->Arguments.size(); i++) {

1334 MIB.addUse(Call->Arguments[i]);

1336 }

1337 updateRegType(VecReg, nullptr, VecType, GR, MIRBuilder,

1339 }

1340

1341

1343 .addDef(GroupResultRegister)

1345 .addUse(ScopeRegister);

1346

1349 if (Call->Arguments.size() > 0) {

1350 MIB.addUse(Arg0.isValid() ? Arg0 : Call->Arguments[0]);

1353 MIB.addUse(VecReg);

1354 else

1355 for (unsigned i = 1; i < Call->Arguments.size(); i++)

1356 MIB.addUse(Call->Arguments[i]);

1357 }

1358

1359

1360 if (HasBoolReturnTy)

1362 Call->ReturnType, GR);

1363 return true;

1364}

1365

1373 SPIRV::lookupIntelSubgroupsBuiltin(Builtin->Name);

1374

1375 if (IntelSubgroups->IsMedia &&

1376 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_media_block_io)) {

1377 std::string DiagMsg = std::string(Builtin->Name) +

1378 ": the builtin requires the following SPIR-V "

1379 "extension: SPV_INTEL_media_block_io";

1381 } else if (!IntelSubgroups->IsMedia &&

1382 !ST->canUseExtension(SPIRV::Extension::SPV_INTEL_subgroups)) {

1383 std::string DiagMsg = std::string(Builtin->Name) +

1384 ": the builtin requires the following SPIR-V "

1385 "extension: SPV_INTEL_subgroups";

1387 }

1388

1390 if (Call->isSpirvOp()) {

1391 bool IsSet = OpCode != SPIRV::OpSubgroupBlockWriteINTEL &&

1392 OpCode != SPIRV::OpSubgroupImageBlockWriteINTEL &&

1393 OpCode != SPIRV::OpSubgroupImageMediaBlockWriteINTEL;

1397 }

1398

1399 if (IntelSubgroups->IsBlock) {

1400

1402 if (Arg0Type->getOpcode() == SPIRV::OpTypeImage) {

1403

1404

1405

1406

1407 switch (OpCode) {

1408 case SPIRV::OpSubgroupBlockReadINTEL:

1409 OpCode = SPIRV::OpSubgroupImageBlockReadINTEL;

1410 break;

1411 case SPIRV::OpSubgroupBlockWriteINTEL:

1412 OpCode = SPIRV::OpSubgroupImageBlockWriteINTEL;

1413 break;

1414 }

1415 }

1416 }

1417 }

1418

1419

1420

1421

1422

1423

1424

1425

1426

1427

1428

1435 for (size_t i = 0; i < Call->Arguments.size(); ++i)

1437 return true;

1438}

1439

1446 if (!ST->canUseExtension(

1447 SPIRV::Extension::SPV_KHR_uniform_group_instructions)) {

1448 std::string DiagMsg = std::string(Builtin->Name) +

1449 ": the builtin requires the following SPIR-V "

1450 "extension: SPV_KHR_uniform_group_instructions";

1452 }

1454 SPIRV::lookupGroupUniformBuiltin(Builtin->Name);

1456

1457 Register GroupResultReg = Call->ReturnRegister;

1460

1461

1462 Register ConstGroupOpReg = Call->Arguments[1];

1464 if (!Const || Const->getOpcode() != TargetOpcode::G_CONSTANT)

1466 "expect a constant group operation for a uniform group instruction",

1467 false);

1468 const MachineOperand &ConstOperand = Const->getOperand(1);

1469 if (!ConstOperand.isCImm())

1470 report_fatal_error("uniform group instructions: group operation must be an "

1471 "integer constant",

1472 false);

1473

1475 .addDef(GroupResultReg)

1479 MIB.addUse(ValueReg);

1480

1481 return true;

1482}

1483

1490 if (!ST->canUseExtension(SPIRV::Extension::SPV_KHR_shader_clock)) {

1491 std::string DiagMsg = std::string(Builtin->Name) +

1492 ": the builtin requires the following SPIR-V "

1493 "extension: SPV_KHR_shader_clock";

1495 }

1496

1498

1499 if (Builtin->Name == "__spirv_ReadClockKHR") {

1500 MIRBuilder.buildInstr(SPIRV::OpReadClockKHR)

1504 } else {

1505

1506 SPIRV::Scope::Scope ScopeArg =

1508 .EndsWith("device", SPIRV::Scope::Scope::Device)

1509 .EndsWith("work_group", SPIRV::Scope::Scope::Workgroup)

1510 .EndsWith("sub_group", SPIRV::Scope::Scope::Subgroup);

1512

1513 MIRBuilder.buildInstr(SPIRV::OpReadClockKHR)

1517 }

1518

1519 return true;

1520}

1521

1522

1523

1524

1525

1526

1527

1528

1529

1530

1531

1532

1533

1534

1535

1536

1537

1538

1539

1540

1541

1542

1543

1544

1545

1546

1547

1551 SPIRV::BuiltIn::BuiltIn BuiltinValue,

1553 Register IndexRegister = Call->Arguments[0];

1554 const unsigned ResultWidth = Call->ReturnType->getOperand(1).getImm();

1556 const SPIRVType *PointerSizeType =

1560

1561

1563

1564

1565 bool IsConstantIndex =

1566 IndexInstruction->getOpcode() == TargetOpcode::G_CONSTANT;

1567

1568

1569

1570 if (IsConstantIndex && getIConstVal(IndexRegister, MRI) >= 3) {

1572 if (PointerSize != ResultWidth) {

1573 DefaultReg = MRI->createGenericVirtualRegister(LLT::scalar(PointerSize));

1574 MRI->setRegClass(DefaultReg, &SPIRV::iIDRegClass);

1576 MIRBuilder.getMF());

1577 ToTruncate = DefaultReg;

1578 }

1579 auto NewRegister =

1580 GR->buildConstantInt(DefaultValue, MIRBuilder, PointerSizeType, true);

1581 MIRBuilder.buildCopy(DefaultReg, NewRegister);

1582 } else {

1583 auto Vec3Ty =

1588

1590 if (!IsConstantIndex || PointerSize != ResultWidth) {

1591 Extracted = MRI->createGenericVirtualRegister(LLT::scalar(PointerSize));

1592 MRI->setRegClass(Extracted, &SPIRV::iIDRegClass);

1594 }

1595

1596

1598 Intrinsic::spv_extractelt, ArrayRef{Extracted}, true, false);

1599 ExtractInst.addUse(LoadedVector).addUse(IndexRegister);

1600

1601

1602 if (!IsConstantIndex) {

1603 updateRegType(Extracted, nullptr, PointerSizeType, GR, MIRBuilder, *MRI);

1604

1607

1610 MRI->setRegClass(CompareRegister, &SPIRV::iIDRegClass);

1612

1613

1617

1618

1619

1621 GR->buildConstantInt(DefaultValue, MIRBuilder, PointerSizeType, true);

1622

1623

1624 Register SelectionResult = Call->ReturnRegister;

1625 if (PointerSize != ResultWidth) {

1626 SelectionResult =

1627 MRI->createGenericVirtualRegister(LLT::scalar(PointerSize));

1628 MRI->setRegClass(SelectionResult, &SPIRV::iIDRegClass);

1630 MIRBuilder.getMF());

1631 }

1632

1633 MIRBuilder.buildSelect(SelectionResult, CompareRegister, Extracted,

1634 DefaultRegister);

1635 ToTruncate = SelectionResult;

1636 } else {

1637 ToTruncate = Extracted;

1638 }

1639 }

1640

1641 if (PointerSize != ResultWidth)

1643 return true;

1644}

1645

1649

1651 SPIRV::BuiltIn::BuiltIn Value =

1652 SPIRV::lookupGetBuiltin(Builtin->Name, Builtin->Set)->Value;

1653

1654 if (Value == SPIRV::BuiltIn::GlobalInvocationId)

1656

1657

1659 LLT LLType;

1660 if (Call->ReturnType->getOpcode() == SPIRV::OpTypeVector)

1661 LLType =

1663 else

1665

1667 LLType, Call->ReturnRegister);

1668}

1669

1673

1675 unsigned Opcode =

1676 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

1677

1678 switch (Opcode) {

1679 case SPIRV::OpStore:

1681 case SPIRV::OpAtomicLoad:

1683 case SPIRV::OpAtomicStore:

1685 case SPIRV::OpAtomicCompareExchange:

1686 case SPIRV::OpAtomicCompareExchangeWeak:

1688 GR);

1689 case SPIRV::OpAtomicIAdd:

1690 case SPIRV::OpAtomicISub:

1691 case SPIRV::OpAtomicOr:

1692 case SPIRV::OpAtomicXor:

1693 case SPIRV::OpAtomicAnd:

1694 case SPIRV::OpAtomicExchange:

1696 case SPIRV::OpMemoryBarrier:

1698 case SPIRV::OpAtomicFlagTestAndSet:

1699 case SPIRV::OpAtomicFlagClear:

1701 default:

1702 if (Call->isSpirvOp())

1705 return false;

1706 }

1707}

1708

1712

1714 unsigned Opcode = SPIRV::lookupAtomicFloatingBuiltin(Builtin->Name)->Opcode;

1715

1716 switch (Opcode) {

1717 case SPIRV::OpAtomicFAddEXT:

1718 case SPIRV::OpAtomicFMinEXT:

1719 case SPIRV::OpAtomicFMaxEXT:

1721 default:

1722 return false;

1723 }

1724}

1725

1729

1731 unsigned Opcode =

1732 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

1733

1735}

1736

1740

1742 unsigned Opcode =

1743 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

1744

1745 if (Opcode == SPIRV::OpGenericCastToPtrExplicit) {

1746 SPIRV::StorageClass::StorageClass ResSC =

1749 return false;

1750

1756 } else {

1757 MIRBuilder.buildInstr(TargetOpcode::G_ADDRSPACE_CAST)

1760 }

1761 return true;

1762}

1763

1768 if (Call->isSpirvOp())

1771

1773 SPIRV::OpTypeVector;

1774

1775 uint32_t OC = IsVec ? SPIRV::OpDot : SPIRV::OpFMulS;

1776 bool IsSwapReq = false;

1777

1778 const auto *ST =

1779 static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());

1781 (ST->canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||

1782 ST->isAtLeastSPIRVVer(VersionTuple(1, 6)))) {

1785 SPIRV::lookupIntegerDotProductBuiltin(Builtin->Name);

1786 if (IntDot) {

1787 OC = IntDot->Opcode;

1789 } else if (IsVec) {

1790

1791

1795 bool IsFirstSigned = TypeStrs[0].trim()[0] != 'u';

1796 bool IsSecondSigned = TypeStrs[1].trim()[0] != 'u';

1797

1798 if (Call->BuiltinName == "dot") {

1799 if (IsFirstSigned && IsSecondSigned)

1800 OC = SPIRV::OpSDot;

1801 else if (!IsFirstSigned && !IsSecondSigned)

1802 OC = SPIRV::OpUDot;

1803 else {

1804 OC = SPIRV::OpSUDot;

1805 if (!IsFirstSigned)

1806 IsSwapReq = true;

1807 }

1808 } else if (Call->BuiltinName == "dot_acc_sat") {

1809 if (IsFirstSigned && IsSecondSigned)

1810 OC = SPIRV::OpSDotAccSat;

1811 else if (!IsFirstSigned && !IsSecondSigned)

1812 OC = SPIRV::OpUDotAccSat;

1813 else {

1814 OC = SPIRV::OpSUDotAccSat;

1815 if (!IsFirstSigned)

1816 IsSwapReq = true;

1817 }

1818 }

1819 }

1820 }

1821

1825

1826 if (IsSwapReq) {

1829

1830 for (size_t i = 2; i < Call->Arguments.size(); ++i)

1832 } else {

1833 for (size_t i = 0; i < Call->Arguments.size(); ++i)

1835 }

1836

1837

1838

1839 if (!IsVec && OC != SPIRV::OpFMulS)

1840 MIB.addImm(SPIRV::PackedVectorFormat4x8Bit);

1841

1842 return true;

1843}

1844

1849 SPIRV::BuiltIn::BuiltIn Value =

1850 SPIRV::lookupGetBuiltin(Builtin->Name, Builtin->Set)->Value;

1851

1852

1853 assert(Call->ReturnType->getOpcode() == SPIRV::OpTypeInt);

1855

1857 MIRBuilder, Call->ReturnType, GR, Value, LLType, Call->ReturnRegister,

1858 false, std::nullopt);

1859}

1860

1861

1862

1863

1864

1865

1866

1871 unsigned Opcode =

1872 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

1873

1877 if (!RetType)

1879 if (RetType->getOpcode() != SPIRV::OpTypeStruct)

1880 report_fatal_error("Expected struct type result for the arithmetic with "

1881 "overflow builtins");

1882

1885 if (!OpType1 || !OpType2 || OpType1 != OpType2)

1887 if (OpType1->getOpcode() == SPIRV::OpTypeVector)

1888 switch (Opcode) {

1889 case SPIRV::OpIAddCarryS:

1890 Opcode = SPIRV::OpIAddCarryV;

1891 break;

1892 case SPIRV::OpISubBorrowS:

1893 Opcode = SPIRV::OpISubBorrowV;

1894 break;

1895 }

1896

1898 Register ResReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);

1900 MRI->getRegClassOrNull(Call->Arguments[1])) {

1901 MRI->setRegClass(ResReg, DstRC);

1902 MRI->setType(ResReg, MRI->getType(Call->Arguments[1]));

1903 } else {

1905 }

1913 return true;

1914}

1915

1919

1920 SPIRV::BuiltIn::BuiltIn Value =

1921 SPIRV::lookupGetBuiltin(Call->Builtin->Name, Call->Builtin->Set)->Value;

1922 const bool IsDefaultOne = (Value == SPIRV::BuiltIn::GlobalSize ||

1923 Value == SPIRV::BuiltIn::NumWorkgroups ||

1924 Value == SPIRV::BuiltIn::WorkgroupSize ||

1925 Value == SPIRV::BuiltIn::EnqueuedWorkgroupSize);

1927}

1928

1932

1935 SPIRV::lookupImageQueryBuiltin(Builtin->Name, Builtin->Set)->Component;

1936

1937

1938

1939 unsigned NumExpectedRetComponents =

1940 Call->ReturnType->getOpcode() == SPIRV::OpTypeVector

1941 ? Call->ReturnType->getOperand(2).getImm()

1942 : 1;

1943

1946 Register QueryResult = Call->ReturnRegister;

1948 if (NumExpectedRetComponents != NumActualRetComponents) {

1949 unsigned Bitwidth = Call->ReturnType->getOpcode() == SPIRV::OpTypeInt

1950 ? Call->ReturnType->getOperand(1).getImm()

1951 : 32;

1954 MIRBuilder.getMRI()->setRegClass(QueryResult, &SPIRV::vIDRegClass);

1957 IntTy, NumActualRetComponents, MIRBuilder, true);

1959 }

1960 bool IsDimBuf = ImgType->getOperand(2).getImm() == SPIRV::Dim::DIM_Buffer;

1961 unsigned Opcode =

1962 IsDimBuf ? SPIRV::OpImageQuerySize : SPIRV::OpImageQuerySizeLod;

1963 auto MIB = MIRBuilder.buildInstr(Opcode)

1964 .addDef(QueryResult)

1967 if (!IsDimBuf)

1969 if (NumExpectedRetComponents == NumActualRetComponents)

1970 return true;

1971 if (NumExpectedRetComponents == 1) {

1972

1973 unsigned ExtractedComposite =

1974 Component == 3 ? NumActualRetComponents - 1 : Component;

1975 assert(ExtractedComposite < NumActualRetComponents &&

1976 "Invalid composite index!");

1979 if (QueryResultType->getOpcode() == SPIRV::OpTypeVector) {

1981 if (TypeReg != NewTypeReg &&

1983 TypeReg = NewTypeReg;

1984 }

1985 MIRBuilder.buildInstr(SPIRV::OpCompositeExtract)

1988 .addUse(QueryResult)

1989 .addImm(ExtractedComposite);

1990 if (NewType != nullptr)

1991 updateRegType(Call->ReturnRegister, nullptr, NewType, GR, MIRBuilder,

1993 } else {

1994

1995 auto MIB = MIRBuilder.buildInstr(SPIRV::OpVectorShuffle)

1998 .addUse(QueryResult)

1999 .addUse(QueryResult);

2000 for (unsigned i = 0; i < NumExpectedRetComponents; ++i)

2001 MIB.addImm(i < NumActualRetComponents ? i : 0xffffffff);

2002 }

2003 return true;

2004}

2005

2009 assert(Call->ReturnType->getOpcode() == SPIRV::OpTypeInt &&

2010 "Image samples query result must be of int type!");

2011

2012

2014 unsigned Opcode =

2015 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

2016

2018 SPIRV::Dim::Dim ImageDimensionality = static_castSPIRV::Dim::Dim\(

2020 (void)ImageDimensionality;

2021

2022 switch (Opcode) {

2023 case SPIRV::OpImageQuerySamples:

2024 assert(ImageDimensionality == SPIRV::Dim::DIM_2D &&

2025 "Image must be of 2D dimensionality");

2026 break;

2027 case SPIRV::OpImageQueryLevels:

2028 assert((ImageDimensionality == SPIRV::Dim::DIM_1D ||

2029 ImageDimensionality == SPIRV::Dim::DIM_2D ||

2030 ImageDimensionality == SPIRV::Dim::DIM_3D ||

2031 ImageDimensionality == SPIRV::Dim::DIM_Cube) &&

2032 "Image must be of 1D/2D/3D/Cube dimensionality");

2033 break;

2034 }

2035

2040 return true;

2041}

2042

2043

2044static SPIRV::SamplerAddressingMode::SamplerAddressingMode

2046 switch (Bitmask & SPIRV::CLK_ADDRESS_MODE_MASK) {

2047 case SPIRV::CLK_ADDRESS_CLAMP:

2048 return SPIRV::SamplerAddressingMode::Clamp;

2049 case SPIRV::CLK_ADDRESS_CLAMP_TO_EDGE:

2050 return SPIRV::SamplerAddressingMode::ClampToEdge;

2051 case SPIRV::CLK_ADDRESS_REPEAT:

2052 return SPIRV::SamplerAddressingMode::Repeat;

2053 case SPIRV::CLK_ADDRESS_MIRRORED_REPEAT:

2054 return SPIRV::SamplerAddressingMode::RepeatMirrored;

2055 case SPIRV::CLK_ADDRESS_NONE:

2056 return SPIRV::SamplerAddressingMode::None;

2057 default:

2059 }

2060}

2061

2063 return (Bitmask & SPIRV::CLK_NORMALIZED_COORDS_TRUE) ? 1 : 0;

2064}

2065

2066static SPIRV::SamplerFilterMode::SamplerFilterMode

2068 if (Bitmask & SPIRV::CLK_FILTER_LINEAR)

2069 return SPIRV::SamplerFilterMode::Linear;

2070 if (Bitmask & SPIRV::CLK_FILTER_NEAREST)

2071 return SPIRV::SamplerFilterMode::Nearest;

2072 return SPIRV::SamplerFilterMode::Nearest;

2073}

2074

2079 if (Call->isSpirvOp())

2086 if (HasOclSampler) {

2088

2089 if (!GR->isScalarOfType(Sampler, SPIRV::OpTypeSampler) &&

2096 }

2100 Register SampledImage = MRI->createVirtualRegister(&SPIRV::iIDRegClass);

2101

2102 MIRBuilder.buildInstr(SPIRV::OpSampledImage)

2103 .addDef(SampledImage)

2107

2109 MIRBuilder);

2110

2111 if (Call->ReturnType->getOpcode() != SPIRV::OpTypeVector) {

2115 MRI->createGenericVirtualRegister(GR->getRegType(TempType));

2116 MRI->setRegClass(TempRegister, GR->getRegClass(TempType));

2118 MIRBuilder.buildInstr(SPIRV::OpImageSampleExplicitLod)

2119 .addDef(TempRegister)

2121 .addUse(SampledImage)

2122 .addUse(Call->Arguments[2])

2123 .addImm(SPIRV::ImageOperand::Lod)

2125 MIRBuilder.buildInstr(SPIRV::OpCompositeExtract)

2128 .addUse(TempRegister)

2130 } else {

2131 MIRBuilder.buildInstr(SPIRV::OpImageSampleExplicitLod)

2134 .addUse(SampledImage)

2135 .addUse(Call->Arguments[2])

2136 .addImm(SPIRV::ImageOperand::Lod)

2138 }

2139 } else if (HasMsaa) {

2140 MIRBuilder.buildInstr(SPIRV::OpImageRead)

2144 .addUse(Call->Arguments[1])

2145 .addImm(SPIRV::ImageOperand::Sample)

2147 } else {

2148 MIRBuilder.buildInstr(SPIRV::OpImageRead)

2152 .addUse(Call->Arguments[1]);

2153 }

2154 return true;

2155}

2156

2169

2175 if (Call->Builtin->Name.contains_insensitive(

2176 "__translate_sampler_initializer")) {

2177

2183 return Sampler.isValid();

2184 } else if (Call->Builtin->Name.contains_insensitive("__spirv_SampledImage")) {

2185

2191 Call->ReturnRegister.isValid()

2192 ? Call->ReturnRegister

2193 : MRI->createVirtualRegister(&SPIRV::iIDRegClass);

2194 MIRBuilder.buildInstr(SPIRV::OpSampledImage)

2195 .addDef(SampledImage)

2198 .addUse(Call->Arguments[1]);

2199 return true;

2200 } else if (Call->Builtin->Name.contains_insensitive(

2201 "__spirv_ImageSampleExplicitLod")) {

2202

2203 std::string ReturnType = DemangledCall.str();

2204 if (DemangledCall.contains("_R")) {

2205 ReturnType = ReturnType.substr(ReturnType.find("_R") + 2);

2206 ReturnType = ReturnType.substr(0, ReturnType.find('('));

2207 }

2209 Call->ReturnType

2210 ? Call->ReturnType

2212 if (Type) {

2213 std::string DiagMsg =

2214 "Unable to recognize SPIRV type name: " + ReturnType;

2216 }

2217 MIRBuilder.buildInstr(SPIRV::OpImageSampleExplicitLod)

2220 .addUse(Call->Arguments[0])

2221 .addUse(Call->Arguments[1])

2222 .addImm(SPIRV::ImageOperand::Lod)

2224 return true;

2225 }

2226 return false;

2227}

2228

2232 Call->Arguments[1], Call->Arguments[2]);

2233 return true;

2234}

2235

2240 SPIRV::OpCompositeConstructContinuedINTEL,

2241 Call->Arguments, Call->ReturnRegister,

2243 return true;

2244}

2245

2250 unsigned Opcode =

2251 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

2252 bool IsSet = Opcode != SPIRV::OpCooperativeMatrixStoreKHR &&

2253 Opcode != SPIRV::OpCooperativeMatrixStoreCheckedINTEL &&

2254 Opcode != SPIRV::OpCooperativeMatrixPrefetchINTEL;

2255 unsigned ArgSz = Call->Arguments.size();

2256 unsigned LiteralIdx = 0;

2257 switch (Opcode) {

2258

2259 case SPIRV::OpCooperativeMatrixLoadKHR:

2260 LiteralIdx = ArgSz > 3 ? 3 : 0;

2261 break;

2262 case SPIRV::OpCooperativeMatrixStoreKHR:

2263 LiteralIdx = ArgSz > 4 ? 4 : 0;

2264 break;

2265 case SPIRV::OpCooperativeMatrixLoadCheckedINTEL:

2266 LiteralIdx = ArgSz > 7 ? 7 : 0;

2267 break;

2268 case SPIRV::OpCooperativeMatrixStoreCheckedINTEL:

2269 LiteralIdx = ArgSz > 8 ? 8 : 0;

2270 break;

2271

2272 case SPIRV::OpCooperativeMatrixMulAddKHR:

2273 LiteralIdx = ArgSz > 3 ? 3 : 0;

2274 break;

2275 };

2276

2279 if (Opcode == SPIRV::OpCooperativeMatrixPrefetchINTEL) {

2281 auto MIB = MIRBuilder.buildInstr(SPIRV::OpCooperativeMatrixPrefetchINTEL)

2282 .addUse(Call->Arguments[0])

2284 .addUse(Call->Arguments[2])

2285 .addImm(CacheLevel)

2286 .addUse(Call->Arguments[4]);

2287 if (ArgSz > 5)

2288 MIB.addUse(Call->Arguments[5]);

2289 if (ArgSz > 6) {

2291 MIB.addImm(MemOp);

2292 }

2293 return true;

2294 }

2295 if (LiteralIdx > 0)

2298 if (Opcode == SPIRV::OpCooperativeMatrixLengthKHR) {

2300 if (!CoopMatrType)

2306 return true;

2307 }

2309 IsSet ? TypeReg : Register(0), ImmArgs);

2310}

2311

2315

2317 unsigned Opcode =

2318 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

2320

2321 switch (Opcode) {

2322 case SPIRV::OpSpecConstant: {

2323

2324 unsigned SpecId =

2326 buildOpDecorate(Call->ReturnRegister, MIRBuilder, SPIRV::Decoration::SpecId,

2327 {SpecId});

2328

2329 Register ConstRegister = Call->Arguments[1];

2332 (Const->getOpcode() == TargetOpcode::G_CONSTANT ||

2333 Const->getOpcode() == TargetOpcode::G_FCONSTANT) &&

2334 "Argument should be either an int or floating-point constant");

2335

2336 const MachineOperand &ConstOperand = Const->getOperand(1);

2337 if (Call->ReturnType->getOpcode() == SPIRV::OpTypeBool) {

2338 assert(ConstOperand.isCImm() && "Int constant operand is expected");

2340 ? SPIRV::OpSpecConstantTrue

2341 : SPIRV::OpSpecConstantFalse;

2342 }

2343 auto MIB = MIRBuilder.buildInstr(Opcode)

2346

2347 if (Call->ReturnType->getOpcode() != SPIRV::OpTypeBool) {

2348 if (Const->getOpcode() == TargetOpcode::G_CONSTANT)

2350 else

2352 }

2353 return true;

2354 }

2355 case SPIRV::OpSpecConstantComposite: {

2357 SPIRV::OpSpecConstantCompositeContinuedINTEL,

2358 Call->Arguments, Call->ReturnRegister,

2360 return true;

2361 }

2362 default:

2363 return false;

2364 }

2365}

2366

2370

2372 unsigned Opcode =

2373 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

2374

2376}

2377

2381

2383 unsigned Opcode =

2384 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

2385

2387}

2388

2393 unsigned Opcode =

2394 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

2396}

2397

2405 bool IsSRet = RetTy->isVoidTy();

2406

2407 if (IsSRet) {

2408 const LLT ValTy = MRI->getType(InputReg);

2409 Register ActualRetValReg = MRI->createGenericVirtualRegister(ValTy);

2412 InputReg = Call->Arguments[1];

2415 if (InputType->getTypeID() == llvm::Type::TypeID::TypedPointerTyID) {

2416 LLT InputLLT = MRI->getType(InputReg);

2417 PtrInputReg = MRI->createGenericVirtualRegister(InputLLT);

2423 MIRBuilder.buildLoad(PtrInputReg, InputReg, *MMO1);

2424 MRI->setRegClass(PtrInputReg, &SPIRV::iIDRegClass);

2426 }

2427

2428 for (unsigned index = 2; index < 7; index++) {

2430 }

2431

2432

2433 auto MIB = MIRBuilder.buildInstr(Opcode)

2434 .addDef(ActualRetValReg)

2436 if (PtrInputReg)

2437 MIB.addUse(PtrInputReg);

2438 else

2439 MIB.addUse(InputReg);

2440

2441 for (uint32_t Imm : ImmArgs)

2443 unsigned Size = ValTy.getSizeInBytes();

2444

2447 MRI->setRegClass(ActualRetValReg, &SPIRV::pIDRegClass);

2448 MIRBuilder.buildStore(ActualRetValReg, Call->Arguments[0], *MMO);

2449 return true;

2450 } else {

2451 for (unsigned index = 1; index < 6; index++)

2453

2456 }

2457}

2458

2463 unsigned Opcode =

2464 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

2465

2467}

2468

2469static bool

2473

2475 unsigned Opcode =

2476 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

2477

2479}

2480

2484

2486 unsigned Opcode =

2487 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

2488

2490}

2491

2496 unsigned Opcode =

2497 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

2498

2499 unsigned Scope = SPIRV::Scope::Workgroup;

2501 Scope = SPIRV::Scope::Subgroup;

2502

2504}

2505

2510 unsigned Opcode =

2511 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

2512

2513 bool IsSet = Opcode != SPIRV::OpPredicatedStoreINTEL;

2514 unsigned ArgSz = Call->Arguments.size();

2517

2518 if (ArgSz > 3)

2521

2524 IsSet ? TypeReg : Register(0), ImmArgs);

2525}

2526

2537 Register TmpReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);

2539

2540

2541 unsigned NumArgs = Call->Arguments.size();

2542 assert(NumArgs >= 2);

2543 Register GlobalWorkSize = Call->Arguments[NumArgs < 4 ? 1 : 2];

2545 NumArgs == 2 ? Register(0) : Call->Arguments[NumArgs < 4 ? 2 : 3];

2546 Register GlobalWorkOffset = NumArgs <= 3 ? Register(0) : Call->Arguments[1];

2547 if (NumArgs < 4) {

2550 if (SpvTy->getOpcode() == SPIRV::OpTypePointer) {

2551 MachineInstr *DefInstr = MRI->getUniqueVRegDef(GlobalWorkSize);

2555

2556 unsigned Size = Call->Builtin->Name == "ndrange_3D" ? 3 : 2;

2561 FieldTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite, true);

2562 GlobalWorkSize = MRI->createVirtualRegister(&SPIRV::iIDRegClass);

2564 MIRBuilder.buildInstr(SPIRV::OpLoad)

2565 .addDef(GlobalWorkSize)

2571 SpvFieldTy, *ST.getInstrInfo());

2572 } else {

2574 }

2575 if (!LocalWorkSize.isValid())

2576 LocalWorkSize = Const;

2577 if (!GlobalWorkOffset.isValid())

2578 GlobalWorkOffset = Const;

2579 }

2581 MIRBuilder.buildInstr(SPIRV::OpBuildNDRange)

2584 .addUse(GlobalWorkSize)

2585 .addUse(LocalWorkSize)

2586 .addUse(GlobalWorkOffset);

2587 return MIRBuilder.buildInstr(SPIRV::OpStore)

2590}

2591

2592

2600 SPIRV::AccessQualifier::ReadWrite, true);

2601}

2602

2608 bool IsSpirvOp = Call->isSpirvOp();

2609 bool HasEvents = Call->Builtin->Name.contains("events") || IsSpirvOp;

2611

2612

2613

2614

2616 if (Call->Builtin->Name.contains("_varargs") || IsSpirvOp) {

2617 const unsigned LocalSizeArrayIdx = HasEvents ? 9 : 6;

2618 Register GepReg = Call->Arguments[LocalSizeArrayIdx];

2623 MachineInstr *ArrayMI = MRI->getUniqueVRegDef(ArrayReg);

2625 assert(LocalSizeTy && "Local size type is expected");

2626 const uint64_t LocalSizeNum =

2631 Int32Ty, MIRBuilder, SPIRV::StorageClass::Function);

2632 for (unsigned I = 0; I < LocalSizeNum; ++I) {

2633 Register Reg = MRI->createVirtualRegister(&SPIRV::pIDRegClass);

2634 MRI->setType(Reg, LLType);

2638 GEPInst

2644 }

2645 }

2646

2647

2648 auto MIB = MIRBuilder.buildInstr(SPIRV::OpEnqueueKernel)

2651

2652

2653 const unsigned BlockFIdx = HasEvents ? 6 : 3;

2654 for (unsigned i = 0; i < BlockFIdx; i++)

2655 MIB.addUse(Call->Arguments[i]);

2656

2657

2658 if (!HasEvents) {

2662 MIB.addUse(NullPtr);

2663 MIB.addUse(NullPtr);

2664 }

2665

2667 assert(BlockMI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE);

2668

2670

2671 Register BlockLiteralReg = Call->Arguments[BlockFIdx + 1];

2672

2673 MIB.addUse(BlockLiteralReg);

2674

2676

2677

2679

2681 MIRBuilder, GR));

2682

2683 for (unsigned i = 0; i < LocalSizes.size(); i++)

2684 MIB.addUse(LocalSizes[i]);

2685 return true;

2686}

2687

2691

2693 unsigned Opcode =

2694 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

2695

2696 switch (Opcode) {

2697 case SPIRV::OpRetainEvent:

2698 case SPIRV::OpReleaseEvent:

2700 case SPIRV::OpCreateUserEvent:

2701 case SPIRV::OpGetDefaultQueue:

2702 return MIRBuilder.buildInstr(Opcode)

2705 case SPIRV::OpIsValidEvent:

2706 return MIRBuilder.buildInstr(Opcode)

2710 case SPIRV::OpSetUserEventStatus:

2711 return MIRBuilder.buildInstr(Opcode)

2714 case SPIRV::OpCaptureEventProfilingInfo:

2715 return MIRBuilder.buildInstr(Opcode)

2719 case SPIRV::OpBuildNDRange:

2721 case SPIRV::OpEnqueueKernel:

2723 default:

2724 return false;

2725 }

2726}

2727

2731

2733 unsigned Opcode =

2734 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

2735

2736 bool IsSet = Opcode == SPIRV::OpGroupAsyncCopy;

2738 if (Call->isSpirvOp())

2740 IsSet ? TypeReg : Register(0));

2741

2743

2744 switch (Opcode) {

2745 case SPIRV::OpGroupAsyncCopy: {

2747 Call->ReturnType->getOpcode() == SPIRV::OpTypeEvent

2748 ? nullptr

2751 unsigned NumArgs = Call->Arguments.size();

2752 Register EventReg = Call->Arguments[NumArgs - 1];

2753 bool Res = MIRBuilder.buildInstr(Opcode)

2761 ? Call->Arguments[3]

2764 if (NewType != nullptr)

2765 updateRegType(Call->ReturnRegister, nullptr, NewType, GR, MIRBuilder,

2767 return Res;

2768 }

2769 case SPIRV::OpGroupWaitEvents:

2770 return MIRBuilder.buildInstr(Opcode)

2774 default:

2775 return false;

2776 }

2777}

2778

2783

2785 SPIRV::lookupConvertBuiltin(Call->Builtin->Name, Call->Builtin->Set);

2786

2787 if (!Builtin && Call->isSpirvOp()) {

2789 unsigned Opcode =

2790 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

2793 }

2794

2795 assert(Builtin && "Conversion builtin not found.");

2798 SPIRV::Decoration::SaturatedConversion, {});

2801 SPIRV::Decoration::FPRoundingMode,

2802 {(unsigned)Builtin->RoundingMode});

2803

2804 std::string NeedExtMsg;

2805 bool IsRightComponentsNumber = true;

2806 unsigned Opcode = SPIRV::OpNop;

2808

2810

2813 : SPIRV::OpSatConvertSToU;

2814 else

2816 : SPIRV::OpSConvert;

2818 SPIRV::OpTypeFloat)) {

2819

2821 const auto *ST = static_cast<const SPIRVSubtarget *>(

2822 &MIRBuilder.getMF().getSubtarget());

2823 if (!ST->canUseExtension(

2824 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))

2825 NeedExtMsg = "SPV_INTEL_bfloat16_conversion";

2826 IsRightComponentsNumber =

2829 Opcode = SPIRV::OpConvertBF16ToFINTEL;

2830 } else {

2831 bool IsSourceSigned =

2832 DemangledCall[DemangledCall.find_first_of('(') + 1] != 'u';

2833 Opcode = IsSourceSigned ? SPIRV::OpConvertSToF : SPIRV::OpConvertUToF;

2834 }

2835 }

2837 SPIRV::OpTypeFloat)) {

2838

2840

2842 const auto *ST = static_cast<const SPIRVSubtarget *>(

2843 &MIRBuilder.getMF().getSubtarget());

2844 if (!ST->canUseExtension(

2845 SPIRV::Extension::SPV_INTEL_bfloat16_conversion))

2846 NeedExtMsg = "SPV_INTEL_bfloat16_conversion";

2847 IsRightComponentsNumber =

2850 Opcode = SPIRV::OpConvertFToBF16INTEL;

2851 } else {

2853 : SPIRV::OpConvertFToU;

2854 }

2856 SPIRV::OpTypeFloat)) {

2857 if (Builtin->IsTF32) {

2858 const auto *ST = static_cast<const SPIRVSubtarget *>(

2859 &MIRBuilder.getMF().getSubtarget());

2860 if (!ST->canUseExtension(

2861 SPIRV::Extension::SPV_INTEL_tensor_float32_conversion))

2862 NeedExtMsg = "SPV_INTEL_tensor_float32_conversion";

2863 IsRightComponentsNumber =

2866 Opcode = SPIRV::OpRoundFToTF32INTEL;

2867 } else {

2868

2869 Opcode = SPIRV::OpFConvert;

2870 }

2871 }

2872 }

2873

2874 if (!NeedExtMsg.empty()) {

2875 std::string DiagMsg = std::string(Builtin->Name) +

2876 ": the builtin requires the following SPIR-V "

2877 "extension: " +

2878 NeedExtMsg;

2880 }

2881 if (!IsRightComponentsNumber) {

2882 std::string DiagMsg =

2883 std::string(Builtin->Name) +

2884 ": result and argument must have the same number of components";

2886 }

2887 assert(Opcode != SPIRV::OpNop &&

2888 "Conversion between the types not implemented!");

2889

2894 return true;

2895}

2896

2900

2902 SPIRV::lookupVectorLoadStoreBuiltin(Call->Builtin->Name,

2903 Call->Builtin->Set);

2904

2905 auto MIB =

2906 MIRBuilder.buildInstr(SPIRV::OpExtInst)

2909 .addImm(static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))

2915

2916

2917

2920 return true;

2921}

2922

2926

2928 unsigned Opcode =

2929 SPIRV::lookupNativeBuiltin(Builtin->Name, Builtin->Set)->Opcode;

2930 bool IsLoad = Opcode == SPIRV::OpLoad;

2931

2932 auto MIB = MIRBuilder.buildInstr(Opcode);

2933 if (IsLoad) {

2934 MIB.addDef(Call->ReturnRegister);

2936 }

2937

2940

2941 if (!IsLoad)

2942 MIB.addUse(Call->Arguments[1]);

2943

2944 unsigned NumArgs = Call->Arguments.size();

2945 if ((IsLoad && NumArgs >= 2) || NumArgs >= 3)

2947 if ((IsLoad && NumArgs >= 3) || NumArgs >= 4)

2949 return true;

2950}

2951

2952namespace SPIRV {

2953

2954

2955

2956

2957

2958

2959

2960std::tuple<int, unsigned, unsigned>

2962 SPIRV::InstructionSet::InstructionSet Set) {

2965 std::unique_ptr Call =

2968 return std::make_tuple(-1, 0, 0);

2969

2970 switch (Call->Builtin->Group) {

2971 case SPIRV::Relational:

2972 case SPIRV::Atomic:

2973 case SPIRV::Barrier:

2974 case SPIRV::CastToPtr:

2975 case SPIRV::ImageMiscQuery:

2976 case SPIRV::SpecConstant:

2977 case SPIRV::Enqueue:

2978 case SPIRV::AsyncCopy:

2979 case SPIRV::LoadStore:

2980 case SPIRV::CoopMatr:

2981 if (const auto *R =

2982 SPIRV::lookupNativeBuiltin(Call->Builtin->Name, Call->Builtin->Set))

2983 return std::make_tuple(Call->Builtin->Group, R->Opcode, 0);

2984 break;

2985 case SPIRV::Extended:

2986 if (const auto *R = SPIRV::lookupExtendedBuiltin(Call->Builtin->Name,

2987 Call->Builtin->Set))

2988 return std::make_tuple(Call->Builtin->Group, 0, R->Number);

2989 break;

2990 case SPIRV::VectorLoadStore:

2991 if (const auto *R = SPIRV::lookupVectorLoadStoreBuiltin(Call->Builtin->Name,

2992 Call->Builtin->Set))

2993 return std::make_tuple(SPIRV::Extended, 0, R->Number);

2994 break;

2995 case SPIRV::Group:

2996 if (const auto *R = SPIRV::lookupGroupBuiltin(Call->Builtin->Name))

2997 return std::make_tuple(Call->Builtin->Group, R->Opcode, 0);

2998 break;

2999 case SPIRV::AtomicFloating:

3000 if (const auto *R = SPIRV::lookupAtomicFloatingBuiltin(Call->Builtin->Name))

3001 return std::make_tuple(Call->Builtin->Group, R->Opcode, 0);

3002 break;

3003 case SPIRV::IntelSubgroups:

3004 if (const auto *R = SPIRV::lookupIntelSubgroupsBuiltin(Call->Builtin->Name))

3005 return std::make_tuple(Call->Builtin->Group, R->Opcode, 0);

3006 break;

3007 case SPIRV::GroupUniform:

3008 if (const auto *R = SPIRV::lookupGroupUniformBuiltin(Call->Builtin->Name))

3009 return std::make_tuple(Call->Builtin->Group, R->Opcode, 0);

3010 break;

3011 case SPIRV::IntegerDot:

3012 if (const auto *R =

3013 SPIRV::lookupIntegerDotProductBuiltin(Call->Builtin->Name))

3014 return std::make_tuple(Call->Builtin->Group, R->Opcode, 0);

3015 break;

3016 case SPIRV::WriteImage:

3017 return std::make_tuple(Call->Builtin->Group, SPIRV::OpImageWrite, 0);

3018 case SPIRV::Select:

3019 return std::make_tuple(Call->Builtin->Group, TargetOpcode::G_SELECT, 0);

3020 case SPIRV::Construct:

3021 return std::make_tuple(Call->Builtin->Group, SPIRV::OpCompositeConstruct,

3022 0);

3023 case SPIRV::KernelClock:

3024 return std::make_tuple(Call->Builtin->Group, SPIRV::OpReadClockKHR, 0);

3025 default:

3026 return std::make_tuple(-1, 0, 0);

3027 }

3028 return std::make_tuple(-1, 0, 0);

3029}

3030

3032 SPIRV::InstructionSet::InstructionSet Set,

3034 const Register OrigRet, const Type *OrigRetTy,

3037 LLVM_DEBUG(dbgs() << "Lowering builtin call: " << DemangledCall << "\n");

3038

3039

3041 assert(SpvType && "Inconsistent return register: expected valid type info");

3042 std::unique_ptr Call =

3043 lookupBuiltin(DemangledCall, Set, OrigRet, SpvType, Args);

3044

3045 if (Call) {

3046 LLVM_DEBUG(dbgs() << "Builtin record was not found!\n");

3047 return std::nullopt;

3048 }

3049

3050

3051 assert(Args.size() >= Call->Builtin->MinNumArgs &&

3052 "Too few arguments to generate the builtin");

3053 if (Call->Builtin->MaxNumArgs && Args.size() > Call->Builtin->MaxNumArgs)

3054 LLVM_DEBUG(dbgs() << "More arguments provided than required!\n");

3055

3056

3057 switch (Call->Builtin->Group) {

3058 case SPIRV::Extended:

3060 case SPIRV::Relational:

3062 case SPIRV::Group:

3064 case SPIRV::Variable:

3066 case SPIRV::Atomic:

3068 case SPIRV::AtomicFloating:

3070 case SPIRV::Barrier:

3072 case SPIRV::CastToPtr:

3074 case SPIRV::Dot:

3075 case SPIRV::IntegerDot:

3077 case SPIRV::Wave:

3079 case SPIRV::ICarryBorrow:

3081 case SPIRV::GetQuery:

3083 case SPIRV::ImageSizeQuery:

3085 case SPIRV::ImageMiscQuery:

3087 case SPIRV::ReadImage:

3089 case SPIRV::WriteImage:

3091 case SPIRV::SampleImage:

3093 case SPIRV::Select:

3095 case SPIRV::Construct:

3097 case SPIRV::SpecConstant:

3099 case SPIRV::Enqueue:

3101 case SPIRV::AsyncCopy:

3103 case SPIRV::Convert:

3105 case SPIRV::VectorLoadStore:

3107 case SPIRV::LoadStore:

3109 case SPIRV::IntelSubgroups:

3111 case SPIRV::GroupUniform:

3113 case SPIRV::KernelClock:

3115 case SPIRV::CoopMatr:

3117 case SPIRV::ExtendedBitOps:

3119 case SPIRV::BindlessINTEL:

3121 case SPIRV::TernaryBitwiseINTEL:

3123 case SPIRV::Block2DLoadStore:

3125 case SPIRV::Pipe:

3127 case SPIRV::PredicatedLoadStore:

3129 case SPIRV::BlockingPipes:

3131 case SPIRV::ArbitraryPrecisionFixedPoint:

3133 }

3134 return false;

3135}

3136

3138

3140

3141

3142 [[maybe_unused]] bool IsOCLBuiltinType = TypeStr.consume_front("ocl_");

3143 assert(IsOCLBuiltinType && "Invalid OpenCL builtin prefix");

3144

3145

3146

3147

3148

3149

3152

3154 Ctx);

3155 }

3156

3157

3158

3160 unsigned VecElts = 0;

3161

3164

3165 return nullptr;

3166

3167

3169

3171 TypeStr = TypeStr.substr(0, TypeStr.find(']'));

3172

3174 if (VecElts > 0)

3177

3179}

3180

3183 auto Pos1 = DemangledCall.find('(');

3185 return false;

3186 auto Pos2 = DemangledCall.find(')');

3188 return false;

3189 DemangledCall.slice(Pos1 + 1, Pos2)

3190 .split(BuiltinArgsTypeStrs, ',', -1, false);

3191 return true;

3192}

3193

3198 if (ArgIdx >= BuiltinArgsTypeStrs.size())

3199 return nullptr;

3200 StringRef TypeStr = BuiltinArgsTypeStrs[ArgIdx].trim();

3202}

3203

3208

3209#define GET_BuiltinTypes_DECL

3210#define GET_BuiltinTypes_IMPL

3211

3216

3217#define GET_OpenCLTypes_DECL

3218#define GET_OpenCLTypes_IMPL

3219

3220#include "SPIRVGenTables.inc"

3221}

3222

3223

3224

3225

3226

3228 if (Name.starts_with("void"))

3230 else if (Name.starts_with("int") || Name.starts_with("uint"))

3232 else if (Name.starts_with("float"))

3234 else if (Name.starts_with("half"))

3237}

3238

3239

3240

3241

3242

3247 unsigned Opcode = TypeRecord->Opcode;

3248

3250}

3251

3257

3262 "Invalid number of parameters for SPIR-V pipe builtin!");

3263

3265 SPIRV::AccessQualifier::AccessQualifier(

3267}

3268

3273 "Invalid number of parameters for SPIR-V coop matrices builtin!");

3275 "SPIR-V coop matrices builtin type must have a type parameter!");

3278 SPIRV::AccessQualifier::ReadWrite, true);

3279

3281 MIRBuilder, ExtensionType, ElemType, ExtensionType->getIntParameter(0),

3284}

3285

3290 OpaqueType, SPIRV::AccessQualifier::ReadOnly, MIRBuilder);

3291

3293}

3294

3299 "Inline SPIR-V type builtin takes an opcode, size, and alignment "

3300 "parameter");

3302

3306 if (ParamEType->getName() == "spirv.IntegralConstant") {

3307 assert(ParamEType->getNumTypeParameters() == 1 &&

3308 "Inline SPIR-V integral constant builtin must have a type "

3309 "parameter");

3310 assert(ParamEType->getNumIntParameters() == 1 &&

3311 "Inline SPIR-V integral constant builtin must have a "

3312 "value parameter");

3313

3314 auto OperandValue = ParamEType->getIntParameter(0);

3315 auto *OperandType = ParamEType->getTypeParameter(0);

3316

3318 OperandType, MIRBuilder, SPIRV::AccessQualifier::ReadWrite, true);

3319

3321 OperandValue, MIRBuilder, OperandSPIRVType, true)));

3322 continue;

3323 } else if (ParamEType->getName() == "spirv.Literal") {

3324 assert(ParamEType->getNumTypeParameters() == 0 &&

3325 "Inline SPIR-V literal builtin does not take type "

3326 "parameters");

3327 assert(ParamEType->getNumIntParameters() == 1 &&

3328 "Inline SPIR-V literal builtin must have an integer "

3329 "parameter");

3330

3331 auto OperandValue = ParamEType->getIntParameter(0);

3332

3334 continue;

3335 }

3336 }

3338 Param, MIRBuilder, SPIRV::AccessQualifier::ReadWrite, true);

3340 }

3341

3343 Operands);

3344}

3345

3350 "Vulkan buffers have exactly one type for the type of the buffer.");

3352 "Vulkan buffer have 2 integer parameters: storage class and is "

3353 "writable.");

3354

3356 auto SC = static_castSPIRV::StorageClass::StorageClass\(

3360}

3361

3367

3368namespace SPIRV {

3371 StringRef NameWithParameters = TypeName;

3372

3373

3374

3375

3376 if (NameWithParameters.starts_with("opencl.")) {

3378 SPIRV::lookupOpenCLType(NameWithParameters);

3379 if (!OCLTypeRecord)

3381 NameWithParameters);

3383

3384 }

3385

3386

3387

3389 "Unknown builtin opaque type!");

3390

3391

3392

3393 if (!NameWithParameters.contains('_'))

3395

3397 unsigned BaseNameLength = NameWithParameters.find('_') - 1;

3398 SplitString(NameWithParameters.substr(BaseNameLength + 1), Parameters, "_");

3399

3401 bool HasTypeParameter = isDigit(Parameters[0][0]);

3402 if (HasTypeParameter)

3405 for (unsigned i = HasTypeParameter ? 1 : 0; i < Parameters.size(); i++) {

3406 unsigned IntParameter = 0;

3407 bool ValidLiteral = !Parameters[i].getAsInteger(10, IntParameter);

3408 (void)ValidLiteral;

3409 assert(ValidLiteral &&

3410 "Invalid format of SPIR-V builtin parameter literal!");

3411 IntParameters.push_back(IntParameter);

3412 }

3414 NameWithParameters.substr(0, BaseNameLength),

3415 TypeParameters, IntParameters);

3416}

3417

3419 SPIRV::AccessQualifier::AccessQualifier AccessQual,

3422

3423

3424

3425

3426

3427

3428

3429

3434

3436

3438 LLVM_DEBUG(dbgs() << "Lowering builtin type: " << Name << "\n");

3439

3441 if (Name == "spirv.Type") {

3443 } else if (Name == "spirv.VulkanBuffer") {

3445 } else if (Name == "spirv.Padding") {

3447 } else if (Name == "spirv.Layout") {

3449 } else {

3450

3451 const SPIRV::BuiltinType *TypeRecord = SPIRV::lookupBuiltinType(Name);

3452 if (!TypeRecord)

3453 report_fatal_error("Missing TableGen record for builtin type: " + Name);

3454

3455

3456

3457

3458

3459

3460

3461 switch (TypeRecord->Opcode) {

3462 case SPIRV::OpTypeImage:

3464 break;

3465 case SPIRV::OpTypePipe:

3467 break;

3468 case SPIRV::OpTypeDeviceEvent:

3470 break;

3471 case SPIRV::OpTypeSampler:

3473 break;

3474 case SPIRV::OpTypeSampledImage:

3476 break;

3477 case SPIRV::OpTypeCooperativeMatrixKHR:

3479 break;

3480 default:

3481 TargetType =

3483 break;

3484 }

3485 }

3486

3487

3488

3491

3492 return TargetType;

3493}

3494}

3495}

unsigned const MachineRegisterInfo * MRI

MachineInstrBuilder MachineInstrBuilder & DefMI

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

AMDGPU Lower Kernel Arguments

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

Promote Memory to Register

BaseType

A given derived pointer can have multiple base pointers through phi/selects.

static const fltSemantics & IEEEsingle()

APInt bitcastToAPInt() const

static APFloat getZero(const fltSemantics &Sem, bool Negative=false)

Factory for Positive and Negative Zero.

static APInt getAllOnes(unsigned numBits)

Return an APInt of a specified width with all bits set.

uint64_t getZExtValue() const

Get zero extended value.

This class represents an incoming formal argument to a Function.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)

This static method is the primary way to construct an ArrayType.

Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...

@ ICMP_ULT

unsigned less than

const APFloat & getValueAPF() const

const APInt & getValue() const

Return the constant as an APInt value reference.

A parsed version of the target data layout string in and methods for querying it.

Tagged union holding either a T or a Error.

Class to represent fixed width SIMD vectors.

LLVMContext & getContext() const

getContext - Return a reference to the LLVMContext associated with this function.

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".

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 TypeSize getSizeInBytes() const

Returns the total size of the type in bytes, i.e.

This is an important class for using LLVM in a threaded context.

static MCOperand createReg(MCRegister Reg)

static MCOperand createImm(int64_t Val)

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)

getMachineMemOperand - Allocate a new MachineMemOperand.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

Helper class to build MachineInstr.

LLVMContext & getContext() const

MachineInstrBuilder buildSelect(const DstOp &Res, const SrcOp &Tst, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)

Build and insert a Res = G_SELECT Tst, Op0, Op1.

MachineInstrBuilder buildICmp(CmpInst::Predicate Pred, const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)

Build and insert a Res = G_ICMP Pred, Op0, Op1.

MachineBasicBlock::iterator getInsertPt()

Current insertion point for new instructions.

MachineInstrBuilder buildIntrinsic(Intrinsic::ID ID, ArrayRef< Register > Res, bool HasSideEffects, bool isConvergent)

Build and insert a G_INTRINSIC instruction.

MachineInstrBuilder buildLoad(const DstOp &Res, const SrcOp &Addr, MachineMemOperand &MMO)

Build and insert Res = G_LOAD Addr, MMO.

MachineInstrBuilder buildZExtOrTrunc(const DstOp &Res, const SrcOp &Op)

Build and insert Res = G_ZEXT Op, Res = G_TRUNC Op, or Res = COPY Op depending on the differing sizes...

MachineInstrBuilder buildStore(const SrcOp &Val, const SrcOp &Addr, MachineMemOperand &MMO)

Build and insert G_STORE Val, Addr, MMO.

MachineInstrBuilder buildInstr(unsigned Opcode)

Build and insert = Opcode .

MachineFunction & getMF()

Getter for the function we currently build.

MachineRegisterInfo * getMRI()

Getter for MRI.

MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)

Build and insert Res = COPY Op.

const DataLayout & getDataLayout() const

virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)

Build and insert Res = G_CONSTANT Val.

Register getReg(unsigned Idx) const

Get the register for the operand index.

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const

Add a virtual register use operand.

MachineInstr * getInstr() const

If conversion operators fail, use this method to get the MachineInstr explicitly.

const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const

Add a virtual register definition operand.

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

LLVM_ABI void copyIRFlags(const Instruction &I)

Copy all flags to MachineInst MIFlags.

const MachineOperand & getOperand(unsigned i) const

A description of a memory reference used in the backend.

@ MOLoad

The memory access reads data.

@ MOStore

The memory access writes data.

MachineOperand class - Representation of each machine instruction operand.

const GlobalValue * getGlobal() const

const ConstantInt * getCImm() const

bool isCImm() const

isCImm - Test if this is a MO_CImmediate operand.

bool isReg() const

isReg - Tests if this is a MO_Register operand.

const MDNode * getMetadata() const

Register getReg() const

getReg - Returns the register number.

const ConstantFP * getFPImm() const

MachineRegisterInfo - Keep track of information for virtual and physical registers,...

LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")

createVirtualRegister - Create and return a new virtual register in the function with the specified r...

LLVM_ABI void setType(Register VReg, LLT Ty)

Set the low-level type of VReg to Ty.

LLVM_ABI void setRegClass(Register Reg, const TargetRegisterClass *RC)

setRegClass - Set the register class of the specified virtual register.

LLVM_ABI Register createGenericVirtualRegister(LLT Ty, StringRef Name="")

Create and return a new generic virtual register with low-level type Ty.

unsigned getNumVirtRegs() const

getNumVirtRegs - Return the number of virtual registers created.

static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)

This constructs a pointer to an object of the specified type in a numbered address space.

Wrapper class representing virtual and physical registers.

constexpr bool isValid() const

SPIRVType * getOrCreateOpTypePipe(MachineIRBuilder &MIRBuilder, SPIRV::AccessQualifier::AccessQualifier AccQual)

SPIRVType * getSPIRVTypeForVReg(Register VReg, const MachineFunction *MF=nullptr) const

SPIRVType * getOrCreateSPIRVBoolType(MachineIRBuilder &MIRBuilder, bool EmitIR)

SPIRVType * getOrCreatePaddingType(MachineIRBuilder &MIRBuilder)

void assignSPIRVTypeToVReg(SPIRVType *Type, Register VReg, const MachineFunction &MF)

Register buildGlobalVariable(Register Reg, SPIRVType *BaseType, StringRef Name, const GlobalValue *GV, SPIRV::StorageClass::StorageClass Storage, const MachineInstr *Init, bool IsConst, const std::optional< SPIRV::LinkageType::LinkageType > &LinkageType, MachineIRBuilder &MIRBuilder, bool IsInstSelector)

const Type * getTypeForSPIRVType(const SPIRVType *Ty) const

SPIRVType * getOrCreateUnknownType(const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode, const ArrayRef< MCOperand > Operands)

unsigned getScalarOrVectorComponentCount(Register VReg) const

SPIRVType * getOrCreateSPIRVType(const Type *Type, MachineInstr &I, SPIRV::AccessQualifier::AccessQualifier AQ, bool EmitIR)

unsigned getPointerSize() const

SPIRVType * getOrCreateSPIRVPointerType(const Type *BaseType, MachineIRBuilder &MIRBuilder, SPIRV::StorageClass::StorageClass SC)

SPIRVType * getOrCreateOpTypeByOpcode(const Type *Ty, MachineIRBuilder &MIRBuilder, unsigned Opcode)

Register buildConstantFP(APFloat Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType=nullptr)

SPIRVType * getPointeeType(SPIRVType *PtrType)

Register getSPIRVTypeID(const SPIRVType *SpirvType) const

bool isScalarOfType(Register VReg, unsigned TypeOpcode) const

SPIRVType * getOrCreateOpTypeSampledImage(SPIRVType *ImageType, MachineIRBuilder &MIRBuilder)

SPIRVType * getOrCreateVulkanBufferType(MachineIRBuilder &MIRBuilder, Type *ElemType, SPIRV::StorageClass::StorageClass SC, bool IsWritable, bool EmitIr=false)

SPIRVType * getOrCreateSPIRVTypeByName(StringRef TypeStr, MachineIRBuilder &MIRBuilder, bool EmitIR, SPIRV::StorageClass::StorageClass SC=SPIRV::StorageClass::Function, SPIRV::AccessQualifier::AccessQualifier AQ=SPIRV::AccessQualifier::ReadWrite)

SPIRVType * getOrCreateLayoutType(MachineIRBuilder &MIRBuilder, const TargetExtType *T, bool EmitIr=false)

Register getOrCreateConsIntVector(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR)

const TargetRegisterClass * getRegClass(SPIRVType *SpvType) const

SPIRVType * getOrCreateSPIRVVectorType(SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder, bool EmitIR)

SPIRVType * getOrCreateOpTypeCoopMatr(MachineIRBuilder &MIRBuilder, const TargetExtType *ExtensionType, const SPIRVType *ElemType, uint32_t Scope, uint32_t Rows, uint32_t Columns, uint32_t Use, bool EmitIR)

bool isScalarOrVectorOfType(Register VReg, unsigned TypeOpcode) const

Register getOrCreateConstIntArray(uint64_t Val, size_t Num, MachineInstr &I, SPIRVType *SpvType, const SPIRVInstrInfo &TII)

SPIRVType * getOrCreateOpTypeDeviceEvent(MachineIRBuilder &MIRBuilder)

SPIRVType * getImageType(const TargetExtType *ExtensionType, const SPIRV::AccessQualifier::AccessQualifier Qualifier, MachineIRBuilder &MIRBuilder)

SPIRVType * getOrCreateSPIRVIntegerType(unsigned BitWidth, MachineIRBuilder &MIRBuilder)

Register buildConstantInt(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVType *SpvType, bool EmitIR, bool ZeroAsNull=true)

LLT getRegType(SPIRVType *SpvType) const

SPIRV::StorageClass::StorageClass getPointerStorageClass(Register VReg) const

SPIRVType * getOrCreateOpTypeSampler(MachineIRBuilder &MIRBuilder)

Register buildConstantSampler(Register Res, unsigned AddrMode, unsigned Param, unsigned FilerMode, MachineIRBuilder &MIRBuilder)

Register getOrCreateConstNullPtr(MachineIRBuilder &MIRBuilder, SPIRVType *SpvType)

unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

std::pair< StringRef, StringRef > split(char Separator) const

Split into two substrings around the first occurrence of a separator character.

static constexpr size_t npos

bool consume_back(StringRef Suffix)

Returns true if this StringRef has the given suffix and removes that suffix.

bool getAsInteger(unsigned Radix, T &Result) const

Parse the current string as an integer of the specified radix.

std::string str() const

str - Get the contents as an std::string.

constexpr StringRef substr(size_t Start, size_t N=npos) const

Return a reference to the substring from [Start, Start + N).

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

bool contains_insensitive(StringRef Other) const

Return true if the given string is a substring of *this, and false otherwise.

StringRef slice(size_t Start, size_t End) const

Return a reference to the substring from [Start, End).

constexpr size_t size() const

size - Get the string size.

bool contains(StringRef Other) const

Return true if the given string is a substring of *this, and false otherwise.

bool consume_front(StringRef Prefix)

Returns true if this StringRef has the given prefix and removes that prefix.

size_t find_first_of(char C, size_t From=0) const

Find the first character in the string that is C, or npos if not found.

size_t rfind(char C, size_t From=npos) const

Search for the last character C in the string.

size_t find(char C, size_t From=0) const

Search for the first character C in the string.

bool ends_with(StringRef Suffix) const

Check if this string ends with the given Suffix.

A switch()-like statement whose cases are string literals.

StringSwitch & EndsWith(StringLiteral S, T Value)

Class to represent struct types.

Class to represent target extensions types, which are generally unintrospectable from target-independ...

ArrayRef< Type * > type_params() const

Return the type parameters for this particular target extension type.

unsigned getNumIntParameters() const

static LLVM_ABI TargetExtType * get(LLVMContext &Context, StringRef Name, ArrayRef< Type * > Types={}, ArrayRef< unsigned > Ints={})

Return a target extension type having the specified name and optional type and integer parameters.

Type * getTypeParameter(unsigned i) const

unsigned getNumTypeParameters() const

unsigned getIntParameter(unsigned i) const

The instances of the Type class are immutable: once they are created, they are never changed.

static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)

LLVM_ABI StringRef getStructName() const

static LLVM_ABI Type * getVoidTy(LLVMContext &C)

static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)

static LLVM_ABI Type * getFloatTy(LLVMContext &C)

static LLVM_ABI Type * getHalfTy(LLVMContext &C)

bool isVoidTy() const

Return true if this is 'void'.

LLVM Value Representation.

LLVM_ABI Value(Type *Ty, unsigned scid)

static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)

This static method is the primary way to construct an VectorType.

Represents a version number in the form major[.minor[.subminor[.build]]].

NodeTy * getNextNode()

Get the next node, or nullptr for the list tail.

LLVM_C_ABI LLVMTypeRef LLVMVectorType(LLVMTypeRef ElementType, unsigned ElementCount)

Create a vector type that contains a defined type and has a specific number of elements.

std::string lookupBuiltinNameHelper(StringRef DemangledCall, FPDecorationId *DecorationId)

Parses the name part of the demangled builtin call.

Definition SPIRVBuiltins.cpp:186

Type * parseBuiltinCallArgumentType(StringRef TypeStr, LLVMContext &Ctx)

Definition SPIRVBuiltins.cpp:3137

bool parseBuiltinTypeStr(SmallVector< StringRef, 10 > &BuiltinArgsTypeStrs, const StringRef DemangledCall, LLVMContext &Ctx)

Definition SPIRVBuiltins.cpp:3181

std::optional< bool > lowerBuiltin(const StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set, MachineIRBuilder &MIRBuilder, const Register OrigRet, const Type *OrigRetTy, const SmallVectorImpl< Register > &Args, SPIRVGlobalRegistry *GR, const CallBase &CB)

Definition SPIRVBuiltins.cpp:3031

std::tuple< int, unsigned, unsigned > mapBuiltinToOpcode(const StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set)

Helper function for finding a builtin function attributes by a demangled function name.

Definition SPIRVBuiltins.cpp:2961

Type * parseBuiltinCallArgumentBaseType(const StringRef DemangledCall, unsigned ArgIdx, LLVMContext &Ctx)

Parses the provided ArgIdx argument base type in the DemangledCall skeleton.

Definition SPIRVBuiltins.cpp:3194

TargetExtType * parseBuiltinTypeNameToTargetExtType(std::string TypeName, LLVMContext &Context)

Translates a string representing a SPIR-V or OpenCL builtin type to a TargetExtType that can be furth...

Definition SPIRVBuiltins.cpp:3369

SPIRVType * lowerBuiltinType(const Type *OpaqueType, SPIRV::AccessQualifier::AccessQualifier AccessQual, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:3418

This is an optimization pass for GlobalISel generic memory operations.

void buildOpName(Register Target, const StringRef &Name, MachineIRBuilder &MIRBuilder)

static bool build2DBlockIOINTELInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Helper function for building Intel's 2d block io instructions.

Definition SPIRVBuiltins.cpp:1080

static SPIRVType * getVulkanBufferType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:3346

static bool generateExtInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, const CallBase &CB)

Definition SPIRVBuiltins.cpp:1161

static bool generateBindlessImageINTELInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2378

static bool generateGetQueryInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1916

static bool generateLoadStoreInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2923

static SPIRVType * getInlineSpirvType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:3295

static bool generateConstructInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2236

static bool buildAtomicFlagInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Helper function for building atomic flag instructions (e.g.

Definition SPIRVBuiltins.cpp:898

static bool generateImageSizeQueryInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1929

static SPIRV::SamplerFilterMode::SamplerFilterMode getSamplerFilterModeFromBitmask(unsigned Bitmask)

Definition SPIRVBuiltins.cpp:2067

static bool buildAtomicStoreInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Helper function for building an atomic store instruction.

Definition SPIRVBuiltins.cpp:696

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty

void addNumImm(const APInt &Imm, MachineInstrBuilder &MIB)

static bool buildExtendedBitOpsInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Helper function for building extended bit operations.

Definition SPIRVBuiltins.cpp:1012

static const Type * getBlockStructType(Register ParamReg, MachineRegisterInfo *MRI)

Definition SPIRVBuiltins.cpp:420

static bool generateGroupInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1228

FPDecorationId demangledPostfixToDecorationId(const std::string &S)

void updateRegType(Register Reg, Type *Ty, SPIRVType *SpirvTy, SPIRVGlobalRegistry *GR, MachineIRBuilder &MIB, MachineRegisterInfo &MRI)

Helper external function for assigning SPIRVType to a register, ensuring the register class and type ...

static unsigned getNumComponentsForDim(SPIRV::Dim::Dim dim)

Definition SPIRVBuiltins.cpp:1132

static bool generateICarryBorrowInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1867

static Register buildScopeReg(Register CLScopeRegister, SPIRV::Scope::Scope Scope, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI)

Definition SPIRVBuiltins.cpp:584

static std::tuple< Register, SPIRVType * > buildBoolRegister(MachineIRBuilder &MIRBuilder, const SPIRVType *ResultType, SPIRVGlobalRegistry *GR)

Helper function building either a resulting scalar or vector bool register depending on the expected ...

Definition SPIRVBuiltins.cpp:444

static unsigned getNumSizeComponents(SPIRVType *imgType)

Helper function for obtaining the number of size components.

Definition SPIRVBuiltins.cpp:1149

uint64_t getIConstVal(Register ConstReg, const MachineRegisterInfo *MRI)

static Register buildConstantIntReg32(uint64_t Val, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:577

static SPIRVType * getSampledImageType(const TargetExtType *OpaqueType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:3286

SmallVector< MachineInstr *, 4 > createContinuedInstructions(MachineIRBuilder &MIRBuilder, unsigned Opcode, unsigned MinWC, unsigned ContinuedOpcode, ArrayRef< Register > Args, Register ReturnRegister, Register TypeID)

SPIRV::MemorySemantics::MemorySemantics getMemSemanticsForStorageClass(SPIRV::StorageClass::StorageClass SC)

constexpr unsigned storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC)

static bool generateSampleImageInst(const StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2170

static bool generateBarrierInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1726

LLVM_ABI void SplitString(StringRef Source, SmallVectorImpl< StringRef > &OutFragments, StringRef Delimiters=" \t\n\v\f\r")

SplitString - Split up the specified string according to the specified delimiters,...

static SPIRVType * getCoopMatrType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:3269

static bool generateKernelClockInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1484

static void setRegClassIfNull(Register Reg, MachineRegisterInfo *MRI, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:602

static bool generateGroupUniformInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1440

static bool generateWaveInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1845

void buildOpDecorate(Register Reg, MachineIRBuilder &MIRBuilder, SPIRV::Decoration::Decoration Dec, const std::vector< uint32_t > &DecArgs, StringRef StrImm)

Register createVirtualRegister(SPIRVType *SpvType, SPIRVGlobalRegistry *GR, MachineRegisterInfo *MRI, const MachineFunction &MF)

MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)

static bool buildBarrierInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Helper function for building barriers, i.e., memory/control ordering operations.

Definition SPIRVBuiltins.cpp:935

static bool generateAsyncCopy(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2728

static SPIRV::Scope::Scope getSPIRVScope(SPIRV::CLMemoryScope ClScope)

Definition SPIRVBuiltins.cpp:561

static bool buildAPFixedPointInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2398

static SPIRVType * getSamplerType(MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:3252

static bool generateBlockingPipesInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2389

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

static Register buildLoadInst(SPIRVType *BaseType, Register PtrRegister, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, LLT LowLevelType, Register DestinationReg=Register(0))

Helper function for building a load instruction loading into the DestinationReg.

Definition SPIRVBuiltins.cpp:492

static bool generateEnqueueInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2688

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

static bool buildSelectInst(MachineIRBuilder &MIRBuilder, Register ReturnRegister, Register SourceRegister, const SPIRVType *ReturnType, SPIRVGlobalRegistry *GR)

Helper function for building either a vector or scalar select instruction depending on the expected R...

Definition SPIRVBuiltins.cpp:469

static const Type * getMachineInstrType(MachineInstr *MI)

Definition SPIRVBuiltins.cpp:403

bool isDigit(char C)

Checks if character C is one of the 10 decimal digits.

static SPIRV::SamplerAddressingMode::SamplerAddressingMode getSamplerAddressingModeFromBitmask(unsigned Bitmask)

Definition SPIRVBuiltins.cpp:2045

static bool generateAtomicInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1670

const MachineInstr SPIRVType

static SPIRVType * getLayoutType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:3362

static bool generateDotOrFMulInst(const StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1764

static Register buildBuiltinVariableLoad(MachineIRBuilder &MIRBuilder, SPIRVType *VariableType, SPIRVGlobalRegistry *GR, SPIRV::BuiltIn::BuiltIn BuiltinValue, LLT LLType, Register Reg=Register(0), bool isConst=true, const std::optional< SPIRV::LinkageType::LinkageType > &LinkageTy={ SPIRV::LinkageType::Import})

Helper function for building a load instruction for loading a builtin global variable of BuiltinValue...

Definition SPIRVBuiltins.cpp:507

static bool generateConvertInst(const StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2779

static bool generateTernaryBitwiseFunctionINTELInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2470

static bool generateCastToPtrInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1737

constexpr bool isGenericCastablePtr(SPIRV::StorageClass::StorageClass SC)

static Register buildMemSemanticsReg(Register SemanticsRegister, Register PtrRegister, unsigned &Semantics, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:611

static unsigned getConstFromIntrinsic(Register Reg, MachineRegisterInfo *MRI)

Definition SPIRVBuiltins.cpp:394

static bool generateImageMiscQueryInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2006

static bool generateSelectInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder)

Definition SPIRVBuiltins.cpp:2229

static bool buildAtomicLoadInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Helper function for building an atomic load instruction.

Definition SPIRVBuiltins.cpp:660

static bool generateIntelSubgroupsInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1366

static bool generateExtendedBitOpsInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2367

static bool buildPipeInst(const SPIRV::IncomingCall *Call, unsigned Opcode, unsigned Scope, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1097

static bool generateSpecConstantInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2312

static SPIRVType * getOrCreateSPIRVDeviceEventPointer(MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2594

Type * parseBasicTypeName(StringRef &TypeName, LLVMContext &Ctx)

static bool generateVectorLoadStoreInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2897

static bool genWorkgroupQuery(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR, SPIRV::BuiltIn::BuiltIn BuiltinValue, uint64_t DefaultValue)

Definition SPIRVBuiltins.cpp:1548

static bool generateCoopMatrInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2246

static bool buildBindlessImageINTELInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Helper function for building Intel's bindless image instructions.

Definition SPIRVBuiltins.cpp:1044

static std::unique_ptr< const SPIRV::IncomingCall > lookupBuiltin(StringRef DemangledCall, SPIRV::InstructionSet::InstructionSet Set, Register ReturnRegister, const SPIRVType *ReturnType, const SmallVectorImpl< Register > &Arguments)

Looks up the demangled builtin call in the SPIRVBuiltins.td records using the provided DemangledCall ...

Definition SPIRVBuiltins.cpp:275

static bool buildAtomicFloatingRMWInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Helper function for building an atomic floating-type instruction.

Definition SPIRVBuiltins.cpp:876

MachineInstr * getDefInstrMaybeConstant(Register &ConstReg, const MachineRegisterInfo *MRI)

constexpr unsigned BitWidth

OutputIt move(R &&Range, OutputIt Out)

Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.

static bool generate2DBlockIOINTELInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2481

static bool generateReadImageInst(const StringRef DemangledCall, const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2075

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

bool hasBuiltinTypePrefix(StringRef Name)

static bool buildEnqueueKernel(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2603

Type * getMDOperandAsType(const MDNode *N, unsigned I)

static bool generatePipeInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2492

static bool buildTernaryBitwiseFunctionINTELInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Helper function for building Intel's OpBitwiseFunctionINTEL instruction.

Definition SPIRVBuiltins.cpp:1062

static bool generateAPFixedPointInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2459

static bool buildAtomicRMWInst(const SPIRV::IncomingCall *Call, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Helper function for building atomic instructions.

Definition SPIRVBuiltins.cpp:820

static SPIRV::MemorySemantics::MemorySemantics getSPIRVMemSemantics(std::memory_order MemOrder)

Definition SPIRVBuiltins.cpp:544

static bool generateRelationalInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1202

static bool buildAtomicInitInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder)

Helper function for translating atomic init to OpStore.

Definition SPIRVBuiltins.cpp:646

static bool generateWriteImageInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2157

static SPIRVType * getPipeType(const TargetExtType *ExtensionType, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:3258

static Type * parseTypeString(const StringRef Name, LLVMContext &Context)

Definition SPIRVBuiltins.cpp:3227

bool isSpvIntrinsic(const MachineInstr &MI, Intrinsic::ID IntrinsicID)

static bool generatePredicatedLoadStoreInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2506

static bool generateAtomicFloatingInst(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1709

static bool buildNDRange(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:2527

static SPIRVType * getNonParameterizedType(const TargetExtType *ExtensionType, const SPIRV::BuiltinType *TypeRecord, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:3243

static MachineInstr * getBlockStructInstr(Register ParamReg, MachineRegisterInfo *MRI)

Definition SPIRVBuiltins.cpp:372

static bool buildOpFromWrapper(MachineIRBuilder &MIRBuilder, unsigned Opcode, const SPIRV::IncomingCall *Call, Register TypeReg, ArrayRef< uint32_t > ImmArgs={})

Definition SPIRVBuiltins.cpp:630

static unsigned getSamplerParamFromBitmask(unsigned Bitmask)

Definition SPIRVBuiltins.cpp:2062

static bool buildAtomicCompareExchangeInst(const SPIRV::IncomingCall *Call, const SPIRV::DemangledBuiltin *Builtin, unsigned Opcode, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Helper function for building an atomic compare-exchange instruction.

Definition SPIRVBuiltins.cpp:719

std::string getLinkStringForBuiltIn(SPIRV::BuiltIn::BuiltIn BuiltInValue)

static bool generateBuiltinVar(const SPIRV::IncomingCall *Call, MachineIRBuilder &MIRBuilder, SPIRVGlobalRegistry *GR)

Definition SPIRVBuiltins.cpp:1646

Implement std::hash so that hash_code can be used in STL containers.

This struct is a compact representation of a valid (non-zero power of two) alignment.

This class contains a discriminated union of information about pointers in memory operands,...

Definition SPIRVBuiltins.cpp:100

StringRef Name

Definition SPIRVBuiltins.cpp:101

uint32_t Opcode

Definition SPIRVBuiltins.cpp:102

Definition SPIRVBuiltins.cpp:3204

StringRef Name

Definition SPIRVBuiltins.cpp:3205

uint32_t Opcode

Definition SPIRVBuiltins.cpp:3206

Definition SPIRVBuiltins.cpp:144

bool IsSaturated

Definition SPIRVBuiltins.cpp:148

FPRoundingMode::FPRoundingMode RoundingMode

Definition SPIRVBuiltins.cpp:152

bool IsTF32

Definition SPIRVBuiltins.cpp:151

bool IsDestinationSigned

Definition SPIRVBuiltins.cpp:147

bool IsRounded

Definition SPIRVBuiltins.cpp:149

StringRef Name

Definition SPIRVBuiltins.cpp:145

bool IsBfloat16

Definition SPIRVBuiltins.cpp:150

InstructionSet::InstructionSet Set

Definition SPIRVBuiltins.cpp:146

Definition SPIRVBuiltins.cpp:32

InstructionSet::InstructionSet Set

Definition SPIRVBuiltins.cpp:34

uint8_t MaxNumArgs

Definition SPIRVBuiltins.cpp:37

uint8_t MinNumArgs

Definition SPIRVBuiltins.cpp:36

StringRef Name

Definition SPIRVBuiltins.cpp:33

BuiltinGroup Group

Definition SPIRVBuiltins.cpp:35

Definition SPIRVBuiltins.cpp:116

InstructionSet::InstructionSet Set

Definition SPIRVBuiltins.cpp:118

StringRef Name

Definition SPIRVBuiltins.cpp:117

BuiltIn::BuiltIn Value

Definition SPIRVBuiltins.cpp:119

Definition SPIRVBuiltins.cpp:70

bool IsBallotFindBit

Definition SPIRVBuiltins.cpp:80

bool IsBallot

Definition SPIRVBuiltins.cpp:77

StringRef Name

Definition SPIRVBuiltins.cpp:71

bool HasBoolArg

Definition SPIRVBuiltins.cpp:83

bool IsAllEqual

Definition SPIRVBuiltins.cpp:76

bool IsAllOrAny

Definition SPIRVBuiltins.cpp:75

bool IsBallotBitExtract

Definition SPIRVBuiltins.cpp:79

bool NoGroupOperation

Definition SPIRVBuiltins.cpp:82

bool IsInverseBallot

Definition SPIRVBuiltins.cpp:78

bool IsLogical

Definition SPIRVBuiltins.cpp:81

uint32_t Opcode

Definition SPIRVBuiltins.cpp:72

bool IsElect

Definition SPIRVBuiltins.cpp:74

uint32_t GroupOperation

Definition SPIRVBuiltins.cpp:73

Definition SPIRVBuiltins.cpp:107

uint32_t Opcode

Definition SPIRVBuiltins.cpp:109

StringRef Name

Definition SPIRVBuiltins.cpp:108

bool IsLogical

Definition SPIRVBuiltins.cpp:110

Definition SPIRVBuiltins.cpp:126

StringRef Name

Definition SPIRVBuiltins.cpp:127

uint32_t Component

Definition SPIRVBuiltins.cpp:129

InstructionSet::InstructionSet Set

Definition SPIRVBuiltins.cpp:128

Definition SPIRVBuiltins.cpp:43

const SmallVectorImpl< Register > & Arguments

Definition SPIRVBuiltins.cpp:49

bool isSpirvOp() const

Definition SPIRVBuiltins.cpp:58

const std::string BuiltinName

Definition SPIRVBuiltins.cpp:44

const SPIRVType * ReturnType

Definition SPIRVBuiltins.cpp:48

const Register ReturnRegister

Definition SPIRVBuiltins.cpp:47

const DemangledBuiltin * Builtin

Definition SPIRVBuiltins.cpp:45

IncomingCall(const std::string BuiltinName, const DemangledBuiltin *Builtin, const Register ReturnRegister, const SPIRVType *ReturnType, const SmallVectorImpl< Register > &Arguments)

Definition SPIRVBuiltins.cpp:51

Definition SPIRVBuiltins.cpp:135

uint32_t Opcode

Definition SPIRVBuiltins.cpp:137

bool IsSwapReq

Definition SPIRVBuiltins.cpp:138

StringRef Name

Definition SPIRVBuiltins.cpp:136

Definition SPIRVBuiltins.cpp:89

uint32_t Opcode

Definition SPIRVBuiltins.cpp:91

bool IsWrite

Definition SPIRVBuiltins.cpp:93

bool IsBlock

Definition SPIRVBuiltins.cpp:92

bool IsMedia

Definition SPIRVBuiltins.cpp:94

StringRef Name

Definition SPIRVBuiltins.cpp:90

Definition SPIRVBuiltins.cpp:61

StringRef Name

Definition SPIRVBuiltins.cpp:62

InstructionSet::InstructionSet Set

Definition SPIRVBuiltins.cpp:63

uint32_t Opcode

Definition SPIRVBuiltins.cpp:64

Definition SPIRVBuiltins.cpp:3212

StringRef SpirvTypeLiteral

Definition SPIRVBuiltins.cpp:3214

StringRef Name

Definition SPIRVBuiltins.cpp:3213

Definition SPIRVBuiltins.cpp:155

StringRef Name

Definition SPIRVBuiltins.cpp:156

bool IsRounded

Definition SPIRVBuiltins.cpp:160

uint32_t ElementCount

Definition SPIRVBuiltins.cpp:159

uint32_t Number

Definition SPIRVBuiltins.cpp:158

InstructionSet::InstructionSet Set

Definition SPIRVBuiltins.cpp:157

FPRoundingMode::FPRoundingMode RoundingMode

Definition SPIRVBuiltins.cpp:161