LLVM: lib/Target/X86/GISel/X86LegalizerInfo.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

24#include "llvm/IR/IntrinsicsX86.h"

26

27using namespace llvm;

31

34 : Subtarget(STI) {

35

36 bool Is64Bit = Subtarget.is64Bit();

37 bool HasCMOV = Subtarget.canUseCMOV();

38 bool HasSSE1 = Subtarget.hasSSE1();

39 bool HasSSE2 = Subtarget.hasSSE2();

40 bool HasSSE41 = Subtarget.hasSSE41();

41 bool HasAVX = Subtarget.hasAVX();

42 bool HasAVX2 = Subtarget.hasAVX2();

43 bool HasAVX512 = Subtarget.hasAVX512();

44 bool HasVLX = Subtarget.hasVLX();

45 bool HasDQI = Subtarget.hasAVX512() && Subtarget.hasDQI();

46 bool HasBWI = Subtarget.hasAVX512() && Subtarget.hasBWI();

47 bool UseX87 = !Subtarget.useSoftFloat() && Subtarget.hasX87();

48 bool HasPOPCNT = Subtarget.hasPOPCNT();

49 bool HasLZCNT = Subtarget.hasLZCNT();

50 bool HasBMI = Subtarget.hasBMI();

51

60 const LLT sMaxScalar = Subtarget.is64Bit() ? s64 : s32;

63

69

75

80

81 const LLT s8MaxVector = HasAVX512 ? v64s8 : HasAVX ? v32s8 : v16s8;

82 const LLT s16MaxVector = HasAVX512 ? v32s16 : HasAVX ? v16s16 : v8s16;

83 const LLT s32MaxVector = HasAVX512 ? v16s32 : HasAVX ? v8s32 : v4s32;

84 const LLT s64MaxVector = HasAVX512 ? v8s64 : HasAVX ? v4s64 : v2s64;

85

86

87

88

89

90

91

93 {G_IMPLICIT_DEF, G_PHI, G_FREEZE, G_CONSTANT_FOLD_BARRIER})

94 .legalFor({p0, s1, s8, s16, s32, s64})

95 .legalFor(UseX87, {s80})

96 .legalFor(Is64Bit, {s128})

97 .legalFor(HasSSE2, {v16s8, v8s16, v4s32, v2s64})

98 .legalFor(HasAVX, {v32s8, v16s16, v8s32, v4s64})

99 .legalFor(HasAVX512, {v64s8, v32s16, v16s32, v8s64})

100 .widenScalarOrEltToNextPow2(0, 8)

101 .clampScalarOrElt(0, s8, sMaxScalar)

102 .moreElementsToNextPow2(0)

103 .clampMinNumElements(0, s8, 16)

104 .clampMinNumElements(0, s16, 8)

105 .clampMinNumElements(0, s32, 4)

106 .clampMinNumElements(0, s64, 2)

107 .clampMaxNumElements(0, s8, HasAVX512 ? 64 : (HasAVX ? 32 : 16))

108 .clampMaxNumElements(0, s16, HasAVX512 ? 32 : (HasAVX ? 16 : 8))

109 .clampMaxNumElements(0, s32, HasAVX512 ? 16 : (HasAVX ? 8 : 4))

110 .clampMaxNumElements(0, s64, HasAVX512 ? 8 : (HasAVX ? 4 : 2))

111 .clampMaxNumElements(0, p0,

112 Is64Bit ? s64MaxVector.getNumElements()

113 : s32MaxVector.getNumElements())

115

117 .legalFor({p0, s8, s16, s32})

118 .legalFor(Is64Bit, {s64})

119 .widenScalarToNextPow2(0, 8)

121

123 G_FSIN, G_FSINH, G_FASIN, G_FTAN, G_FTANH,

124 G_FATAN, G_FATAN2, G_FPOW, G_FEXP, G_FEXP2,

125 G_FEXP10, G_FLOG, G_FLOG2, G_FLOG10, G_FPOWI,

126 G_FSINCOS, G_FCEIL, G_FFLOOR})

128

130 .legalFor(HasSSE1 || UseX87, {s32})

131 .legalFor(HasSSE2 || UseX87, {s64})

132 .legalFor(UseX87, {s80});

133

135 .customFor({s32});

136

137

138 for (unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {

139 unsigned BigTyIdx = Op == G_MERGE_VALUES ? 0 : 1;

140 unsigned LitTyIdx = Op == G_MERGE_VALUES ? 1 : 0;

147 switch (Q.Types[BigTyIdx].getSizeInBits()) {

148 case 16:

149 case 32:

150 case 64:

151 case 128:

152 case 256:

153 case 512:

154 break;

155 default:

156 return false;

157 }

158 switch (Q.Types[LitTyIdx].getSizeInBits()) {

159 case 8:

160 case 16:

161 case 32:

162 case 64:

163 case 128:

164 case 256:

165 return true;

166 default:

167 return false;

168 }

169 });

170 }

171

173 .widenScalarToNextPow2(0, 32)

175

176

178 .legalFor({s8, s16, s32})

179 .legalFor(Is64Bit, {s64})

180 .legalFor(HasSSE2, {v16s8, v8s16, v4s32, v2s64})

181 .legalFor(HasAVX2, {v32s8, v16s16, v8s32, v4s64})

182 .legalFor(HasAVX512, {v16s32, v8s64})

183 .legalFor(HasBWI, {v64s8, v32s16})

184 .clampMinNumElements(0, s8, 16)

195

197 .legalFor({{s8, s8}, {s16, s8}, {s32, s8}})

198 .legalFor(Is64Bit, {{s64, s8}})

199 .widenScalarToNextPow2(0, 32)

203

204

207 .legalFor(Is64Bit, {s64})

208 .legalFor(HasSSE2, {v8s16})

209 .legalFor(HasSSE41, {v4s32})

210 .legalFor(HasAVX2, {v16s16, v8s32})

211 .legalFor(HasAVX512, {v16s32})

212 .legalFor(HasDQI, {v8s64})

213 .legalFor(HasDQI && HasVLX, {v2s64, v4s64})

214 .legalFor(HasBWI, {v32s16})

215 .clampMinNumElements(0, s16, 8)

224

226 .legalFor({s8, s16, s32})

227 .legalFor(Is64Bit, {s64})

228 .widenScalarToNextPow2(0, 32)

231

232

234 .legalFor({s8, s16, s32})

235 .legalFor(Is64Bit, {s64})

236 .libcallFor({s64})

237 .clampScalar(0, s8, sMaxScalar);

238

239

241 .legalFor({{s8, s8}, {s16, s8}, {s32, s8}})

242 .legalFor(Is64Bit, {{s64, s8}})

243 .clampScalar(0, s8, sMaxScalar)

245

246

248 .legalFor({s8, s16, s32})

249 .legalFor(Is64Bit, {s64})

250 .legalFor(HasSSE2, {v16s8, v8s16, v4s32, v2s64})

251 .legalFor(HasAVX, {v32s8, v16s16, v8s32, v4s64})

252 .legalFor(HasAVX512, {v64s8, v32s16, v16s32, v8s64})

253 .clampMinNumElements(0, s8, 16)

264

265

266 const std::initializer_list IntTypes32 = {s8, s16, s32, p0};

267 const std::initializer_list IntTypes64 = {s8, s16, s32, s64, p0};

268

271 .clampScalar(0, s8, s8)

273

274

277 .legalFor(Is64Bit, {s64})

278 .widenScalarToNextPow2(0, 32)

280

281

283 .legalFor(HasPOPCNT, {{s16, s16}, {s32, s32}})

284 .legalFor(HasPOPCNT && Is64Bit, {{s64, s64}})

285 .widenScalarToNextPow2(1, 16)

288

289

291 .legalFor(HasLZCNT, {{s16, s16}, {s32, s32}})

292 .legalFor(HasLZCNT && Is64Bit, {{s64, s64}})

293 .widenScalarToNextPow2(1, 16)

296

297

299 .legalFor({{s16, s16}, {s32, s32}})

300 .legalFor(Is64Bit, {{s64, s64}})

301 .widenScalarToNextPow2(1, 16)

304

306 .legalFor(HasBMI, {{s16, s16}, {s32, s32}})

307 .legalFor(HasBMI && Is64Bit, {{s64, s64}})

308 .widenScalarToNextPow2(1, 16)

311

313

314

315 const std::initializer_list PtrTypes32 = {s1, s8, s16, s32};

316 const std::initializer_list PtrTypes64 = {s1, s8, s16, s32, s64};

317

320 .maxScalar(0, sMaxScalar)

322

324

326

329 .legalFor(Is64Bit, {{p0, s64}})

330 .widenScalarToNextPow2(1, 32)

332

334

335

336 for (unsigned Op : {G_LOAD, G_STORE}) {

338 Action.legalForTypesWithMemDesc({{s8, p0, s8, 1},

339 {s16, p0, s16, 1},

340 {s32, p0, s32, 1},

341 {s80, p0, s80, 1},

342 {p0, p0, p0, 1},

343 {v4s8, p0, v4s8, 1}});

344 if (Is64Bit)

345 Action.legalForTypesWithMemDesc(

346 {{s64, p0, s64, 1}, {v2s32, p0, v2s32, 1}});

347

348 if (HasSSE1)

349 Action.legalForTypesWithMemDesc({{v4s32, p0, v4s32, 1}});

350 if (HasSSE2)

351 Action.legalForTypesWithMemDesc({{v16s8, p0, v16s8, 1},

352 {v8s16, p0, v8s16, 1},

353 {v2s64, p0, v2s64, 1},

354 {v2p0, p0, v2p0, 1}});

355 if (HasAVX)

356 Action.legalForTypesWithMemDesc({{v32s8, p0, v32s8, 1},

357 {v16s16, p0, v16s16, 1},

358 {v8s32, p0, v8s32, 1},

359 {v4s64, p0, v4s64, 1},

360 {v4p0, p0, v4p0, 1}});

361 if (HasAVX512)

362 Action.legalForTypesWithMemDesc({{v64s8, p0, v64s8, 1},

363 {v32s16, p0, v32s16, 1},

364 {v16s32, p0, v16s32, 1},

365 {v8s64, p0, v8s64, 1}});

366

367

368 if (Op == G_LOAD) {

369 Action.legalForTypesWithMemDesc({{s8, p0, s1, 1},

370 {s16, p0, s8, 1},

371 {s32, p0, s8, 1},

372 {s32, p0, s16, 1}});

373 if (Is64Bit)

374 Action.legalForTypesWithMemDesc(

375 {{s64, p0, s8, 1}, {s64, p0, s16, 1}, {s64, p0, s32, 1}});

376 } else {

377 Action.customIf([=](const LegalityQuery &Query) {

378 return Query.Types[0] != Query.MMODescrs[0].MemoryTy;

379 });

380 }

381 Action.widenScalarToNextPow2(0, 8)

382 .clampScalar(0, s8, sMaxScalar)

383 .scalarize(0);

384 }

385

386 for (unsigned Op : {G_SEXTLOAD, G_ZEXTLOAD}) {

388 Action.legalForTypesWithMemDesc(

389 {{s16, p0, s8, 1}, {s32, p0, s8, 1}, {s32, p0, s16, 1}});

390 if (Is64Bit)

391 Action.legalForTypesWithMemDesc(

392 {{s64, p0, s8, 1}, {s64, p0, s16, 1}, {s64, p0, s32, 1}});

393

394 }

395

396

398 .legalFor({s8, s16, s32, s128})

399 .legalFor(Is64Bit, {s64})

400 .widenScalarToNextPow2(0, 8)

405

407 .legalFor({s8, s16, s32})

408 .legalFor(Is64Bit, {s64})

409 .widenScalarToNextPow2(0, 8)

414

416

417

420 .legalFor(UseX87, {s80});

421

422

424 .legalFor({s32, s64})

425 .legalFor(HasSSE1, {v4s32})

426 .legalFor(HasSSE2, {v2s64})

427 .legalFor(HasAVX, {v8s32, v4s64})

428 .legalFor(HasAVX512, {v16s32, v8s64})

429 .legalFor(UseX87, {s80});

430

433 .legalFor(UseX87 && !Is64Bit, {s64})

434 .lower();

435

436

438 .legalFor(HasSSE1 || UseX87, {s8, s32})

439 .legalFor(HasSSE2 || UseX87, {s8, s64})

440 .legalFor(UseX87, {s8, s80})

441 .clampScalar(0, s8, s8)

442 .clampScalar(1, s32, HasSSE2 ? s64 : s32)

444

445

447 .legalFor(HasSSE2, {{s64, s32}})

448 .legalFor(HasAVX, {{v4s64, v4s32}})

449 .legalFor(HasAVX512, {{v8s64, v8s32}});

450

452 .legalFor(HasSSE2, {{s32, s64}})

453 .legalFor(HasAVX, {{v4s32, v4s64}})

454 .legalFor(HasAVX512, {{v8s32, v8s64}});

455

457 .legalFor(HasSSE1, {{s32, s32}})

458 .legalFor(HasSSE1 && Is64Bit, {{s32, s64}})

459 .legalFor(HasSSE2, {{s64, s32}})

460 .legalFor(HasSSE2 && Is64Bit, {{s64, s64}})

461 .clampScalar(1, (UseX87 && !HasSSE1) ? s16 : s32, sMaxScalar)

464 .clampScalar(0, s32, HasSSE2 ? s64 : s32)

466

468 .legalFor(HasSSE1, {{s32, s32}})

469 .legalFor(HasSSE1 && Is64Bit, {{s64, s32}})

470 .legalFor(HasSSE2, {{s32, s64}})

471 .legalFor(HasSSE2 && Is64Bit, {{s64, s64}})

472 .clampScalar(0, (UseX87 && !HasSSE1) ? s16 : s32, sMaxScalar)

475 .clampScalar(1, s32, HasSSE2 ? s64 : s32)

477

478

479

480

481

482

483

484

486 .legalFor(HasAVX512, {{s32, s32}, {s32, s64}, {s64, s32}, {s64, s64}})

488 return !HasAVX512 &&

489 ((HasSSE1 && typeIs(0, s32)(Query)) ||

490 (HasSSE2 && typeIs(0, s64)(Query))) &&

492 })

494

495 return !HasAVX512 &&

496 ((HasSSE1 && typeIs(0, s32)(Query)) ||

497 (HasSSE2 && typeIs(0, s64)(Query))) &&

498 (Is64Bit && typeIs(1, s64)(Query));

499 })

500 .clampScalar(0, s32, HasSSE2 ? s64 : s32)

504

506 .legalFor(HasAVX512, {{s32, s32}, {s32, s64}, {s64, s32}, {s64, s64}})

508 return !HasAVX512 &&

509 ((HasSSE1 && typeIs(1, s32)(Query)) ||

510 (HasSSE2 && typeIs(1, s64)(Query))) &&

512 })

513

514

515

516

518 return !HasAVX512 &&

519 ((HasSSE1 && typeIs(1, s32)(Query)) ||

520 (HasSSE2 && typeIs(1, s64)(Query))) &&

521 (Is64Bit && typeIs(0, s64)(Query));

522 })

523 .clampScalar(0, s32, sMaxScalar)

525 .clampScalar(1, s32, HasSSE2 ? s64 : s32)

527

528

531 return (HasSSE1 && typeInSet(0, {v4s32})(Query)) ||

532 (HasSSE2 && typeInSet(0, {v2s64, v8s16, v16s8})(Query)) ||

533 (HasAVX && typeInSet(0, {v4s64, v8s32, v16s16, v32s8})(Query)) ||

534 (HasAVX512 && typeInSet(0, {v8s64, v16s32, v32s16, v64s8}));

535 })

536 .clampNumElements(0, v16s8, s8MaxVector)

541

544 unsigned SubIdx = Query.Opcode == G_EXTRACT ? 0 : 1;

545 unsigned FullIdx = Query.Opcode == G_EXTRACT ? 1 : 0;

547 {{v16s8, v32s8},

548 {v8s16, v16s16},

549 {v4s32, v8s32},

550 {v2s64, v4s64}})(Query)) ||

552 {{v16s8, v64s8},

553 {v32s8, v64s8},

554 {v8s16, v32s16},

555 {v16s16, v32s16},

556 {v4s32, v16s32},

557 {v8s32, v16s32},

558 {v2s64, v8s64},

559 {v4s64, v8s64}})(Query));

560 });

561

562

565 HasSSE1,

566 {{v32s8, v16s8}, {v16s16, v8s16}, {v8s32, v4s32}, {v4s64, v2s64}})

567 .legalFor(HasAVX, {{v64s8, v16s8},

568 {v64s8, v32s8},

569 {v32s16, v8s16},

570 {v32s16, v16s16},

571 {v16s32, v4s32},

572 {v16s32, v8s32},

573 {v8s64, v2s64},

574 {v8s64, v4s64}});

575

576

578 .legalFor({{s16, s32}, {s32, s32}, {p0, s32}})

579 .legalFor(!HasCMOV, {{s8, s32}})

580 .legalFor(Is64Bit, {{s64, s32}})

581 .legalFor(UseX87, {{s80, s32}})

582 .clampScalar(1, s32, s32)

584 .clampScalar(0, HasCMOV ? s16 : s8, sMaxScalar);

585

586

588

590 .lower();

591

592

597

600}

601

606 switch (MI.getOpcode()) {

607 default:

608

609 return false;

610 case TargetOpcode::G_BUILD_VECTOR:

611 return legalizeBuildVector(MI, MRI, Helper);

612 case TargetOpcode::G_FPTOUI:

613 return legalizeFPTOUI(MI, MRI, Helper);

614 case TargetOpcode::G_UITOFP:

615 return legalizeUITOFP(MI, MRI, Helper);

616 case TargetOpcode::G_STORE:

617 return legalizeNarrowingStore(MI, MRI, Helper);

618 case TargetOpcode::G_SITOFP:

619 return legalizeSITOFP(MI, MRI, Helper);

620 case TargetOpcode::G_FPTOSI:

621 return legalizeFPTOSI(MI, MRI, Helper);

622 case TargetOpcode::G_GET_ROUNDING:

623 return legalizeGETROUNDING(MI, MRI, Helper);

624 case TargetOpcode::G_SET_ROUNDING:

625 return legalizeSETROUNDING(MI, MRI, Helper);

626 }

628}

629

630bool X86LegalizerInfo::legalizeSITOFP(MachineInstr &MI,

635 auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();

636

637 assert((SrcTy.getSizeInBits() == 16 || SrcTy.getSizeInBits() == 32 ||

638 SrcTy.getSizeInBits() == 64) &&

639 "Unexpected source type for SITOFP in X87 mode.");

640

641 TypeSize MemSize = SrcTy.getSizeInBytes();

647

648

649 MIRBuilder.buildStore(Src, SlotPointer, *StoreMMO);

650

655 .addUse(SlotPointer.getReg(0))

657

658 MI.eraseFromParent();

659 return true;

660}

661

662bool X86LegalizerInfo::legalizeFPTOSI(MachineInstr &MI,

667 auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();

668

669 TypeSize MemSize = DstTy.getSizeInBytes();

675

678 .addUse(SlotPointer.getReg(0))

680

681 MIRBuilder.buildLoad(Dst, SlotPointer, PtrInfo, Align(MemSize));

682 MI.eraseFromParent();

683 return true;

684}

685

686bool X86LegalizerInfo::legalizeBuildVector(MachineInstr &MI,

689 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;

691 Register Dst = BuildVector.getReg(0);

692 LLT DstTy = MRI.getType(Dst);

693 MachineFunction &MF = MIRBuilder.getMF();

696

698 for (unsigned i = 0; i < BuildVector.getNumSources(); ++i) {

700

702 if (ValueAndReg) {

703 CstIdxs.emplace_back(ConstantInt::get(Ctx, ValueAndReg->Value));

704 continue;

705 }

706

708 if (FPValueAndReg) {

709 CstIdxs.emplace_back(ConstantFP::get(Ctx, FPValueAndReg->Value));

710 continue;

711 }

712

715 continue;

716 }

717 return false;

718 }

719

721

723 unsigned AddrSpace = DL.getDefaultGlobalsAddressSpace();

724 Align Alignment(DL.getABITypeAlign(ConstVal->getType()));

726 LLT::pointer(AddrSpace, DL.getPointerSizeInBits(AddrSpace)),

728 MachineMemOperand *MMO =

731

732 MIRBuilder.buildLoad(Dst, Addr, *MMO);

733 MI.eraseFromParent();

734 return true;

735}

736

737bool X86LegalizerInfo::legalizeFPTOUI(MachineInstr &MI,

740 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;

741 auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();

742 unsigned DstSizeInBits = DstTy.getScalarSizeInBits();

745

746

747 if (DstSizeInBits <= 32) {

748 auto Casted = MIRBuilder.buildFPTOSI(DstTy == s32 ? s64 : s32, Src);

750 MI.eraseFromParent();

751 return true;

752 }

753

754 return false;

755}

756

757bool X86LegalizerInfo::legalizeUITOFP(MachineInstr &MI,

760 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;

761 auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();

764

765

766 if (SrcTy.getSizeInBits() <= 32) {

767 auto Ext = MIRBuilder.buildZExt(SrcTy == s32 ? s64 : s32, Src);

769 MI.eraseFromParent();

770 return true;

771 }

772

773 return false;

774}

775

776bool X86LegalizerInfo::legalizeNarrowingStore(MachineInstr &MI,

780 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;

781 MachineMemOperand &MMO = **Store.memoperands_begin();

782 MachineFunction &MF = MIRBuilder.getMF();

783 LLT ValTy = MRI.getType(Store.getValueReg());

785

787 Store.setMemRefs(MF, {NewMMO});

789 return true;

790}

791

792bool X86LegalizerInfo::legalizeGETROUNDING(MachineInstr &MI,

795

796

797

798

799

800

801

802

803

804

805

806

807

808

809

810

811

812

813

814

815

816

817 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;

818 MachineFunction &MF = MIRBuilder.getMF();

819 Register Dst = MI.getOperand(0).getReg();

820 LLT DstTy = MRI.getType(Dst);

824

825

826 int MemSize = 2;

828 MachinePointerInfo PtrInfo;

830 Alignment, PtrInfo);

832

834 MemSize, Alignment);

835

836

837 MIRBuilder.buildInstr(X86::G_FNSTCW16)

840

841

843 MemSize, Alignment);

844

845 auto CWD32 =

846 MIRBuilder.buildZExt(s32, MIRBuilder.buildLoad(s16, StackPtr, *LoadMMO));

847 auto Shifted8 = MIRBuilder.buildTrunc(

849 auto Masked32 = MIRBuilder.buildZExt(

851

852

853

854

855

857 auto LUTShifted = MIRBuilder.buildLShr(s32, LUT, Masked32);

858 auto RetVal =

860 auto RetValTrunc = MIRBuilder.buildZExtOrTrunc(DstTy, RetVal);

861

862 MIRBuilder.buildCopy(Dst, RetValTrunc);

863

864 MI.eraseFromParent();

865 return true;

866}

867

868bool X86LegalizerInfo::legalizeSETROUNDING(MachineInstr &MI,

871 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;

872 MachineFunction &MF = MIRBuilder.getMF();

873 Register Src = MI.getOperand(0).getReg();

877

878

879 int MemSize = 4;

881 MachinePointerInfo PtrInfo;

883 Alignment, PtrInfo);

885

886 auto StoreMMO =

888 MIRBuilder.buildInstr(X86::G_FNSTCW16)

891

892 auto LoadMMO =

894 auto CWD16 = MIRBuilder.buildLoad(s16, StackPtr, *LoadMMO);

895

896

897 auto ClearedCWD =

899

900

901 auto *SrcDef = MRI.getVRegDef(Src);

904

905 if (SrcDef && SrcDef->getOpcode() == TargetOpcode::G_CONSTANT) {

908

912 C.diagnose(DiagnosticInfoUnsupported(

913 MF.getFunction(), "rounding mode is not supported by X86 hardware",

914 DiagnosticLocation(MI.getDebugLoc()), DS_Error));

915 return false;

916 }

917

918 FieldVal = FieldVal << 3;

921 } else {

922

923

925 auto ShiftAmt = MIRBuilder.buildAdd(

928 auto ShiftAmt8 = MIRBuilder.buildTrunc(s8, ShiftAmt);

930 ShiftAmt8);

931 RMBits =

934

935

936 auto RMBits32 = MIRBuilder.buildZExt(s32, RMBits);

937 MXCSRRMBits =

940 }

941

942 auto NewCWD =

944

945

946 auto StoreNewMMO =

948 MIRBuilder.buildStore(NewCWD, StackPtr, *StoreNewMMO);

949

950

951 auto LoadNewMMO =

953 MIRBuilder.buildInstr(X86::G_FLDCW16)

956

957 if (Subtarget.hasSSE1()) {

958

961 MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS)

965

966

969 auto MXCSR = MIRBuilder.buildLoad(s32, StackPtr, *LoadMXCSRMMO);

970

971

972 auto ClearedMXCSR = MIRBuilder.buildAnd(

973 s32, MXCSR, MIRBuilder.buildConstant(s32, 0xffff9fff));

974

975

976 auto NewMXCSR = MIRBuilder.buildOr(s32, ClearedMXCSR, MXCSRRMBits);

977

978

981 MIRBuilder.buildStore(NewMXCSR, StackPtr, *StoreNewMXCSRMMO);

982

983

986 MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS)

990 }

991

992 MI.eraseFromParent();

993 return true;

994}

995

unsigned const MachineRegisterInfo * MRI

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

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static void scalarize(Instruction *I, SmallVectorImpl< Instruction * > &Worklist)

Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...

This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...

This file declares the MachineIRBuilder class.

Promote Memory to Register

This file declares the targeting of the Machinelegalizer class for X86.

uint64_t getZExtValue() const

Get zero extended value.

static LLVM_ABI Constant * get(ArrayRef< Constant * > V)

LLVMContext & getContext() const

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

virtual void changingInstr(MachineInstr &MI)=0

This instruction is about to be mutated in some way.

virtual void changedInstr(MachineInstr &MI)=0

This instruction was mutated in some way.

constexpr unsigned getScalarSizeInBits() const

static constexpr LLT scalar(unsigned SizeInBits)

Get a low-level scalar or aggregate "bag of bits".

static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)

Get a low-level pointer in the given address space.

static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)

Get a low-level fixed-width vector of some number of elements and element width.

LLVM_ABI void diagnose(const DiagnosticInfo &DI)

Report a message to the currently installed diagnostic handler.

LLVM_ABI void computeTables()

Compute any ancillary tables needed to quickly decide how an operation should be handled.

LegalizeRuleSet & minScalar(unsigned TypeIdx, const LLT Ty)

Ensure the scalar is at least as wide as Ty.

LegalizeRuleSet & legalFor(std::initializer_list< LLT > Types)

The instruction is legal when type index 0 is any type in the given list.

LegalizeRuleSet & scalarSameSizeAs(unsigned TypeIdx, unsigned SameSizeIdx)

Change the type TypeIdx to have the same scalar size as type SameSizeIdx.

LegalizeRuleSet & libcall()

The instruction is emitted as a library call.

LegalizeRuleSet & clampMaxNumElements(unsigned TypeIdx, const LLT EltTy, unsigned MaxElements)

Limit the number of elements in EltTy vectors to at most MaxElements.

LegalizeRuleSet & clampMinNumElements(unsigned TypeIdx, const LLT EltTy, unsigned MinElements)

Limit the number of elements in EltTy vectors to at least MinElements.

LegalizeRuleSet & customForCartesianProduct(std::initializer_list< LLT > Types)

LegalizeRuleSet & moreElementsToNextPow2(unsigned TypeIdx)

Add more elements to the vector to reach the next power of two.

LegalizeRuleSet & lower()

The instruction is lowered.

LegalizeRuleSet & clampScalar(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)

Limit the range of scalar sizes to MinTy and MaxTy.

LegalizeRuleSet & clampNumElements(unsigned TypeIdx, const LLT MinTy, const LLT MaxTy)

Limit the number of elements for the given vectors to at least MinTy's number of elements and at most...

LegalizeRuleSet & customIf(LegalityPredicate Predicate)

LegalizeRuleSet & widenScalarToNextPow2(unsigned TypeIdx, unsigned MinSize=0)

Widen the scalar to the next power of two that is at least MinSize.

LegalizeRuleSet & scalarize(unsigned TypeIdx)

LegalizeRuleSet & legalForCartesianProduct(std::initializer_list< LLT > Types)

The instruction is legal when type indexes 0 and 1 are both in the given list.

LegalizeRuleSet & legalIf(LegalityPredicate Predicate)

The instruction is legal if predicate is true.

LLVM_ABI MachineInstrBuilder createStackTemporary(TypeSize Bytes, Align Alignment, MachinePointerInfo &PtrInfo)

Create a stack temporary based on the size in bytes and the alignment.

GISelChangeObserver & Observer

To keep track of changes made by the LegalizerHelper.

MachineIRBuilder & MIRBuilder

Expose MIRBuilder so clients can set their own RecordInsertInstruction functions.

LLVM_ABI Align getStackTemporaryAlignment(LLT Type, Align MinAlign=Align()) const

Return the alignment to use for a stack temporary object with the given type.

LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)

Get the action definition builder for the given opcode.

const LegacyLegalizerInfo & getLegacyLegalizerInfo() const

unsigned getConstantPoolIndex(const Constant *C, Align Alignment)

getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.

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

getMachineMemOperand - Allocate a new MachineMemOperand.

Function & getFunction()

Return the LLVM function that this machine code represents.

MachineConstantPool * getConstantPool()

getConstantPool - Return the constant pool object for the current function.

Helper class to build MachineInstr.

MachineInstrBuilder buildFPTOSI(const DstOp &Dst, const SrcOp &Src0)

Build and insert Res = G_FPTOSI Src0.

MachineInstrBuilder buildAdd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)

Build and insert Res = G_ADD Op0, Op1.

MachineInstrBuilder buildConstantPool(const DstOp &Res, unsigned Idx)

Build and insert Res = G_CONSTANT_POOL Idx.

MachineInstrBuilder buildAnd(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1)

Build and insert Res = G_AND Op0, Op1.

MachineInstrBuilder buildLShr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)

MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)

Build and insert Res = G_ZEXT Op.

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

Build and insert Res = G_LOAD Addr, MMO.

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

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

MachineInstrBuilder buildShl(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)

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

Build and insert G_STORE Val, Addr, MMO.

MachineInstrBuilder buildInstr(unsigned Opcode)

Build and insert = Opcode .

MachineInstrBuilder buildSITOFP(const DstOp &Dst, const SrcOp &Src0)

Build and insert Res = G_SITOFP Src0.

MachineFunction & getMF()

Getter for the function we currently build.

MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op, std::optional< unsigned > Flags=std::nullopt)

Build and insert Res = G_TRUNC Op.

MachineRegisterInfo * getMRI()

Getter for MRI.

MachineInstrBuilder buildOr(const DstOp &Dst, const SrcOp &Src0, const SrcOp &Src1, std::optional< unsigned > Flags=std::nullopt)

Build and insert Res = G_OR Op0, Op1.

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

Build and insert Res = COPY Op.

const DataLayout & getDataLayout() const

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

Build and insert Res = G_CONSTANT Val.

Register getReg(unsigned Idx) const

Get the register for the operand index.

const MachineInstrBuilder & addIntrinsicID(Intrinsic::ID ID) const

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

Add a virtual register use operand.

const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const

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

Add a virtual register definition operand.

Representation of each machine instruction.

A description of a memory reference used in the backend.

@ MOLoad

The memory access reads data.

@ MOStore

The memory access writes data.

const MachinePointerInfo & getPointerInfo() const

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

reference emplace_back(ArgTypes &&... Args)

unsigned getPointerSizeInBits(unsigned AS) const

static constexpr TypeSize getFixed(ScalarTy ExactSize)

static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)

static LLVM_ABI UndefValue * get(Type *T)

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

Type * getType() const

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

bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override

Called for instructions with the Custom LegalizationAction.

Definition X86LegalizerInfo.cpp:602

bool legalizeIntrinsic(LegalizerHelper &Helper, MachineInstr &MI) const override

Definition X86LegalizerInfo.cpp:996

X86LegalizerInfo(const X86Subtarget &STI, const X86TargetMachine &TM)

Definition X86LegalizerInfo.cpp:32

const X86InstrInfo * getInstrInfo() const override

#define llvm_unreachable(msg)

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

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

@ C

The default llvm calling convention, compatible with C.

LLVM_ABI LegalityPredicate scalarOrEltWiderThan(unsigned TypeIdx, unsigned Size)

True iff the specified type index is a scalar or a vector with an element type that's wider than the ...

LLVM_ABI LegalityPredicate typeInSet(unsigned TypeIdx, std::initializer_list< LLT > TypesInit)

True iff the given type index is one of the specified types.

LLVM_ABI LegalityPredicate typePairInSet(unsigned TypeIdx0, unsigned TypeIdx1, std::initializer_list< std::pair< LLT, LLT > > TypesInit)

True iff the given types for the given pair of type indexes is one of the specified type pairs.

LLVM_ABI LegalityPredicate typeIs(unsigned TypeIdx, LLT TypesInit)

True iff the given type index is the specified type.

LLVM_ABI LegalityPredicate scalarNarrowerThan(unsigned TypeIdx, unsigned Size)

True iff the specified type index is a scalar that's narrower than the given size.

Invariant opcodes: All instruction sets have these as their low opcodes.

int getRoundingModeX86(unsigned RM)

Convert LLVM rounding mode to X86 rounding mode.

This is an optimization pass for GlobalISel generic memory operations.

LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)

See if Reg is defined by an single def instruction that is Opcode.

LLVM_ABI const APInt & getIConstantFromReg(Register VReg, const MachineRegisterInfo &MRI)

VReg is defined by a G_CONSTANT, return the corresponding value.

class LLVM_GSL_OWNER SmallVector

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

DWARFExpression::Operation Op

LLVM_ABI std::optional< FPValueAndVReg > getFConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)

If VReg is defined by a statically evaluable chain of instructions rooted on a G_FCONSTANT returns it...

decltype(auto) cast(const From &Val)

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

LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)

If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...

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

The LegalityQuery object bundles together all the information that's needed to decide whether a given...

ArrayRef< MemDesc > MMODescrs

Operations which require memory can use this to place requirements on the memory type for each MMO.

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

static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)

Return a MachinePointerInfo record that refers to the constant pool.