LLVM: lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

21#include "llvm/IR/IntrinsicsAMDGPU.h"

23#include

24

25using namespace llvm;

27

28#define DEBUG_TYPE "AMDGPUtti"

29

30namespace {

31

32struct AMDGPUImageDMaskIntrinsic {

33 unsigned Intr;

34};

35

36#define GET_AMDGPUImageDMaskIntrinsicTable_IMPL

37#include "InstCombineTables.inc"

38

39}

40

41

42

43

44

48

50 assert(Cmp0 != APFloat::cmpUnordered && "nans handled separately");

51 if (Cmp0 == APFloat::cmpEqual)

52 return maxnum(Src1, Src2);

53

55 assert(Cmp1 != APFloat::cmpUnordered && "nans handled separately");

56 if (Cmp1 == APFloat::cmpEqual)

57 return maxnum(Src0, Src2);

58

59 return maxnum(Src0, Src1);

60}

61

62

63

64

65

67 Type *VTy = V.getType();

69

70 return false;

71 }

72 if (IsFloat) {

73 if (ConstantFP *ConstFloat = dyn_cast(&V)) {

74

75

76 APFloat FloatValue(ConstFloat->getValueAPF());

77 bool LosesInfo = true;

78 FloatValue.convert(APFloat::IEEEhalf(), APFloat::rmTowardZero,

79 &LosesInfo);

80 return !LosesInfo;

81 }

82 } else {

83 if (ConstantInt *ConstInt = dyn_cast(&V)) {

84

85

86 APInt IntValue(ConstInt->getValue());

88 }

89 }

90

94 if (IsExt) {

97 return true;

98 }

99

100 return false;

101}

102

103

105 Type *VTy = V.getType();

106 if (isa(&V) || isa(&V) || isa(&V))

107 return cast(&V)->getOperand(0);

112

114}

115

116

117

118

123 Func) {

126 return std::nullopt;

127

129

130

131 Func(Args, ArgTys);

132

136 if (isa(NewCall))

138

139

142

143 bool RemoveOldIntr = &OldIntr != &InstToReplace;

144

146 if (RemoveOldIntr)

148

149 return RetValue;

150}

151

152static std::optional<Instruction *>

156

157 if (const auto *LZMappingInfo =

159 if (auto *ConstantLod =

160 dyn_cast(II.getOperand(ImageDimIntr->LodIndex))) {

161 if (ConstantLod->isZero() || ConstantLod->isNegative()) {

164 ImageDimIntr->Dim);

166 II, II, NewImageDimIntr->Intr, IC, [&](auto &Args, auto &ArgTys) {

167 Args.erase(Args.begin() + ImageDimIntr->LodIndex);

168 });

169 }

170 }

171 }

172

173

174 if (const auto *MIPMappingInfo =

176 if (auto *ConstantMip =

177 dyn_cast(II.getOperand(ImageDimIntr->MipIndex))) {

178 if (ConstantMip->isZero()) {

181 ImageDimIntr->Dim);

183 II, II, NewImageDimIntr->Intr, IC, [&](auto &Args, auto &ArgTys) {

184 Args.erase(Args.begin() + ImageDimIntr->MipIndex);

185 });

186 }

187 }

188 }

189

190

191 if (const auto *BiasMappingInfo =

193 if (auto *ConstantBias =

194 dyn_cast(II.getOperand(ImageDimIntr->BiasIndex))) {

195 if (ConstantBias->isZero()) {

198 ImageDimIntr->Dim);

200 II, II, NewImageDimIntr->Intr, IC, [&](auto &Args, auto &ArgTys) {

201 Args.erase(Args.begin() + ImageDimIntr->BiasIndex);

202 ArgTys.erase(ArgTys.begin() + ImageDimIntr->BiasTyArg);

203 });

204 }

205 }

206 }

207

208

209 if (const auto *OffsetMappingInfo =

211 if (auto *ConstantOffset =

212 dyn_cast(II.getOperand(ImageDimIntr->OffsetIndex))) {

213 if (ConstantOffset->isZero()) {

216 OffsetMappingInfo->NoOffset, ImageDimIntr->Dim);

218 II, II, NewImageDimIntr->Intr, IC, [&](auto &Args, auto &ArgTys) {

219 Args.erase(Args.begin() + ImageDimIntr->OffsetIndex);

220 });

221 }

222 }

223 }

224

225

226 if (ST->hasD16Images()) {

227

230

231 if (BaseOpcode->HasD16) {

232

233

234

235

236 if (II.hasOneUse()) {

238

239 if (User->getOpcode() == Instruction::FPTrunc &&

241

243 [&](auto &Args, auto &ArgTys) {

244

245

246 ArgTys[0] = User->getType();

247 });

248 }

249 }

250 }

251 }

252

253

254 if (!ST->hasA16() && !ST->hasG16())

255 return std::nullopt;

256

257

258

259 bool HasSampler =

261 bool FloatCoord = false;

262

263 bool OnlyDerivatives = false;

264

265 for (unsigned OperandIndex = ImageDimIntr->GradientStart;

266 OperandIndex < ImageDimIntr->VAddrEnd; OperandIndex++) {

267 Value *Coord = II.getOperand(OperandIndex);

268

270 if (OperandIndex < ImageDimIntr->CoordStart ||

272 return std::nullopt;

273 }

274

275 OnlyDerivatives = true;

276 break;

277 }

278

282 }

283

284 if (!OnlyDerivatives && !ST->hasA16())

285 OnlyDerivatives = true;

286

287

288 if (!OnlyDerivatives && ImageDimIntr->NumBiasArgs != 0) {

291 "Only image instructions with a sampler can have a bias");

293 OnlyDerivatives = true;

294 }

295

296 if (OnlyDerivatives && (!ST->hasG16() || ImageDimIntr->GradientStart ==

298 return std::nullopt;

299

302

304 II, II, II.getIntrinsicID(), IC, [&](auto &Args, auto &ArgTys) {

305 ArgTys[ImageDimIntr->GradientTyArg] = CoordType;

306 if (!OnlyDerivatives) {

307 ArgTys[ImageDimIntr->CoordTyArg] = CoordType;

308

309

310 if (ImageDimIntr->NumBiasArgs != 0)

311 ArgTys[ImageDimIntr->BiasTyArg] = Type::getHalfTy(II.getContext());

312 }

313

314 unsigned EndIndex =

317 OperandIndex < EndIndex; OperandIndex++) {

318 Args[OperandIndex] =

319 convertTo16Bit(*II.getOperand(OperandIndex), IC.Builder);

320 }

321

322

323 if (!OnlyDerivatives && ImageDimIntr->NumBiasArgs != 0) {

324 Value *Bias = II.getOperand(ImageDimIntr->BiasIndex);

325 Args[ImageDimIntr->BiasIndex] = convertTo16Bit(*Bias, IC.Builder);

326 }

327 });

328}

329

333

334

335

336

337

340

341 return true;

342 }

343

347

348 return true;

349 }

350 return false;

351}

352

353

355 Value *Src = nullptr;

358 if (Src->getType()->isHalfTy())

359 return Src;

361 bool LosesInfo;

364 if (!LosesInfo)

366 }

367 return nullptr;

368}

369

370

371

374 auto *VTy = cast(UseV->getType());

375 unsigned VWidth = VTy->getNumElements();

377

378 for (int i = VWidth - 1; i > 0; --i) {

380 if (!Elt)

381 break;

382

383 if (auto *ConstElt = dyn_cast(Elt)) {

384 if (!ConstElt->isNullValue() && !isa(Elt))

385 break;

386 } else {

387 break;

388 }

389

391 }

392

393 return DemandedElts;

394}

395

396

397

399 auto *VTy = cast(V->getType());

400 unsigned VWidth = VTy->getNumElements();

403

405 if (auto *SVI = dyn_cast(V))

406 SVI->getShuffleMask(ShuffleMask);

407

408 for (int I = VWidth - 1; I > 0; --I) {

409 if (ShuffleMask.empty()) {

411 if (!Elt || (Elt != FirstComponent && !isa(Elt)))

412 break;

413 } else {

414

415

416 if (ShuffleMask[I] != ShuffleMask[0] && ShuffleMask[I] != PoisonMaskElem)

417 break;

418 }

420 }

421

422 return DemandedElts;

423}

424

427 APInt DemandedElts,

428 int DMaskIdx = -1,

429 bool IsLoad = true);

430

431

436}

437

438

440 Value *V = U.get();

441 if (isa(V))

442 return true;

443 if (const auto *II = dyn_cast(V)) {

445 return false;

446

447

448 return II->getParent() == cast(U.getUser())->getParent();

449 }

450 return false;

451}

452

453

454

455

458 unsigned LaneArgIdx) const {

460 APInt DemandedMask(32, maskTrailingOnes(MaskBits));

461

464 return true;

465

467 return false;

468

469

470

471

472

473 Value *LaneArg = II.getArgOperand(LaneArgIdx);

475 ConstantInt::get(LaneArg->getType(), Known.getConstant() & DemandedMask);

476 if (MaskedConst != LaneArg) {

477 II.getOperandUse(LaneArgIdx).set(MaskedConst);

478 return true;

479 }

480

481 return false;

482}

483

484std::optional<Instruction *>

487 switch (IID) {

488 case Intrinsic::amdgcn_rcp: {

489 Value *Src = II.getArgOperand(0);

490

491

492 if (isa(Src)) {

493 Type *Ty = II.getType();

496 }

497

498 if (II.isStrictFP())

499 break;

500

501 if (const ConstantFP *C = dyn_cast(Src)) {

502 const APFloat &ArgVal = C->getValueAPF();

505

506

507

508

509

511 }

512

513 FastMathFlags FMF = cast(II).getFastMathFlags();

515 break;

516 auto *SrcCI = dyn_cast(Src);

517 if (!SrcCI)

518 break;

519

520 auto IID = SrcCI->getIntrinsicID();

521

522

523

524

525 if (IID == Intrinsic::amdgcn_sqrt || IID == Intrinsic::sqrt) {

526 const FPMathOperator *SqrtOp = cast(SrcCI);

528 if (!InnerFMF.allowContract() || !SrcCI->hasOneUse())

529 break;

530

532 break;

533

535 SrcCI->getModule(), Intrinsic::amdgcn_rsq, {SrcCI->getType()});

536

537 InnerFMF |= FMF;

538 II.setFastMathFlags(InnerFMF);

539

540 II.setCalledFunction(NewDecl);

542 }

543

544 break;

545 }

546 case Intrinsic::amdgcn_sqrt:

547 case Intrinsic::amdgcn_rsq: {

548 Value *Src = II.getArgOperand(0);

549

550

551 if (isa(Src)) {

552 Type *Ty = II.getType();

555 }

556

557

558 if (IID == Intrinsic::amdgcn_sqrt && Src->getType()->isHalfTy()) {

560 II.getModule(), Intrinsic::sqrt, {II.getType()});

561 II.setCalledFunction(NewDecl);

562 return &II;

563 }

564

565 break;

566 }

567 case Intrinsic::amdgcn_log:

568 case Intrinsic::amdgcn_exp2: {

569 const bool IsLog = IID == Intrinsic::amdgcn_log;

570 const bool IsExp = IID == Intrinsic::amdgcn_exp2;

571 Value *Src = II.getArgOperand(0);

572 Type *Ty = II.getType();

573

574 if (isa(Src))

576

579

580 if (ConstantFP *C = dyn_cast(Src)) {

581 if (C->isInfinity()) {

582

583

584 if (C->isNegative())

586

587

588 if (IsExp && C->isNegative())

590 }

591

592 if (II.isStrictFP())

593 break;

594

595 if (C->isNaN()) {

596 Constant *Quieted = ConstantFP::get(Ty, C->getValue().makeQuiet());

598 }

599

600

601 if (C->isZero() || (C->getValue().isDenormal() && Ty->isFloatTy())) {

603 : ConstantFP::get(Ty, 1.0);

605 }

606

607 if (IsLog && C->isNegative())

609

610

611 }

612

613 break;

614 }

615 case Intrinsic::amdgcn_frexp_mant:

616 case Intrinsic::amdgcn_frexp_exp: {

617 Value *Src = II.getArgOperand(0);

618 if (const ConstantFP *C = dyn_cast(Src)) {

619 int Exp;

622

623 if (IID == Intrinsic::amdgcn_frexp_mant) {

625 II, ConstantFP::get(II.getContext(), Significand));

626 }

627

628

630 Exp = 0;

631

633 }

634

635 if (isa(Src)) {

637 }

638

639 break;

640 }

641 case Intrinsic::amdgcn_class: {

642 Value *Src0 = II.getArgOperand(0);

643 Value *Src1 = II.getArgOperand(1);

644 const ConstantInt *CMask = dyn_cast(Src1);

645 if (CMask) {

647 II.getModule(), Intrinsic::is_fpclass, Src0->getType()));

648

649

650 II.setArgOperand(1, ConstantInt::get(Src1->getType(),

652 return &II;

653 }

654

655

656 if (isa(Src0) || isa(Src1))

658

659

662

663

668 }

669 break;

670 }

671 case Intrinsic::amdgcn_cvt_pkrtz: {

672 auto foldFPTruncToF16RTZ = [](Value *Arg) -> Value * {

674

675 if (isa(Arg))

677 if (isa(Arg))

679

682 bool LosesInfo;

685 return ConstantFP::get(HalfTy, Val);

686 }

687

688 Value *Src = nullptr;

690 if (Src->getType()->isHalfTy())

691 return Src;

692 }

693

694 return nullptr;

695 };

696

697 if (Value *Src0 = foldFPTruncToF16RTZ(II.getArgOperand(0))) {

698 if (Value *Src1 = foldFPTruncToF16RTZ(II.getArgOperand(1))) {

703 }

704 }

705

706 break;

707 }

708 case Intrinsic::amdgcn_cvt_pknorm_i16:

709 case Intrinsic::amdgcn_cvt_pknorm_u16:

710 case Intrinsic::amdgcn_cvt_pk_i16:

711 case Intrinsic::amdgcn_cvt_pk_u16: {

712 Value *Src0 = II.getArgOperand(0);

713 Value *Src1 = II.getArgOperand(1);

714

715 if (isa(Src0) && isa(Src1)) {

717 }

718

719 break;

720 }

721 case Intrinsic::amdgcn_ubfe:

722 case Intrinsic::amdgcn_sbfe: {

723

724 Value *Src = II.getArgOperand(0);

725 if (isa(Src)) {

727 }

728

729 unsigned Width;

730 Type *Ty = II.getType();

732

733 ConstantInt *CWidth = dyn_cast(II.getArgOperand(2));

734 if (CWidth) {

736 if ((Width & (IntSize - 1)) == 0) {

738 }

739

740

741 if (Width >= IntSize) {

743 II, 2, ConstantInt::get(CWidth->getType(), Width & (IntSize - 1)));

744 }

745 }

746

748 ConstantInt *COffset = dyn_cast(II.getArgOperand(1));

749 if (COffset) {

751 if (Offset >= IntSize) {

753 II, 1,

754 ConstantInt::get(COffset->getType(), Offset & (IntSize - 1)));

755 }

756 }

757

758 bool Signed = IID == Intrinsic::amdgcn_sbfe;

759

760 if (!CWidth || !COffset)

761 break;

762

763

764

765

767

768

769

770 if (Offset + Width < IntSize) {

774 RightShift->takeName(&II);

776 }

777

780

781 RightShift->takeName(&II);

783 }

784 case Intrinsic::amdgcn_exp:

785 case Intrinsic::amdgcn_exp_row:

786 case Intrinsic::amdgcn_exp_compr: {

787 ConstantInt *En = cast(II.getArgOperand(1));

789 if (EnBits == 0xf)

790 break;

791

792 bool IsCompr = IID == Intrinsic::amdgcn_exp_compr;

793 bool Changed = false;

794 for (int I = 0; I < (IsCompr ? 2 : 4); ++I) {

795 if ((!IsCompr && (EnBits & (1 << I)) == 0) ||

796 (IsCompr && ((EnBits & (0x3 << (2 * I))) == 0))) {

797 Value *Src = II.getArgOperand(I + 2);

798 if (!isa(Src)) {

800 Changed = true;

801 }

802 }

803 }

804

805 if (Changed) {

806 return &II;

807 }

808

809 break;

810 }

811 case Intrinsic::amdgcn_fmed3: {

812

813

814

815 Value *Src0 = II.getArgOperand(0);

816 Value *Src1 = II.getArgOperand(1);

817 Value *Src2 = II.getArgOperand(2);

818

819

820

821

822 Value *V = nullptr;

829 }

830

831 if (V) {

832 if (auto *CI = dyn_cast(V)) {

833 CI->copyFastMathFlags(&II);

835 }

837 }

838

839 bool Swap = false;

840

841

842

843 if (isa(Src0) && !isa(Src1)) {

845 Swap = true;

846 }

847

848 if (isa(Src1) && !isa(Src2)) {

850 Swap = true;

851 }

852

853 if (isa(Src0) && !isa(Src1)) {

855 Swap = true;

856 }

857

858 if (Swap) {

859 II.setArgOperand(0, Src0);

860 II.setArgOperand(1, Src1);

861 II.setArgOperand(2, Src2);

862 return &II;

863 }

864

865 if (const ConstantFP *C0 = dyn_cast(Src0)) {

866 if (const ConstantFP *C1 = dyn_cast(Src1)) {

867 if (const ConstantFP *C2 = dyn_cast(Src2)) {

869 C2->getValueAPF());

872 }

873 }

874 }

875

877 break;

878

879

880

885 IID, {X->getType()}, {X, Y, Z}, &II, II.getName());

886 return new FPExtInst(NewCall, II.getType());

887 }

888 }

889 }

890

891 break;

892 }

893 case Intrinsic::amdgcn_icmp:

894 case Intrinsic::amdgcn_fcmp: {

895 const ConstantInt *CC = cast(II.getArgOperand(2));

896

897 int64_t CCVal = CC->getZExtValue();

898 bool IsInteger = IID == Intrinsic::amdgcn_icmp;

903 break;

904

905 Value *Src0 = II.getArgOperand(0);

906 Value *Src1 = II.getArgOperand(1);

907

908 if (auto *CSrc0 = dyn_cast(Src0)) {

909 if (auto *CSrc1 = dyn_cast(Src1)) {

915 }

916

917

918

919

920

921

926 II.getType(), Args);

927 NewCall->addFnAttr(Attribute::Convergent);

930 }

931

932

935 II.setArgOperand(0, Src1);

936 II.setArgOperand(1, Src0);

937 II.setArgOperand(

938 2, ConstantInt::get(CC->getType(), static_cast<int>(SwapPred)));

939 return &II;

940 }

941

943 break;

944

945

946

947

948

949

960 return &II;

961 }

962

966

967

968

969

970

971

972

973

974

975

976

983

985 ? Intrinsic::amdgcn_fcmp

986 : Intrinsic::amdgcn_icmp;

987

989 if (auto *CmpType = dyn_cast(Ty)) {

990

991 unsigned Width = CmpType->getBitWidth();

992 unsigned NewWidth = Width;

993

994

995 if (Width == 1)

996 break;

997

998 if (Width <= 16)

999 NewWidth = 16;

1000 else if (Width <= 32)

1001 NewWidth = 32;

1002 else if (Width <= 64)

1003 NewWidth = 64;

1004 else

1005 break;

1006

1007 if (Width != NewWidth) {

1012 } else {

1015 }

1016 }

1018 break;

1019

1020 Value *Args[] = {SrcLHS, SrcRHS,

1021 ConstantInt::get(CC->getType(), SrcPred)};

1023 NewIID, {II.getType(), SrcLHS->getType()}, Args);

1026 }

1027

1028 break;

1029 }

1030 case Intrinsic::amdgcn_mbcnt_hi: {

1031

1034 break;

1035 }

1036 case Intrinsic::amdgcn_ballot: {

1037 if (auto *Src = dyn_cast(II.getArgOperand(0))) {

1038 if (Src->isZero()) {

1039

1041 }

1042 }

1043 if (ST->isWave32() && II.getType()->getIntegerBitWidth() == 64) {

1044

1045

1046

1047

1050 {IC.Builder.getInt32Ty()},

1051 {II.getArgOperand(0)}),

1052 II.getType());

1053 Call->takeName(&II);

1055 }

1056 break;

1057 }

1058 case Intrinsic::amdgcn_wavefrontsize: {

1062 break;

1063 }

1064 case Intrinsic::amdgcn_wqm_vote: {

1065

1066 if (!isa(II.getArgOperand(0)))

1067 break;

1068

1070 }

1071 case Intrinsic::amdgcn_kill: {

1072 const ConstantInt *C = dyn_cast(II.getArgOperand(0));

1073 if (C || C->getZExtValue())

1074 break;

1075

1076

1078 }

1079 case Intrinsic::amdgcn_update_dpp: {

1080 Value *Old = II.getArgOperand(0);

1081

1082 auto *BC = cast(II.getArgOperand(5));

1083 auto *RM = cast(II.getArgOperand(3));

1084 auto *BM = cast(II.getArgOperand(4));

1085 if (BC->isZeroValue() || RM->getZExtValue() != 0xF ||

1086 BM->getZExtValue() != 0xF || isa(Old))

1087 break;

1088

1089

1091 }

1092 case Intrinsic::amdgcn_permlane16:

1093 case Intrinsic::amdgcn_permlane16_var:

1094 case Intrinsic::amdgcn_permlanex16:

1095 case Intrinsic::amdgcn_permlanex16_var: {

1096

1097 Value *VDstIn = II.getArgOperand(0);

1098 if (isa(VDstIn))

1099 break;

1100

1101

1102 unsigned int FiIdx = (IID == Intrinsic::amdgcn_permlane16 ||

1103 IID == Intrinsic::amdgcn_permlanex16)

1104 ? 4

1105 : 3;

1106

1107

1108

1109

1110 unsigned int BcIdx = FiIdx + 1;

1111

1112 ConstantInt *FetchInvalid = cast(II.getArgOperand(FiIdx));

1113 ConstantInt *BoundCtrl = cast(II.getArgOperand(BcIdx));

1115 break;

1116

1118 }

1119 case Intrinsic::amdgcn_permlane64:

1120 case Intrinsic::amdgcn_readfirstlane:

1121 case Intrinsic::amdgcn_readlane: {

1122

1123 const Use &Src = II.getArgOperandUse(0);

1126

1127 if (IID == Intrinsic::amdgcn_readlane &&

1129 return &II;

1130

1131 return std::nullopt;

1132 }

1133 case Intrinsic::amdgcn_writelane: {

1135 return &II;

1136 return std::nullopt;

1137 }

1138 case Intrinsic::amdgcn_trig_preop: {

1139

1140

1141 if (II.getType()->isDoubleTy())

1142 break;

1143

1144 Value *Src = II.getArgOperand(0);

1145 Value *Segment = II.getArgOperand(1);

1146 if (isa(Src) || isa(Segment))

1148

1149 if (isa(Src)) {

1150 auto *QNaN = ConstantFP::get(

1153 }

1154

1155 const ConstantFP *Csrc = dyn_cast(Src);

1156 if (!Csrc)

1157 break;

1158

1159 if (II.isStrictFP())

1160 break;

1161

1163 if (Fsrc.isNaN()) {

1164 auto *Quieted = ConstantFP::get(II.getType(), Fsrc.makeQuiet());

1166 }

1167

1168 const ConstantInt *Cseg = dyn_cast(Segment);

1169 if (!Cseg)

1170 break;

1171

1174 unsigned Shift = SegmentVal * 53;

1177

1178

1179 static const uint32_t TwoByPi[] = {

1180 0xa2f9836e, 0x4e441529, 0xfc2757d1, 0xf534ddc0, 0xdb629599, 0x3c439041,

1181 0xfe5163ab, 0xdebbc561, 0xb7246e3a, 0x424dd2e0, 0x06492eea, 0x09d1921c,

1182 0xfe1deb1c, 0xb129a73e, 0xe88235f5, 0x2ebb4484, 0xe99c7026, 0xb45f7e41,

1183 0x3991d639, 0x835339f4, 0x9c845f8b, 0xbdf9283b, 0x1ff897ff, 0xde05980f,

1184 0xef2f118b, 0x5a0a6d1f, 0x6d367ecf, 0x27cb09b7, 0x4f463f66, 0x9e5fea2d,

1185 0x7527bac7, 0xebe5f17b, 0x3d0739f7, 0x8a5292ea, 0x6bfb5fb1, 0x1f8d5d08,

1186 0x56033046};

1187

1188

1189 unsigned Idx = Shift >> 5;

1190 if (Idx + 2 >= std::size(TwoByPi)) {

1193 }

1194

1195 unsigned BShift = Shift & 0x1f;

1198 if (BShift)

1199 Thi = (Thi << BShift) | (Tlo >> (64 - BShift));

1200 Thi = Thi >> 11;

1202

1203 int Scale = -53 - Shift;

1205 Scale += 128;

1206

1209 }

1210 case Intrinsic::amdgcn_fmul_legacy: {

1211 Value *Op0 = II.getArgOperand(0);

1212 Value *Op1 = II.getArgOperand(1);

1213

1214

1215

1216

1220

1221

1222

1225 FMul->takeName(&II);

1227 }

1228 break;

1229 }

1230 case Intrinsic::amdgcn_fma_legacy: {

1231 Value *Op0 = II.getArgOperand(0);

1232 Value *Op1 = II.getArgOperand(1);

1233 Value *Op2 = II.getArgOperand(2);

1234

1235

1236

1237

1240

1241

1244 FAdd->takeName(&II);

1246 }

1247

1248

1249

1252 II.getModule(), Intrinsic::fma, II.getType()));

1253 return &II;

1254 }

1255 break;

1256 }

1257 case Intrinsic::amdgcn_is_shared:

1258 case Intrinsic::amdgcn_is_private: {

1259 if (isa(II.getArgOperand(0)))

1261

1262 if (isa(II.getArgOperand(0)))

1264 break;

1265 }

1266 case Intrinsic::amdgcn_raw_buffer_store_format:

1267 case Intrinsic::amdgcn_struct_buffer_store_format:

1268 case Intrinsic::amdgcn_raw_tbuffer_store:

1269 case Intrinsic::amdgcn_struct_tbuffer_store:

1270 case Intrinsic::amdgcn_image_store_1d:

1271 case Intrinsic::amdgcn_image_store_1darray:

1272 case Intrinsic::amdgcn_image_store_2d:

1273 case Intrinsic::amdgcn_image_store_2darray:

1274 case Intrinsic::amdgcn_image_store_2darraymsaa:

1275 case Intrinsic::amdgcn_image_store_2dmsaa:

1276 case Intrinsic::amdgcn_image_store_3d:

1277 case Intrinsic::amdgcn_image_store_cube:

1278 case Intrinsic::amdgcn_image_store_mip_1d:

1279 case Intrinsic::amdgcn_image_store_mip_1darray:

1280 case Intrinsic::amdgcn_image_store_mip_2d:

1281 case Intrinsic::amdgcn_image_store_mip_2darray:

1282 case Intrinsic::amdgcn_image_store_mip_3d:

1283 case Intrinsic::amdgcn_image_store_mip_cube: {

1284 if (!isa(II.getArgOperand(0)->getType()))

1285 break;

1286

1287 APInt DemandedElts;

1292 else

1293 break;

1294

1295 int DMaskIdx = getAMDGPUImageDMaskIntrinsic(II.getIntrinsicID()) ? 1 : -1;

1297 false)) {

1299 }

1300

1301 break;

1302 }

1303 case Intrinsic::amdgcn_prng_b32: {

1304 auto *Src = II.getArgOperand(0);

1305 if (isa(Src)) {

1307 }

1308 return std::nullopt;

1309 }

1310 case Intrinsic::amdgcn_mfma_scale_f32_16x16x128_f8f6f4:

1311 case Intrinsic::amdgcn_mfma_scale_f32_32x32x64_f8f6f4: {

1312 Value *Src0 = II.getArgOperand(0);

1313 Value *Src1 = II.getArgOperand(1);

1314 uint64_t CBSZ = cast(II.getArgOperand(3))->getZExtValue();

1315 uint64_t BLGP = cast(II.getArgOperand(4))->getZExtValue();

1316 auto *Src0Ty = cast(Src0->getType());

1317 auto *Src1Ty = cast(Src1->getType());

1318

1319 auto getFormatNumRegs = [](unsigned FormatVal) {

1320 switch (FormatVal) {

1323 return 6u;

1325 return 4u;

1328 return 8u;

1329 default:

1331 }

1332 };

1333

1334 bool MadeChange = false;

1335 unsigned Src0NumElts = getFormatNumRegs(CBSZ);

1336 unsigned Src1NumElts = getFormatNumRegs(BLGP);

1337

1338

1339

1340 if (Src0Ty->getNumElements() > Src0NumElts) {

1344 MadeChange = true;

1345 }

1346

1347 if (Src1Ty->getNumElements() > Src1NumElts) {

1351 MadeChange = true;

1352 }

1353

1354 if (!MadeChange)

1355 return std::nullopt;

1356

1358 Args[0] = Src0;

1359 Args[1] = Src1;

1360

1365 }

1366 }

1370 }

1371 return std::nullopt;

1372}

1373

1374

1375

1376

1377

1378

1379

1380

1383 APInt DemandedElts,

1384 int DMaskIdx, bool IsLoad) {

1385

1386 auto *IIVTy = cast(IsLoad ? II.getType()

1387 : II.getOperand(0)->getType());

1388 unsigned VWidth = IIVTy->getNumElements();

1389 if (VWidth == 1)

1390 return nullptr;

1391 Type *EltTy = IIVTy->getElementType();

1392

1395

1396

1398

1399 if (DMaskIdx < 0) {

1400

1401

1402 const unsigned ActiveBits = DemandedElts.getActiveBits();

1403 const unsigned UnusedComponentsAtFront = DemandedElts.countr_zero();

1404

1405

1406

1407

1408 DemandedElts = (1 << ActiveBits) - 1;

1409

1410 if (UnusedComponentsAtFront > 0) {

1411 static const unsigned InvalidOffsetIdx = 0xf;

1412

1413 unsigned OffsetIdx;

1414 switch (II.getIntrinsicID()) {

1415 case Intrinsic::amdgcn_raw_buffer_load:

1416 case Intrinsic::amdgcn_raw_ptr_buffer_load:

1417 OffsetIdx = 1;

1418 break;

1419 case Intrinsic::amdgcn_s_buffer_load:

1420

1421

1422

1423 if (ActiveBits == 4 && UnusedComponentsAtFront == 1)

1424 OffsetIdx = InvalidOffsetIdx;

1425 else

1426 OffsetIdx = 1;

1427 break;

1428 case Intrinsic::amdgcn_struct_buffer_load:

1429 case Intrinsic::amdgcn_struct_ptr_buffer_load:

1430 OffsetIdx = 2;

1431 break;

1432 default:

1433

1434 OffsetIdx = InvalidOffsetIdx;

1435 break;

1436 }

1437

1438 if (OffsetIdx != InvalidOffsetIdx) {

1439

1440 DemandedElts &= ~((1 << UnusedComponentsAtFront) - 1);

1441 auto *Offset = Args[OffsetIdx];

1442 unsigned SingleComponentSizeInBits =

1444 unsigned OffsetAdd =

1445 UnusedComponentsAtFront * SingleComponentSizeInBits / 8;

1446 auto *OffsetAddVal = ConstantInt::get(Offset->getType(), OffsetAdd);

1448 }

1449 }

1450 } else {

1451

1452

1453 ConstantInt *DMask = cast(Args[DMaskIdx]);

1454 unsigned DMaskVal = DMask->getZExtValue() & 0xf;

1455

1456

1457 if (DMaskVal == 0)

1458 return nullptr;

1459

1460

1461 DemandedElts &= (1 << llvm::popcount(DMaskVal)) - 1;

1462

1463 unsigned NewDMaskVal = 0;

1464 unsigned OrigLdStIdx = 0;

1465 for (unsigned SrcIdx = 0; SrcIdx < 4; ++SrcIdx) {

1466 const unsigned Bit = 1 << SrcIdx;

1467 if (!!(DMaskVal & Bit)) {

1468 if (!!DemandedElts[OrigLdStIdx])

1469 NewDMaskVal |= Bit;

1470 OrigLdStIdx++;

1471 }

1472 }

1473

1474 if (DMaskVal != NewDMaskVal)

1475 Args[DMaskIdx] = ConstantInt::get(DMask->getType(), NewDMaskVal);

1476 }

1477

1478 unsigned NewNumElts = DemandedElts.popcount();

1479 if (!NewNumElts)

1481

1482 if (NewNumElts >= VWidth && DemandedElts.isMask()) {

1483 if (DMaskIdx >= 0)

1484 II.setArgOperand(DMaskIdx, Args[DMaskIdx]);

1485 return nullptr;

1486 }

1487

1488

1489

1492 return nullptr;

1493

1494 Type *NewTy =

1496 OverloadTys[0] = NewTy;

1497

1498 if (!IsLoad) {

1500 for (unsigned OrigStoreIdx = 0; OrigStoreIdx < VWidth; ++OrigStoreIdx)

1501 if (DemandedElts[OrigStoreIdx])

1502 EltMask.push_back(OrigStoreIdx);

1503

1504 if (NewNumElts == 1)

1506 else

1508 }

1509

1514

1515 if (IsLoad) {

1516 if (NewNumElts == 1) {

1519 }

1520

1522 unsigned NewLoadIdx = 0;

1523 for (unsigned OrigLoadIdx = 0; OrigLoadIdx < VWidth; ++OrigLoadIdx) {

1524 if (!!DemandedElts[OrigLoadIdx])

1525 EltMask.push_back(NewLoadIdx++);

1526 else

1528 }

1529

1531

1532 return Shuffle;

1533 }

1534

1535 return NewCall;

1536}

1537

1540 APInt &UndefElts2, APInt &UndefElts3,

1542 SimplifyAndSetOp) const {

1543 switch (II.getIntrinsicID()) {

1544 case Intrinsic::amdgcn_raw_buffer_load:

1545 case Intrinsic::amdgcn_raw_ptr_buffer_load:

1546 case Intrinsic::amdgcn_raw_buffer_load_format:

1547 case Intrinsic::amdgcn_raw_ptr_buffer_load_format:

1548 case Intrinsic::amdgcn_raw_tbuffer_load:

1549 case Intrinsic::amdgcn_raw_ptr_tbuffer_load:

1550 case Intrinsic::amdgcn_s_buffer_load:

1551 case Intrinsic::amdgcn_struct_buffer_load:

1552 case Intrinsic::amdgcn_struct_ptr_buffer_load:

1553 case Intrinsic::amdgcn_struct_buffer_load_format:

1554 case Intrinsic::amdgcn_struct_ptr_buffer_load_format:

1555 case Intrinsic::amdgcn_struct_tbuffer_load:

1556 case Intrinsic::amdgcn_struct_ptr_tbuffer_load:

1558 default: {

1559 if (getAMDGPUImageDMaskIntrinsic(II.getIntrinsicID())) {

1561 }

1562 break;

1563 }

1564 }

1565 return std::nullopt;

1566}

for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))

static bool canContractSqrtToRsq(const FPMathOperator *SqrtOp)

Return true if it's legal to contract llvm.amdgcn.rcp(llvm.sqrt)

static bool isTriviallyUniform(const Use &U)

Return true if we can easily prove that use U is uniform.

static Value * convertTo16Bit(Value &V, InstCombiner::BuilderTy &Builder)

static APInt trimTrailingZerosInVector(InstCombiner &IC, Value *UseV, Instruction *I)

static APInt defaultComponentBroadcast(Value *V)

static std::optional< Instruction * > modifyIntrinsicCall(IntrinsicInst &OldIntr, Instruction &InstToReplace, unsigned NewIntr, InstCombiner &IC, std::function< void(SmallVectorImpl< Value * > &, SmallVectorImpl< Type * > &)> Func)

Applies Func(OldIntr.Args, OldIntr.ArgTys), creates intrinsic call with modified arguments (based on ...

static APFloat fmed3AMDGCN(const APFloat &Src0, const APFloat &Src1, const APFloat &Src2)

static Value * simplifyAMDGCNMemoryIntrinsicDemanded(InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, int DMaskIdx=-1, bool IsLoad=true)

Implement SimplifyDemandedVectorElts for amdgcn buffer and image intrinsics.

static std::optional< Instruction * > simplifyAMDGCNImageIntrinsic(const GCNSubtarget *ST, const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr, IntrinsicInst &II, InstCombiner &IC)

static bool canSafelyConvertTo16Bit(Value &V, bool IsFloat)

static Value * matchFPExtFromF16(Value *Arg)

Match an fpext from half to float, or a constant we can convert.

Contains the definition of a TargetInstrInfo class that is common to all AMD GPUs.

This file a TargetTransformInfo::Concept conforming object specific to the AMDGPU target machine.

Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx

static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")

Utilities for dealing with flags related to floating point properties and mode controls.

AMD GCN specific subclass of TargetSubtarget.

This file provides the interface for the instcombine pass implementation.

uint64_t IntrinsicInst * II

static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

unsigned getWavefrontSizeLog2() const

unsigned getWavefrontSize() const

static APFloat getQNaN(const fltSemantics &Sem, bool Negative=false, const APInt *payload=nullptr)

Factory for QNaN values.

opStatus divide(const APFloat &RHS, roundingMode RM)

opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)

const fltSemantics & getSemantics() const

APFloat makeQuiet() const

Assuming this is an IEEE-754 NaN value, quiet its signaling bit.

APInt bitcastToAPInt() const

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

Factory for Positive and Negative Zero.

cmpResult compare(const APFloat &RHS) const

Class for arbitrary precision integers.

static APInt getAllOnes(unsigned numBits)

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

void clearBit(unsigned BitPosition)

Set a given bit to 0.

uint64_t getZExtValue() const

Get zero extended value.

unsigned popcount() const

Count the number of bits set.

unsigned getActiveBits() const

Compute the number of active bits in the value.

APInt trunc(unsigned width) const

Truncate to new width.

unsigned countr_zero() const

Count the number of trailing zero bits.

bool isMask(unsigned numBits) const

void addFnAttr(Attribute::AttrKind Kind)

Adds the attribute to the function.

Function * getCalledFunction() const

Returns the function called, or null if this is an indirect function invocation or the function signa...

iterator_range< User::op_iterator > args()

Iteration adapter for range-for loops.

This class represents a function call, abstracting a target machine's calling convention.

Predicate

This enumeration lists the possible predicates for CmpInst subclasses.

Predicate getSwappedPredicate() const

For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.

bool isFPPredicate() const

Predicate getInversePredicate() const

For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...

An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...

ConstantFP - Floating Point Values [float, double].

const APFloat & getValueAPF() const

static Constant * getInfinity(Type *Ty, bool Negative=false)

static Constant * getZero(Type *Ty, bool Negative=false)

static Constant * getNaN(Type *Ty, bool Negative=false, uint64_t Payload=0)

This is the shared class of boolean and integer constants.

static ConstantInt * getFalse(LLVMContext &Context)

uint64_t getZExtValue() const

Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...

const APInt & getValue() const

Return the constant as an APInt value reference.

This is an important base class in LLVM.

static Constant * getNullValue(Type *Ty)

Constructor to create a '0' constant of arbitrary type.

bool isNullValue() const

Return true if this is the value that would be returned by getNullValue.

TypeSize getTypeSizeInBits(Type *Ty) const

Size examples:

This class represents an extension of floating point types.

Utility class for floating point operations which can have information about relaxed accuracy require...

FastMathFlags getFastMathFlags() const

Convenience function for getting all the fast-math flags.

bool hasApproxFunc() const

Test if this operation allows approximations of math library functions or intrinsics.

float getFPAccuracy() const

Get the maximum error permitted by this operation in ULPs.

Convenience struct for specifying and reasoning about fast-math flags.

bool allowContract() const

static FixedVectorType * get(Type *ElementType, unsigned NumElts)

bool hasDefaultComponentZero() const

bool isWaveSizeKnown() const

Returns if the wavesize of this subtarget is known reliable.

bool hasDefaultComponentBroadcast() const

bool simplifyDemandedLaneMaskArg(InstCombiner &IC, IntrinsicInst &II, unsigned LaneAgIdx) const

Simplify a lane index operand (e.g.

std::optional< Value * > simplifyDemandedVectorEltsIntrinsic(InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, APInt &UndefElts2, APInt &UndefElts3, std::function< void(Instruction *, unsigned, APInt, APInt &)> SimplifyAndSetOp) const

std::optional< Instruction * > instCombineIntrinsic(InstCombiner &IC, IntrinsicInst &II) const

bool canSimplifyLegacyMulToMul(const Instruction &I, const Value *Op0, const Value *Op1, InstCombiner &IC) const

Value * CreateMaxNum(Value *LHS, Value *RHS, const Twine &Name="")

Create call to the maxnum intrinsic.

CallInst * CreateExtractVector(Type *DstType, Value *SrcVec, Value *Idx, const Twine &Name="")

Create a call to the vector.extract intrinsic.

Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")

Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")

IntegerType * getIntNTy(unsigned N)

Fetch the type representing an N-bit integer.

Value * CreateMinNum(Value *LHS, Value *RHS, const Twine &Name="")

Create call to the minnum intrinsic.

Value * CreateSExt(Value *V, Type *DestTy, const Twine &Name="")

Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)

Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")

ConstantInt * getInt64(uint64_t C)

Get a constant 64-bit value.

CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")

Create a call to intrinsic ID with Args, mangled using Types.

Value * CreateFPCast(Value *V, Type *DestTy, const Twine &Name="", MDNode *FPMathTag=nullptr)

Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)

Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)

Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")

LLVMContext & getContext() const

Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)

Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")

void SetInsertPoint(BasicBlock *TheBB)

This specifies that created instructions should be appended to the end of the specified block.

Value * CreateFAddFMF(Value *L, Value *R, FMFSource FMFSource, const Twine &Name="", MDNode *FPMD=nullptr)

Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)

Value * CreateFMulFMF(Value *L, Value *R, FMFSource FMFSource, const Twine &Name="", MDNode *FPMD=nullptr)

The core instruction combiner logic.

const DataLayout & getDataLayout() const

virtual Instruction * eraseInstFromFunction(Instruction &I)=0

Combiner aware instruction erasure.

Instruction * replaceInstUsesWith(Instruction &I, Value *V)

A combiner-aware RAUW-like routine.

virtual bool SimplifyDemandedBits(Instruction *I, unsigned OpNo, const APInt &DemandedMask, KnownBits &Known, unsigned Depth, const SimplifyQuery &Q)=0

Instruction * replaceOperand(Instruction &I, unsigned OpNum, Value *V)

Replace operand of instruction and add old operand to the worklist.

const SimplifyQuery & getSimplifyQuery() const

void copyFastMathFlags(FastMathFlags FMF)

Convenience function for transferring all fast-math flag values to this instruction,...

void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())

Copy metadata from SrcInst to this instruction.

Class to represent integer types.

A wrapper class for inspecting calls to intrinsic functions.

static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)

static MDString * get(LLVMContext &Context, StringRef Str)

static PoisonValue * get(Type *T)

Static factory methods - Return an 'poison' object of the specified type.

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.

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

static Type * getHalfTy(LLVMContext &C)

unsigned getIntegerBitWidth() const

const fltSemantics & getFltSemantics() const

bool isFloatTy() const

Return true if this is 'float', a 32-bit IEEE fp type.

static IntegerType * getInt16Ty(LLVMContext &C)

bool isHalfTy() const

Return true if this is 'half', a 16-bit IEEE fp type.

bool isDoubleTy() const

Return true if this is 'double', a 64-bit IEEE fp type.

bool isFloatingPointTy() const

Return true if this is one of the floating-point types.

bool isIntegerTy() const

True if this is an instance of IntegerType.

bool isVoidTy() const

Return true if this is 'void'.

Type * getScalarType() const

If this is a vector type, return the element type, otherwise return 'this'.

static UndefValue * get(Type *T)

Static factory methods - Return an 'undef' object of the specified type.

A Use represents the edge between a Value definition and its users.

LLVM Value Representation.

Type * getType() const

All values are typed, get the type of this value.

LLVMContext & getContext() const

All values hold a context through their type.

void takeName(Value *V)

Transfer the name from V to this value.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

LLVM_READONLY const MIMGOffsetMappingInfo * getMIMGOffsetMappingInfo(unsigned Offset)

const ImageDimIntrinsicInfo * getImageDimIntrinsicByBaseOpcode(unsigned BaseOpcode, unsigned Dim)

LLVM_READONLY const MIMGMIPMappingInfo * getMIMGMIPMappingInfo(unsigned MIP)

bool isIntrinsicAlwaysUniform(unsigned IntrID)

LLVM_READONLY const MIMGBiasMappingInfo * getMIMGBiasMappingInfo(unsigned Bias)

LLVM_READONLY const MIMGLZMappingInfo * getMIMGLZMappingInfo(unsigned L)

LLVM_READONLY const MIMGBaseOpcodeInfo * getMIMGBaseOpcodeInfo(unsigned BaseOpcode)

const ImageDimIntrinsicInfo * getImageDimIntrinsicInfo(unsigned Intr)

@ C

The default llvm calling convention, compatible with C.

Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})

Look up the Function declaration of the intrinsic id in the Module M.

bool getIntrinsicSignature(Intrinsic::ID, FunctionType *FT, SmallVectorImpl< Type * > &ArgTys)

Gets the type arguments of an intrinsic call by matching type contraints specified by the ....

cst_pred_ty< is_all_ones > m_AllOnes()

Match an integer or vector with all bits set.

bool match(Val *V, const Pattern &P)

cstfp_pred_ty< is_any_zero_fp > m_AnyZeroFP()

Match a floating-point negative zero or positive zero.

cst_pred_ty< is_one > m_One()

Match an integer 1 or a vector with all elements equal to 1.

OneUse_match< T > m_OneUse(const T &SubPattern)

CastInst_match< OpTy, FPExtInst > m_FPExt(const OpTy &Op)

class_match< ConstantFP > m_ConstantFP()

Match an arbitrary ConstantFP and ignore it.

CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)

Matches ZExt.

class_match< CmpInst > m_Cmp()

Matches any compare instruction and ignore it.

cstfp_pred_ty< is_finitenonzero > m_FiniteNonZero()

Match a finite non-zero FP constant.

class_match< Value > m_Value()

Match an arbitrary value and ignore it.

match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)

cstfp_pred_ty< is_nan > m_NaN()

Match an arbitrary NaN constant.

CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)

Matches SExt.

is_zero m_Zero()

Match any null constant or a vector with all elements equal to 0.

This is an optimization pass for GlobalISel generic memory operations.

int popcount(T Value) noexcept

Count the number of set bits in a value.

Constant * ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS, Constant *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr, const Instruction *I=nullptr)

Attempt to constant fold a compare instruction (icmp/fcmp) with the specified operands.

bool isKnownNeverInfOrNaN(const Value *V, unsigned Depth, const SimplifyQuery &SQ)

Return true if the floating-point value can never contain a NaN or infinity.

APFloat frexp(const APFloat &X, int &Exp, APFloat::roundingMode RM)

Equivalent of C standard library function.

LLVM_READONLY APFloat maxnum(const APFloat &A, const APFloat &B)

Implements IEEE-754 2019 maximumNumber semantics.

APFloat scalbn(APFloat X, int Exp, APFloat::roundingMode RM)

constexpr int PoisonMaskElem

Value * findScalarElement(Value *V, unsigned EltNo)

Given a vector and an element number, see if the scalar value is already around as a register,...

@ NearestTiesToEven

roundTiesToEven.

constexpr uint64_t Make_64(uint32_t High, uint32_t Low)

Make a 64-bit integer from a high / low pair of 32-bit integers.

void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)

Implement std::swap in terms of BitVector swap.

cmpResult

IEEE-754R 5.11: Floating Point Comparison Relations.

static constexpr roundingMode rmNearestTiesToEven

static constexpr roundingMode rmTowardZero

static const fltSemantics & IEEEhalf() LLVM_READNONE

bool isConstant() const

Returns true if we know the value of all bits.

const APInt & getConstant() const

Returns the value when all bits have a known value.

SimplifyQuery getWithInstruction(const Instruction *I) const

bool isUndefValue(Value *V) const

If CanUseUndef is true, returns whether V is undef.