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)

274

275

278 .legalFor(Is64Bit, {s64})

279 .widenScalarToNextPow2(0, 32)

281

282

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

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

286 .widenScalarToNextPow2(1, 16)

289

290

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

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

294 .widenScalarToNextPow2(1, 16)

297

298

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

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

302 .widenScalarToNextPow2(1, 16)

305

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

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

309 .widenScalarToNextPow2(1, 16)

312

314

315

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

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

318

321 .maxScalar(0, sMaxScalar)

323

325

327

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

331 .widenScalarToNextPow2(1, 32)

333

335

336

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

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

340 {s16, p0, s16, 1},

341 {s32, p0, s32, 1},

342 {s80, p0, s80, 1},

343 {p0, p0, p0, 1},

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

345 if (Is64Bit)

346 Action.legalForTypesWithMemDesc(

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

348

349 if (HasSSE1)

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

351 if (HasSSE2)

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

353 {v8s16, p0, v8s16, 1},

354 {v2s64, p0, v2s64, 1},

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

356 if (HasAVX)

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

358 {v16s16, p0, v16s16, 1},

359 {v8s32, p0, v8s32, 1},

360 {v4s64, p0, v4s64, 1},

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

362 if (HasAVX512)

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

364 {v32s16, p0, v32s16, 1},

365 {v16s32, p0, v16s32, 1},

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

367

368

369 if (Op == G_LOAD) {

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

371 {s16, p0, s8, 1},

372 {s32, p0, s8, 1},

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

374 if (Is64Bit)

375 Action.legalForTypesWithMemDesc(

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

377 } else {

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

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

380 });

381 }

382 Action.widenScalarToNextPow2(0, 8)

383 .clampScalar(0, s8, sMaxScalar)

384 .scalarize(0);

385 }

386

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

389 Action.legalForTypesWithMemDesc(

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

391 if (Is64Bit)

392 Action.legalForTypesWithMemDesc(

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

394

395 }

396

397

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

400 .legalFor(Is64Bit, {s64})

401 .widenScalarToNextPow2(0, 8)

406

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

409 .legalFor(Is64Bit, {s64})

410 .widenScalarToNextPow2(0, 8)

415

417

418

421 .legalFor(UseX87, {s80});

422

423

425 .legalFor({s32, s64})

426 .legalFor(HasSSE1, {v4s32})

427 .legalFor(HasSSE2, {v2s64})

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

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

430 .legalFor(UseX87, {s80});

431

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

435 .lower();

436

437

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

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

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

442 .clampScalar(0, s8, s8)

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

445

446

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

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

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

451

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

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

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

456

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

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

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

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

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

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

467

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

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

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

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

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

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

478

479

480

481

482

483

484

485

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

489 return !HasAVX512 &&

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

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

493 })

495

496 return !HasAVX512 &&

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

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

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

500 })

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

505

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

509 return !HasAVX512 &&

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

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

513 })

514

515

516

517

519 return !HasAVX512 &&

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

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

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

523 })

524 .clampScalar(0, s32, sMaxScalar)

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

528

529

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

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

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

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

536 })

537 .clampNumElements(0, v16s8, s8MaxVector)

542

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

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

548 {{v16s8, v32s8},

549 {v8s16, v16s16},

550 {v4s32, v8s32},

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

553 {{v16s8, v64s8},

554 {v32s8, v64s8},

555 {v8s16, v32s16},

556 {v16s16, v32s16},

557 {v4s32, v16s32},

558 {v8s32, v16s32},

559 {v2s64, v8s64},

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

561 });

562

563

566 HasSSE1,

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

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

569 {v64s8, v32s8},

570 {v32s16, v8s16},

571 {v32s16, v16s16},

572 {v16s32, v4s32},

573 {v16s32, v8s32},

574 {v8s64, v2s64},

575 {v8s64, v4s64}});

576

577

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

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

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

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

583 .clampScalar(1, s32, s32)

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

586

587

589

591 .lower();

592

593

598

601}

602

607 switch (MI.getOpcode()) {

608 default:

609

610 return false;

611 case TargetOpcode::G_BUILD_VECTOR:

612 return legalizeBuildVector(MI, MRI, Helper);

613 case TargetOpcode::G_FPTOUI:

614 return legalizeFPTOUI(MI, MRI, Helper);

615 case TargetOpcode::G_UITOFP:

616 return legalizeUITOFP(MI, MRI, Helper);

617 case TargetOpcode::G_STORE:

618 return legalizeNarrowingStore(MI, MRI, Helper);

619 case TargetOpcode::G_SITOFP:

620 return legalizeSITOFP(MI, MRI, Helper);

621 case TargetOpcode::G_FPTOSI:

622 return legalizeFPTOSI(MI, MRI, Helper);

623 case TargetOpcode::G_GET_ROUNDING:

624 return legalizeGETROUNDING(MI, MRI, Helper);

625 case TargetOpcode::G_SET_ROUNDING:

626 return legalizeSETROUNDING(MI, MRI, Helper);

627 }

629}

630

631bool X86LegalizerInfo::legalizeSITOFP(MachineInstr &MI,

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

637

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

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

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

641

642 TypeSize MemSize = SrcTy.getSizeInBytes();

648

649

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

651

656 .addUse(SlotPointer.getReg(0))

658

659 MI.eraseFromParent();

660 return true;

661}

662

663bool X86LegalizerInfo::legalizeFPTOSI(MachineInstr &MI,

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

669

670 TypeSize MemSize = DstTy.getSizeInBytes();

676

679 .addUse(SlotPointer.getReg(0))

681

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

683 MI.eraseFromParent();

684 return true;

685}

686

687bool X86LegalizerInfo::legalizeBuildVector(MachineInstr &MI,

690 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;

692 Register Dst = BuildVector.getReg(0);

693 LLT DstTy = MRI.getType(Dst);

694 MachineFunction &MF = MIRBuilder.getMF();

697

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

701

703 if (ValueAndReg) {

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

705 continue;

706 }

707

709 if (FPValueAndReg) {

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

711 continue;

712 }

713

716 continue;

717 }

718 return false;

719 }

720

722

724 unsigned AddrSpace = DL.getDefaultGlobalsAddressSpace();

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

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

729 MachineMemOperand *MMO =

732

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

734 MI.eraseFromParent();

735 return true;

736}

737

738bool X86LegalizerInfo::legalizeFPTOUI(MachineInstr &MI,

741 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;

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

743 unsigned DstSizeInBits = DstTy.getScalarSizeInBits();

746

747

748 if (DstSizeInBits <= 32) {

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

751 MI.eraseFromParent();

752 return true;

753 }

754

755 return false;

756}

757

758bool X86LegalizerInfo::legalizeUITOFP(MachineInstr &MI,

761 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;

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

765

766

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

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

770 MI.eraseFromParent();

771 return true;

772 }

773

774 return false;

775}

776

777bool X86LegalizerInfo::legalizeNarrowingStore(MachineInstr &MI,

781 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;

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

783 MachineFunction &MF = MIRBuilder.getMF();

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

786

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

790 return true;

791}

792

793bool X86LegalizerInfo::legalizeGETROUNDING(MachineInstr &MI,

796

797

798

799

800

801

802

803

804

805

806

807

808

809

810

811

812

813

814

815

816

817

818 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;

819 MachineFunction &MF = MIRBuilder.getMF();

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

821 LLT DstTy = MRI.getType(Dst);

825

826

827 int MemSize = 2;

829 MachinePointerInfo PtrInfo;

831 Alignment, PtrInfo);

833

835 MemSize, Alignment);

836

837

838 MIRBuilder.buildInstr(X86::G_FNSTCW16)

841

842

844 MemSize, Alignment);

845

846 auto CWD32 =

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

848 auto Shifted8 = MIRBuilder.buildTrunc(

850 auto Masked32 = MIRBuilder.buildZExt(

852

853

854

855

856

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

859 auto RetVal =

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

862

863 MIRBuilder.buildCopy(Dst, RetValTrunc);

864

865 MI.eraseFromParent();

866 return true;

867}

868

869bool X86LegalizerInfo::legalizeSETROUNDING(MachineInstr &MI,

872 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;

873 MachineFunction &MF = MIRBuilder.getMF();

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

878

879

880 int MemSize = 4;

882 MachinePointerInfo PtrInfo;

884 Alignment, PtrInfo);

886

887 auto StoreMMO =

889 MIRBuilder.buildInstr(X86::G_FNSTCW16)

892

893 auto LoadMMO =

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

896

897

898 auto ClearedCWD =

900

901

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

905

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

909

913 C.diagnose(DiagnosticInfoUnsupported(

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

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

916 return false;

917 }

918

919 FieldVal = FieldVal << 3;

922 } else {

923

924

926 auto ShiftAmt = MIRBuilder.buildAdd(

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

931 ShiftAmt8);

932 RMBits =

935

936

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

938 MXCSRRMBits =

941 }

942

943 auto NewCWD =

945

946

947 auto StoreNewMMO =

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

950

951

952 auto LoadNewMMO =

954 MIRBuilder.buildInstr(X86::G_FLDCW16)

957

958 if (Subtarget.hasSSE1()) {

959

962 MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS)

966

967

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

971

972

973 auto ClearedMXCSR = MIRBuilder.buildAnd(

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

975

976

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

978

979

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

983

984

987 MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS)

991 }

992

993 MI.eraseFromParent();

994 return true;

995}

996

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:603

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

Definition X86LegalizerInfo.cpp:997

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.