clang: lib/CodeGen/CGHLSLBuiltins.cpp Source File (original) (raw)

24 "asdouble operands types mismatch");

27

28 llvm::Type *ResultType = CGF.DoubleTy;

29 int N = 1;

31 N = VTy->getNumElements();

32 ResultType = llvm::FixedVectorType::get(CGF.DoubleTy, N);

33 }

34

36 return CGF.Builder.CreateIntrinsic(

37 ResultType, Intrinsic::dx_asdouble,

38 {OpLowBits, OpHighBits}, nullptr, "hlsl.asdouble");

39

41 OpLowBits = CGF.Builder.CreateVectorSplat(1, OpLowBits);

42 OpHighBits = CGF.Builder.CreateVectorSplat(1, OpHighBits);

43 }

44

46 for (int i = 0; i < N; i++) {

47 Mask.push_back(i);

48 Mask.push_back(i + N);

49 }

50

51 Value *BitVec = CGF.Builder.CreateShuffleVector(OpLowBits, OpHighBits, Mask);

52

53 return CGF.Builder.CreateBitCast(BitVec, ResultType);

54}

58

59 Constant *FZeroConst = ConstantFP::getZero(CGF->FloatTy);

62

64 FZeroConst = ConstantVector::getSplat(

65 ElementCount::getFixed(VecTy->getNumElements()), FZeroConst);

66 auto *FCompInst = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst);

67 CMP = CGF->Builder.CreateIntrinsic(

69 {FCompInst});

70 } else {

71 CMP = CGF->Builder.CreateFCmpOLT(Op0, FZeroConst);

72 }

73

75 LastInstr = CGF->Builder.CreateIntrinsic(Intrinsic::dx_discard, {CMP});

79

80 CGF->Builder.CreateCondBr(CMP, LT0, End);

81

82 CGF->Builder.SetInsertPoint(LT0);

83

84 CGF->Builder.CreateIntrinsic(Intrinsic::spv_discard, {});

85

86 LastInstr = CGF->Builder.CreateBr(End);

87 CGF->Builder.SetInsertPoint(End);

88 } else {

89 llvm_unreachable("Backend Codegen not supported.");

90 }

91

92 return LastInstr;

93}

97 const auto *OutArg1 = dyn_cast(E->getArg(1));

98 const auto *OutArg2 = dyn_cast(E->getArg(2));

99

101 LValue Op1TmpLValue =

103 LValue Op2TmpLValue =

105

108

109 Value *LowBits = nullptr;

110 Value *HighBits = nullptr;

111

113 llvm::Type *RetElementTy = CGF->Int32Ty;

115 RetElementTy = llvm::VectorType::get(

116 CGF->Int32Ty, ElementCount::getFixed(Op0VecTy->getNumElements()));

117 auto *RetTy = llvm::StructType::get(RetElementTy, RetElementTy);

118

119 CallInst *CI = CGF->Builder.CreateIntrinsic(

120 RetTy, Intrinsic::dx_splitdouble, {Op0}, nullptr, "hlsl.splitdouble");

121

122 LowBits = CGF->Builder.CreateExtractValue(CI, 0);

123 HighBits = CGF->Builder.CreateExtractValue(CI, 1);

124 } else {

125

126

127 if (!Op0->getType()->isVectorTy()) {

128 FixedVectorType *DestTy = FixedVectorType::get(CGF->Int32Ty, 2);

129 Value *Bitcast = CGF->Builder.CreateBitCast(Op0, DestTy);

130

131 LowBits = CGF->Builder.CreateExtractElement(Bitcast, (uint64_t)0);

132 HighBits = CGF->Builder.CreateExtractElement(Bitcast, 1);

133 } else {

134 int NumElements = 1;

135 if (const auto *VecTy =

137 NumElements = VecTy->getNumElements();

138

139 FixedVectorType *Uint32VecTy =

140 FixedVectorType::get(CGF->Int32Ty, NumElements * 2);

141 Value *Uint32Vec = CGF->Builder.CreateBitCast(Op0, Uint32VecTy);

142 if (NumElements == 1) {

143 LowBits = CGF->Builder.CreateExtractElement(Uint32Vec, (uint64_t)0);

144 HighBits = CGF->Builder.CreateExtractElement(Uint32Vec, 1);

145 } else {

147 for (int I = 0, E = NumElements; I != E; ++I) {

148 EvenMask.push_back(I * 2);

149 OddMask.push_back(I * 2 + 1);

150 }

151 LowBits = CGF->Builder.CreateShuffleVector(Uint32Vec, EvenMask);

152 HighBits = CGF->Builder.CreateShuffleVector(Uint32Vec, OddMask);

153 }

154 }

155 }

157 auto *LastInst =

160 return LastInst;

161}

167 llvm::Type *ResType = CGF.FloatTy;

168 uint64_t NumElements = 0;

169 if (Op0->getType()->isVectorTy()) {

170 NumElements =

172 ResType =

173 llvm::VectorType::get(ResType, ElementCount::getFixed(NumElements));

174 }

176 llvm_unreachable(

177 "f16tof32 operand must have an unsigned int representation");

178

180 return CGF.Builder.CreateIntrinsic(ResType, Intrinsic::dx_legacyf16tof32,

182 "hlsl.f16tof32");

183

185

186

187 auto UnpackType =

188 llvm::VectorType::get(CGF.FloatTy, ElementCount::getFixed(2));

189 if (NumElements == 0) {

190

191

193 UnpackType, Intrinsic::spv_unpackhalf2x16, ArrayRef<Value *>{Op0});

194 return CGF.Builder.CreateExtractElement(Unpack, (uint64_t)0);

195 } else {

196

197

198 Value *Result = PoisonValue::get(ResType);

199 for (uint64_t i = 0; i < NumElements; i++) {

200 Value *InVal = CGF.Builder.CreateExtractElement(Op0, i);

202 UnpackType, Intrinsic::spv_unpackhalf2x16,

204 Value *Res = CGF.Builder.CreateExtractElement(Unpack, (uint64_t)0);

205 Result = CGF.Builder.CreateInsertElement(Result, Res, i);

206 }

207 return Result;

208 }

209 }

210

211 llvm_unreachable("Intrinsic F16ToF32 not supported by target architecture");

212}

215 LValue &Stride) {

216

217 auto *HandleTy =

219 QualType ElementTy = HandleTy->getContainedType();

222}

227 return RT.getFDotIntrinsic();

229 return RT.getSDotIntrinsic();

231 return RT.getUDotIntrinsic();

232}

236 return RT.getFirstBitSHighIntrinsic();

237 }

238

240 return RT.getFirstBitUHighIntrinsic();

241}

246 switch (Arch) {

247 case llvm::Triple::spirv:

248 return Intrinsic::spv_wave_reduce_sum;

249 case llvm::Triple::dxil: {

251 return Intrinsic::dx_wave_reduce_usum;

252 return Intrinsic::dx_wave_reduce_sum;

253 }

254 default:

255 llvm_unreachable("Intrinsic WaveActiveSum"

256 " not supported by target architecture");

257 }

258}

263 switch (Arch) {

264 case llvm::Triple::spirv:

266 return Intrinsic::spv_wave_reduce_umax;

267 return Intrinsic::spv_wave_reduce_max;

268 case llvm::Triple::dxil: {

270 return Intrinsic::dx_wave_reduce_umax;

271 return Intrinsic::dx_wave_reduce_max;

272 }

273 default:

274 llvm_unreachable("Intrinsic WaveActiveMax"

275 " not supported by target architecture");

276 }

277}

282 switch (Arch) {

283 case llvm::Triple::spirv:

285 return Intrinsic::spv_wave_reduce_umin;

286 return Intrinsic::spv_wave_reduce_min;

287 case llvm::Triple::dxil: {

289 return Intrinsic::dx_wave_reduce_umin;

290 return Intrinsic::dx_wave_reduce_min;

291 }

292 default:

293 llvm_unreachable("Intrinsic WaveActiveMin"

294 " not supported by target architecture");

295 }

296}

302

303 QualType ClangParamTypes[] = {Context.IntTy, SpecConstantType};

304

305

306

309 Context.getFunctionType(SpecConstantType, ClangParamTypes, EPI);

310 DeclarationName FuncName = &Context.Idents.get("__spirv_SpecConstant");

312 Context, Context.getTranslationUnitDecl(), SourceLocation(),

314

315

317 for (QualType ParamType : ClangParamTypes) {

320 nullptr, ParamType, nullptr, SC_None,

321 nullptr);

322 ParamDecls.push_back(PD);

323 }

324 FnDeclForMangling->setParams(ParamDecls);

325

326

327 std::string Name;

328 llvm::raw_string_ostream MangledNameStream(Name);

329 std::unique_ptr Mangler(Context.createMangleContext());

330 Mangler->mangleName(FnDeclForMangling, MangledNameStream);

331 MangledNameStream.flush();

332

333 return Name;

334}

340 return nullptr;

341

342 switch (BuiltinID) {

343 case Builtin::BI__builtin_hlsl_adduint64: {

347 uint64_t NumElements = Arg0Ty->castAs<VectorType>()->getNumElements();

349 "AddUint64 operand types must match");

351 "AddUint64 operands must have an integer representation");

352 assert((NumElements == 2 || NumElements == 4) &&

353 "AddUint64 operands must have 2 or 4 elements");

354

355 llvm::Value *LowA;

356 llvm::Value *HighA;

357 llvm::Value *LowB;

358 llvm::Value *HighB;

359

360

361 if (NumElements == 2) {

362 LowA = Builder.CreateExtractElement(OpA, (uint64_t)0, "LowA");

363 HighA = Builder.CreateExtractElement(OpA, (uint64_t)1, "HighA");

364 LowB = Builder.CreateExtractElement(OpB, (uint64_t)0, "LowB");

365 HighB = Builder.CreateExtractElement(OpB, (uint64_t)1, "HighB");

366 } else {

367 LowA = Builder.CreateShuffleVector(OpA, {0, 2}, "LowA");

368 HighA = Builder.CreateShuffleVector(OpA, {1, 3}, "HighA");

369 LowB = Builder.CreateShuffleVector(OpB, {0, 2}, "LowB");

370 HighB = Builder.CreateShuffleVector(OpB, {1, 3}, "HighB");

371 }

372

373

374

375 llvm::Value *Carry;

377 *this, Intrinsic::uadd_with_overflow, LowA, LowB, Carry);

378 llvm::Value *ZExtCarry =

379 Builder.CreateZExt(Carry, HighA->getType(), "CarryZExt");

380

381

382 llvm::Value *HighSum = Builder.CreateAdd(HighA, HighB, "HighSum");

383 llvm::Value *HighSumPlusCarry =

384 Builder.CreateAdd(HighSum, ZExtCarry, "HighSumPlusCarry");

385

386 if (NumElements == 4) {

387 return Builder.CreateShuffleVector(LowSum, HighSumPlusCarry, {0, 2, 1, 3},

388 "hlsl.AddUint64");

389 }

390

391 llvm::Value *Result = PoisonValue::get(OpA->getType());

393 "hlsl.AddUint64.upto0");

394 Result = Builder.CreateInsertElement(Result, HighSumPlusCarry, (uint64_t)1,

395 "hlsl.AddUint64");

397 }

398 case Builtin::BI__builtin_hlsl_resource_getpointer: {

401

403 return Builder.CreateIntrinsic(

404 RetTy, CGM.getHLSLRuntime().getCreateResourceGetPointerIntrinsic(),

406 }

407 case Builtin::BI__builtin_hlsl_resource_load_with_status: {

410

411

414

416 const HLSLAttributedResourceType *RT =

417 HandleTy->getAs();

418 assert(CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil &&

419 "Only DXIL currently implements load with status");

420

421 Intrinsic::ID IntrID = RT->getAttrs().RawBuffer

422 ? llvm::Intrinsic::dx_resource_load_rawbuffer

423 : llvm::Intrinsic::dx_resource_load_typedbuffer;

424

426 llvm::Type *RetTy = llvm::StructType::get(Builder.getContext(),

427 {DataTy, Builder.getInt1Ty()});

428

430 Args.push_back(HandleOp);

431 Args.push_back(IndexOp);

432

433 if (RT->getAttrs().RawBuffer) {

435 Args.push_back(Offset);

436 }

437

438

439

441 Builder.CreateIntrinsic(RetTy, IntrID, Args, {}, "ld.struct");

442 Value *LoadedValue = Builder.CreateExtractValue(ResRet, {0}, "ld.value");

443 Value *StatusBit = Builder.CreateExtractValue(ResRet, {1}, "ld.status");

444 Value *ExtendedStatus =

445 Builder.CreateZExt(StatusBit, Builder.getInt32Ty(), "ld.status.ext");

446 Builder.CreateStore(ExtendedStatus, StatusAddr);

447

448 return LoadedValue;

449 }

450 case Builtin::BI__builtin_hlsl_resource_uninitializedhandle: {

451 llvm::Type *HandleTy = CGM.getTypes().ConvertType(E->getType());

452 return llvm::PoisonValue::get(HandleTy);

453 }

454 case Builtin::BI__builtin_hlsl_resource_handlefrombinding: {

455 llvm::Type *HandleTy = CGM.getTypes().ConvertType(E->getType());

461 llvm::Intrinsic::ID IntrinsicID =

462 CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic();

464 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);

465 }

466 case Builtin::BI__builtin_hlsl_resource_handlefromimplicitbinding: {

467 llvm::Type *HandleTy = CGM.getTypes().ConvertType(E->getType());

473 llvm::Intrinsic::ID IntrinsicID =

474 CGM.getHLSLRuntime().getCreateHandleFromImplicitBindingIntrinsic();

476 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);

477 }

478 case Builtin::BI__builtin_hlsl_resource_counterhandlefromimplicitbinding: {

480 if (CGM.getTriple().isSPIRV())

481 return MainHandle;

482

483 llvm::Type *HandleTy = CGM.getTypes().ConvertType(E->getType());

486 llvm::Intrinsic::ID IntrinsicID =

487 llvm::Intrinsic::spv_resource_counterhandlefromimplicitbinding;

489 return Builder.CreateIntrinsic(HandleTy, IntrinsicID, Args);

490 }

491 case Builtin::BI__builtin_hlsl_resource_nonuniformindex: {

494 return Builder.CreateIntrinsic(

495 RetTy, CGM.getHLSLRuntime().getNonUniformResourceIndexIntrinsic(),

497 }

498 case Builtin::BI__builtin_hlsl_resource_getdimensions_x: {

501 llvm::Type *RetTy = llvm::Type::getInt32Ty(getLLVMContext());

503 RetTy, CGM.getHLSLRuntime().getGetDimensionsXIntrinsic(),

505 return Builder.CreateStore(DimValue, Dim.getAddress());

506 }

507 case Builtin::BI__builtin_hlsl_resource_getstride: {

510 }

511 case Builtin::BI__builtin_hlsl_all: {

513 return Builder.CreateIntrinsic(

514 llvm::Type::getInt1Ty(getLLVMContext()),

516 "hlsl.all");

517 }

518 case Builtin::BI__builtin_hlsl_and: {

521 return Builder.CreateAnd(Op0, Op1, "hlsl.and");

522 }

523 case Builtin::BI__builtin_hlsl_or: {

526 return Builder.CreateOr(Op0, Op1, "hlsl.or");

527 }

528 case Builtin::BI__builtin_hlsl_any: {

530 return Builder.CreateIntrinsic(

531 llvm::Type::getInt1Ty(getLLVMContext()),

533 "hlsl.any");

534 }

535 case Builtin::BI__builtin_hlsl_asdouble:

537 case Builtin::BI__builtin_hlsl_elementwise_clamp: {

541

544 Ty = VecTy->getElementType();

545

546 Intrinsic::ID Intr;

548 Intr = CGM.getHLSLRuntime().getNClampIntrinsic();

550 Intr = CGM.getHLSLRuntime().getUClampIntrinsic();

551 } else {

553 Intr = CGM.getHLSLRuntime().getSClampIntrinsic();

554 }

555 return Builder.CreateIntrinsic(

556 OpX->getType(), Intr,

558 }

559 case Builtin::BI__builtin_hlsl_crossf16:

560 case Builtin::BI__builtin_hlsl_crossf32: {

565 "cross operands must have a float representation");

566

567 assert(

570 "input vectors must have 3 elements each");

571 return Builder.CreateIntrinsic(

572 Op0->getType(), CGM.getHLSLRuntime().getCrossIntrinsic(),

574 }

575 case Builtin::BI__builtin_hlsl_dot: {

578 llvm::Type *T0 = Op0->getType();

579 llvm::Type *T1 = Op1->getType();

580

581

582 if (!T0->isVectorTy() && !T1->isVectorTy()) {

583 if (T0->isFloatingPointTy())

584 return Builder.CreateFMul(Op0, Op1, "hlsl.dot");

585

586 if (T0->isIntegerTy())

587 return Builder.CreateMul(Op0, Op1, "hlsl.dot");

588

589 llvm_unreachable(

590 "Scalar dot product is only supported on ints and floats.");

591 }

592

593 assert(CGM.getContext().hasSameUnqualifiedType(E->getArg(0)->getType(),

595 "Dot product operands must have the same type.");

596

598 assert(VecTy0 && "Dot product argument must be a vector.");

599

600 return Builder.CreateIntrinsic(

601 T0->getScalarType(),

604 }

605 case Builtin::BI__builtin_hlsl_dot4add_i8packed: {

609

610 Intrinsic::ID ID = CGM.getHLSLRuntime().getDot4AddI8PackedIntrinsic();

611

612

613 return Builder.CreateIntrinsic(

615 nullptr, "hlsl.dot4add.i8packed");

616 }

617 case Builtin::BI__builtin_hlsl_dot4add_u8packed: {

621

622 Intrinsic::ID ID = CGM.getHLSLRuntime().getDot4AddU8PackedIntrinsic();

623

624

625 return Builder.CreateIntrinsic(

627 nullptr, "hlsl.dot4add.u8packed");

628 }

629 case Builtin::BI__builtin_hlsl_elementwise_firstbithigh: {

631

632 return Builder.CreateIntrinsic(

636 }

637 case Builtin::BI__builtin_hlsl_elementwise_firstbitlow: {

639

640 return Builder.CreateIntrinsic(

643 nullptr, "hlsl.firstbitlow");

644 }

645 case Builtin::BI__builtin_hlsl_lerp: {

650 llvm_unreachable("lerp operand must have a float representation");

651 return Builder.CreateIntrinsic(

652 X->getType(), CGM.getHLSLRuntime().getLerpIntrinsic(),

654 }

655 case Builtin::BI__builtin_hlsl_normalize: {

657

659 "normalize operand must have a float representation");

660

661 return Builder.CreateIntrinsic(

662 X->getType(),

664 nullptr, "hlsl.normalize");

665 }

666 case Builtin::BI__builtin_hlsl_elementwise_degrees: {

668

670 "degree operand must have a float representation");

671

672 return Builder.CreateIntrinsic(

673 X->getType(), CGM.getHLSLRuntime().getDegreesIntrinsic(),

675 }

676 case Builtin::BI__builtin_hlsl_elementwise_f16tof32: {

678 }

679 case Builtin::BI__builtin_hlsl_elementwise_frac: {

682 llvm_unreachable("frac operand must have a float representation");

683 return Builder.CreateIntrinsic(

684 Op0->getType(), CGM.getHLSLRuntime().getFracIntrinsic(),

686 }

687 case Builtin::BI__builtin_hlsl_elementwise_isinf: {

689 llvm::Type *Xty = Op0->getType();

690 llvm::Type *retType = llvm::Type::getInt1Ty(this->getLLVMContext());

691 if (Xty->isVectorTy()) {

693 retType = llvm::VectorType::get(

694 retType, ElementCount::getFixed(XVecTy->getNumElements()));

695 }

697 llvm_unreachable("isinf operand must have a float representation");

698 return Builder.CreateIntrinsic(

699 retType, CGM.getHLSLRuntime().getIsInfIntrinsic(),

701 }

702 case Builtin::BI__builtin_hlsl_elementwise_isnan: {

704 llvm::Type *Xty = Op0->getType();

705 llvm::Type *retType = llvm::Type::getInt1Ty(this->getLLVMContext());

706 if (Xty->isVectorTy()) {

708 retType = llvm::VectorType::get(

709 retType, ElementCount::getFixed(XVecTy->getNumElements()));

710 }

712 llvm_unreachable("isnan operand must have a float representation");

713 return Builder.CreateIntrinsic(

714 retType, CGM.getHLSLRuntime().getIsNaNIntrinsic(),

716 }

717 case Builtin::BI__builtin_hlsl_mad: {

722 return Builder.CreateIntrinsic(

723 M->getType(), Intrinsic::fmuladd,

725

727 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)

728 return Builder.CreateIntrinsic(

729 M->getType(), Intrinsic::dx_imad,

731

733 return Builder.CreateNSWAdd(Mul, B);

734 }

736 if (CGM.getTarget().getTriple().getArch() == llvm::Triple::dxil)

737 return Builder.CreateIntrinsic(

738 M->getType(), Intrinsic::dx_umad,

740

742 return Builder.CreateNUWAdd(Mul, B);

743 }

744 case Builtin::BI__builtin_hlsl_elementwise_rcp: {

747 llvm_unreachable("rcp operand must have a float representation");

748 llvm::Type *Ty = Op0->getType();

749 llvm::Type *EltTy = Ty->getScalarType();

750 Constant *One = Ty->isVectorTy()

751 ? ConstantVector::getSplat(

752 ElementCount::getFixed(

754 ConstantFP::get(EltTy, 1.0))

755 : ConstantFP::get(EltTy, 1.0);

756 return Builder.CreateFDiv(One, Op0, "hlsl.rcp");

757 }

758 case Builtin::BI__builtin_hlsl_elementwise_rsqrt: {

761 llvm_unreachable("rsqrt operand must have a float representation");

762 return Builder.CreateIntrinsic(

763 Op0->getType(), CGM.getHLSLRuntime().getRsqrtIntrinsic(),

765 }

766 case Builtin::BI__builtin_hlsl_elementwise_saturate: {

769 "saturate operand must have a float representation");

770 return Builder.CreateIntrinsic(

771 Op0->getType(),

773 nullptr, "hlsl.saturate");

774 }

775 case Builtin::BI__builtin_hlsl_select: {

788 if (!OpTrue->getType()->isVectorTy())

789 OpTrue =

790 Builder.CreateVectorSplat(VTy->getNumElements(), OpTrue, "splat");

791 if (!OpFalse->getType()->isVectorTy())

792 OpFalse =

793 Builder.CreateVectorSplat(VTy->getNumElements(), OpFalse, "splat");

794 }

795

796 Value *SelectVal =

797 Builder.CreateSelect(OpCond, OpTrue, OpFalse, "hlsl.select");

801

802 return SelectVal;

803 }

804 case Builtin::BI__builtin_hlsl_step: {

809 "step operands must have a float representation");

810 return Builder.CreateIntrinsic(

811 Op0->getType(), CGM.getHLSLRuntime().getStepIntrinsic(),

813 }

814 case Builtin::BI__builtin_hlsl_wave_active_all_true: {

816 assert(Op->getType()->isIntegerTy(1) &&

817 "Intrinsic WaveActiveAllTrue operand must be a bool");

818

819 Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveActiveAllTrueIntrinsic();

821 Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID), {Op});

822 }

823 case Builtin::BI__builtin_hlsl_wave_active_any_true: {

825 assert(Op->getType()->isIntegerTy(1) &&

826 "Intrinsic WaveActiveAnyTrue operand must be a bool");

827

828 Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveActiveAnyTrueIntrinsic();

830 Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID), {Op});

831 }

832 case Builtin::BI__builtin_hlsl_wave_active_count_bits: {

834 Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveActiveCountBitsIntrinsic();

836 Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID),

838 }

839 case Builtin::BI__builtin_hlsl_wave_active_sum: {

840

843 getTarget().getTriple().getArch(), CGM.getHLSLRuntime(),

845

846 return EmitRuntimeCall(Intrinsic::getOrInsertDeclaration(

847 &CGM.getModule(), IID, {OpExpr->getType()}),

848 ArrayRef{OpExpr}, "hlsl.wave.active.sum");

849 }

850 case Builtin::BI__builtin_hlsl_wave_active_max: {

851

854 getTarget().getTriple().getArch(), CGM.getHLSLRuntime(),

856

857 return EmitRuntimeCall(Intrinsic::getOrInsertDeclaration(

858 &CGM.getModule(), IID, {OpExpr->getType()}),

859 ArrayRef{OpExpr}, "hlsl.wave.active.max");

860 }

861 case Builtin::BI__builtin_hlsl_wave_active_min: {

862

865 getTarget().getTriple().getArch(), CGM.getHLSLRuntime(),

867

868 return EmitRuntimeCall(Intrinsic::getOrInsertDeclaration(

869 &CGM.getModule(), IID, {OpExpr->getType()}),

870 ArrayRef{OpExpr}, "hlsl.wave.active.min");

871 }

872 case Builtin::BI__builtin_hlsl_wave_get_lane_index: {

873

874

875

876 switch (CGM.getTarget().getTriple().getArch()) {

877 case llvm::Triple::dxil:

878 return EmitRuntimeCall(Intrinsic::getOrInsertDeclaration(

879 &CGM.getModule(), Intrinsic::dx_wave_getlaneindex));

880 case llvm::Triple::spirv:

882 llvm::FunctionType::get(IntTy, {}, false),

883 "__hlsl_wave_get_lane_index", {}, false, true));

884 default:

885 llvm_unreachable(

886 "Intrinsic WaveGetLaneIndex not supported by target architecture");

887 }

888 }

889 case Builtin::BI__builtin_hlsl_wave_is_first_lane: {

890 Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveIsFirstLaneIntrinsic();

892 Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID));

893 }

894 case Builtin::BI__builtin_hlsl_wave_get_lane_count: {

895 Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveGetLaneCountIntrinsic();

897 Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID));

898 }

899 case Builtin::BI__builtin_hlsl_wave_read_lane_at: {

900

901

905 Intrinsic::getOrInsertDeclaration(

906 &CGM.getModule(), CGM.getHLSLRuntime().getWaveReadLaneAtIntrinsic(),

907 {OpExpr->getType()}),

908 ArrayRef{OpExpr, OpIndex}, "hlsl.wave.readlane");

909 }

910 case Builtin::BI__builtin_hlsl_elementwise_sign: {

911 auto *Arg0 = E->getArg(0);

913 llvm::Type *Xty = Op0->getType();

914 llvm::Type *retType = llvm::Type::getInt32Ty(this->getLLVMContext());

915 if (Xty->isVectorTy()) {

916 auto *XVecTy = Arg0->getType()->castAs<VectorType>();

917 retType = llvm::VectorType::get(

918 retType, ElementCount::getFixed(XVecTy->getNumElements()));

919 }

920 assert((Arg0->getType()->hasFloatingRepresentation() ||

921 Arg0->getType()->hasIntegerRepresentation()) &&

922 "sign operand must have a float or int representation");

923

924 if (Arg0->getType()->hasUnsignedIntegerRepresentation()) {

925 Value *Cmp = Builder.CreateICmpEQ(Op0, ConstantInt::get(Xty, 0));

926 return Builder.CreateSelect(Cmp, ConstantInt::get(retType, 0),

927 ConstantInt::get(retType, 1), "hlsl.sign");

928 }

929

930 return Builder.CreateIntrinsic(

931 retType, CGM.getHLSLRuntime().getSignIntrinsic(),

933 }

934 case Builtin::BI__builtin_hlsl_elementwise_radians: {

937 "radians operand must have a float representation");

938 return Builder.CreateIntrinsic(

939 Op0->getType(),

941 nullptr, "hlsl.radians");

942 }

943 case Builtin::BI__builtin_hlsl_buffer_update_counter: {

947 return Builder.CreateIntrinsic(

948 Offset->getType(),

949 CGM.getHLSLRuntime().getBufferUpdateCounterIntrinsic(),

951 }

952 case Builtin::BI__builtin_hlsl_elementwise_splitdouble: {

953

957 "asuint operands types mismatch");

959 }

960 case Builtin::BI__builtin_hlsl_elementwise_clip:

962 "clip operands types mismatch");

964 case Builtin::BI__builtin_hlsl_group_memory_barrier_with_group_sync: {

965 Intrinsic::ID ID =

966 CGM.getHLSLRuntime().getGroupMemoryBarrierWithGroupSyncIntrinsic();

968 Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID));

969 }

970 case Builtin::BI__builtin_hlsl_elementwise_ddx_coarse: {

973 llvm_unreachable("ddx_coarse operand must have a float representation");

974 Intrinsic::ID ID = CGM.getHLSLRuntime().getDdxCoarseIntrinsic();

975 return Builder.CreateIntrinsic(Op0->getType(), ID,

977 "hlsl.ddx.coarse");

978 }

979 case Builtin::BI__builtin_hlsl_elementwise_ddy_coarse: {

982 llvm_unreachable("ddy_coarse operand must have a float representation");

983 Intrinsic::ID ID = CGM.getHLSLRuntime().getDdyCoarseIntrinsic();

984 return Builder.CreateIntrinsic(Op0->getType(), ID,

986 "hlsl.ddy.coarse");

987 }

988 case Builtin::BI__builtin_hlsl_elementwise_ddx_fine: {

991 llvm_unreachable("ddx_fine operand must have a float representation");

992 Intrinsic::ID ID = CGM.getHLSLRuntime().getDdxFineIntrinsic();

993 return Builder.CreateIntrinsic(Op0->getType(), ID,

995 "hlsl.ddx.fine");

996 }

997 case Builtin::BI__builtin_hlsl_elementwise_ddy_fine: {

1000 llvm_unreachable("ddy_fine operand must have a float representation");

1001 Intrinsic::ID ID = CGM.getHLSLRuntime().getDdyFineIntrinsic();

1002 return Builder.CreateIntrinsic(Op0->getType(), ID,

1004 "hlsl.ddy.fine");

1005 }

1006 case Builtin::BI__builtin_get_spirv_spec_constant_bool:

1007 case Builtin::BI__builtin_get_spirv_spec_constant_short:

1008 case Builtin::BI__builtin_get_spirv_spec_constant_ushort:

1009 case Builtin::BI__builtin_get_spirv_spec_constant_int:

1010 case Builtin::BI__builtin_get_spirv_spec_constant_uint:

1011 case Builtin::BI__builtin_get_spirv_spec_constant_longlong:

1012 case Builtin::BI__builtin_get_spirv_spec_constant_ulonglong:

1013 case Builtin::BI__builtin_get_spirv_spec_constant_half:

1014 case Builtin::BI__builtin_get_spirv_spec_constant_float:

1015 case Builtin::BI__builtin_get_spirv_spec_constant_double: {

1019 llvm::Value *Args[] = {SpecId, DefaultVal};

1020 return Builder.CreateCall(SpecConstantFn, Args);

1021 }

1022 }

1023 return nullptr;

1024}

1028

1029

1030 llvm::Module *M = &CGM.getModule();

1031 std::string MangledName =

1033 llvm::Function *SpecConstantFn = M->getFunction(MangledName);

1034

1035 if (!SpecConstantFn) {

1037 llvm::Type *RetTy = ConvertType(SpecConstantType);

1038 llvm::Type *ArgTypes[] = {IntType, RetTy};

1039 llvm::FunctionType *FnTy = llvm::FunctionType::get(RetTy, ArgTypes, false);

1040 SpecConstantFn = llvm::Function::Create(

1041 FnTy, llvm::GlobalValue::ExternalLinkage, MangledName, M);

1042 }

1043 return SpecConstantFn;

1044}