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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

42

43#define GET_GICOMBINER_DEPS

44#include "AArch64GenPostLegalizeGICombiner.inc"

45#undef GET_GICOMBINER_DEPS

46

47#define DEBUG_TYPE "aarch64-postlegalizer-combiner"

48

49using namespace llvm;

51

52namespace {

53

54#define GET_GICOMBINER_TYPES

55#include "AArch64GenPostLegalizeGICombiner.inc"

56#undef GET_GICOMBINER_TYPES

57

58

59

60

61

62

63

64

65

66bool matchExtractVecEltPairwiseAdd(

68 std::tuple<unsigned, LLT, Register> &MatchInfo) {

69 Register Src1 = MI.getOperand(1).getReg();

70 Register Src2 = MI.getOperand(2).getReg();

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

72

74 if (!Cst || Cst->Value != 0)

75 return false;

76

77

78

79 auto *FAddMI = getOpcodeDef(TargetOpcode::G_FADD, Src1, MRI);

80 if (!FAddMI)

81 return false;

82

83

85 if (DstSize != 16 && DstSize != 32 && DstSize != 64)

86 return false;

87

88 Register Src1Op1 = FAddMI->getOperand(1).getReg();

89 Register Src1Op2 = FAddMI->getOperand(2).getReg();

91 getOpcodeDef(TargetOpcode::G_SHUFFLE_VECTOR, Src1Op2, MRI);

93 if (!Shuffle) {

94 Shuffle = getOpcodeDef(TargetOpcode::G_SHUFFLE_VECTOR, Src1Op1, MRI);

95 Other = MRI.getVRegDef(Src1Op2);

96 }

97

98

101 std::get<0>(MatchInfo) = TargetOpcode::G_FADD;

102 std::get<1>(MatchInfo) = DstTy;

103 std::get<2>(MatchInfo) = Other->getOperand(0).getReg();

104 return true;

105 }

106 return false;

107}

108

109void applyExtractVecEltPairwiseAdd(

111 std::tuple<unsigned, LLT, Register> &MatchInfo) {

112 unsigned Opc = std::get<0>(MatchInfo);

113 assert(Opc == TargetOpcode::G_FADD && "Unexpected opcode!");

114

115 LLT Ty = std::get<1>(MatchInfo);

116 Register Src = std::get<2>(MatchInfo);

118 B.setInstrAndDebugLoc(MI);

119 auto Elt0 = B.buildExtractVectorElement(Ty, Src, B.buildConstant(s64, 0));

120 auto Elt1 = B.buildExtractVectorElement(Ty, Src, B.buildConstant(s64, 1));

121 B.buildInstr(Opc, {MI.getOperand(0).getReg()}, {Elt0, Elt1});

122 MI.eraseFromParent();

123}

124

126

127 unsigned Opc = MRI.getVRegDef(R)->getOpcode();

128 return Opc == TargetOpcode::G_SEXT || Opc == TargetOpcode::G_SEXT_INREG;

129}

130

132

133 return MRI.getVRegDef(R)->getOpcode() == TargetOpcode::G_ZEXT;

134}

135

136bool matchAArch64MulConstCombine(

139 assert(MI.getOpcode() == TargetOpcode::G_MUL);

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

144

145

147 if (!Const)

148 return false;

149

150 APInt ConstValue = Const->Value.sext(Ty.getSizeInBits());

151

152

153

154

155

156

157

158

159

160

161

162

163

164 unsigned TrailingZeroes = ConstValue.countr_zero();

165 if (TrailingZeroes) {

166

167

168 if (MRI.hasOneNonDBGUse(LHS) &&

170 return false;

171

172

173 if (MRI.hasOneNonDBGUse(Dst)) {

175 unsigned UseOpc = UseMI.getOpcode();

176 if (UseOpc == TargetOpcode::G_ADD || UseOpc == TargetOpcode::G_PTR_ADD ||

177 UseOpc == TargetOpcode::G_SUB)

178 return false;

179 }

180 }

181

182

183 APInt ShiftedConstValue = ConstValue.ashr(TrailingZeroes);

184

185 unsigned ShiftAmt, AddSubOpc;

186

187 bool ShiftValUseIsLHS = true;

188

189 bool NegateResult = false;

190

192

193

194

195 APInt SCVMinus1 = ShiftedConstValue - 1;

196 APInt CVPlus1 = ConstValue + 1;

198 ShiftAmt = SCVMinus1.logBase2();

199 AddSubOpc = TargetOpcode::G_ADD;

201 ShiftAmt = CVPlus1.logBase2();

202 AddSubOpc = TargetOpcode::G_SUB;

203 } else

204 return false;

205 } else {

206

207

208 APInt CVNegPlus1 = -ConstValue + 1;

209 APInt CVNegMinus1 = -ConstValue - 1;

211 ShiftAmt = CVNegPlus1.logBase2();

212 AddSubOpc = TargetOpcode::G_SUB;

213 ShiftValUseIsLHS = false;

214 } else if (CVNegMinus1.isPowerOf2()) {

215 ShiftAmt = CVNegMinus1.logBase2();

216 AddSubOpc = TargetOpcode::G_ADD;

217 NegateResult = true;

218 } else

219 return false;

220 }

221

222 if (NegateResult && TrailingZeroes)

223 return false;

224

226 auto Shift = B.buildConstant(LLT::scalar(64), ShiftAmt);

227 auto ShiftedVal = B.buildShl(Ty, LHS, Shift);

228

229 Register AddSubLHS = ShiftValUseIsLHS ? ShiftedVal.getReg(0) : LHS;

230 Register AddSubRHS = ShiftValUseIsLHS ? LHS : ShiftedVal.getReg(0);

231 auto Res = B.buildInstr(AddSubOpc, {Ty}, {AddSubLHS, AddSubRHS});

232 assert(!(NegateResult && TrailingZeroes) &&

233 "NegateResult and TrailingZeroes cannot both be true for now.");

234

235 if (NegateResult) {

236 B.buildSub(DstReg, B.buildConstant(Ty, 0), Res);

237 return;

238 }

239

240 if (TrailingZeroes) {

241 B.buildShl(DstReg, Res, B.buildConstant(LLT::scalar(64), TrailingZeroes));

242 return;

243 }

244 B.buildCopy(DstReg, Res.getReg(0));

245 };

246 return true;

247}

248

249void applyAArch64MulConstCombine(

252 B.setInstrAndDebugLoc(MI);

253 ApplyFn(B, MI.getOperand(0).getReg());

254 MI.eraseFromParent();

255}

256

257

258

261 LLT SrcTy = MRI.getType(Merge.getSourceReg(0));

263 return false;

265}

266

269

270

271

273 MI.setDesc(B.getTII().get(TargetOpcode::G_ZEXT));

274 MI.removeOperand(2);

276}

277

278

279

281

282

283

284

285

286

287

288 assert(MI.getOpcode() == TargetOpcode::G_ANYEXT);

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

290 Register Src = MI.getOperand(1).getReg();

291 return MRI.getType(Dst).isScalar() &&

295}

296

301 MI.setDesc(B.getTII().get(TargetOpcode::G_ZEXT));

303}

304

305

306

309 if (Store.isSimple())

310 return false;

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

312 if (ValTy.isScalableVector())

313 return false;

314 if (!ValTy.isVector() || ValTy.getSizeInBits() != 128)

315 return false;

316 if (Store.getMemSizeInBits() != ValTy.getSizeInBits())

317 return false;

318 if (MRI.hasOneNonDBGUse(Store.getValueReg()))

319 return false;

321 *MRI.getVRegDef(Store.getValueReg()), MRI);

322 return MaybeCst && MaybeCst->isZero();

323}

324

328 B.setInstrAndDebugLoc(MI);

330 assert(MRI.getType(Store.getValueReg()).isVector() &&

331 "Expected a vector store value");

334 auto Zero = B.buildConstant(NewTy, 0);

335 auto HighPtr = B.buildPtrAdd(MRI.getType(PtrReg), PtrReg,

337 auto &MF = *MI.getMF();

338 auto *LowMMO = MF.getMachineMemOperand(&Store.getMMO(), 0, NewTy);

339 auto *HighMMO = MF.getMachineMemOperand(&Store.getMMO(), 8, NewTy);

340 B.buildStore(Zero, PtrReg, *LowMMO);

341 B.buildStore(Zero, HighPtr, *HighMMO);

342 Store.eraseFromParent();

343}

344

346 std::tuple<Register, Register, Register> &MatchInfo) {

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

349 return false;

350

351 Register AO1, AO2, BVO1, BVO2;

355 return false;

356

359 if (!BV1 || !BV2)

360 return false;

361

363 auto ValAndVReg1 =

365 auto ValAndVReg2 =

367 if (!ValAndVReg1 || !ValAndVReg2 ||

368 ValAndVReg1->Value != ~ValAndVReg2->Value)

369 return false;

370 }

371

372 MatchInfo = {AO1, AO2, BVO1};

373 return true;

374}

375

378 std::tuple<Register, Register, Register> &MatchInfo) {

379 B.setInstrAndDebugLoc(MI);

380 B.buildInstr(

381 AArch64::G_BSP, {MI.getOperand(0).getReg()},

382 {std::get<2>(MatchInfo), std::get<0>(MatchInfo), std::get<1>(MatchInfo)});

383 MI.eraseFromParent();

384}

385

386

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

390

394 return false;

395

397 if (AndMI->getOpcode() != TargetOpcode::G_AND)

398 return false;

400 if (LShrMI->getOpcode() != TargetOpcode::G_LSHR)

401 return false;

402

403

405 *MRI.getVRegDef(MI.getOperand(2).getReg()), MRI);

407 *MRI.getVRegDef(AndMI->getOperand(2).getReg()), MRI);

409 *MRI.getVRegDef(LShrMI->getOperand(2).getReg()), MRI);

410 if (!V1.has_value() || !V2.has_value() || !V3.has_value())

411 return false;

413 if (!V1.value().isMask(HalfSize) || V2.value() != (1ULL | 1ULL << HalfSize) ||

414 V3 != (HalfSize - 1))

415 return false;

416

417 SrcReg = LShrMI->getOperand(1).getReg();

418

419 return true;

420}

421

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

425 LLT DstTy = MRI.getType(DstReg);

426 LLT HalfTy =

429

430 Register ZeroVec = B.buildConstant(HalfTy, 0).getReg(0);

432 B.buildInstr(TargetOpcode::G_BITCAST, {HalfTy}, {SrcReg}).getReg(0);

435 .getReg(0);

436

437 B.buildInstr(TargetOpcode::G_BITCAST, {DstReg}, {CMLTReg}).getReg(0);

438 MI.eraseFromParent();

439}

440

441

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

445

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

449 unsigned I1Opc = I1->getOpcode();

450 unsigned I2Opc = I2->getOpcode();

452

454 return false;

455

456 auto IsAtLeastDoubleExtend = [&](Register R) {

457 LLT Ty = MRI.getType(R);

458 return EltSize >= Ty.getScalarSizeInBits() * 2;

459 };

460

461

462 bool IsZExt1 =

463 I1Opc == TargetOpcode::G_ZEXT || I1Opc == TargetOpcode::G_ANYEXT;

464 bool IsZExt2 =

465 I2Opc == TargetOpcode::G_ZEXT || I2Opc == TargetOpcode::G_ANYEXT;

466 if (IsZExt1 && IsZExt2 && IsAtLeastDoubleExtend(I1->getOperand(1).getReg()) &&

468 get<0>(MatchInfo) = true;

469 get<1>(MatchInfo) = I1->getOperand(1).getReg();

471 return true;

472 }

473

474 bool IsSExt1 =

475 I1Opc == TargetOpcode::G_SEXT || I1Opc == TargetOpcode::G_ANYEXT;

476 bool IsSExt2 =

477 I2Opc == TargetOpcode::G_SEXT || I2Opc == TargetOpcode::G_ANYEXT;

478 if (IsSExt1 && IsSExt2 && IsAtLeastDoubleExtend(I1->getOperand(1).getReg()) &&

480 get<0>(MatchInfo) = false;

481 get<1>(MatchInfo) = I1->getOperand(1).getReg();

483 return true;

484 }

485

486

488 if (KB && (IsZExt1 || IsZExt2) &&

489 IsAtLeastDoubleExtend(IsZExt1 ? I1->getOperand(1).getReg()

492 IsZExt1 ? MI.getOperand(2).getReg() : MI.getOperand(1).getReg();

494 get<0>(MatchInfo) = true;

495 get<1>(MatchInfo) = IsZExt1 ? I1->getOperand(1).getReg() : ZExtOp;

497 return true;

498 }

502 get<0>(MatchInfo) = true;

503 get<1>(MatchInfo) = MI.getOperand(1).getReg();

504 get<2>(MatchInfo) = MI.getOperand(2).getReg();

505 return true;

506 }

507

508 if (KB && (IsSExt1 || IsSExt2) &&

509 IsAtLeastDoubleExtend(IsSExt1 ? I1->getOperand(1).getReg()

512 IsSExt1 ? MI.getOperand(2).getReg() : MI.getOperand(1).getReg();

514 get<0>(MatchInfo) = false;

515 get<1>(MatchInfo) = IsSExt1 ? I1->getOperand(1).getReg() : SExtOp;

517 return true;

518 }

522 get<0>(MatchInfo) = false;

523 get<1>(MatchInfo) = MI.getOperand(1).getReg();

524 get<2>(MatchInfo) = MI.getOperand(2).getReg();

525 return true;

526 }

527

528 return false;

529}

530

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

534 assert(MI.getOpcode() == TargetOpcode::G_MUL &&

535 "Expected a G_MUL instruction");

536

537

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

539 bool IsZExt = get<0>(MatchInfo);

542 LLT Src1Ty = MRI.getType(Src1Reg);

543 LLT Src2Ty = MRI.getType(Src2Reg);

545 unsigned ExtOpc = IsZExt ? TargetOpcode::G_ZEXT : TargetOpcode::G_SEXT;

546

548 Src1Reg = B.buildExtOrTrunc(ExtOpc, {HalfDstTy}, {Src1Reg}).getReg(0);

550 Src2Reg = B.buildExtOrTrunc(ExtOpc, {HalfDstTy}, {Src2Reg}).getReg(0);

551

552 B.buildInstr(IsZExt ? AArch64::G_UMULL : AArch64::G_SMULL,

553 {MI.getOperand(0).getReg()}, {Src1Reg, Src2Reg});

554 MI.eraseFromParent();

555}

556

557class AArch64PostLegalizerCombinerImpl : public Combiner {

558protected:

559 const CombinerHelper Helper;

560 const AArch64PostLegalizerCombinerImplRuleConfig &RuleConfig;

561 const AArch64Subtarget &STI;

562

563public:

564 AArch64PostLegalizerCombinerImpl(

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

566 GISelValueTracking &VT, GISelCSEInfo *CSEInfo,

567 const AArch64PostLegalizerCombinerImplRuleConfig &RuleConfig,

568 const AArch64Subtarget &STI, MachineDominatorTree *MDT,

569 const LegalizerInfo *LI);

570

571 static const char *getName() { return "AArch64PostLegalizerCombiner"; }

572

573 bool tryCombineAll(MachineInstr &I) const override;

574

575private:

576#define GET_GICOMBINER_CLASS_MEMBERS

577#include "AArch64GenPostLegalizeGICombiner.inc"

578#undef GET_GICOMBINER_CLASS_MEMBERS

579};

580

581#define GET_GICOMBINER_IMPL

582#include "AArch64GenPostLegalizeGICombiner.inc"

583#undef GET_GICOMBINER_IMPL

584

585AArch64PostLegalizerCombinerImpl::AArch64PostLegalizerCombinerImpl(

588 const AArch64PostLegalizerCombinerImplRuleConfig &RuleConfig,

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

592 Helper(Observer, B, false, &VT, MDT, LI),

593 RuleConfig(RuleConfig), STI(STI),

595#include "AArch64GenPostLegalizeGICombiner.inc"

597{

598}

599

601public:

602 static char ID;

603

604 AArch64PostLegalizerCombiner(bool IsOptNone = false);

605

607 return "AArch64PostLegalizerCombiner";

608 }

609

612

613private:

614 bool IsOptNone;

615 AArch64PostLegalizerCombinerImplRuleConfig RuleConfig;

616

617

618 struct StoreInfo {

619 GStore *St = nullptr;

620

621

622 GPtrAdd *Ptr = nullptr;

623

625 LLT StoredType;

626 };

627 bool tryOptimizeConsecStores(SmallVectorImpl &Stores,

628 CSEMIRBuilder &MIB);

629

630 bool optimizeConsecutiveMemOpAddressing(MachineFunction &MF,

631 CSEMIRBuilder &MIB);

632};

633}

634

635void AArch64PostLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {

641 if (!IsOptNone) {

646 }

648}

649

650AArch64PostLegalizerCombiner::AArch64PostLegalizerCombiner(bool IsOptNone)

652 if (!RuleConfig.parseCommandLineOption())

654}

655

656bool AArch64PostLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {

658 return false;

659 assert(MF.getProperties().hasLegalized() && "Expected a legalized function?");

660 auto *TPC = &getAnalysis();

662 bool EnableOpt =

664

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

667

669 &getAnalysis().get(MF);

671 IsOptNone ? nullptr

672 : &getAnalysis().getDomTree();

674 getAnalysis().getCSEWrapper();

675 auto *CSEInfo = &Wrapper.get(TPC->getCSEConfig());

676

677 CombinerInfo CInfo( true, false,

678 nullptr, EnableOpt, F.hasOptSize(),

679 F.hasMinSize());

680

681 CInfo.MaxIterations = 1;

683

684 CInfo.EnableFullDCE = false;

685 AArch64PostLegalizerCombinerImpl Impl(MF, CInfo, TPC, *VT, CSEInfo,

686 RuleConfig, ST, MDT, LI);

687 bool Changed = Impl.combineMachineInstrs();

688

690 MIB.setCSEInfo(CSEInfo);

691 Changed |= optimizeConsecutiveMemOpAddressing(MF, MIB);

693}

694

695bool AArch64PostLegalizerCombiner::tryOptimizeConsecStores(

697 if (Stores.size() <= 2)

698 return false;

699

700

701 int64_t BaseOffset = Stores[0].Offset;

702 unsigned NumPairsExpected = Stores.size() / 2;

703 unsigned TotalInstsExpected = NumPairsExpected + (Stores.size() % 2);

704

705

707 if (!TLI.isLegalAddImmediate(BaseOffset))

708 TotalInstsExpected++;

709 int SavingsExpected = Stores.size() - TotalInstsExpected;

710 if (SavingsExpected <= 0)

711 return false;

712

714

715

716

717 Register NewBase = Stores[0].Ptr->getReg(0);

718 for (auto &SInfo : Stores) {

719

722 auto NewPtr = MIB.buildPtrAdd(MRI.getType(SInfo.St->getPointerReg()),

723 NewBase, NewOff);

726 SInfo.St->getOperand(1).setReg(NewPtr.getReg(0));

729 }

730 LLVM_DEBUG(dbgs() << "Split a series of " << Stores.size()

731 << " stores into a base pointer and offsets.\n");

732 return true;

733}

734

738 cl::desc("Enable consecutive memop optimization "

739 "in AArch64PostLegalizerCombiner"));

740

741bool AArch64PostLegalizerCombiner::optimizeConsecutiveMemOpAddressing(

743

744

745

746

747

748

749

750

751

752

753

754

755

756

757

758

759

760

761

762

763

766

769

771

772

773

774

775

776

777

778

780

782

783 if (Last.Ptr->getBaseReg() != New.Ptr->getBaseReg() ||

784 (Last.Offset + static_cast<int64_t>(Last.StoredType.getSizeInBytes()) !=

785 New.Offset) ||

786 Last.StoredType != New.StoredType)

787 return false;

788

789

790

791 if (any_of(LoadValsSinceLastStore, [&](Register LoadVal) {

792 return New.St->getValueReg() == LoadVal;

793 }))

794 return false;

795

796

797

798

799 int64_t MaxLegalOffset;

800 switch (New.StoredType.getSizeInBits()) {

801 case 32:

802 MaxLegalOffset = 252;

803 break;

804 case 64:

805 MaxLegalOffset = 504;

806 break;

807 case 128:

808 MaxLegalOffset = 1008;

809 break;

810 default:

812 }

813 if (New.Offset < MaxLegalOffset)

814 return false;

815

816

817 return New.Offset - Stores[0].Offset <= MaxLegalOffset;

818 };

819

820 auto resetState = [&]() {

822 LoadValsSinceLastStore.clear();

823 };

824

825 for (auto &MBB : MF) {

826

827

828 resetState();

829 for (auto &MI : MBB) {

830

832 LdSt && MRI.getType(LdSt->getOperand(0).getReg()).isScalableVector())

833 continue;

834

838 LLT StoredValTy = MRI.getType(St->getValueReg());

840 if (ValSize < 32 || St->getMMO().getSizeInBits() != ValSize)

841 continue;

842

843 Register PtrReg = St->getPointerReg();

845 PtrReg, MRI,

849

850 if (Stores.empty()) {

852 continue;

853 }

854

855

857 if (storeIsValid(Last, New)) {

859 LoadValsSinceLastStore.clear();

860 } else {

861

862

863 Changed |= tryOptimizeConsecStores(Stores, MIB);

864 resetState();

866 }

867 }

869 LoadValsSinceLastStore.push_back(Ld->getDstReg());

870 }

871 }

872 Changed |= tryOptimizeConsecStores(Stores, MIB);

873 resetState();

874 }

875

877}

878

879char AArch64PostLegalizerCombiner::ID = 0;

881 "Combine AArch64 MachineInstrs after legalization", false,

882 false)

886 "Combine AArch64 MachineInstrs after legalization", false,

888

889namespace llvm {

891 return new AArch64PostLegalizerCombiner(IsOptNone);

892}

893}

unsigned const MachineRegisterInfo * MRI

MachineInstrBuilder & UseMI

static bool isZeroExtended(SDValue N, SelectionDAG &DAG)

static bool isSignExtended(SDValue N, SelectionDAG &DAG)

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

#define GET_GICOMBINER_CONSTRUCTOR_INITS

static cl::opt< bool > EnableConsecutiveMemOpOpt("aarch64-postlegalizer-consecutive-memops", cl::init(true), cl::Hidden, cl::desc("Enable consecutive memop optimization " "in AArch64PostLegalizerCombiner"))

amdgpu aa AMDGPU Address space based Alias Analysis Wrapper

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

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

Provides analysis for continuously CSEing during GISel passes.

This file implements a version of MachineIRBuilder which CSEs insts within a MachineBasicBlock.

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.

This contains common code to allow clients to notify changes to machine instr.

Provides analysis for querying information about KnownBits during GISel passes.

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

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.

Class for arbitrary precision integers.

unsigned countr_zero() const

Count the number of trailing zero bits.

unsigned logBase2() const

APInt ashr(unsigned ShiftAmt) const

Arithmetic right-shift function.

bool isNonNegative() const

Determine if this APInt Value is non-negative (>= 0)

bool isPowerOf2() const

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

static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)

Constructs an APInt value that has the top hiBitsSet bits set.

Represent the analysis usage information of a pass.

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:

Defines a builder that does CSE of MachineInstructions using GISelCSEInfo.

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

Build and insert Res = G_CONSTANT Val.

@ ICMP_SLT

signed less than

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.

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

bool maskedValueIsZero(Register Val, const APInt &Mask)

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

constexpr unsigned getScalarSizeInBits() 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 ElementCount getElementCount() const

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.

constexpr LLT changeElementCount(ElementCount EC) const

Return a vector or scalar with the same element type and the new element count.

Analysis pass which computes a MachineDominatorTree.

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

MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

virtual bool runOnMachineFunction(MachineFunction &MF)=0

runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...

const TargetSubtargetInfo & getSubtarget() const

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

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

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.

GISelChangeObserver * getObserver()

MachineInstrBuilder buildPtrAdd(const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)

Build and insert Res = G_PTR_ADD Op0, Op1.

MachineFunction & getMF()

Getter for the function we currently build.

void setInstrAndDebugLoc(MachineInstr &MI)

Set the insertion point to before MI, and set the debug loc to MI's loc.

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

unsigned getNumOperands() const

Retuns the total number of operands.

const MachineOperand & getOperand(unsigned i) const

ArrayRef< int > getShuffleMask() const

Register getReg() const

getReg - Returns the register number.

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

virtual StringRef getPassName() const

getPassName - Return a nice clean name for a pass.

Wrapper class representing virtual and physical registers.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void push_back(const T &Elt)

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

CodeGenOptLevel getOptLevel() const

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

Target-Independent Code Generator Pass Configuration Options.

virtual const TargetLowering * getTargetLowering() const

constexpr LeafTy multiplyCoefficientBy(ScalarTy RHS) const

#define llvm_unreachable(msg)

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

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.

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.

operand_type_match m_Pred()

ConstantMatch< APInt > m_ICst(APInt &Cst)

BinaryOp_match< LHS, RHS, TargetOpcode::G_OR, true > m_GOr(const LHS &L, const RHS &R)

OneNonDBGUse_match< SubPat > m_OneNonDBGUse(const SubPat &SP)

CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_ICMP > m_GICmp(const Pred &P, const LHS &L, const RHS &R)

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

BinaryOp_match< LHS, RHS, TargetOpcode::G_PTR_ADD, false > m_GPtrAdd(const LHS &L, const RHS &R)

Or< Preds... > m_any_of(Preds &&... preds)

BinaryOp_match< LHS, RHS, TargetOpcode::G_AND, true > m_GAnd(const LHS &L, const RHS &R)

CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_FCMP > m_GFCmp(const Pred &P, const LHS &L, const RHS &R)

initializer< Ty > init(const Ty &Val)

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.

decltype(auto) dyn_cast(const From &Val)

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

LLVM_ABI std::optional< APInt > isConstantOrConstantSplatVector(MachineInstr &MI, const MachineRegisterInfo &MRI)

Determines if MI defines a constant integer or a splat vector of constant integers.

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.

decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)

LLVM_ABI raw_ostream & dbgs()

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

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

FunctionPass * createAArch64PostLegalizerCombiner(bool IsOptNone)

Definition AArch64PostLegalizerCombiner.cpp:890

LLVM_ABI void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)

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

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

@ SinglePass

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