LLVM: lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

31

32#define GET_GICOMBINER_DEPS

33#include "AArch64GenPreLegalizeGICombiner.inc"

34#undef GET_GICOMBINER_DEPS

35

36#define DEBUG_TYPE "aarch64-prelegalizer-combiner"

37

38using namespace llvm;

40

41namespace {

42

43#define GET_GICOMBINER_TYPES

44#include "AArch64GenPreLegalizeGICombiner.inc"

45#undef GET_GICOMBINER_TYPES

46

47

48

49

52 assert(MI.getOpcode() == TargetOpcode::G_ICMP && VT);

53

56 return false;

57

61 return false;

62

65

68 return false;

69

70 LLT WideTy = MRI.getType(WideReg);

73 return false;

74

75 MatchInfo = WideReg;

76 return true;

77}

78

82 assert(MI.getOpcode() == TargetOpcode::G_ICMP);

83

84 LLT WideTy = MRI.getType(WideReg);

85

86

87 Builder.setInstrAndDebugLoc(MI);

88 auto WideZero = Builder.buildConstant(WideTy, 0);

90 MI.getOperand(2).setReg(WideReg);

91 MI.getOperand(3).setReg(WideZero.getReg(0));

93}

94

95

96

97

98

99

101 std::pair<uint64_t, uint64_t> &MatchInfo) {

102 assert(MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE);

104 auto &GlobalOp = MI.getOperand(1);

105 auto *GV = GlobalOp.getGlobal();

106 if (GV->isThreadLocal())

107 return false;

108

109

112 return false;

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

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

130 for (auto &UseInstr : MRI.use_nodbg_instructions(Dst)) {

131 if (UseInstr.getOpcode() != TargetOpcode::G_PTR_ADD)

132 return false;

134 UseInstr.getOperand(2).getReg(), MRI);

135 if (!Cst)

136 return false;

137 MinOffset = std::min(MinOffset, Cst->Value.getZExtValue());

138 }

139

140

141

142 uint64_t CurrOffset = GlobalOp.getOffset();

143 uint64_t NewOffset = MinOffset + CurrOffset;

144 if (NewOffset <= CurrOffset)

145 return false;

146

147

148

149

150

151

152

153

154

155

156 if (NewOffset >= (1 << 20))

157 return false;

158

159 Type *T = GV->getValueType();

160 if (T->isSized() ||

161 NewOffset > GV->getDataLayout().getTypeAllocSize(T))

162 return false;

163 MatchInfo = std::make_pair(NewOffset, MinOffset);

164 return true;

165}

166

169 std::pair<uint64_t, uint64_t> &MatchInfo) {

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

191 std::tie(Offset, MinOffset) = MatchInfo;

192 B.setInstrAndDebugLoc(*std::next(MI.getIterator()));

194 auto &GlobalOp = MI.getOperand(1);

195 auto *GV = GlobalOp.getGlobal();

196 GlobalOp.ChangeToGA(GV, Offset, GlobalOp.getTargetFlags());

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

198 Register NewGVDst = MRI.cloneVirtualRegister(Dst);

199 MI.getOperand(0).setReg(NewGVDst);

201 B.buildPtrAdd(

202 Dst, NewGVDst,

203 B.buildConstant(LLT::scalar(64), -static_cast<int64_t>(MinOffset)));

204}

205

206

207

208

209

212 std::tuple<Register, Register, bool> &MatchInfo) {

213 assert(MI.getOpcode() == TargetOpcode::G_VECREDUCE_ADD &&

214 "Expected a G_VECREDUCE_ADD instruction");

215 assert(STI.hasDotProd() && "Target should have Dot Product feature");

216

218 Register DstReg = MI.getOperand(0).getReg();

219 Register MidReg = I1->getOperand(0).getReg();

220 LLT DstTy = MRI.getType(DstReg);

221 LLT MidTy = MRI.getType(MidReg);

223 return false;

224

225

226

227

229 Register &Out2, unsigned &I1Opc) {

230

231

232 if (MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()))

233 return false;

234

241

242 if (ExtMI1->getOpcode() != ExtMI2->getOpcode() || Ext1DstTy != Ext2DstTy)

243 return false;

244 if ((I1Opc == TargetOpcode::G_ZEXT || I1Opc == TargetOpcode::G_SEXT) &&

246 return false;

250 return true;

251 };

252

253 LLT SrcTy;

254 unsigned I1Opc = I1->getOpcode();

255 if (I1Opc == TargetOpcode::G_MUL) {

257 if (!tryMatchingMulOfExt(I1, Out1, Out2, I1Opc))

258 return false;

259 SrcTy = MRI.getType(Out1);

260 std::get<0>(MatchInfo) = Out1;

261 std::get<1>(MatchInfo) = Out2;

262 } else if (I1Opc == TargetOpcode::G_ZEXT || I1Opc == TargetOpcode::G_SEXT) {

263 Register I1Op = I1->getOperand(1).getReg();

266 if (M->getOpcode() == TargetOpcode::G_MUL &&

267 tryMatchingMulOfExt(M, Out1, Out2, I1Opc)) {

268 SrcTy = MRI.getType(Out1);

269 std::get<0>(MatchInfo) = Out1;

270 std::get<1>(MatchInfo) = Out2;

271 } else {

272 SrcTy = MRI.getType(I1Op);

273 std::get<0>(MatchInfo) = I1Op;

274 std::get<1>(MatchInfo) = 0;

275 }

276 } else {

277 return false;

278 }

279

280 if (I1Opc == TargetOpcode::G_ZEXT)

281 std::get<2>(MatchInfo) = 0;

282 else if (I1Opc == TargetOpcode::G_SEXT)

283 std::get<2>(MatchInfo) = 1;

284 else

285 return false;

286

287 if (SrcTy.getScalarSizeInBits() != 8 || SrcTy.getNumElements() % 8 != 0)

288 return false;

289

290 return true;

291}

292

297 std::tuple<Register, Register, bool> &MatchInfo) {

298 assert(MI.getOpcode() == TargetOpcode::G_VECREDUCE_ADD &&

299 "Expected a G_VECREDUCE_ADD instruction");

300 assert(STI.hasDotProd() && "Target should have Dot Product feature");

301

302

303 unsigned DotOpcode =

304 std::get<2>(MatchInfo) ? AArch64::G_SDOT : AArch64::G_UDOT;

305 Register Ext1SrcReg = std::get<0>(MatchInfo);

306

307

308

310 if (std::get<1>(MatchInfo) == 0)

311 Ext2SrcReg = Builder.buildConstant(MRI.getType(Ext1SrcReg), 1)

312 ->getOperand(0)

313 .getReg();

314 else

315 Ext2SrcReg = std::get<1>(MatchInfo);

316

317

318 LLT SrcTy = MRI.getType(Ext1SrcReg);

319 LLT MidTy;

320 unsigned NumOfDotMI;

321 if (SrcTy.getNumElements() % 16 == 0) {

322 NumOfDotMI = SrcTy.getNumElements() / 16;

324 } else if (SrcTy.getNumElements() % 8 == 0) {

325 NumOfDotMI = SrcTy.getNumElements() / 8;

327 } else {

328 llvm_unreachable("Source type number of elements is not multiple of 8");

329 }

330

331

332 if (NumOfDotMI == 1) {

333 auto Zeroes = Builder.buildConstant(MidTy, 0)->getOperand(0).getReg();

334 auto Dot = Builder.buildInstr(DotOpcode, {MidTy},

335 {Zeroes, Ext1SrcReg, Ext2SrcReg});

336 Builder.buildVecReduceAdd(MI.getOperand(0), Dot->getOperand(0));

337 } else {

338

341 if (SrcTy.getNumElements() % 16 != 0) {

344

345

347 LLT LeftoverTy1, LeftoverTy2;

348 if ((extractParts(Ext1SrcReg, MRI.getType(Ext1SrcReg), MainTy,

349 LeftoverTy1, Ext1UnmergeReg, Leftover1, Builder,

351 (extractParts(Ext2SrcReg, MRI.getType(Ext2SrcReg), MainTy,

352 LeftoverTy2, Ext2UnmergeReg, Leftover2, Builder,

355 }

356

357

359 ->getOperand(0)

360 .getReg();

361

363 Builder

365 {Leftover1[0], v8Zeroes})

366 .getReg(0));

368 Builder

370 {Leftover2[0], v8Zeroes})

371 .getReg(0));

372

373 } else {

374

375 unsigned SrcNumElts = SrcTy.getNumElements();

377 Ext1UnmergeReg, Builder, MRI);

379 Ext2UnmergeReg, Builder, MRI);

380 }

381

382

384 unsigned NumElements = 0;

385 for (unsigned i = 0; i < Ext1UnmergeReg.size(); i++) {

386 LLT ZeroesLLT;

387

388 if (MRI.getType(Ext1UnmergeReg[i]).getNumElements() == 16) {

390 NumElements += 4;

391 } else {

393 NumElements += 2;

394 }

395 auto Zeroes = Builder.buildConstant(ZeroesLLT, 0)->getOperand(0).getReg();

397 Builder

398 .buildInstr(DotOpcode, {MRI.getType(Zeroes)},

399 {Zeroes, Ext1UnmergeReg[i], Ext2UnmergeReg[i]})

400 .getReg(0));

401 }

402

403

404 auto ConcatMI =

405 Builder.buildConcatVectors(LLT::fixed_vector(NumElements, 32), DotReg);

406

407

408 Builder.buildVecReduceAdd(MI.getOperand(0).getReg(),

409 ConcatMI->getOperand(0).getReg());

410 }

411

412

413 MI.eraseFromParent();

414}

415

416

417

419 std::pair<Register, bool> &MatchInfo) {

420 assert(MI.getOpcode() == TargetOpcode::G_VECREDUCE_ADD &&

421 "Expected G_VECREDUCE_ADD Opcode");

422

423

425 auto ExtOpc = ExtMI->getOpcode();

426

427 if (ExtOpc == TargetOpcode::G_ZEXT)

428 std::get<1>(MatchInfo) = 0;

429 else if (ExtOpc == TargetOpcode::G_SEXT)

430 std::get<1>(MatchInfo) = 1;

431 else

432 return false;

433

434

436 LLT ExtSrcTy = MRI.getType(ExtSrcReg);

437 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());

439 return false;

446 std::get<0>(MatchInfo) = ExtSrcReg;

447 return true;

448 }

449 return false;

450}

451

454 std::pair<Register, bool> &MatchInfo) {

455 assert(MI.getOpcode() == TargetOpcode::G_VECREDUCE_ADD &&

456 "Expected G_VECREDUCE_ADD Opcode");

457

458 unsigned Opc = std::get<1>(MatchInfo) ? AArch64::G_SADDLV : AArch64::G_UADDLV;

459 Register SrcReg = std::get<0>(MatchInfo);

460 Register DstReg = MI.getOperand(0).getReg();

461 LLT SrcTy = MRI.getType(SrcReg);

462 LLT DstTy = MRI.getType(DstReg);

463

464

465

466 LLT MainTy;

468 unsigned SrcScalSize = SrcTy.getScalarSizeInBits();

469 unsigned SrcNumElem = SrcTy.getNumElements();

470 if ((SrcScalSize == 8 && SrcNumElem > 16) ||

471 (SrcScalSize == 16 && SrcNumElem > 8) ||

472 (SrcScalSize == 32 && SrcNumElem > 4)) {

473

474 LLT LeftoverTy;

476 if (SrcScalSize == 8)

478 else if (SrcScalSize == 16)

480 else if (SrcScalSize == 32)

482 else

484

485

486

487 extractParts(SrcReg, SrcTy, MainTy, LeftoverTy, WorkingRegisters,

488 LeftoverRegs, B, MRI);

490 } else {

491 WorkingRegisters.push_back(SrcReg);

492 MainTy = SrcTy;

493 }

494

498 for (unsigned I = 0; I < WorkingRegisters.size(); I++) {

499

500

501 LLT WorkingRegTy = MRI.getType(WorkingRegisters[I]);

504 WorkingRegisters[I] =

505 B.buildInstr(std::get<1>(MatchInfo) ? TargetOpcode::G_SEXT

506 : TargetOpcode::G_ZEXT,

509 }

510

511

512

514 : LLT::fixed_vector(2, 64);

516 B.buildInstr(Opc, {AddlvTy}, {WorkingRegisters[I]}).getReg(0);

517

518

519

520

521

522

523 if (MidScalarSize == 32 || MidScalarSize == 64) {

524 WorkingRegisters[I] = B.buildInstr(AArch64::G_EXTRACT_VECTOR_ELT,

525 {MidScalarLLT}, {AddlvReg, ZeroReg})

527 } else {

528 Register ExtractReg = B.buildInstr(AArch64::G_EXTRACT_VECTOR_ELT,

531 WorkingRegisters[I] =

532 B.buildTrunc({MidScalarLLT}, {ExtractReg}).getReg(0);

533 }

534 }

535

537 if (WorkingRegisters.size() > 1) {

538 OutReg = B.buildAdd(MidScalarLLT, WorkingRegisters[0], WorkingRegisters[1])

539 .getReg(0);

540 for (unsigned I = 2; I < WorkingRegisters.size(); I++) {

541 OutReg = B.buildAdd(MidScalarLLT, OutReg, WorkingRegisters[I]).getReg(0);

542 }

543 } else {

544 OutReg = WorkingRegisters[0];

545 }

546

548

549

550 B.buildInstr(std::get<1>(MatchInfo) ? TargetOpcode::G_SEXT

551 : TargetOpcode::G_ZEXT,

552 {DstReg}, {OutReg});

553 } else {

554 B.buildCopy(DstReg, OutReg);

555 }

556

557 MI.eraseFromParent();

558}

559

560

561

562

565 assert((MI.getOpcode() == TargetOpcode::G_ADD ||

566 MI.getOpcode() == TargetOpcode::G_SUB ||

567 MI.getOpcode() == TargetOpcode::G_MUL) &&

568 "Expected a G_ADD, G_SUB or G_MUL instruction\n");

569

570

571 LLT DstTy = MRI.getType(DstReg);

573 return false;

574

575

576 Register ExtDstReg = MI.getOperand(1).getReg();

577 LLT Ext1SrcTy = MRI.getType(SrcReg1);

578 LLT Ext2SrcTy = MRI.getType(SrcReg2);

579 unsigned ExtDstScal = MRI.getType(ExtDstReg).getScalarSizeInBits();

581 if (((Ext1SrcScal == 8 && ExtDstScal == 32) ||

582 ((Ext1SrcScal == 8 || Ext1SrcScal == 16) && ExtDstScal == 64)) &&

583 Ext1SrcTy == Ext2SrcTy)

584 return true;

585

586 return false;

587}

588

592 LLT SrcTy = MRI.getType(SrcReg1);

594 unsigned Opc = isSExt ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;

598 B.buildInstr(MI.getOpcode(), {MidTy}, {Ext1Reg, Ext2Reg}).getReg(0);

599

600

601

602

603 if (MI.getOpcode() == TargetOpcode::G_ADD ||

604 MI.getOpcode() == TargetOpcode::G_MUL)

605 B.buildInstr(Opc, {DstReg}, {AddReg});

606 else

607 B.buildSExt(DstReg, AddReg);

608

609 MI.eraseFromParent();

610}

611

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635

636

637

638

639

640

641

642

643 auto &MRI = *B.getMRI();

644

651 return false;

652 LLT WideTy0 = MRI.getType(Op0Wide);

653 LLT WideTy1 = MRI.getType(Op1Wide);

654 Register ResVal = MI.getOperand(0).getReg();

655 LLT OpTy = MRI.getType(ResVal);

658

660

661

662 if (Op0WideDef->getOpcode() != TargetOpcode::G_ASSERT_ZEXT ||

663 Op1WideDef->getOpcode() != TargetOpcode::G_ASSERT_ZEXT ||

666 return false;

667

668

669 if (!WideTy0.isScalar() || !WideTy1.isScalar() || WideTy0 != WideTy1 ||

671 (OpTySize != 8 && OpTySize != 16))

672 return false;

673

674

675 Register ResStatus = MI.getOperand(1).getReg();

676 if (MRI.hasOneNonDBGUse(ResStatus))

677 return false;

678 MachineInstr *CondUser = &*MRI.use_instr_nodbg_begin(ResStatus);

679 if (CondUser->getOpcode() != TargetOpcode::G_BRCOND)

680 return false;

681

682

686 return false;

687 if (any_of(MRI.use_nodbg_instructions(ResVal),

689 return &MI != &I &&

690 (I.getParent() == FailMBB || I.getParent() == CurrentMBB);

691 }))

692 return false;

693

694

695 B.setInstrAndDebugLoc(*MI.getNextNode());

696 MI.eraseFromParent();

697

698

699 Register AddDst = MRI.cloneVirtualRegister(Op0Wide);

700 B.buildInstr(TargetOpcode::G_ADD, {AddDst}, {Op0Wide, Op1Wide});

701

702

703

704 Register CondBit = MRI.cloneVirtualRegister(Op0Wide);

705 B.buildAnd(

706 CondBit, AddDst,

707 B.buildConstant(LLT::scalar(32), OpTySize == 8 ? 1 << 8 : 1 << 16));

710

711

712

713 B.buildZExtOrTrunc(ResVal, AddDst);

717 auto OldR = U.getParent()->getOperand(0).getReg();

719 U.getParent()->eraseFromParent();

721 }

722 }

723

724 return true;

725}

726

727class AArch64PreLegalizerCombinerImpl : public Combiner {

728protected:

729 const CombinerHelper Helper;

730 const AArch64PreLegalizerCombinerImplRuleConfig &RuleConfig;

731 const AArch64Subtarget &STI;

732

733public:

734 AArch64PreLegalizerCombinerImpl(

735 MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,

736 GISelValueTracking &VT, GISelCSEInfo *CSEInfo,

737 const AArch64PreLegalizerCombinerImplRuleConfig &RuleConfig,

738 const AArch64Subtarget &STI, MachineDominatorTree *MDT,

739 const LegalizerInfo *LI);

740

741 static const char *getName() { return "AArch6400PreLegalizerCombiner"; }

742

743 bool tryCombineAll(MachineInstr &I) const override;

744

745 bool tryCombineAllImpl(MachineInstr &I) const;

746

747private:

748#define GET_GICOMBINER_CLASS_MEMBERS

749#include "AArch64GenPreLegalizeGICombiner.inc"

750#undef GET_GICOMBINER_CLASS_MEMBERS

751};

752

753#define GET_GICOMBINER_IMPL

754#include "AArch64GenPreLegalizeGICombiner.inc"

755#undef GET_GICOMBINER_IMPL

756

757AArch64PreLegalizerCombinerImpl::AArch64PreLegalizerCombinerImpl(

760 const AArch64PreLegalizerCombinerImplRuleConfig &RuleConfig,

763 : Combiner(MF, CInfo, TPC, &VT, CSEInfo),

764 Helper(Observer, B, true, &VT, MDT, LI),

765 RuleConfig(RuleConfig), STI(STI),

767#include "AArch64GenPreLegalizeGICombiner.inc"

769{

770}

771

772bool AArch64PreLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const {

773 if (tryCombineAllImpl(MI))

774 return true;

775

776 unsigned Opc = MI.getOpcode();

777 switch (Opc) {

778 case TargetOpcode::G_SHUFFLE_VECTOR:

780 case TargetOpcode::G_UADDO:

781 return tryToSimplifyUADDO(MI, B, Helper, Observer);

782 case TargetOpcode::G_MEMCPY_INLINE:

784 case TargetOpcode::G_MEMCPY:

785 case TargetOpcode::G_MEMMOVE:

786 case TargetOpcode::G_MEMSET: {

787

788

789 unsigned MaxLen = CInfo.EnableOpt ? 0 : 32;

790

792 return true;

793 if (Opc == TargetOpcode::G_MEMSET)

795 return false;

796 }

797 }

798

799 return false;

800}

801

802

803

804

805class AArch64PreLegalizerCombiner : public MachineFunctionPass {

806public:

807 static char ID;

808

809 AArch64PreLegalizerCombiner();

810

811 StringRef getPassName() const override {

812 return "AArch64PreLegalizerCombiner";

813 }

814

815 bool runOnMachineFunction(MachineFunction &MF) override;

816

817 void getAnalysisUsage(AnalysisUsage &AU) const override;

818

819private:

820 AArch64PreLegalizerCombinerImplRuleConfig RuleConfig;

821};

822}

823

824void AArch64PreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {

828 AU.addRequired();

829 AU.addPreserved();

830 AU.addRequired();

831 AU.addPreserved();

832 AU.addRequired();

833 AU.addPreserved();

835}

836

837AArch64PreLegalizerCombiner::AArch64PreLegalizerCombiner()

838 : MachineFunctionPass(ID) {

839 if (!RuleConfig.parseCommandLineOption())

841}

842

843bool AArch64PreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {

845 return false;

846 auto &TPC = getAnalysis();

847

848

850 getAnalysis().getCSEWrapper();

851 auto *CSEInfo = &Wrapper.get(TPC.getCSEConfig());

852

854 const auto *LI = ST.getLegalizerInfo();

855

857 bool EnableOpt =

860 &getAnalysis().get(MF);

862 &getAnalysis().getDomTree();

863 CombinerInfo CInfo( true, false,

864 nullptr, EnableOpt, F.hasOptSize(),

865 F.hasMinSize());

866

867 CInfo.MaxIterations = 1;

869

870

871 CInfo.EnableFullDCE = true;

872 AArch64PreLegalizerCombinerImpl Impl(MF, CInfo, &TPC, *VT, CSEInfo,

873 RuleConfig, ST, MDT, LI);

874 return Impl.combineMachineInstrs();

875}

876

877char AArch64PreLegalizerCombiner::ID = 0;

879 "Combine AArch64 machine instrs before legalization",

880 false, false)

885 "Combine AArch64 machine instrs before legalization", false,

887

888namespace llvm {

890 return new AArch64PreLegalizerCombiner();

891}

892}

unsigned const MachineRegisterInfo * MRI

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

#define GET_GICOMBINER_CONSTRUCTOR_INITS

amdgpu aa AMDGPU Address space based Alias Analysis Wrapper

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

Provides analysis for continuously CSEing during GISel passes.

This contains common combine transformations that may be used in a combine pass,or by the target else...

Option class for Targets to specify which operations are combined how and when.

This contains the base class for all Combiners generated by TableGen.

Provides analysis for querying information about KnownBits during GISel passes.

Contains matchers for matching SSA Machine Instructions.

This file declares the MachineIRBuilder class.

static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)

#define INITIALIZE_PASS_DEPENDENCY(depName)

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

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

static StringRef getName(Value *V)

Target-Independent Code Generator Pass Configuration Options pass.

unsigned ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const

ClassifyGlobalReference - Find the target operand flags that describe how a global value should be re...

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

Add the specified Pass class to the set of analyses preserved by this pass.

LLVM_ABI void setPreservesCFG()

This function should be called by the pass, iff they do not:

Predicate

This enumeration lists the possible predicates for CmpInst subclasses.

void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg, Register ToReg) const

MachineRegisterInfo::replaceRegWith() and inform the observer of the changes.

bool tryEmitMemcpyInline(MachineInstr &MI) const

Emit loads and stores that perform the given memcpy.

bool tryCombineShuffleVector(MachineInstr &MI) const

Try to combine G_SHUFFLE_VECTOR into G_CONCAT_VECTORS.

bool tryCombineMemCpyFamily(MachineInstr &MI, unsigned MaxLen=0) const

Optimize memcpy intrinsics et al, e.g.

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

The actual analysis pass wrapper.

Simple wrapper that does the following.

Abstract class that contains various methods for clients to notify about changes.

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.

virtual void erasingInstr(MachineInstr &MI)=0

An instruction is about to be erased.

To use KnownBitsInfo analysis in a pass, KnownBitsInfo &Info = getAnalysis<GISelValueTrackingInfoAnal...

unsigned computeNumSignBits(Register R, const APInt &DemandedElts, unsigned Depth=0)

static bool isEquality(Predicate P)

Return true if this predicate is either EQ or NE.

constexpr unsigned getScalarSizeInBits() const

constexpr bool isScalar() const

static constexpr LLT scalar(unsigned SizeInBits)

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

constexpr uint16_t getNumElements() const

Returns the number of elements in a vector LLT.

constexpr bool isVector() const

constexpr TypeSize getSizeInBits() const

Returns the total size of the type. Must only be called on sized types.

constexpr LLT changeElementSize(unsigned NewEltSize) const

If this type is a vector, return a vector with the same number of elements but the new element size.

static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)

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

DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

const TargetSubtargetInfo & getSubtarget() const

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

Function & getFunction()

Return the LLVM function that this machine code represents.

const MachineFunctionProperties & getProperties() const

Get the function properties.

const TargetMachine & getTarget() const

getTarget - Return the target machine this machine code is compiled with

Helper class to build MachineInstr.

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

const MachineBasicBlock * getParent() const

const MachineOperand & getOperand(unsigned i) const

MachineOperand class - Representation of each machine instruction operand.

MachineBasicBlock * getMBB() const

MachineInstr * getParent()

getParent - Return the instruction that this operand belongs to.

Register getReg() const

getReg - Returns the register number.

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

Wrapper class representing virtual and physical registers.

void push_back(const T &Elt)

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

CodeGenOptLevel getOptLevel() const

Returns the optimization level: None, Less, Default, or Aggressive.

Target-Independent Code Generator Pass Configuration Options.

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

#define llvm_unreachable(msg)

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

bool tryEmitBZero(MachineInstr &MI, MachineIRBuilder &MIRBuilder, bool MinSize)

Replace a G_MEMSET with a value of 0 with a G_BZERO instruction if it is supported and beneficial to ...

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

operand_type_match m_Reg()

SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue)

Matches a constant equal to RequestedValue.

UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)

bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)

UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)

This is an optimization pass for GlobalISel generic memory operations.

FunctionPass * createAArch64PreLegalizerCombiner()

Definition AArch64PreLegalizerCombiner.cpp:889

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

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...

LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)

Find the def instruction for Reg, folding away any trivial copies.

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

LLVM_ABI void extractParts(Register Reg, LLT Ty, int NumParts, SmallVectorImpl< Register > &VRegs, MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI)

Helper function to split a wide generic register into bitwise blocks with the given Type (which impli...

LLVM_ABI void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)

Modify analysis usage so it preserves passes required for the SelectionDAG fallback.

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...

@ SinglePass

Enables Observer-based DCE and additional heuristics that retry combining defined and used instructio...