LLVM: lib/Target/Hexagon/HexagonISelDAGToDAG.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

22#include "llvm/IR/IntrinsicsHexagon.h"

25using namespace llvm;

26

27#define DEBUG_TYPE "hexagon-isel"

28#define PASS_NAME "Hexagon DAG->DAG Pattern Instruction Selection"

29

30static

33 cl::desc("Rebalance address calculation trees to improve "

34 "instruction selection"));

35

36

37

38static

41 cl::desc("Rebalance address tree only if this allows optimizations"));

42

43static

46 cl::init(false), cl::desc("Rebalance address tree only if it is imbalanced"));

47

49 cl::init(true), cl::desc("Enable checking of SDNode's single-use status"));

50

51

52

53

54

55#define GET_DAGISEL_BODY HexagonDAGToDAGISel

56#include "HexagonGenDAGISel.inc"

57

58namespace llvm {

59

60

65}

66

71

73

75

77 SDValue Chain = LD->getChain();

81 EVT LoadedVT = LD->getMemoryVT();

82 unsigned Opcode = 0;

83

84

85

88 bool IsValidInc = HII->isValidAutoIncImm(LoadedVT, Inc);

89

92 case MVT::i8:

93 if (IsZeroExt)

94 Opcode = IsValidInc ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrub_io;

95 else

96 Opcode = IsValidInc ? Hexagon::L2_loadrb_pi : Hexagon::L2_loadrb_io;

97 break;

98 case MVT::i16:

99 if (IsZeroExt)

100 Opcode = IsValidInc ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadruh_io;

101 else

102 Opcode = IsValidInc ? Hexagon::L2_loadrh_pi : Hexagon::L2_loadrh_io;

103 break;

104 case MVT::i32:

105 case MVT::f32:

106 case MVT::v2i16:

107 case MVT::v4i8:

108 Opcode = IsValidInc ? Hexagon::L2_loadri_pi : Hexagon::L2_loadri_io;

109 break;

110 case MVT::i64:

111 case MVT::f64:

112 case MVT::v2i32:

113 case MVT::v4i16:

114 case MVT::v8i8:

115 Opcode = IsValidInc ? Hexagon::L2_loadrd_pi : Hexagon::L2_loadrd_io;

116 break;

117 case MVT::v64i8:

118 case MVT::v32i16:

119 case MVT::v16i32:

120 case MVT::v8i64:

121 case MVT::v128i8:

122 case MVT::v64i16:

123 case MVT::v32i32:

124 case MVT::v16i64:

125 if (isAlignedMemNode(LD)) {

126 if (LD->isNonTemporal())

127 Opcode = IsValidInc ? Hexagon::V6_vL32b_nt_pi : Hexagon::V6_vL32b_nt_ai;

128 else

129 Opcode = IsValidInc ? Hexagon::V6_vL32b_pi : Hexagon::V6_vL32b_ai;

130 } else {

131 Opcode = IsValidInc ? Hexagon::V6_vL32Ub_pi : Hexagon::V6_vL32Ub_ai;

132 }

133 break;

134 default:

136 }

137

138 SDValue IncV = CurDAG->getSignedTargetConstant(Inc, dl, MVT::i32);

140

144 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);

145 return CurDAG->getMachineNode(Hexagon::A4_combineir, dl, MVT::i64,

147 }

149 return CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,

151 return N;

152 };

153

154

157

158 EVT ValueVT = LD->getValueType(0);

160

161

163 ValueVT = MVT::i32;

164 }

165

166 if (IsValidInc) {

168 MVT::i32, MVT::Other, Base,

169 IncV, Chain);

171 To[1] = SDValue(L, 1);

172 To[2] = SDValue(L, 2);

173

174 if (LD->getValueType(0) == MVT::i64)

175 L = getExt64(L, dl);

176 To[0] = SDValue(L, 0);

177 } else {

178 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);

179 MachineSDNode *L = CurDAG->getMachineNode(Opcode, dl, ValueVT, MVT::Other,

180 Base, Zero, Chain);

182 To[2] = SDValue(L, 1);

185 To[1] = SDValue(A, 0);

186

187 if (LD->getValueType(0) == MVT::i64)

188 L = getExt64(L, dl);

189 To[0] = SDValue(L, 0);

190 }

192 CurDAG->RemoveDeadNode(LD);

193}

194

197 return nullptr;

198

201

202 static std::map<unsigned,unsigned> LoadPciMap = {

203 { Intrinsic::hexagon_circ_ldb, Hexagon::L2_loadrb_pci },

204 { Intrinsic::hexagon_circ_ldub, Hexagon::L2_loadrub_pci },

205 { Intrinsic::hexagon_circ_ldh, Hexagon::L2_loadrh_pci },

206 { Intrinsic::hexagon_circ_lduh, Hexagon::L2_loadruh_pci },

207 { Intrinsic::hexagon_circ_ldw, Hexagon::L2_loadri_pci },

208 { Intrinsic::hexagon_circ_ldd, Hexagon::L2_loadrd_pci },

209 };

210 auto FLC = LoadPciMap.find(IntNo);

211 if (FLC != LoadPciMap.end()) {

212 EVT ValTy = (IntNo == Intrinsic::hexagon_circ_ldd) ? MVT::i64 : MVT::i32;

213 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };

214

217 CurDAG->getSignedTargetConstant(Inc->getSExtValue(), dl, MVT::i32);

219 { IntN->getOperand(2), I, IntN->getOperand(4),

220 IntN->getOperand(0) });

221 return Res;

222 }

223

224 return nullptr;

225}

226

229

230

231

235 unsigned Size = 1U << (SizeBits-1);

236

241

242 if (Size >= 4)

245 else

248

250 {

254 }

255

256

259 return StoreN;

260}

261

263

264

265

266

267

268

269

270

271

272

273

274

275

276 SDValue Ch = N->getOperand(0);

278

279

280

281

282

284

286 return false;

287

288

289

290

291

293 switch (C->getConstantOperandVal(1)) {

294 case Intrinsic::hexagon_circ_ldub:

295 case Intrinsic::hexagon_circ_lduh:

297 break;

298 case Intrinsic::hexagon_circ_ldw:

299 case Intrinsic::hexagon_circ_ldd:

301 break;

302 default:

304 break;

305 }

306 if (N->getExtensionType() != IntExt)

307 return false;

308

309

310

311 if (C->getNumOperands() < 4 || Loc.getNode() != C->getOperand(3).getNode())

312 return false;

313

319

320

321

322 CurDAG->RemoveDeadNode(C);

323 return true;

324 }

325 return false;

326}

327

328

331 return false;

332

333 const SDLoc &dl(IntN);

335

336 static const std::map<unsigned, unsigned> LoadBrevMap = {

337 { Intrinsic::hexagon_L2_loadrb_pbr, Hexagon::L2_loadrb_pbr },

338 { Intrinsic::hexagon_L2_loadrub_pbr, Hexagon::L2_loadrub_pbr },

339 { Intrinsic::hexagon_L2_loadrh_pbr, Hexagon::L2_loadrh_pbr },

340 { Intrinsic::hexagon_L2_loadruh_pbr, Hexagon::L2_loadruh_pbr },

341 { Intrinsic::hexagon_L2_loadri_pbr, Hexagon::L2_loadri_pbr },

342 { Intrinsic::hexagon_L2_loadrd_pbr, Hexagon::L2_loadrd_pbr }

343 };

344 auto FLI = LoadBrevMap.find(IntNo);

345 if (FLI != LoadBrevMap.end()) {

346 EVT ValTy =

347 (IntNo == Intrinsic::hexagon_L2_loadrd_pbr) ? MVT::i64 : MVT::i32;

348 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };

349

350

351

353 FLI->second, dl, RTys,

354 {IntN->getOperand(2), IntN->getOperand(3), IntN->getOperand(0)});

355

358

362 CurDAG->RemoveDeadNode(IntN);

363 return true;

364 }

365 return false;

366}

367

368

369

372 return false;

373

377

378 static std::map<unsigned,unsigned> LoadNPcMap = {

379 { Intrinsic::hexagon_L2_loadrub_pci, Hexagon::PS_loadrub_pci },

380 { Intrinsic::hexagon_L2_loadrb_pci, Hexagon::PS_loadrb_pci },

381 { Intrinsic::hexagon_L2_loadruh_pci, Hexagon::PS_loadruh_pci },

382 { Intrinsic::hexagon_L2_loadrh_pci, Hexagon::PS_loadrh_pci },

383 { Intrinsic::hexagon_L2_loadri_pci, Hexagon::PS_loadri_pci },

384 { Intrinsic::hexagon_L2_loadrd_pci, Hexagon::PS_loadrd_pci },

385 { Intrinsic::hexagon_L2_loadrub_pcr, Hexagon::PS_loadrub_pcr },

386 { Intrinsic::hexagon_L2_loadrb_pcr, Hexagon::PS_loadrb_pcr },

387 { Intrinsic::hexagon_L2_loadruh_pcr, Hexagon::PS_loadruh_pcr },

388 { Intrinsic::hexagon_L2_loadrh_pcr, Hexagon::PS_loadrh_pcr },

389 { Intrinsic::hexagon_L2_loadri_pcr, Hexagon::PS_loadri_pcr },

390 { Intrinsic::hexagon_L2_loadrd_pcr, Hexagon::PS_loadrd_pcr }

391 };

392 auto FLI = LoadNPcMap.find (IntNo);

393 if (FLI != LoadNPcMap.end()) {

394 EVT ValTy = MVT::i32;

395 if (IntNo == Intrinsic::hexagon_L2_loadrd_pci ||

396 IntNo == Intrinsic::hexagon_L2_loadrd_pcr)

397 ValTy = MVT::i64;

398 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };

399

402 SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), DL, MVT::i32);

403

406 } else

407

408

415 CurDAG->RemoveDeadNode(IntN);

416 return true;

417 }

418

419 static std::map<unsigned,unsigned> StoreNPcMap = {

420 { Intrinsic::hexagon_S2_storerb_pci, Hexagon::PS_storerb_pci },

421 { Intrinsic::hexagon_S2_storerh_pci, Hexagon::PS_storerh_pci },

422 { Intrinsic::hexagon_S2_storerf_pci, Hexagon::PS_storerf_pci },

423 { Intrinsic::hexagon_S2_storeri_pci, Hexagon::PS_storeri_pci },

424 { Intrinsic::hexagon_S2_storerd_pci, Hexagon::PS_storerd_pci },

425 { Intrinsic::hexagon_S2_storerb_pcr, Hexagon::PS_storerb_pcr },

426 { Intrinsic::hexagon_S2_storerh_pcr, Hexagon::PS_storerh_pcr },

427 { Intrinsic::hexagon_S2_storerf_pcr, Hexagon::PS_storerf_pcr },

428 { Intrinsic::hexagon_S2_storeri_pcr, Hexagon::PS_storeri_pcr },

429 { Intrinsic::hexagon_S2_storerd_pcr, Hexagon::PS_storerd_pcr }

430 };

431 auto FSI = StoreNPcMap.find (IntNo);

432 if (FSI != StoreNPcMap.end()) {

433 EVT RTys[] = { MVT::i32, MVT::Other };

434

437 SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), DL, MVT::i32);

438

441 } else

442

443

449 CurDAG->RemoveDeadNode(IntN);

450 return true;

451 }

452

453 return false;

454}

455

459

460

464 return;

465 }

466

467

469 return;

470

471 SelectCode(LD);

472}

473

475 SDValue Chain = ST->getChain();

479

481 EVT StoredVT = ST->getMemoryVT();

482 EVT ValueVT = Value.getValueType();

483

484 bool IsValidInc = HII->isValidAutoIncImm(StoredVT, Inc);

485 unsigned Opcode = 0;

486

489 case MVT::i8:

490 Opcode = IsValidInc ? Hexagon::S2_storerb_pi : Hexagon::S2_storerb_io;

491 break;

492 case MVT::i16:

493 Opcode = IsValidInc ? Hexagon::S2_storerh_pi : Hexagon::S2_storerh_io;

494 break;

495 case MVT::i32:

496 case MVT::f32:

497 case MVT::v2i16:

498 case MVT::v4i8:

499 Opcode = IsValidInc ? Hexagon::S2_storeri_pi : Hexagon::S2_storeri_io;

500 break;

501 case MVT::i64:

502 case MVT::f64:

503 case MVT::v2i32:

504 case MVT::v4i16:

505 case MVT::v8i8:

506 Opcode = IsValidInc ? Hexagon::S2_storerd_pi : Hexagon::S2_storerd_io;

507 break;

508 case MVT::v64i8:

509 case MVT::v32i16:

510 case MVT::v16i32:

511 case MVT::v8i64:

512 case MVT::v128i8:

513 case MVT::v64i16:

514 case MVT::v32i32:

515 case MVT::v16i64:

516 if (isAlignedMemNode(ST)) {

517 if (ST->isNonTemporal())

518 Opcode = IsValidInc ? Hexagon::V6_vS32b_nt_pi : Hexagon::V6_vS32b_nt_ai;

519 else

520 Opcode = IsValidInc ? Hexagon::V6_vS32b_pi : Hexagon::V6_vS32b_ai;

521 } else {

522 Opcode = IsValidInc ? Hexagon::V6_vS32Ub_pi : Hexagon::V6_vS32Ub_ai;

523 }

524 break;

525 default:

527 }

528

529 if (ST->isTruncatingStore() && ValueVT.getSizeInBits() == 64) {

531 Value = CurDAG->getTargetExtractSubreg(Hexagon::isub_lo,

532 dl, MVT::i32, Value);

533 }

534

535 SDValue IncV = CurDAG->getSignedTargetConstant(Inc, dl, MVT::i32);

537

538

541

542 if (IsValidInc) {

543

545 MachineSDNode *S = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Other,

550 } else {

551 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);

559 }

560

562 CurDAG->RemoveDeadNode(ST);

563}

564

568

569

573 return;

574 }

575

576 SelectCode(ST);

577}

578

581 SDValue Shl_0 = N->getOperand(0);

582 SDValue Shl_1 = N->getOperand(1);

583

584 auto Default = [this,N] () -> void { SelectCode(N); };

585

588

589

591

595

597 int32_t ValConst = C->getSExtValue() << ShlConst;

599 SDValue Val = CurDAG->getTargetConstant(ValConst, dl, MVT::i32);

600 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,

601 MVT::i32, Mul_0, Val);

603 return;

604 }

605 }

607 }

608

618 int32_t ValConst = 1 << (ShlConst + C2->getSExtValue());

621 CurDAG->getSignedTargetConstant(-ValConst, dl, MVT::i32);

622 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,

623 MVT::i32, Shl2_0, Val);

625 return;

626 }

627 }

628 }

629 }

630

632}

633

634

635

636

640 CurDAG->RemoveDeadNode(N);

641 return;

642 }

643

644

646 return;

647

649 return;

650

651 unsigned IntNo = N->getConstantOperandVal(1);

652 if (IntNo == Intrinsic::hexagon_V6_vgathermw ||

653 IntNo == Intrinsic::hexagon_V6_vgathermw_128B ||

654 IntNo == Intrinsic::hexagon_V6_vgathermh ||

655 IntNo == Intrinsic::hexagon_V6_vgathermh_128B ||

656 IntNo == Intrinsic::hexagon_V6_vgathermhw ||

657 IntNo == Intrinsic::hexagon_V6_vgathermhw_128B ||

658 IntNo == Intrinsic::hexagon_V6_vgather_vscattermh ||

659 IntNo == Intrinsic::hexagon_V6_vgather_vscattermh_128B) {

661 return;

662 }

663 if (IntNo == Intrinsic::hexagon_V6_vgathermwq ||

664 IntNo == Intrinsic::hexagon_V6_vgathermwq_128B ||

665 IntNo == Intrinsic::hexagon_V6_vgathermhq ||

666 IntNo == Intrinsic::hexagon_V6_vgathermhq_128B ||

667 IntNo == Intrinsic::hexagon_V6_vgathermhwq ||

668 IntNo == Intrinsic::hexagon_V6_vgathermhwq_128B) {

670 return;

671 }

672

673 SelectCode(N);

674}

675

677 unsigned IID = N->getConstantOperandVal(0);

678 unsigned Bits;

679 switch (IID) {

680 case Intrinsic::hexagon_S2_vsplatrb:

681 Bits = 8;

682 break;

683 case Intrinsic::hexagon_S2_vsplatrh:

684 Bits = 16;

685 break;

686 case Intrinsic::hexagon_V6_vaddcarry:

687 case Intrinsic::hexagon_V6_vaddcarry_128B:

688 case Intrinsic::hexagon_V6_vsubcarry:

689 case Intrinsic::hexagon_V6_vsubcarry_128B:

691 return;

692 default:

693 SelectCode(N);

694 return;

695 }

696

697 SDValue V = N->getOperand(1);

699

700 if (keepsLowBits(V, Bits, U)) {

702 N->getOperand(0), U);

704 SelectCode(R.getNode());

705 return;

706 }

707 SelectCode(N);

708}

709

711 SDValue Inp = N->getOperand(0);

712 MVT ResTy = N->getValueType(0).getSimpleVT();

713 unsigned Idx = N->getConstantOperandVal(1);

714

720 assert(Idx == 0 || Idx == ResLen);

721

722 unsigned SubReg = Idx == 0 ? Hexagon::isub_lo : Hexagon::isub_hi;

724

726}

727

728

729

730

734 APInt A = CN->getValueAPF().bitcastToAPInt();

735 if (N->getValueType(0) == MVT::f32) {

736 SDValue V = CurDAG->getTargetConstant(A.getZExtValue(), dl, MVT::i32);

737 ReplaceNode(N, CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, V));

738 return;

739 }

740 if (N->getValueType(0) == MVT::f64) {

741 SDValue V = CurDAG->getTargetConstant(A.getZExtValue(), dl, MVT::i64);

742 ReplaceNode(N, CurDAG->getMachineNode(Hexagon::CONST64, dl, MVT::f64, V));

743 return;

744 }

745

746 SelectCode(N);

747}

748

749

750

751

753 if (N->getValueType(0) == MVT::i1) {

754 assert(!(N->getAsZExtVal() >> 1));

756 ? Hexagon::PS_true

757 : Hexagon::PS_false;

759 return;

760 }

761

762 SelectCode(N);

763}

764

771 SDValue FI = CurDAG->getTargetFrameIndex(FX, MVT::i32);

773 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);

775

776

777

778

779

780

782 R = CurDAG->getMachineNode(Hexagon::PS_fi, DL, MVT::i32, FI, Zero);

783 } else {

785 Register AR = HMFI.getStackAlignBaseReg();

788 R = CurDAG->getMachineNode(Hexagon::PS_fia, DL, MVT::i32, Ops);

789 }

790

792}

793

795 unsigned OpcCarry = N->getOpcode() == HexagonISD::ADDC ? Hexagon::A4_addp_c

796 : Hexagon::A4_subp_c;

798 { N->getOperand(0), N->getOperand(1),

799 N->getOperand(2) });

801}

802

804 MVT ResTy = N->getValueType(0).getSimpleVT();

805 if (HST->isHVXVectorType(ResTy, true))

806 return SelectHvxVAlign(N);

807

810 if (VecLen == 32) {

812 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),

813 N->getOperand(0),

814 CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),

815 N->getOperand(1),

816 CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)

817 };

818 SDNode *R = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,

819 MVT::i64, Ops);

820

821

823 SDValue M0 = CurDAG->getTargetConstant(0x18, dl, MVT::i32);

824 SDValue M1 = CurDAG->getTargetConstant(0x03, dl, MVT::i32);

825 if (HST->useCompound()) {

826 C = CurDAG->getMachineNode(Hexagon::S4_andi_asl_ri, dl, MVT::i32,

827 M0, N->getOperand(2), M1);

828 } else {

829 SDNode *T = CurDAG->getMachineNode(Hexagon::S2_asl_i_r, dl, MVT::i32,

830 N->getOperand(2), M1);

831 C = CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,

833 }

834 SDNode *S = CurDAG->getMachineNode(Hexagon::S2_lsr_r_p, dl, MVT::i64,

836 SDValue E = CurDAG->getTargetExtractSubreg(Hexagon::isub_lo, dl, ResTy,

839 } else {

840 assert(VecLen == 64);

841 SDNode *Pu = CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::v8i1,

842 N->getOperand(2));

843 SDNode *VA = CurDAG->getMachineNode(Hexagon::S2_valignrb, dl, ResTy,

844 N->getOperand(0), N->getOperand(1),

847 }

848}

849

855

856 SDValue M = CurDAG->getTargetConstant(Mask, dl, MVT::i32);

857 SDNode *AA = CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,

858 N->getOperand(0), M);

860}

861

862

863

864

867 MVT OpTy = Op.getValueType().getSimpleVT();

869 CurDAG->getVTList(OpTy), {Op});

871}

872

874 MVT ResTy = N->getValueType(0).getSimpleVT();

876 N->getOperand(0));

878}

879

882 MVT ResTy = N->getValueType(0).getSimpleVT();

883 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);

884 SDNode *T = CurDAG->getMachineNode(Hexagon::A4_vcmpbgtui, dl, ResTy,

885 N->getOperand(0), Zero);

887}

888

891 MVT ResTy = N->getValueType(0).getSimpleVT();

892

893 MVT OpTy = N->getOperand(0).getValueType().getSimpleVT(); (void)OpTy;

895

896 SDValue C = CurDAG->getSignedTargetConstant(-1, dl, MVT::i32);

897 SDNode *R = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, C);

898 SDNode *T = CurDAG->getMachineNode(Hexagon::V6_vandvrt, dl, ResTy,

899 N->getOperand(0), SDValue(R,0));

901}

902

905 MVT ResTy = N->getValueType(0).getSimpleVT();

906

908

909 SDValue C = CurDAG->getSignedTargetConstant(-1, dl, MVT::i32);

910 SDNode *R = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, C);

911 SDNode *T = CurDAG->getMachineNode(Hexagon::V6_vandqrt, dl, ResTy,

912 N->getOperand(0), SDValue(R,0));

914}

915

918 ArrayRef ResultType(N->value_begin(), N->value_end());

920 Ops = {N->getOperand(0), N->getOperand(1)};

922 VTs = CurDAG->getVTList(MVT::f32, MVT::f32);

923 SDNode *ResScale = CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs, Ops);

924 SDNode *D = CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32, Ops);

925

926 SDValue C = CurDAG->getTargetConstant(0x3f800000, dl, MVT::i32);

928 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, C);

929

930 SDNode *n = CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32, Ops);

931 SDNode *Err = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,

934 SDNode *NewRec = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,

937 SDNode *newErr = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,

941 Hexagon::A2_andir, dl, MVT::f32, SDValue(n, 0),

942 CurDAG->getTargetConstant(0x80000000, dl, MVT::i32));

944 CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(q, 0),

947 Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(NewRec, 0),

950 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, SDValue(n, 0),

952 SDNode *NNewQ = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,

955

957 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, SDValue(n, 0),

959 std::array<SDValue, 4> temp1 = {SDValue(NNewQ, 0), SDValue(NqErr, 0),

963 CurDAG->getMachineNode(Hexagon::F2_sffma_sc, dl, MVT::f32, OpValue1);

965}

966

969 ArrayRef ResultType(N->value_begin(), N->value_end());

971 Ops = {N->getOperand(0), N->getOperand(1)};

973 VTs = CurDAG->getVTList(MVT::f32, MVT::f32);

974 SDNode *ResScale = CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs, Ops);

975 SDNode *D = CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32, Ops);

976

977 SDValue C = CurDAG->getTargetConstant(0x3f800000, dl, MVT::i32);

979 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, C);

980

981 SDNode *n = CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32, Ops);

982 SDNode *Err = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,

985 SDNode *NewRec = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,

988 SDNode *newErr = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,

991

993 Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(NewRec, 0),

996 Hexagon::F2_sfmpy, dl, MVT::f32, SDValue(NNewRec, 0), SDValue(n, 0));

998}

999

1001 if (N->getFlags().hasAllowReassociation())

1003 else

1005}

1006

1008 if (N->isMachineOpcode())

1009 return N->setNodeId(-1);

1010

1011 auto isHvxOp = [this](SDNode *N) {

1012 for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) {

1013 if (HST->isHVXVectorType(N->getValueType(i), true))

1014 return true;

1015 }

1017 if (HST->isHVXVectorType(I.getValueType(), true))

1018 return true;

1019 }

1020 return false;

1021 };

1022

1023 if (HST->useHVXOps() && isHvxOp(N)) {

1024 switch (N->getOpcode()) {

1027

1029 }

1030 }

1031

1032 switch (N->getOpcode()) {

1042

1054 }

1055

1056 SelectCode(N);

1057}

1058

1061 std::vector &OutOps) {

1063

1064 switch (ConstraintID) {

1065 default:

1066 return true;

1071 OutOps.push_back(Res);

1072 else

1073 OutOps.push_back(Inp);

1074 break;

1075 }

1076

1077 OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32));

1078 return false;

1079}

1080

1082

1083

1084

1085

1086 if (!U->hasOneUse())

1087 return false;

1088 unsigned Opc = U->getOpcode();

1089 switch (Opc) {

1094 break;

1095 default:

1096 return false;

1097 }

1098

1102

1105 return false;

1106

1107

1108

1109

1110

1111 SDNode *SYNode = SY.getNode();

1112 if (UUse->getOpcode() == ISD::STORE && SYNode->getOpcode() == ISD::LOAD) {

1115 if (LDBasePtr == STBasePtr)

1116 return true;

1117 }

1118 return false;

1119}

1120

1121

1122

1123

1124void HexagonDAGToDAGISel::ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes) {

1125 SelectionDAG &DAG = *CurDAG;

1126

1127 for (auto *I : Nodes) {

1128 if (I->getOpcode() != ISD::OR)

1129 continue;

1130

1131 auto IsSelect0 = [](const SDValue &Op) -> bool {

1133 return false;

1136 };

1137

1138 SDValue N0 = I->getOperand(0), N1 = I->getOperand(1);

1139 EVT VT = I->getValueType(0);

1140 bool SelN0 = IsSelect0(N0);

1141 SDValue SOp = SelN0 ? N0 : N1;

1142 SDValue VOp = SelN0 ? N1 : N0;

1143

1148 SDLoc DLS = SOp;

1157 }

1158 }

1159 }

1160}

1161

1162

1163

1164

1165

1166

1167

1168void HexagonDAGToDAGISel::ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes) {

1169 SelectionDAG &DAG = *CurDAG;

1170

1171 for (auto *I : Nodes) {

1172 if (I->getOpcode() != ISD::STORE)

1173 continue;

1174

1175

1177

1179 continue;

1180

1182

1184 continue;

1185

1188

1190 continue;

1193 if (CN == nullptr)

1194 continue;

1196 if (CV > 2)

1197 continue;

1198

1200 if (EN == nullptr)

1201 continue;

1203 if (EV % (1 << CV) != 0)

1204 continue;

1205 unsigned DV = EV / (1 << CV);

1206

1207

1208 SDLoc DL = SDLoc(I);

1211

1213

1216 }

1217}

1218

1219

1220

1221

1222

1223

1224

1225

1226

1227

1228

1229

1230

1231

1232void HexagonDAGToDAGISel::ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes) {

1233 SelectionDAG &DAG = *CurDAG;

1234

1235 for (SDNode *N : Nodes) {

1236 unsigned Opc = N->getOpcode();

1237 if (Opc != ISD::LOAD && Opc != ISD::STORE)

1238 continue;

1239 SDValue Addr = Opc == ISD::LOAD ? N->getOperand(1) : N->getOperand(2);

1240

1242 continue;

1244

1246 continue;

1247

1248

1249

1250

1253 continue;

1255 if (SN == nullptr)

1256 continue;

1258 continue;

1260

1261

1263 if (MN == nullptr)

1264 continue;

1266 continue;

1268

1272

1273 if (TZ + M1 + LZ != 32)

1274 continue;

1275

1276 if (TZ > 2)

1277 continue;

1278

1279 if (LZ > CV)

1280 continue;

1281

1282

1285 SDLoc dl(S);

1286

1292 }

1293}

1294

1295

1296

1297void HexagonDAGToDAGISel::ppHoistZextI1(std::vector<SDNode*> &&Nodes) {

1298 SelectionDAG &DAG = *CurDAG;

1299

1300 for (SDNode *N : Nodes) {

1301 unsigned Opc = N->getOpcode();

1303 continue;

1304 SDValue OpI1 = N->getOperand(0);

1307 continue;

1308 for (SDUse &Use : N->uses()) {

1309 SDNode *U = Use.getUser();

1310 if (U->getNumValues() != 1)

1311 continue;

1312 EVT UVT = U->getValueType(0);

1314 continue;

1315

1317 continue;

1319 continue;

1320

1321

1322 unsigned I1N = Use.getOperandNo();

1324 for (unsigned i = 0, n = U->getNumOperands(); i != n; ++i)

1325 Ops[i] = U->getOperand(i);

1326 EVT BVT = Ops[I1N].getValueType();

1327

1328 const SDLoc &dl(U);

1332

1334 unsigned UseOpc = U->getMachineOpcode();

1335 Ops[I1N] = C0;

1337 Ops[I1N] = C1;

1339 } else {

1340 unsigned UseOpc = U->getOpcode();

1341 Ops[I1N] = C0;

1342 If0 = DAG.getNode(UseOpc, dl, UVT, Ops);

1343 Ops[I1N] = C1;

1344 If1 = DAG.getNode(UseOpc, dl, UVT, Ops);

1345 }

1346

1347

1355 }

1356 }

1357}

1358

1360

1361

1362 auto getNodes = [this]() -> std::vector<SDNode *> {

1363 std::vector<SDNode *> T;

1364 T.reserve(CurDAG->allnodes_size());

1366 T.push_back(&N);

1367 return T;

1368 };

1369

1370 if (HST->useHVXOps())

1371 PreprocessHvxISelDAG();

1372

1373

1374

1375 ppSimplifyOrSelect0(getNodes());

1376

1377

1378

1379

1380

1381

1382

1383 ppAddrReorderAddShl(getNodes());

1384

1385

1386

1387

1388

1389

1390

1391

1392

1393

1394

1395

1396

1397

1398 ppAddrRewriteAndSrl(getNodes());

1399

1400

1401

1402 ppHoistZextI1(getNodes());

1403

1405 dbgs() << "Preprocessed (Hexagon) selection DAG:";

1407 });

1408

1410 rebalanceAddressTrees();

1411

1413 dbgs() << "Address tree balanced selection DAG:";

1415 });

1416 }

1417}

1418

1422 if (!HFI.needsAligna(*MF))

1423 return;

1424

1428

1429

1431 auto &HRI = *HST.getRegisterInfo();

1433 for (const MCPhysReg *R = HRI.getCalleeSavedRegs(MF); *R; ++R) {

1435 continue;

1436 AP = *R;

1437 break;

1438 }

1439 assert(AP.isValid() && "Couldn't reserve stack align register");

1440 BuildMI(EntryBB, DebugLoc(), HII->get(Hexagon::PS_aligna), AP)

1443}

1444

1445void HexagonDAGToDAGISel::updateAligna() {

1447 if (!HFI.needsAligna(*MF))

1448 return;

1449 auto *AlignaI = const_cast<MachineInstr*>(HFI.getAlignaInstr(*MF));

1450 assert(AlignaI != nullptr);

1452 if (AlignaI->getOperand(1).getImm() < MaxA)

1453 AlignaI->getOperand(1).setImm(MaxA);

1454}

1455

1456

1459 return false;

1460 auto &HFI = *HST->getFrameLowering();

1464 return false;

1465 R = CurDAG->getTargetFrameIndex(FX, MVT::i32);

1466 return true;

1467}

1468

1472

1476

1480

1493

1495 EVT T = N.getValueType();

1497 return false;

1499 R = CurDAG->getTargetConstant(V, SDLoc(N), N.getValueType());

1500 return true;

1501}

1502

1504 Align Alignment) {

1505 switch (N.getOpcode()) {

1507 if (N.getValueType() != MVT::i32)

1508 return false;

1511 return false;

1512 R = CurDAG->getTargetConstant(V, SDLoc(N), N.getValueType());

1513 return true;

1514 }

1517

1518 if (Alignment > Align(8))

1519 return false;

1520 R = N.getOperand(0);

1521 return true;

1523

1524 if (Alignment > Align(1))

1525 return false;

1526 R = N;

1527 return true;

1529

1530 if (Alignment > Align(4) ||

1532 return false;

1533 R = N;

1534 return true;

1535 }

1536

1539 return true;

1540

1541 return false;

1542}

1543

1545 bool UseGP, Align Alignment) {

1546 switch (N.getOpcode()) {

1548 SDValue N0 = N.getOperand(0);

1549 SDValue N1 = N.getOperand(1);

1550 unsigned GAOpc = N0.getOpcode();

1552 return false;

1554 return false;

1556 if (isAligned(Alignment, Const->getZExtValue()))

1557 return false;

1561 uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();

1562 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(Const),

1563 N.getValueType(), NewOff);

1564 return true;

1565 }

1566 }

1567 }

1568 break;

1569 }

1573

1574

1575 if (!UseGP)

1576 R = N.getOperand(0);

1577 return !UseGP;

1579 if (UseGP)

1580 R = N.getOperand(0);

1581 return UseGP;

1582 default:

1583 return false;

1584 }

1585

1586 return false;

1587}

1588

1590

1591

1592

1593

1594

1595

1596

1597

1598

1599

1600

1601

1602

1603

1604

1605

1606

1607

1608 if (N.getValueType() != MVT::i64)

1609 return false;

1610 unsigned Opc = N.getOpcode();

1611 switch (Opc) {

1614

1616 ? N.getOperand(0).getValueType()

1618 unsigned SW = T.getSizeInBits();

1619 if (SW == 32)

1620 R = N.getOperand(0);

1621 else if (SW < 32)

1622 R = N;

1623 else

1624 return false;

1625 break;

1626 }

1627 case ISD::LOAD: {

1630 return false;

1631

1632

1633 if (L->getMemoryVT().getSizeInBits() > 32)

1634 return false;

1635 R = N;

1636 break;

1637 }

1640 if (!S || S->getZExtValue() != 32)

1641 return false;

1642 R = N;

1643 break;

1644 }

1647 if (T.getSizeInBits() == 32)

1648 R = N.getOperand(0);

1649 else

1650 return false;

1651 break;

1652 }

1653

1654 default:

1655 return false;

1656 }

1657 EVT RT = R.getValueType();

1658 if (RT == MVT::i64)

1659 return true;

1660 assert(RT == MVT::i32);

1661

1662

1665 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),

1666 R, CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),

1667 R, CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)

1668 };

1669 SDNode *T = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,

1670 MVT::i64, Ops);

1672 return true;

1673}

1674

1675bool HexagonDAGToDAGISel::keepsLowBits(const SDValue &Val, unsigned NumBits,

1678 switch (Opc) {

1684 if (T.isInteger() && T.getSizeInBits() == NumBits) {

1685 Src = Op0;

1686 return true;

1687 }

1688 break;

1689 }

1695 if (T->getVT().getSizeInBits() == NumBits) {

1697 return true;

1698 }

1699 }

1700 break;

1702

1703 uint64_t Mask = (1ULL << NumBits) - 1;

1705 if (C->getZExtValue() == Mask) {

1707 return true;

1708 }

1709 }

1711 if (C->getZExtValue() == Mask) {

1713 return true;

1714 }

1715 }

1716 break;

1717 }

1720

1721 uint64_t Mask = (1ULL << NumBits) - 1;

1723 if ((C->getZExtValue() & Mask) == 0) {

1725 return true;

1726 }

1727 }

1729 if ((C->getZExtValue() & Mask) == 0) {

1731 return true;

1732 }

1733 }

1734 break;

1735 }

1736 default:

1737 break;

1738 }

1739 return false;

1740}

1741

1742bool HexagonDAGToDAGISel::isAlignedMemNode(const MemSDNode *N) const {

1743 return N->getAlign().value() >= N->getMemoryVT().getStoreSize();

1744}

1745

1746bool HexagonDAGToDAGISel::isSmallStackStore(const StoreSDNode *N) const {

1747 unsigned StackSize = MF->getFrameInfo().estimateStackSize(*MF);

1748 switch (N->getMemoryVT().getStoreSize()) {

1749 case 1:

1750 return StackSize <= 56;

1751 case 2:

1752 return StackSize <= 120;

1753 case 4:

1754 return StackSize <= 248;

1755 default:

1756 return false;

1757 }

1758}

1759

1760

1761bool HexagonDAGToDAGISel::isPositiveHalfWord(const SDNode *N) const {

1765 }

1769 }

1770 return false;

1771}

1772

1773bool HexagonDAGToDAGISel::hasOneUse(const SDNode *N) const {

1775}

1776

1777

1778

1779

1781 switch (N->getOpcode()) {

1784 return true;

1786

1787

1789 default:

1790 return false;

1791 }

1792}

1793

1794

1795int HexagonDAGToDAGISel::getWeight(SDNode *N) {

1797 return 1;

1798 assert(RootWeights.count(N) && "Cannot get weight of unseen root!");

1799 assert(RootWeights[N] != -1 && "Cannot get weight of unvisited root!");

1800 assert(RootWeights[N] != -2 && "Cannot get weight of RAWU'd root!");

1801 return RootWeights[N];

1802}

1803

1804int HexagonDAGToDAGISel::getHeight(SDNode *N) {

1806 return 0;

1807 assert(RootWeights.count(N) && RootWeights[N] >= 0 &&

1808 "Cannot query height of unvisited/RAUW'd node!");

1809 return RootHeights[N];

1810}

1811

1812namespace {

1813struct WeightedLeaf {

1815 int Weight;

1816 int InsertionOrder;

1817

1818 WeightedLeaf() = default;

1819

1820 WeightedLeaf(SDValue Value, int Weight, int InsertionOrder) :

1821 Value(Value), Weight(Weight), InsertionOrder(InsertionOrder) {

1822 assert(Weight >= 0 && "Weight must be >= 0");

1823 }

1824

1825 static bool Compare(const WeightedLeaf &A, const WeightedLeaf &B) {

1826 assert(A.Value.getNode() && B.Value.getNode());

1827 return A.Weight == B.Weight ?

1828 (A.InsertionOrder > B.InsertionOrder) :

1829 (A.Weight > B.Weight);

1830 }

1831};

1832

1833

1834

1835

1836class LeafPrioQueue {

1838 bool HaveConst;

1839 WeightedLeaf ConstElt;

1840 unsigned Opcode;

1841

1842public:

1844 return (!HaveConst && Q.empty());

1845 }

1846

1847 size_t size() {

1848 return Q.size() + HaveConst;

1849 }

1850

1851 bool hasConst() {

1852 return HaveConst;

1853 }

1854

1855 const WeightedLeaf &top() {

1856 if (HaveConst)

1857 return ConstElt;

1858 return Q.front();

1859 }

1860

1861 WeightedLeaf pop() {

1862 if (HaveConst) {

1863 HaveConst = false;

1864 return ConstElt;

1865 }

1866 std::pop_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);

1868 }

1869

1870 void push(WeightedLeaf L, bool SeparateConst=true) {

1874 return;

1877 return;

1878

1879 HaveConst = true;

1880 ConstElt = L;

1881 } else {

1883 std::push_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);

1884 }

1885 }

1886

1887

1888

1889 void pushToBottom(WeightedLeaf L) {

1890 L.Weight = 1000;

1891 push(L, false);

1892 }

1893

1894

1895

1896 WeightedLeaf findSHL(uint64_t MaxAmount);

1897

1898 WeightedLeaf findMULbyConst();

1899

1900 LeafPrioQueue(unsigned Opcode) :

1901 HaveConst(false), Opcode(Opcode) { }

1902};

1903}

1904

1905WeightedLeaf LeafPrioQueue::findSHL(uint64_t MaxAmount) {

1906 int ResultPos;

1907 WeightedLeaf Result;

1908

1909 for (int Pos = 0, End = Q.size(); Pos != End; ++Pos) {

1910 const WeightedLeaf &L = Q[Pos];

1911 const SDValue &Val = L.Value;

1915 continue;

1916 if (Result.Value.getNode() || Result.Weight > L.Weight ||

1917 (Result.Weight == L.Weight && Result.InsertionOrder > L.InsertionOrder))

1918 {

1920 ResultPos = Pos;

1921 }

1922 }

1923

1924 if (Result.Value.getNode()) {

1925 Q.erase(&Q[ResultPos]);

1926 std::make_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);

1927 }

1928

1930}

1931

1932WeightedLeaf LeafPrioQueue::findMULbyConst() {

1933 int ResultPos;

1934 WeightedLeaf Result;

1935

1936 for (int Pos = 0, End = Q.size(); Pos != End; ++Pos) {

1937 const WeightedLeaf &L = Q[Pos];

1938 const SDValue &Val = L.Value;

1942 continue;

1943 if (Result.Value.getNode() || Result.Weight > L.Weight ||

1944 (Result.Weight == L.Weight && Result.InsertionOrder > L.InsertionOrder))

1945 {

1947 ResultPos = Pos;

1948 }

1949 }

1950

1951 if (Result.Value.getNode()) {

1952 Q.erase(&Q[ResultPos]);

1953 std::make_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);

1954 }

1955

1957}

1958

1959SDValue HexagonDAGToDAGISel::getMultiplierForSHL(SDNode *N) {

1961 return CurDAG->getConstant(MulFactor, SDLoc(N),

1962 N->getOperand(1).getValueType());

1963}

1964

1965

1968 unsigned MaxFactor = 0;

1969 for (int i = 0; i < 2; ++i) {

1971 if (C)

1972 continue;

1973 const APInt &CInt = C->getAPIntValue();

1976 }

1977 return MaxFactor;

1978 }

1981 return 0;

1983 }

1984

1985 return 0;

1986}

1987

1988

1990 if (V.getOpcode() == ISD::MUL) {

1991 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };

1992 for (int i = 0; i < 2; ++i)

1994 V.getConstantOperandVal(i) % (1ULL << Amount) == 0) {

1995 uint64_t NewConst = V.getConstantOperandVal(i) >> Amount;

1996 return (NewConst == 1);

1997 }

1998 } else if (V.getOpcode() == ISD::SHL) {

1999 return (Amount == V.getConstantOperandVal(1));

2000 }

2001

2002 return false;

2003}

2004

2005SDValue HexagonDAGToDAGISel::factorOutPowerOf2(SDValue V, unsigned Power) {

2006 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };

2007 if (V.getOpcode() == ISD::MUL) {

2008 for (int i=0; i < 2; ++i) {

2010 V.getConstantOperandVal(i) % ((uint64_t)1 << Power) == 0) {

2011 uint64_t NewConst = V.getConstantOperandVal(i) >> Power;

2012 if (NewConst == 1)

2013 return Ops[!i];

2014 Ops[i] = CurDAG->getConstant(NewConst,

2015 SDLoc(V), V.getValueType());

2016 break;

2017 }

2018 }

2019 } else if (V.getOpcode() == ISD::SHL) {

2020 uint64_t ShiftAmount = V.getConstantOperandVal(1);

2021 if (ShiftAmount == Power)

2022 return Ops[0];

2023 Ops[1] = CurDAG->getConstant(ShiftAmount - Power,

2024 SDLoc(V), V.getValueType());

2025 }

2026

2027 return CurDAG->getNode(V.getOpcode(), SDLoc(V), V.getValueType(), Ops);

2028}

2029

2034

2035unsigned HexagonDAGToDAGISel::getUsesInFunction(const Value *V) {

2036 auto [It, Inserted] = GAUsesInFunction.try_emplace(V);

2037 if (!Inserted)

2038 return It->second;

2039

2040 unsigned Result = 0;

2041 const Function &CurF = CurDAG->getMachineFunction().getFunction();

2042 for (const User *U : V->users()) {

2046 }

2047

2048 It->second = Result;

2049

2051}

2052

2053

2054

2055

2056

2057

2058SDValue HexagonDAGToDAGISel::balanceSubTree(SDNode *N, bool TopLevel) {

2059 assert(RootWeights.count(N) && "Cannot balance non-root node.");

2060 assert(RootWeights[N] != -2 && "This node was RAUW'd!");

2062

2063

2064 if (RootWeights[N] != -1)

2066

2068

2071

2072

2075 SDNode *Op0N = Op0.getNode();

2076 int Weight;

2078 Weight = getWeight(balanceSubTree(Op0N).getNode());

2079

2080 } else

2081 Weight = getWeight(Op0N);

2082

2083 SDNode *Op1N = N->getOperand(1).getNode();

2085 Weight += getWeight(balanceSubTree(Op1N).getNode());

2086

2087 } else

2088 Weight += getWeight(Op1N);

2089

2090 RootWeights[N] = Weight;

2091 RootHeights[N] = std::max(getHeight(N->getOperand(0).getNode()),

2092 getHeight(N->getOperand(1).getNode())) + 1;

2093

2094 LLVM_DEBUG(dbgs() << "--> No need to balance root (Weight=" << Weight

2095 << " Height=" << RootHeights[N] << "): ");

2097

2099 }

2100

2103

2104 unsigned NOpcode = N->getOpcode();

2105

2106 LeafPrioQueue Leaves(NOpcode);

2109

2110

2113

2114 bool CanFactorize = false;

2115 WeightedLeaf Mul1, Mul2;

2116 unsigned MaxPowerOf2 = 0;

2117 WeightedLeaf GA;

2118

2119

2120

2121 bool HaveTopLevelShift = false;

2122 if (TopLevel &&

2127 HaveTopLevelShift = true;

2128

2129

2130

2131 int InsertionOrder = 0;

2132 SmallDenseMap<SDValue, int> NodeHeights;

2133 bool Imbalanced = false;

2134 int CurrentWeight = 0;

2135 while (!Worklist.empty()) {

2137

2138 if (Child.getNode() != N && RootWeights.count(Child.getNode())) {

2139

2140

2141 int Weight = RootWeights[Child.getNode()];

2142 if (Weight == -1) {

2143 Child = balanceSubTree(Child.getNode());

2144

2145 Weight = getWeight(Child.getNode());

2146 } else if (Weight == -2) {

2147

2148

2149

2150 LLVM_DEBUG(dbgs() << "--> Subtree was RAUWd. Restarting...\n");

2151 return balanceSubTree(N, TopLevel);

2152 }

2153

2154 NodeHeights[Child] = 1;

2155 CurrentWeight += Weight;

2156

2157 unsigned PowerOf2;

2158 if (TopLevel && !CanFactorize && !HaveTopLevelShift &&

2161

2162

2163

2164 if (!Mul1.Value.getNode()) {

2165 Mul1 = WeightedLeaf(Child, Weight, InsertionOrder++);

2166 MaxPowerOf2 = PowerOf2;

2167 } else {

2168 Mul2 = WeightedLeaf(Child, Weight, InsertionOrder++);

2169 MaxPowerOf2 = std::min(MaxPowerOf2, PowerOf2);

2170

2171

2172 if (MaxPowerOf2 > 3)

2173 MaxPowerOf2 = 3;

2174

2175 CanFactorize = true;

2176 }

2177 } else

2178 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));

2180

2181 int Weight = getWeight(Child.getNode());

2182

2183 NodeHeights[Child] = getHeight(Child.getNode());

2184 CurrentWeight += Weight;

2185

2187 GA = WeightedLeaf(Child, Weight, InsertionOrder++);

2188 else

2189 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));

2190 } else {

2191

2192

2193 unsigned ChildOpcode = Child.getOpcode();

2194 assert(ChildOpcode == NOpcode ||

2196

2197

2199 if (ChildOpcode == ISD::SHL)

2200 Op1 = getMultiplierForSHL(Child.getNode());

2201 else

2203

2205 assert(!NodeHeights.count(Child) && "Parent visited before children?");

2206

2210 } else {

2211

2212 if (std::abs(NodeHeights[Op1] - NodeHeights[Child->getOperand(0)]) > 1)

2213 Imbalanced = true;

2214

2215 NodeHeights[Child] = std::max(NodeHeights[Op1],

2216 NodeHeights[Child->getOperand(0)]) + 1;

2217 }

2218 }

2219 }

2220

2222 << " weight=" << CurrentWeight

2223 << " imbalanced=" << Imbalanced << "\n");

2224

2225

2226

2229 LLVM_DEBUG(dbgs() << "--> Found common factor for two MUL children!\n");

2230 int Weight = Mul1.Weight + Mul2.Weight;

2231 int Height = std::max(NodeHeights[Mul1.Value], NodeHeights[Mul2.Value]) + 1;

2232 SDValue Mul1Factored = factorOutPowerOf2(Mul1.Value, MaxPowerOf2);

2233 SDValue Mul2Factored = factorOutPowerOf2(Mul2.Value, MaxPowerOf2);

2235 Mul1Factored, Mul2Factored);

2239 Sum, Const);

2240 NodeHeights[New] = Height;

2241 Leaves.push(WeightedLeaf(New, Weight, Mul1.InsertionOrder));

2242 } else if (Mul1.Value.getNode()) {

2243

2244

2245 Leaves.push(Mul1);

2246 if (Mul2.Value.getNode())

2247 Leaves.push(Mul2);

2248 CanFactorize = false;

2249 }

2250

2251

2252

2253

2254 bool CombinedGA = false;

2255 if (NOpcode == ISD::ADD && GA.Value.getNode() && Leaves.hasConst() &&

2256 GA.Value.hasOneUse() && N->use_size() < 3) {

2257 GlobalAddressSDNode *GANode =

2260

2261 if (getUsesInFunction(GANode->getGlobal()) == 1 && Offset->hasOneUse() &&

2263 LLVM_DEBUG(dbgs() << "--> Combining GA and offset ("

2264 << Offset->getSExtValue() << "): ");

2266

2268 CurDAG->getTargetGlobalAddress(GANode->getGlobal(), SDLoc(GA.Value),

2270 GANode->getOffset() + (uint64_t)Offset->getSExtValue());

2271 GA.Value = CurDAG->getNode(GA.Value.getOpcode(), SDLoc(GA.Value),

2273 GA.Weight += Leaves.top().Weight;

2274

2275 NodeHeights[GA.Value] = getHeight(GA.Value.getNode());

2276 CombinedGA = true;

2277

2278 Leaves.pop();

2279 }

2280 }

2281

2284 RootWeights[N] = CurrentWeight;

2285 RootHeights[N] = NodeHeights[SDValue(N, 0)];

2286

2288 }

2289

2290

2292 WeightedLeaf SHL = Leaves.findSHL(31);

2293 if (SHL.Value.getNode()) {

2294 int Height = std::max(NodeHeights[GA.Value], NodeHeights[SHL.Value]) + 1;

2295 GA.Value = CurDAG->getNode(ISD::ADD, SDLoc(GA.Value),

2297 GA.Value, SHL.Value);

2298 GA.Weight = SHL.Weight;

2299 NodeHeights[GA.Value] = Height;

2300 }

2301 }

2302

2304 Leaves.push(GA);

2305

2306

2307

2308 if (TopLevel && !CanFactorize && Leaves.hasConst()) {

2309 LLVM_DEBUG(dbgs() << "--> Pushing constant to tip of tree.");

2310 Leaves.pushToBottom(Leaves.pop());

2311 }

2312

2313 const DataLayout &DL = CurDAG->getDataLayout();

2315

2316

2317 while (Leaves.size() > 1) {

2318 WeightedLeaf L0 = Leaves.pop();

2319

2320

2321

2322 WeightedLeaf L1 = Leaves.findMULbyConst();

2323 if (!L1.Value.getNode())

2324 L1 = Leaves.pop();

2325

2326 assert(L0.Weight <= L1.Weight && "Priority queue is broken!");

2327

2329 int V0Weight = L0.Weight;

2331 int V1Weight = L1.Weight;

2332

2333

2334 if ((RootWeights.count(V0.getNode()) && RootWeights[V0.getNode()] == -2) ||

2335 (RootWeights.count(V1.getNode()) && RootWeights[V1.getNode()] == -2)) {

2336 LLVM_DEBUG(dbgs() << "--> Subtree was RAUWd. Restarting...\n");

2337 return balanceSubTree(N, TopLevel);

2338 }

2339

2342 EVT VT = N->getValueType(0);

2344

2345 if (V0C && !V1C) {

2348 }

2349

2350

2352 "Children must have been visited before re-combining them!");

2353 int Height = std::max(NodeHeights[V0], NodeHeights[V1]) + 1;

2354

2355

2357 NewNode = CurDAG->getNode(

2358 ISD::SHL, SDLoc(V0), VT, V0,

2359 CurDAG->getConstant(

2362 else

2363 NewNode = CurDAG->getNode(NOpcode, SDLoc(N), VT, V0, V1);

2364

2365 NodeHeights[NewNode] = Height;

2366

2367 int Weight = V0Weight + V1Weight;

2368 Leaves.push(WeightedLeaf(NewNode, Weight, L0.InsertionOrder));

2369

2370 LLVM_DEBUG(dbgs() << "--> Built new node (Weight=" << Weight

2371 << ",Height=" << Height << "):\n");

2373 }

2374

2375 assert(Leaves.size() == 1);

2376 SDValue NewRoot = Leaves.top().Value;

2377

2379 int Height = NodeHeights[NewRoot];

2380

2381

2387 NewRoot = CurDAG->getNode(

2388 ISD::SHL, SDLoc(NewRoot), VT, V0,

2389 CurDAG->getConstant(

2392 }

2393 }

2394

2395 if (N != NewRoot.getNode()) {

2398

2399

2401

2402 RootWeights[N] = -2;

2403 } else {

2405 }

2406

2407 RootWeights[NewRoot.getNode()] = Leaves.top().Weight;

2408 RootHeights[NewRoot.getNode()] = Height;

2409

2410 return NewRoot;

2411}

2412

2413void HexagonDAGToDAGISel::rebalanceAddressTrees() {

2415 SDNode *N = &Node;

2416 if (N->getOpcode() != ISD::LOAD && N->getOpcode() != ISD::STORE)

2417 continue;

2418

2421 continue;

2422

2423

2424 if (RootWeights.count(BasePtr.getNode()))

2425 continue;

2426

2427 LLVM_DEBUG(dbgs() << "** Rebalancing address calculation in node: ");

2429

2430

2432

2435

2436 while (!Worklist.empty()) {

2438 unsigned Opcode = N->getOpcode();

2439

2441 continue;

2442

2443 Worklist.push_back(N->getOperand(0).getNode());

2444 Worklist.push_back(N->getOperand(1).getNode());

2445

2446

2447 if (N->hasOneUse() && Opcode == N->user_begin()->getOpcode())

2448 continue;

2449

2450

2451 RootWeights.try_emplace(N, -1);

2452 }

2453

2454

2455 RootWeights[BasePtr.getNode()] = -1;

2456 SDValue NewBasePtr = balanceSubTree(BasePtr.getNode(), true);

2457

2458 if (N->getOpcode() == ISD::LOAD)

2459 N = CurDAG->UpdateNodeOperands(N, N->getOperand(0),

2460 NewBasePtr, N->getOperand(2));

2461 else

2462 N = CurDAG->UpdateNodeOperands(N, N->getOperand(0), N->getOperand(1),

2463 NewBasePtr, N->getOperand(3));

2464

2467 }

2468

2469 CurDAG->RemoveDeadNodes();

2470 GAUsesInFunction.clear();

2471 RootHeights.clear();

2472 RootWeights.clear();

2473}

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

static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

Function Alias Analysis false

static const Function * getParent(const Value *V)

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static bool willShiftRightEliminate(SDValue V, unsigned Amount)

Definition HexagonISelDAGToDAG.cpp:1989

static cl::opt< bool > RebalanceOnlyImbalancedTrees("rebalance-only-imbal", cl::Hidden, cl::init(false), cl::desc("Rebalance address tree only if it is imbalanced"))

static unsigned getPowerOf2Factor(SDValue Val)

Definition HexagonISelDAGToDAG.cpp:1966

static cl::opt< bool > CheckSingleUse("hexagon-isel-su", cl::Hidden, cl::init(true), cl::desc("Enable checking of SDNode's single-use status"))

static cl::opt< bool > EnableAddressRebalancing("isel-rebalance-addr", cl::Hidden, cl::init(true), cl::desc("Rebalance address calculation trees to improve " "instruction selection"))

static bool isMemOPCandidate(SDNode *I, SDNode *U)

Definition HexagonISelDAGToDAG.cpp:1081

static bool isTargetConstant(const SDValue &V)

Definition HexagonISelDAGToDAG.cpp:2030

static bool isOpcodeHandled(const SDNode *N)

Definition HexagonISelDAGToDAG.cpp:1780

static cl::opt< bool > RebalanceOnlyForOptimizations("rebalance-only-opt", cl::Hidden, cl::init(false), cl::desc("Rebalance address tree only if this allows optimizations"))

const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

#define DEBUG_WITH_TYPE(TYPE,...)

DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.

static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")

Class for arbitrary precision integers.

unsigned getBitWidth() const

Return the number of bits in the APInt.

unsigned countr_zero() const

Count the number of trailing zero bits.

unsigned logBase2() const

bool getBoolValue() const

Convert APInt to a boolean value.

bool isPowerOf2() const

Check if this APInt's value is a power of two greater than zero.

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

uint64_t getZExtValue() const

const APInt & getAPIntValue() const

int64_t getSExtValue() const

size_type count(const_arg_type_t< KeyT > Val) const

Return 1 if the specified key is in the map, 0 otherwise.

FunctionPass class - This class is used to implement most global optimizations.

int64_t getOffset() const

const GlobalValue * getGlobal() const

This class is used to form a handle around another node that is persistent and is updated across invo...

const SDValue & getValue() const

HexagonDAGToDAGISelLegacy(HexagonTargetMachine &tm, CodeGenOptLevel OptLevel)

Definition HexagonISelDAGToDAG.cpp:67

void SelectAddSubCarry(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:794

void SelectConstant(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:752

void SelectIntrinsicWOChain(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:676

void Select(SDNode *N) override

Main hook for targets to transform nodes into machine nodes.

Definition HexagonISelDAGToDAG.cpp:1007

bool SelectNewCircIntrinsic(SDNode *IntN)

Generate a machine instruction node for the new circular buffer intrinsics.

Definition HexagonISelDAGToDAG.cpp:370

bool tryLoadOfLoadIntrinsic(LoadSDNode *N)

Definition HexagonISelDAGToDAG.cpp:262

void SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl)

Definition HexagonISelDAGToDAG.cpp:76

void SelectExtractSubvector(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:710

void SelectVAlign(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:803

MachineSDNode * LoadInstrForLoadIntrinsic(SDNode *IntN)

Definition HexagonISelDAGToDAG.cpp:195

bool SelectAnyImm2(SDValue &N, SDValue &R)

Definition HexagonISelDAGToDAG.cpp:1487

bool SelectAnyImm(SDValue &N, SDValue &R)

Definition HexagonISelDAGToDAG.cpp:1477

void SelectV65GatherPred(SDNode *N)

bool SelectAnyImm0(SDValue &N, SDValue &R)

Definition HexagonISelDAGToDAG.cpp:1481

void SelectSHL(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:579

void SelectIntrinsicWChain(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:637

void SelectV2Q(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:889

bool SelectAnyImm1(SDValue &N, SDValue &R)

Definition HexagonISelDAGToDAG.cpp:1484

void SelectConstantFP(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:731

bool DetectUseSxtw(SDValue &N, SDValue &R)

Definition HexagonISelDAGToDAG.cpp:1589

bool SelectBrevLdIntrinsic(SDNode *IntN)

Definition HexagonISelDAGToDAG.cpp:329

void emitFunctionEntryCode() override

Definition HexagonISelDAGToDAG.cpp:1419

bool SelectAddrFI(SDValue &N, SDValue &R)

Definition HexagonISelDAGToDAG.cpp:1457

void FDiv(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:916

SDNode * StoreInstrForLoadIntrinsic(MachineSDNode *LoadN, SDNode *IntN)

Definition HexagonISelDAGToDAG.cpp:227

bool SelectAddrGP(SDValue &N, SDValue &R)

Definition HexagonISelDAGToDAG.cpp:1473

bool SelectAnyImmediate(SDValue &N, SDValue &R, Align Alignment)

Definition HexagonISelDAGToDAG.cpp:1503

bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP, Align Alignment)

Definition HexagonISelDAGToDAG.cpp:1544

void SelectFrameIndex(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:765

bool SelectAnyImm3(SDValue &N, SDValue &R)

Definition HexagonISelDAGToDAG.cpp:1490

void FastFDiv(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:967

void SelectFDiv(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:1000

void SelectStore(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:565

void SelectLoad(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:456

HexagonDAGToDAGISel()=delete

bool SelectAnyInt(SDValue &N, SDValue &R)

Definition HexagonISelDAGToDAG.cpp:1494

bool SelectAddrGA(SDValue &N, SDValue &R)

Definition HexagonISelDAGToDAG.cpp:1469

void PreprocessISelDAG() override

PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...

Definition HexagonISelDAGToDAG.cpp:1359

void SelectTypecast(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:865

void SelectD2P(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:880

void SelectVAlignAddr(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:850

void SelectP2D(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:873

bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps) override

SelectInlineAsmMemoryOperand - Implement addressing mode selection for inline asm expressions.

Definition HexagonISelDAGToDAG.cpp:1059

void SelectV65Gather(SDNode *N)

void SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl)

Definition HexagonISelDAGToDAG.cpp:474

void SelectHVXDualOutput(SDNode *N)

void SelectQ2V(SDNode *N)

Definition HexagonISelDAGToDAG.cpp:903

Hexagon target-specific information for each MachineFunction.

const HexagonFrameLowering * getFrameLowering() const override

This class is used to represent ISD::LOAD nodes.

unsigned getVectorNumElements() const

TypeSize getSizeInBits() const

Returns the size of the specified MVT in bits.

MVT getVectorElementType() const

static MVT getIntegerVT(unsigned BitWidth)

The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.

bool hasVarSizedObjects() const

This method may be called any time after instruction selection is complete to determine if the stack ...

Align getMaxAlign() const

Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...

bool isFixedObjectIndex(int ObjectIdx) const

Returns true if the specified index corresponds to a fixed stack object.

const TargetSubtargetInfo & getSubtarget() const

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

MachineFrameInfo & getFrameInfo()

getFrameInfo - Return the frame info object for the current function.

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

Representation of each machine instruction.

A description of a memory reference used in the backend.

An SDNode that represents everything that will be needed to construct a MachineInstr.

This is an abstract virtual class for memory operations.

Wrapper class representing virtual and physical registers.

constexpr bool isValid() const

Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...

Represents one node in the SelectionDAG.

LLVM_ABI void dump() const

Dump this node, for debugging.

unsigned getOpcode() const

Return the SelectionDAG opcode value for this node.

bool hasOneUse() const

Return true if there is exactly one use of this node.

unsigned getNumValues() const

Return the number of values defined/returned by this operator.

unsigned getNumOperands() const

Return the number of values used by this operation.

unsigned getMachineOpcode() const

This may only be called if isMachineOpcode returns true.

const SDValue & getOperand(unsigned Num) const

uint64_t getConstantOperandVal(unsigned Num) const

Helper method returns the integer value of a ConstantSDNode operand.

EVT getValueType(unsigned ResNo) const

Return the type of a specified result.

user_iterator user_begin() const

Provide iteration support to walk over all users of an SDNode.

Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.

SDNode * getNode() const

get the SDNode which holds the desired result

bool hasOneUse() const

Return true if there is exactly one node using value ResNo of Node.

EVT getValueType() const

Return the ValueType of the referenced return value.

const SDValue & getOperand(unsigned i) const

uint64_t getConstantOperandVal(unsigned i) const

unsigned getOpcode() const

SelectionDAGISelLegacy(char &ID, std::unique_ptr< SelectionDAGISel > S)

const TargetLowering * TLI

void ReplaceUses(SDValue F, SDValue T)

ReplaceUses - replace all uses of the old node F with the use of the new node T.

void ReplaceNode(SDNode *F, SDNode *T)

Replace all uses of F with T, then remove F from the DAG.

const TargetLowering * getTargetLowering() const

LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)

These are used for target selectors to create a new node with specified return type(s),...

LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)

Return a bitcast using the SDLoc of the value operand, and casting to the provided type.

LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)

Create a ConstantSDNode wrapping a constant value.

LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)

Modify anything using 'From' to use 'To' instead.

LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)

Gets or creates the specified node.

iterator erase(const_iterator CI)

void push_back(const T &Elt)

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

This class is used to represent ISD::STORE nodes.

Align getStackAlign() const

getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...

LLVM Value Representation.

#define llvm_unreachable(msg)

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

Abstract Attribute helper functions.

constexpr std::underlying_type_t< E > Mask()

Get a bitmask with 1s in all places up to the high-order bit of E's largest value.

@ C

The default llvm calling convention, compatible with C.

@ ADD

Simple integer binary arithmetic operators.

@ ANY_EXTEND

ANY_EXTEND - Used for integer types. The high bits are undefined.

@ SIGN_EXTEND

Conversion operators.

@ SELECT

Select(COND, TRUEVAL, FALSEVAL).

@ TargetGlobalAddress

TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...

@ SHL

Shift and rotation operations.

@ VECTOR_SHUFFLE

VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.

@ EXTRACT_SUBVECTOR

EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.

@ ZERO_EXTEND

ZERO_EXTEND - Used for integer types, zeroing the new bits.

@ SIGN_EXTEND_INREG

SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...

@ AND

Bitwise operators - logical and, logical or, logical xor.

@ INTRINSIC_WO_CHAIN

RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...

@ AssertSext

AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...

@ INTRINSIC_W_CHAIN

RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...

MemIndexedMode

MemIndexedMode enum - This enum defines the load / store indexed addressing modes.

LoadExtType

LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).

initializer< Ty > init(const Ty &Val)

NodeAddr< UseNode * > Use

NodeAddr< NodeBase * > Node

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)

Get the size of a range.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

constexpr bool isInt(int64_t x)

Checks if an integer fits into the given bit width.

LLVM_ABI bool isNullConstant(SDValue V)

Returns true if V is a constant integer zero.

decltype(auto) dyn_cast(const From &Val)

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

int countr_one(T Value)

Count the number of ones from the least significant bit to the first zero bit.

bool isAligned(Align Lhs, uint64_t SizeInBytes)

Checks that SizeInBytes is a multiple of the alignment.

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

int countr_zero(T Val)

Count number of 0's from the least significant bit to the most stopping at the first 1.

unsigned M1(unsigned Val)

static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)

int countl_zero(T Val)

Count number of 0's from the most significant bit to the least stopping at the first 1.

constexpr bool isPowerOf2_32(uint32_t Value)

Return true if the argument is a power of two > 0.

LLVM_ABI raw_ostream & dbgs()

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

CodeGenOptLevel

Code generation optimization level.

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

uint16_t MCPhysReg

An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...

FunctionPass * createHexagonISelDag(HexagonTargetMachine &TM, CodeGenOptLevel OptLevel)

createHexagonISelDag - This pass converts a legalized DAG into a Hexagon-specific DAG,...

Definition HexagonISelDAGToDAG.cpp:61

DWARFExpression::Operation Op

unsigned M0(unsigned Val)

decltype(auto) cast(const From &Val)

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

@ Default

The result values are uniform if and only if all operands are uniform.

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

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

Implement std::swap in terms of BitVector swap.

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

constexpr uint64_t value() const

This is a hole in the type system and should not be abused.

bool isSimple() const

Test if the given EVT is simple (as opposed to being extended).

TypeSize getSizeInBits() const

Return the size of the specified value type in bits.

MVT getSimpleVT() const

Return the SimpleValueType held in the specified simple EVT.

bool isVector() const

Return true if this is a vector value type.

EVT getVectorElementType() const

Given a vector type, return the type of each element.

bool isInteger() const

Return true if this is an integer or a vector integer type.

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

This represents a list of ValueType's that has been intern'd by a SelectionDAG.