LLVM: lib/Target/ARM/ARMBaseInstrInfo.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

63#include

64#include

65#include

66#include

67#include

68#include

69#include

70

71using namespace llvm;

72

73#define DEBUG_TYPE "arm-instrinfo"

74

75#define GET_INSTRINFO_CTOR_DTOR

76#include "ARMGenInstrInfo.inc"

77

78

86

88

89

90 { ARM::VMLAS, ARM::VMULS, ARM::VADDS, false, false },

91 { ARM::VMLSS, ARM::VMULS, ARM::VSUBS, false, false },

92 { ARM::VMLAD, ARM::VMULD, ARM::VADDD, false, false },

93 { ARM::VMLSD, ARM::VMULD, ARM::VSUBD, false, false },

94 { ARM::VNMLAS, ARM::VNMULS, ARM::VSUBS, true, false },

95 { ARM::VNMLSS, ARM::VMULS, ARM::VSUBS, true, false },

96 { ARM::VNMLAD, ARM::VNMULD, ARM::VSUBD, true, false },

97 { ARM::VNMLSD, ARM::VMULD, ARM::VSUBD, true, false },

98

99

100 { ARM::VMLAfd, ARM::VMULfd, ARM::VADDfd, false, false },

101 { ARM::VMLSfd, ARM::VMULfd, ARM::VSUBfd, false, false },

102 { ARM::VMLAfq, ARM::VMULfq, ARM::VADDfq, false, false },

103 { ARM::VMLSfq, ARM::VMULfq, ARM::VSUBfq, false, false },

104 { ARM::VMLAslfd, ARM::VMULslfd, ARM::VADDfd, false, true },

105 { ARM::VMLSslfd, ARM::VMULslfd, ARM::VSUBfd, false, true },

106 { ARM::VMLAslfq, ARM::VMULslfq, ARM::VADDfq, false, true },

107 { ARM::VMLSslfq, ARM::VMULslfq, ARM::VSUBfq, false, true },

108};

109

113 Subtarget(STI) {

114 for (unsigned i = 0, e = std::size(ARM_MLxTable); i != e; ++i) {

115 if (!MLxEntryMap.insert(std::make_pair(ARM_MLxTable[i].MLxOpc, i)).second)

117 MLxHazardOpcodes.insert(ARM_MLxTable[i].AddSubOpc);

118 MLxHazardOpcodes.insert(ARM_MLxTable[i].MulOpc);

119 }

120}

121

122

123

127 if (usePreRAHazardRecognizer()) {

129 static_cast<const ARMSubtarget *>(STI)->getInstrItineraryData();

131 }

133}

134

135

136

137

141

142

143

144

145

146

149 std::make_unique(DAG, 0x4, true));

150

151

152

153

155 MHR->AddHazardRecognizer(std::unique_ptr(BHR));

156 return MHR;

157}

158

159

164

165 if (Subtarget.isThumb2() || Subtarget.hasVFP2Base())

167

169 if (BHR)

170 MHR->AddHazardRecognizer(std::unique_ptr(BHR));

171 return MHR;

172}

173

174

175

176

177

178

179

180

181

186 bool AllowModify) const {

187 TBB = nullptr;

188 FBB = nullptr;

189

191 if (I == MBB.instr_begin())

192 return false;

193 --I;

194

195

196

197 while (isPredicated(*I) || I->isTerminator() || I->isDebugValue()) {

198

199

200

201 bool CantAnalyze = false;

202

203

204

205 while (I->isDebugInstr() || I->isTerminator() ||

207 I->getOpcode() == ARM::t2DoLoopStartTP){

208 if (I == MBB.instr_begin())

209 return false;

210 --I;

211 }

212

215

216

217 CantAnalyze = true;

219 TBB = I->getOperand(0).getMBB();

221

222 if (Cond.empty())

223 return true;

224

225 assert(!FBB && "FBB should have been null.");

226 FBB = TBB;

227 TBB = I->getOperand(0).getMBB();

228 Cond.push_back(I->getOperand(1));

229 Cond.push_back(I->getOperand(2));

230 } else if (I->isReturn()) {

231

232 CantAnalyze = true;

233 } else if (I->getOpcode() == ARM::t2LoopEnd &&

234 MBB.getParent()

237 if (Cond.empty())

238 return true;

239 FBB = TBB;

240 TBB = I->getOperand(1).getMBB();

242 Cond.push_back(I->getOperand(0));

244 } else {

245

246 return true;

247 }

248

249

250

255 I->isReturn())) {

256

257 Cond.clear();

258 FBB = nullptr;

259

260

261

262 if (AllowModify) {

264 while (DI != MBB.instr_end()) {

266 ++DI;

267

269 continue;

271 }

272 }

273 }

274

275 if (CantAnalyze) {

276

277

278

279

282 TBB && MBB.isLayoutSuccessor(TBB))

284 return true;

285 }

286

287 if (I == MBB.instr_begin())

288 return false;

289

290 --I;

291 }

292

293

294

295 return false;

296}

297

299 int *BytesRemoved) const {

300 assert(!BytesRemoved && "code size not handled");

301

303 if (I == MBB.end())

304 return 0;

305

308 return 0;

309

310

311 I->eraseFromParent();

312

313 I = MBB.end();

314

315 if (I == MBB.begin()) return 1;

316 --I;

318 return 1;

319

320

321 I->eraseFromParent();

322 return 2;

323}

324

330 int *BytesAdded) const {

331 assert(!BytesAdded && "code size not handled");

336 ? ARM::Bcc : (AFI->isThumb2Function() ? ARM::t2Bcc : ARM::tBcc);

338

339

340 assert(TBB && "insertBranch must not be told to insert a fallthrough");

342 "ARM branch conditions have two or three components!");

343

344

345

346 if (!FBB) {

347 if (Cond.empty()) {

350 else

352 } else if (Cond.size() == 2) {

357 } else

359 return 1;

360 }

361

362

363 if (Cond.size() == 2)

368 else if (Cond.size() == 3)

372 else

374 return 2;

375}

376

379 if (Cond.size() == 2) {

382 return false;

383 }

384 return true;

385}

386

388 if (MI.isBundle()) {

391 while (++I != E && I->isInsideBundle()) {

392 int PIdx = I->findFirstPredOperandIdx();

393 if (PIdx != -1 && I->getOperand(PIdx).getImm() != ARMCC::AL)

394 return true;

395 }

396 return false;

397 }

398

399 int PIdx = MI.findFirstPredOperandIdx();

400 return PIdx != -1 && MI.getOperand(PIdx).getImm() != ARMCC::AL;

401}

402

406

407

408 std::string GenericComment =

410 if (!GenericComment.empty())

411 return GenericComment;

412

413

414 if (Op.isImm())

415 return std::string();

416

417

418

419 int FirstPredOp = MI.findFirstPredOperandIdx();

420 if (FirstPredOp != (int) OpIdx)

421 return std::string();

422

423 std::string CC = "CC::";

425 return CC;

426}

427

430 unsigned Opc = MI.getOpcode();

436 return true;

437 }

438

439 int PIdx = MI.findFirstPredOperandIdx();

440 if (PIdx != -1) {

443 MI.getOperand(PIdx+1).setReg(Pred[1].getReg());

444

445

446

449 assert(MCID.operands()[1].isOptionalDef() &&

450 "CPSR def isn't expected operand");

451 assert((MI.getOperand(1).isDead() ||

452 MI.getOperand(1).getReg() != ARM::CPSR) &&

453 "if conversion tried to stop defining used CPSR");

454 MI.getOperand(1).setReg(ARM::NoRegister);

455 }

456

457 return true;

458 }

459 return false;

460}

461

464 if (Pred1.size() > 2 || Pred2.size() > 2)

465 return false;

466

469 if (CC1 == CC2)

470 return true;

471

472 switch (CC1) {

473 default:

474 return false;

476 return true;

485 }

486}

487

489 std::vector &Pred,

490 bool SkipDead) const {

491 bool Found = false;

493 bool ClobbersCPSR = MO.isRegMask() && MO.clobbersPhysReg(ARM::CPSR);

494 bool IsCPSR = MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR;

495 if (ClobbersCPSR || IsCPSR) {

496

497

498

501 SkipDead)

502 continue;

503

504 Pred.push_back(MO);

505 Found = true;

506 }

507 }

508

509 return Found;

510}

511

513 for (const auto &MO : MI.operands())

514 if (MO.isReg() && MO.getReg() == ARM::CPSR && MO.isDef() && !MO.isDead())

515 return true;

516 return false;

517}

518

520 switch (MI->getOpcode()) {

521 default: return true;

522 case ARM::tADC:

523 case ARM::tADDi3:

524 case ARM::tADDi8:

525 case ARM::tADDrr:

526 case ARM::tAND:

527 case ARM::tASRri:

528 case ARM::tASRrr:

529 case ARM::tBIC:

530 case ARM::tEOR:

531 case ARM::tLSLri:

532 case ARM::tLSLrr:

533 case ARM::tLSRri:

534 case ARM::tLSRrr:

535 case ARM::tMUL:

536 case ARM::tMVN:

537 case ARM::tORR:

538 case ARM::tROR:

539 case ARM::tRSB:

540 case ARM::tSBC:

541 case ARM::tSUBi3:

542 case ARM::tSUBi8:

543 case ARM::tSUBrr:

545 }

546}

547

548

549

550

552 if (MI.isPredicable())

553 return false;

554

555 if (MI.isBundle())

556 return false;

557

559 return false;

560

564

565

566

568 return false;

569

570

571

574 return false;

576 return false;

577

581 }

582

583 return true;

584}

585

586namespace llvm {

587

590 if (!MO.isReg() || MO.isUndef() || MO.isUse())

591 continue;

592 if (MO.getReg() != ARM::CPSR)

593 continue;

594 if (!MO.isDead())

595 return false;

596 }

597

598 return true;

599}

600

601}

602

603

604

609

611

612 switch (MI.getOpcode()) {

613 default:

614

615

616

617

618

619 return MCID.getSize();

620 case TargetOpcode::BUNDLE:

621 return getInstBundleLength(MI);

622 case ARM::CONSTPOOL_ENTRY:

623 case ARM::JUMPTABLE_INSTS:

624 case ARM::JUMPTABLE_ADDRS:

625 case ARM::JUMPTABLE_TBB:

626 case ARM::JUMPTABLE_TBH:

627

628

629 return MI.getOperand(2).getImm();

630 case ARM::SPACE:

631 return MI.getOperand(1).getImm();

632 case ARM::INLINEASM:

633 case ARM::INLINEASM_BR: {

634

635 unsigned Size = getInlineAsmLength(MI.getOperand(0).getSymbolName(), *MAI);

639 }

640 }

641}

642

643unsigned ARMBaseInstrInfo::getInstBundleLength(const MachineInstr &MI) const {

644 unsigned Size = 0;

647 while (++I != E && I->isInsideBundle()) {

648 assert(I->isBundle() && "No nested bundle!");

650 }

652}

653

658 unsigned Opc = Subtarget.isThumb()

659 ? (Subtarget.isMClass() ? ARM::t2MRS_M : ARM::t2MRS_AR)

660 : ARM::MRS;

661

664

665

666

667 if (Subtarget.isMClass())

669

672}

673

678 unsigned Opc = Subtarget.isThumb()

679 ? (Subtarget.isMClass() ? ARM::t2MSR_M : ARM::t2MSR_AR)

680 : ARM::MSR;

681

683

684 if (Subtarget.isMClass())

686 else

688

692}

693

699

705

711

713 unsigned Cond, unsigned Inactive) {

715 MIB.addReg(Inactive);

716}

717

721 Register SrcReg, bool KillSrc,

722 bool RenamableDest,

723 bool RenamableSrc) const {

724 bool GPRDest = ARM::GPRRegClass.contains(DestReg);

725 bool GPRSrc = ARM::GPRRegClass.contains(SrcReg);

726

727 if (GPRDest && GPRSrc) {

732 return;

733 }

734

735 bool SPRDest = ARM::SPRRegClass.contains(DestReg);

736 bool SPRSrc = ARM::SPRRegClass.contains(SrcReg);

737

738 unsigned Opc = 0;

739 if (SPRDest && SPRSrc)

740 Opc = ARM::VMOVS;

741 else if (GPRDest && SPRSrc)

742 Opc = ARM::VMOVRS;

743 else if (SPRDest && GPRSrc)

744 Opc = ARM::VMOVSR;

745 else if (ARM::DPRRegClass.contains(DestReg, SrcReg) && Subtarget.hasFP64())

746 Opc = ARM::VMOVD;

747 else if (ARM::QPRRegClass.contains(DestReg, SrcReg))

748 Opc = Subtarget.hasNEON() ? ARM::VORRq : ARM::MQPRCopy;

749

750 if (Opc) {

753 if (Opc == ARM::VORRq || Opc == ARM::MVE_VORR)

755 if (Opc == ARM::MVE_VORR)

757 else if (Opc != ARM::MQPRCopy)

759 return;

760 }

761

762

763 unsigned BeginIdx = 0;

764 unsigned SubRegs = 0;

765 int Spacing = 1;

766

767

768 if (ARM::QQPRRegClass.contains(DestReg, SrcReg)) {

769 Opc = Subtarget.hasNEON() ? ARM::VORRq : ARM::MVE_VORR;

770 BeginIdx = ARM::qsub_0;

771 SubRegs = 2;

772 } else if (ARM::QQQQPRRegClass.contains(DestReg, SrcReg)) {

773 Opc = Subtarget.hasNEON() ? ARM::VORRq : ARM::MVE_VORR;

774 BeginIdx = ARM::qsub_0;

775 SubRegs = 4;

776

777 } else if (ARM::DPairRegClass.contains(DestReg, SrcReg)) {

778 Opc = ARM::VMOVD;

779 BeginIdx = ARM::dsub_0;

780 SubRegs = 2;

781 } else if (ARM::DTripleRegClass.contains(DestReg, SrcReg)) {

782 Opc = ARM::VMOVD;

783 BeginIdx = ARM::dsub_0;

784 SubRegs = 3;

785 } else if (ARM::DQuadRegClass.contains(DestReg, SrcReg)) {

786 Opc = ARM::VMOVD;

787 BeginIdx = ARM::dsub_0;

788 SubRegs = 4;

789 } else if (ARM::GPRPairRegClass.contains(DestReg, SrcReg)) {

790 Opc = Subtarget.isThumb2() ? ARM::tMOVr : ARM::MOVr;

791 BeginIdx = ARM::gsub_0;

792 SubRegs = 2;

793 } else if (ARM::DPairSpcRegClass.contains(DestReg, SrcReg)) {

794 Opc = ARM::VMOVD;

795 BeginIdx = ARM::dsub_0;

796 SubRegs = 2;

797 Spacing = 2;

798 } else if (ARM::DTripleSpcRegClass.contains(DestReg, SrcReg)) {

799 Opc = ARM::VMOVD;

800 BeginIdx = ARM::dsub_0;

801 SubRegs = 3;

802 Spacing = 2;

803 } else if (ARM::DQuadSpcRegClass.contains(DestReg, SrcReg)) {

804 Opc = ARM::VMOVD;

805 BeginIdx = ARM::dsub_0;

806 SubRegs = 4;

807 Spacing = 2;

808 } else if (ARM::DPRRegClass.contains(DestReg, SrcReg) &&

809 !Subtarget.hasFP64()) {

810 Opc = ARM::VMOVS;

811 BeginIdx = ARM::ssub_0;

812 SubRegs = 2;

813 } else if (SrcReg == ARM::CPSR) {

815 return;

816 } else if (DestReg == ARM::CPSR) {

818 return;

819 } else if (DestReg == ARM::VPR) {

821 BuildMI(MBB, I, I->getDebugLoc(), get(ARM::VMSR_P0), DestReg)

824 return;

825 } else if (SrcReg == ARM::VPR) {

827 BuildMI(MBB, I, I->getDebugLoc(), get(ARM::VMRS_P0), DestReg)

830 return;

831 } else if (DestReg == ARM::FPSCR_NZCV) {

833 BuildMI(MBB, I, I->getDebugLoc(), get(ARM::VMSR_FPSCR_NZCVQC), DestReg)

836 return;

837 } else if (SrcReg == ARM::FPSCR_NZCV) {

839 BuildMI(MBB, I, I->getDebugLoc(), get(ARM::VMRS_FPSCR_NZCVQC), DestReg)

842 return;

843 }

844

845 assert(Opc && "Impossible reg-to-reg copy");

846

849

850

851 if (TRI->regsOverlap(SrcReg, TRI->getSubReg(DestReg, BeginIdx))) {

852 BeginIdx = BeginIdx + ((SubRegs - 1) * Spacing);

853 Spacing = -Spacing;

854 }

855#ifndef NDEBUG

857#endif

858 for (unsigned i = 0; i != SubRegs; ++i) {

859 Register Dst = TRI->getSubReg(DestReg, BeginIdx + i * Spacing);

860 Register Src = TRI->getSubReg(SrcReg, BeginIdx + i * Spacing);

861 assert(Dst && Src && "Bad sub-register");

862#ifndef NDEBUG

863 assert(!DstRegs.count(Src) && "destructive vector copy");

865#endif

867

868 if (Opc == ARM::VORRq || Opc == ARM::MVE_VORR) {

870 }

871

872 if (Opc == ARM::MVE_VORR)

874 else

876

877 if (Opc == ARM::MOVr)

879 }

880

882 if (KillSrc)

884}

885

886std::optional

888

889

890

891

892

893

894

895 if (MI.isMoveReg() ||

896 (MI.getOpcode() == ARM::VORRq &&

897 MI.getOperand(1).getReg() != MI.getOperand(2).getReg()))

898 return std::nullopt;

900}

901

902std::optional

906 Register DstReg = DstSrcPair->Destination->getReg();

907

908

909

910

911

912

913

914

915

916

917

918

919

920

921

922

923

924

925

926 if (DstReg != Reg)

927 return std::nullopt;

928 }

930}

931

933 unsigned Reg,

934 unsigned SubIdx,

935 unsigned State) const {

936 if (!SubIdx)

937 return MIB.addReg(Reg, State);

938

941 return MIB.addReg(Reg, State, SubIdx);

942}

943

946 Register SrcReg, bool isKill, int FI,

954

958

959 switch (TRI.getSpillSize(*RC)) {

960 case 2:

961 if (ARM::HPRRegClass.hasSubClassEq(RC)) {

968 } else

970 break;

971 case 4:

972 if (ARM::GPRRegClass.hasSubClassEq(RC)) {

979 } else if (ARM::SPRRegClass.hasSubClassEq(RC)) {

986 } else if (ARM::VCCRRegClass.hasSubClassEq(RC)) {

993 } else if (ARM::cl_FPSCR_NZCVRegClass.hasSubClassEq(RC)) {

1000 } else

1002 break;

1003 case 8:

1004 if (ARM::DPRRegClass.hasSubClassEq(RC)) {

1011 } else if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {

1012 if (Subtarget.hasV5TEOps()) {

1015 AddDReg(MIB, SrcReg, ARM::gsub_1, 0);

1018 } else {

1019

1020

1026 AddDReg(MIB, SrcReg, ARM::gsub_1, 0);

1027 }

1028 } else

1030 break;

1031 case 16:

1032 if (ARM::DPairRegClass.hasSubClassEq(RC) && Subtarget.hasNEON()) {

1033

1034 if (Alignment >= 16 && getRegisterInfo().canRealignStack(MF)) {

1041 } else {

1047 }

1048 } else if (ARM::QPRRegClass.hasSubClassEq(RC) &&

1049 Subtarget.hasMVEIntegerOps()) {

1052 .addFrameIndex(FI)

1053 .addImm(0)

1054 .addMemOperand(MMO);

1056 } else

1058 break;

1059 case 24:

1060 if (ARM::DTripleRegClass.hasSubClassEq(RC)) {

1061

1062 if (Alignment >= 16 && getRegisterInfo().canRealignStack(MF) &&

1063 Subtarget.hasNEON()) {

1070 } else {

1072 get(ARM::VSTMDIA))

1077 MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0);

1078 AddDReg(MIB, SrcReg, ARM::dsub_2, 0);

1079 }

1080 } else

1082 break;

1083 case 32:

1084 if (ARM::QQPRRegClass.hasSubClassEq(RC) ||

1085 ARM::MQQPRRegClass.hasSubClassEq(RC) ||

1086 ARM::DQuadRegClass.hasSubClassEq(RC)) {

1087 if (Alignment >= 16 && getRegisterInfo().canRealignStack(MF) &&

1088 Subtarget.hasNEON()) {

1089

1090

1097 } else if (Subtarget.hasMVEIntegerOps()) {

1102 } else {

1104 get(ARM::VSTMDIA))

1109 MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0);

1110 MIB = AddDReg(MIB, SrcReg, ARM::dsub_2, 0);

1111 AddDReg(MIB, SrcReg, ARM::dsub_3, 0);

1112 }

1113 } else

1115 break;

1116 case 64:

1117 if (ARM::MQQQQPRRegClass.hasSubClassEq(RC) &&

1118 Subtarget.hasMVEIntegerOps()) {

1123 } else if (ARM::QQQQPRRegClass.hasSubClassEq(RC)) {

1129 MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0);

1130 MIB = AddDReg(MIB, SrcReg, ARM::dsub_2, 0);

1131 MIB = AddDReg(MIB, SrcReg, ARM::dsub_3, 0);

1132 MIB = AddDReg(MIB, SrcReg, ARM::dsub_4, 0);

1133 MIB = AddDReg(MIB, SrcReg, ARM::dsub_5, 0);

1134 MIB = AddDReg(MIB, SrcReg, ARM::dsub_6, 0);

1135 AddDReg(MIB, SrcReg, ARM::dsub_7, 0);

1136 } else

1138 break;

1139 default:

1141 }

1142}

1143

1145 int &FrameIndex) const {

1146 switch (MI.getOpcode()) {

1147 default: break;

1148 case ARM::STRrs:

1149 case ARM::t2STRs:

1150 if (MI.getOperand(1).isFI() && MI.getOperand(2).isReg() &&

1151 MI.getOperand(3).isImm() && MI.getOperand(2).getReg() == 0 &&

1152 MI.getOperand(3).getImm() == 0) {

1153 FrameIndex = MI.getOperand(1).getIndex();

1154 return MI.getOperand(0).getReg();

1155 }

1156 break;

1157 case ARM::STRi12:

1158 case ARM::t2STRi12:

1159 case ARM::tSTRspi:

1160 case ARM::VSTRD:

1161 case ARM::VSTRS:

1162 case ARM::VSTRH:

1163 case ARM::VSTR_P0_off:

1164 case ARM::VSTR_FPSCR_NZCVQC_off:

1165 case ARM::MVE_VSTRWU32:

1166 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&

1167 MI.getOperand(2).getImm() == 0) {

1168 FrameIndex = MI.getOperand(1).getIndex();

1169 return MI.getOperand(0).getReg();

1170 }

1171 break;

1172 case ARM::VST1q64:

1173 case ARM::VST1d64TPseudo:

1174 case ARM::VST1d64QPseudo:

1175 if (MI.getOperand(0).isFI() && MI.getOperand(2).getSubReg() == 0) {

1176 FrameIndex = MI.getOperand(0).getIndex();

1177 return MI.getOperand(2).getReg();

1178 }

1179 break;

1180 case ARM::VSTMQIA:

1181 if (MI.getOperand(1).isFI() && MI.getOperand(0).getSubReg() == 0) {

1182 FrameIndex = MI.getOperand(1).getIndex();

1183 return MI.getOperand(0).getReg();

1184 }

1185 break;

1186 case ARM::MQQPRStore:

1187 case ARM::MQQQQPRStore:

1188 if (MI.getOperand(1).isFI()) {

1189 FrameIndex = MI.getOperand(1).getIndex();

1190 return MI.getOperand(0).getReg();

1191 }

1192 break;

1193 }

1194

1195 return 0;

1196}

1197

1199 int &FrameIndex) const {

1201 if (MI.mayStore() && hasStoreToStackSlot(MI, Accesses) &&

1203 FrameIndex =

1205 ->getFrameIndex();

1206 return true;

1207 }

1208 return false;

1209}

1210

1218 if (I != MBB.end()) DL = I->getDebugLoc();

1225

1227 switch (TRI.getSpillSize(*RC)) {

1228 case 2:

1229 if (ARM::HPRRegClass.hasSubClassEq(RC)) {

1235 } else

1237 break;

1238 case 4:

1239 if (ARM::GPRRegClass.hasSubClassEq(RC)) {

1245 } else if (ARM::SPRRegClass.hasSubClassEq(RC)) {

1251 } else if (ARM::VCCRRegClass.hasSubClassEq(RC)) {

1257 } else if (ARM::cl_FPSCR_NZCVRegClass.hasSubClassEq(RC)) {

1258 BuildMI(MBB, I, DL, get(ARM::VLDR_FPSCR_NZCVQC_off), DestReg)

1263 } else

1265 break;

1266 case 8:

1267 if (ARM::DPRRegClass.hasSubClassEq(RC)) {

1273 } else if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {

1275

1276 if (Subtarget.hasV5TEOps()) {

1282 } else {

1283

1284

1291 }

1292

1295 } else

1297 break;

1298 case 16:

1299 if (ARM::DPairRegClass.hasSubClassEq(RC) && Subtarget.hasNEON()) {

1300 if (Alignment >= 16 && getRegisterInfo().canRealignStack(MF)) {

1306 } else {

1311 }

1312 } else if (ARM::QPRRegClass.hasSubClassEq(RC) &&

1313 Subtarget.hasMVEIntegerOps()) {

1314 auto MIB = BuildMI(MBB, I, DL, get(ARM::MVE_VLDRWU32), DestReg);

1315 MIB.addFrameIndex(FI)

1316 .addImm(0)

1317 .addMemOperand(MMO);

1319 } else

1321 break;

1322 case 24:

1323 if (ARM::DTripleRegClass.hasSubClassEq(RC)) {

1324 if (Alignment >= 16 && getRegisterInfo().canRealignStack(MF) &&

1325 Subtarget.hasNEON()) {

1331 } else {

1341 }

1342 } else

1344 break;

1345 case 32:

1346 if (ARM::QQPRRegClass.hasSubClassEq(RC) ||

1347 ARM::MQQPRRegClass.hasSubClassEq(RC) ||

1348 ARM::DQuadRegClass.hasSubClassEq(RC)) {

1349 if (Alignment >= 16 && getRegisterInfo().canRealignStack(MF) &&

1350 Subtarget.hasNEON()) {

1356 } else if (Subtarget.hasMVEIntegerOps()) {

1360 } else {

1371 }

1372 } else

1374 break;

1375 case 64:

1376 if (ARM::MQQQQPRRegClass.hasSubClassEq(RC) &&

1377 Subtarget.hasMVEIntegerOps()) {

1381 } else if (ARM::QQQQPRRegClass.hasSubClassEq(RC)) {

1396 } else

1398 break;

1399 default:

1401 }

1402}

1403

1405 int &FrameIndex) const {

1406 switch (MI.getOpcode()) {

1407 default: break;

1408 case ARM::LDRrs:

1409 case ARM::t2LDRs:

1410 if (MI.getOperand(1).isFI() && MI.getOperand(2).isReg() &&

1411 MI.getOperand(3).isImm() && MI.getOperand(2).getReg() == 0 &&

1412 MI.getOperand(3).getImm() == 0) {

1413 FrameIndex = MI.getOperand(1).getIndex();

1414 return MI.getOperand(0).getReg();

1415 }

1416 break;

1417 case ARM::LDRi12:

1418 case ARM::t2LDRi12:

1419 case ARM::tLDRspi:

1420 case ARM::VLDRD:

1421 case ARM::VLDRS:

1422 case ARM::VLDRH:

1423 case ARM::VLDR_P0_off:

1424 case ARM::VLDR_FPSCR_NZCVQC_off:

1425 case ARM::MVE_VLDRWU32:

1426 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&

1427 MI.getOperand(2).getImm() == 0) {

1428 FrameIndex = MI.getOperand(1).getIndex();

1429 return MI.getOperand(0).getReg();

1430 }

1431 break;

1432 case ARM::VLD1q64:

1433 case ARM::VLD1d8TPseudo:

1434 case ARM::VLD1d16TPseudo:

1435 case ARM::VLD1d32TPseudo:

1436 case ARM::VLD1d64TPseudo:

1437 case ARM::VLD1d8QPseudo:

1438 case ARM::VLD1d16QPseudo:

1439 case ARM::VLD1d32QPseudo:

1440 case ARM::VLD1d64QPseudo:

1441 if (MI.getOperand(1).isFI() && MI.getOperand(0).getSubReg() == 0) {

1442 FrameIndex = MI.getOperand(1).getIndex();

1443 return MI.getOperand(0).getReg();

1444 }

1445 break;

1446 case ARM::VLDMQIA:

1447 if (MI.getOperand(1).isFI() && MI.getOperand(0).getSubReg() == 0) {

1448 FrameIndex = MI.getOperand(1).getIndex();

1449 return MI.getOperand(0).getReg();

1450 }

1451 break;

1452 case ARM::MQQPRLoad:

1453 case ARM::MQQQQPRLoad:

1454 if (MI.getOperand(1).isFI()) {

1455 FrameIndex = MI.getOperand(1).getIndex();

1456 return MI.getOperand(0).getReg();

1457 }

1458 break;

1459 }

1460

1461 return 0;

1462}

1463

1465 int &FrameIndex) const {

1467 if (MI.mayLoad() && hasLoadFromStackSlot(MI, Accesses) &&

1469 FrameIndex =

1471 ->getFrameIndex();

1472 return true;

1473 }

1474 return false;

1475}

1476

1477

1478

1481 bool isThumb2 = Subtarget.isThumb2();

1483

1486

1488 if (isThumb1 || MI->getOperand(1).isDead()) {

1490 LDM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2LDMIA_UPD

1491 : isThumb1 ? ARM::tLDMIA_UPD

1492 : ARM::LDMIA_UPD))

1493 .add(LDWb);

1494 } else {

1495 LDM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2LDMIA : ARM::LDMIA));

1496 }

1497

1498 if (isThumb1 || MI->getOperand(0).isDead()) {

1499 MachineOperand STWb(MI->getOperand(0));

1500 STM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2STMIA_UPD

1501 : isThumb1 ? ARM::tSTMIA_UPD

1502 : ARM::STMIA_UPD))

1503 .add(STWb);

1504 } else {

1505 STM = BuildMI(*BB, MI, dl, TII->get(isThumb2 ? ARM::t2STMIA : ARM::STMIA));

1506 }

1507

1508 MachineOperand LDBase(MI->getOperand(3));

1510

1511 MachineOperand STBase(MI->getOperand(2));

1513

1514

1518 ScratchRegs.push_back(MO.getReg());

1520 [&TRI](const unsigned &Reg1, const unsigned &Reg2) -> bool {

1521 return TRI.getEncodingValue(Reg1) <

1522 TRI.getEncodingValue(Reg2);

1523 });

1524

1525 for (const auto &Reg : ScratchRegs) {

1528 }

1529

1531}

1532

1534 if (MI.getOpcode() == TargetOpcode::LOAD_STACK_GUARD) {

1535 expandLoadStackGuard(MI);

1536 MI.getParent()->erase(MI);

1537 return true;

1538 }

1539

1540 if (MI.getOpcode() == ARM::MEMCPY) {

1541 expandMEMCPY(MI);

1542 return true;

1543 }

1544

1545

1546

1547

1548

1549 if (MI.isCopy() || Subtarget.dontWidenVMOVS() || !Subtarget.hasFP64())

1550 return false;

1551

1552

1553

1554 Register DstRegS = MI.getOperand(0).getReg();

1555 Register SrcRegS = MI.getOperand(1).getReg();

1556 if (!ARM::SPRRegClass.contains(DstRegS, SrcRegS))

1557 return false;

1558

1561 TRI->getMatchingSuperReg(DstRegS, ARM::ssub_0, &ARM::DPRRegClass);

1563 TRI->getMatchingSuperReg(SrcRegS, ARM::ssub_0, &ARM::DPRRegClass);

1564 if (!DstRegD || !SrcRegD)

1565 return false;

1566

1567

1568

1569

1570 if (MI.definesRegister(DstRegD, TRI) || MI.readsRegister(DstRegD, TRI))

1571 return false;

1572

1573

1574 if (MI.getOperand(0).isDead())

1575 return false;

1576

1577

1580

1581

1582

1583 int ImpDefIdx = MI.findRegisterDefOperandIdx(DstRegD, nullptr);

1584 if (ImpDefIdx != -1)

1585 MI.removeOperand(ImpDefIdx);

1586

1587

1588 MI.setDesc(get(ARM::VMOVD));

1589 MI.getOperand(0).setReg(DstRegD);

1590 MI.getOperand(1).setReg(SrcRegD);

1592

1593

1594

1595

1596

1597 MI.getOperand(1).setIsUndef();

1599

1600

1601

1602 if (MI.getOperand(1).isKill()) {

1603 MI.getOperand(1).setIsKill(false);

1604 MI.addRegisterKilled(SrcRegS, TRI, true);

1605 }

1606

1608 return true;

1609}

1610

1611

1612

1616

1618 assert(MCPE.isMachineConstantPoolEntry() &&

1619 "Expecting a machine constantpool entry!");

1622

1625

1626

1627

1628

1629

1630

1643 else if (ACPV->isLSDA())

1650 else

1651 llvm_unreachable("Unexpected ARM constantpool value type!!");

1653 return PCLabelId;

1654}

1655

1658 Register DestReg, unsigned SubIdx,

1660 unsigned Opcode = Orig.getOpcode();

1661 switch (Opcode) {

1662 default: {

1666 break;

1667 }

1668 case ARM::tLDRpci_pic:

1669 case ARM::t2LDRpci_pic: {

1677 break;

1678 }

1679 }

1680}

1681

1688 for (;;) {

1689 switch (I->getOpcode()) {

1690 case ARM::tLDRpci_pic:

1691 case ARM::t2LDRpci_pic: {

1693 unsigned CPI = I->getOperand(1).getIndex();

1695 I->getOperand(1).setIndex(CPI);

1696 I->getOperand(2).setImm(PCLabelId);

1697 break;

1698 }

1699 }

1700 if (I->isBundledWithSucc())

1701 break;

1702 ++I;

1703 }

1704 return Cloned;

1705}

1706

1710 unsigned Opcode = MI0.getOpcode();

1711 if (Opcode == ARM::t2LDRpci || Opcode == ARM::t2LDRpci_pic ||

1712 Opcode == ARM::tLDRpci || Opcode == ARM::tLDRpci_pic ||

1713 Opcode == ARM::LDRLIT_ga_pcrel || Opcode == ARM::LDRLIT_ga_pcrel_ldr ||

1714 Opcode == ARM::tLDRLIT_ga_pcrel || Opcode == ARM::t2LDRLIT_ga_pcrel ||

1715 Opcode == ARM::MOV_ga_pcrel || Opcode == ARM::MOV_ga_pcrel_ldr ||

1716 Opcode == ARM::t2MOV_ga_pcrel) {

1718 return false;

1720 return false;

1721

1725 return false;

1726

1727 if (Opcode == ARM::LDRLIT_ga_pcrel || Opcode == ARM::LDRLIT_ga_pcrel_ldr ||

1728 Opcode == ARM::tLDRLIT_ga_pcrel || Opcode == ARM::t2LDRLIT_ga_pcrel ||

1729 Opcode == ARM::MOV_ga_pcrel || Opcode == ARM::MOV_ga_pcrel_ldr ||

1730 Opcode == ARM::t2MOV_ga_pcrel)

1731

1733

1742 if (isARMCP0 && isARMCP1) {

1748 } else if (!isARMCP0 && !isARMCP1) {

1750 }

1751 return false;

1752 } else if (Opcode == ARM::PICLDR) {

1754 return false;

1756 return false;

1757

1760 if (Addr0 != Addr1) {

1762 return false;

1763

1764

1767

1768

1770 return false;

1771 }

1772

1773 for (unsigned i = 3, e = MI0.getNumOperands(); i != e; ++i) {

1774

1778 return false;

1779 }

1780 return true;

1781 }

1782

1784}

1785

1786

1787

1788

1789

1790

1791

1792

1793

1795 int64_t &Offset1,

1796 int64_t &Offset2) const {

1797

1798 if (Subtarget.isThumb1Only()) return false;

1799

1801 return false;

1802

1803 auto IsLoadOpcode = [&](unsigned Opcode) {

1804 switch (Opcode) {

1805 default:

1806 return false;

1807 case ARM::LDRi12:

1808 case ARM::LDRBi12:

1809 case ARM::LDRD:

1810 case ARM::LDRH:

1811 case ARM::LDRSB:

1812 case ARM::LDRSH:

1813 case ARM::VLDRD:

1814 case ARM::VLDRS:

1815 case ARM::t2LDRi8:

1816 case ARM::t2LDRBi8:

1817 case ARM::t2LDRDi8:

1818 case ARM::t2LDRSHi8:

1819 case ARM::t2LDRi12:

1820 case ARM::t2LDRBi12:

1821 case ARM::t2LDRSHi12:

1822 return true;

1823 }

1824 };

1825

1828 return false;

1829

1830

1833 return false;

1834

1835

1837 return false;

1838

1839

1844 return true;

1845 }

1846

1847 return false;

1848}

1849

1850

1851

1852

1853

1854

1855

1856

1857

1858

1859

1860

1862 int64_t Offset1, int64_t Offset2,

1863 unsigned NumLoads) const {

1864

1865 if (Subtarget.isThumb1Only()) return false;

1866

1867 assert(Offset2 > Offset1);

1868

1869 if ((Offset2 - Offset1) / 8 > 64)

1870 return false;

1871

1872

1873

1874

1875

1876

1882 return false;

1883

1884

1885 if (NumLoads >= 3)

1886 return false;

1887

1888 return true;

1889}

1890

1894

1895

1896

1897

1898

1899

1900 if (MI.isDebugInstr())

1901 return false;

1902

1903

1904 if (MI.isTerminator() || MI.isPosition())

1905 return true;

1906

1907

1908 if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)

1909 return true;

1910

1912 return true;

1913

1914

1915

1916

1917

1918

1919

1921

1922 while (++I != MBB->end() && I->isDebugInstr())

1923 ;

1924 if (I != MBB->end() && I->getOpcode() == ARM::t2IT)

1925 return true;

1926

1927

1928

1929

1930

1931

1932

1933

1934

1935 if (MI.isCall() && MI.definesRegister(ARM::SP, nullptr))

1936 return true;

1937

1938 return false;

1939}

1940

1943 unsigned NumCycles, unsigned ExtraPredCycles,

1945 if (!NumCycles)

1946 return false;

1947

1948

1949

1950

1951 if (MBB.getParent()->getFunction().hasOptSize()) {

1953 if (!Pred->empty()) {

1955 if (LastMI->getOpcode() == ARM::t2Bcc) {

1958 if (CmpMI)

1959 return false;

1960 }

1961 }

1962 }

1964 MBB, 0, 0, Probability);

1965}

1966

1969 unsigned TCycles, unsigned TExtra,

1971 unsigned FCycles, unsigned FExtra,

1973 if (!TCycles)

1974 return false;

1975

1976

1977

1978

1979

1980 if (Subtarget.isThumb2() && TBB.getParent()->getFunction().hasMinSize()) {

1981 if (TBB.pred_size() != 1 || FBB.pred_size() != 1)

1982 return false;

1983 }

1984

1985

1986

1987

1988 const unsigned ScalingUpFactor = 1024;

1989

1990 unsigned PredCost = (TCycles + FCycles + TExtra + FExtra) * ScalingUpFactor;

1991 unsigned UnpredCost;

1992 if (!Subtarget.hasBranchPredictor()) {

1993

1994

1995 unsigned NotTakenBranchCost = 1;

1996 unsigned TakenBranchCost = Subtarget.getMispredictionPenalty();

1997 unsigned TUnpredCycles, FUnpredCycles;

1998 if (!FCycles) {

1999

2000 TUnpredCycles = TCycles + NotTakenBranchCost;

2001 FUnpredCycles = TakenBranchCost;

2002 } else {

2003

2004 TUnpredCycles = TCycles + TakenBranchCost;

2005 FUnpredCycles = FCycles + NotTakenBranchCost;

2006

2007

2008 PredCost -= 1 * ScalingUpFactor;

2009 }

2010

2011 unsigned TUnpredCost = Probability.scale(TUnpredCycles * ScalingUpFactor);

2012 unsigned FUnpredCost = Probability.getCompl().scale(FUnpredCycles * ScalingUpFactor);

2013 UnpredCost = TUnpredCost + FUnpredCost;

2014

2015

2016 if (Subtarget.isThumb2() && TCycles + FCycles > 4) {

2017 PredCost += ((TCycles + FCycles - 4) / 4) * ScalingUpFactor;

2018 }

2019 } else {

2020 unsigned TUnpredCost = Probability.scale(TCycles * ScalingUpFactor);

2021 unsigned FUnpredCost =

2022 Probability.getCompl().scale(FCycles * ScalingUpFactor);

2023 UnpredCost = TUnpredCost + FUnpredCost;

2024 UnpredCost += 1 * ScalingUpFactor;

2025 UnpredCost += Subtarget.getMispredictionPenalty() * ScalingUpFactor / 10;

2026 }

2027

2028 return PredCost <= UnpredCost;

2029}

2030

2031unsigned

2033 unsigned NumInsts) const {

2034

2035

2036

2037 if (!Subtarget.isThumb2())

2038 return 0;

2039

2040

2041 unsigned MaxInsts = Subtarget.restrictIT() ? 1 : 4;

2042 return divideCeil(NumInsts, MaxInsts) * 2;

2043}

2044

2045unsigned

2047

2048

2049

2050 if (MI.getOpcode() == ARM::t2Bcc &&

2052 return 0;

2053

2055

2056

2057

2058

2059

2060

2061

2062 if (Subtarget.isThumb2())

2064

2065 return Size;

2066}

2067

2068bool

2071

2072

2073 return Subtarget.isProfitableToUnpredicate();

2074}

2075

2076

2077

2078

2081 int PIdx = MI.findFirstPredOperandIdx();

2082 if (PIdx == -1) {

2083 PredReg = 0;

2085 }

2086

2087 PredReg = MI.getOperand(PIdx+1).getReg();

2089}

2090

2092 if (Opc == ARM::B)

2093 return ARM::Bcc;

2094 if (Opc == ARM::tB)

2095 return ARM::tBcc;

2096 if (Opc == ARM::t2B)

2097 return ARM::t2Bcc;

2098

2100}

2101

2103 bool NewMI,

2104 unsigned OpIdx1,

2105 unsigned OpIdx2) const {

2106 switch (MI.getOpcode()) {

2107 case ARM::MOVCCr:

2108 case ARM::t2MOVCCr: {

2109

2112

2113 if (CC == ARMCC::AL || PredReg != ARM::CPSR)

2114 return nullptr;

2117 if (!CommutedMI)

2118 return nullptr;

2119

2122 return CommutedMI;

2123 }

2124 }

2126}

2127

2128

2129

2133 if (!Reg.isVirtual())

2134 return nullptr;

2135 if (MRI.hasOneNonDBGUse(Reg))

2136 return nullptr;

2138 if (MI)

2139 return nullptr;

2140

2142 return nullptr;

2143

2144

2146

2147 if (MO.isFI() || MO.isCPI() || MO.isJTI())

2148 return nullptr;

2149 if (!MO.isReg())

2150 continue;

2151

2152 if (MO.isTied())

2153 return nullptr;

2154 if (MO.getReg().isPhysical())

2155 return nullptr;

2156 if (MO.isDef() && !MO.isDead())

2157 return nullptr;

2158 }

2159 bool DontMoveAcrossStores = true;

2160 if (MI->isSafeToMove(DontMoveAcrossStores))

2161 return nullptr;

2162 return MI;

2163}

2164

2167 unsigned &TrueOp, unsigned &FalseOp,

2168 bool &Optimizable) const {

2169 assert((MI.getOpcode() == ARM::MOVCCr || MI.getOpcode() == ARM::t2MOVCCr) &&

2170 "Unknown select instruction");

2171

2172

2173

2174

2175

2176

2177 TrueOp = 1;

2178 FalseOp = 2;

2179 Cond.push_back(MI.getOperand(3));

2180 Cond.push_back(MI.getOperand(4));

2181

2182 Optimizable = true;

2183 return false;

2184}

2185

2189 bool PreferFalse) const {

2190 assert((MI.getOpcode() == ARM::MOVCCr || MI.getOpcode() == ARM::t2MOVCCr) &&

2191 "Unknown select instruction");

2194 bool Invert = DefMI;

2196 DefMI = canFoldIntoMOVCC(MI.getOperand(1).getReg(), MRI, this);

2198 return nullptr;

2199

2200

2203 Register DestReg = MI.getOperand(0).getReg();

2206 if (MRI.constrainRegClass(DestReg, FalseClass))

2207 return nullptr;

2208 if (MRI.constrainRegClass(DestReg, TrueClass))

2209 return nullptr;

2210

2211

2212

2214 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), DefMI->getDesc(), DestReg);

2215

2216

2219 i != e && !DefDesc.operands()[i].isPredicate(); ++i)

2220 NewMI.add(DefMI->getOperand(i));

2221

2222 unsigned CondCode = MI.getOperand(3).getImm();

2223 if (Invert)

2225 else

2226 NewMI.addImm(CondCode);

2227 NewMI.add(MI.getOperand(4));

2228

2229

2232

2233

2234

2235

2236

2238 NewMI.add(FalseReg);

2240

2241

2242 SeenMIs.insert(NewMI);

2244

2245

2246

2247

2248

2249 if (DefMI->getParent() != MI.getParent())

2251

2252

2253 DefMI->eraseFromParent();

2254 return NewMI;

2255}

2256

2257

2258

2259

2260

2261

2262

2267

2269 {ARM::ADDSri, ARM::ADDri},

2270 {ARM::ADDSrr, ARM::ADDrr},

2271 {ARM::ADDSrsi, ARM::ADDrsi},

2272 {ARM::ADDSrsr, ARM::ADDrsr},

2273

2274 {ARM::SUBSri, ARM::SUBri},

2275 {ARM::SUBSrr, ARM::SUBrr},

2276 {ARM::SUBSrsi, ARM::SUBrsi},

2277 {ARM::SUBSrsr, ARM::SUBrsr},

2278

2279 {ARM::RSBSri, ARM::RSBri},

2280 {ARM::RSBSrsi, ARM::RSBrsi},

2281 {ARM::RSBSrsr, ARM::RSBrsr},

2282

2283 {ARM::tADDSi3, ARM::tADDi3},

2284 {ARM::tADDSi8, ARM::tADDi8},

2285 {ARM::tADDSrr, ARM::tADDrr},

2286 {ARM::tADCS, ARM::tADC},

2287

2288 {ARM::tSUBSi3, ARM::tSUBi3},

2289 {ARM::tSUBSi8, ARM::tSUBi8},

2290 {ARM::tSUBSrr, ARM::tSUBrr},

2291 {ARM::tSBCS, ARM::tSBC},

2292 {ARM::tRSBS, ARM::tRSB},

2293 {ARM::tLSLSri, ARM::tLSLri},

2294

2295 {ARM::t2ADDSri, ARM::t2ADDri},

2296 {ARM::t2ADDSrr, ARM::t2ADDrr},

2297 {ARM::t2ADDSrs, ARM::t2ADDrs},

2298

2299 {ARM::t2SUBSri, ARM::t2SUBri},

2300 {ARM::t2SUBSrr, ARM::t2SUBrr},

2301 {ARM::t2SUBSrs, ARM::t2SUBrs},

2302

2303 {ARM::t2RSBSri, ARM::t2RSBri},

2304 {ARM::t2RSBSrs, ARM::t2RSBrs},

2305};

2306

2309 if (OldOpc == Entry.PseudoOpc)

2310 return Entry.MachineOpc;

2311 return 0;

2312}

2313

2317 Register BaseReg, int NumBytes,

2320 unsigned MIFlags) {

2321 if (NumBytes == 0 && DestReg != BaseReg) {

2327 return;

2328 }

2329

2330 bool isSub = NumBytes < 0;

2331 if (isSub) NumBytes = -NumBytes;

2332

2333 while (NumBytes) {

2336 assert(ThisVal && "Didn't extract field correctly");

2337

2338

2339 NumBytes &= ~ThisVal;

2340

2342

2343

2344 unsigned Opc = isSub ? ARM::SUBri : ARM::ADDri;

2351 BaseReg = DestReg;

2352 }

2353}

2354

2357 unsigned NumBytes) {

2358

2359

2361 return false;

2362

2363

2364

2365

2368 if (!IsPush && !IsPop)

2369 return false;

2370

2371 bool IsVFPPushPop = MI->getOpcode() == ARM::VSTMDDB_UPD ||

2372 MI->getOpcode() == ARM::VLDMDIA_UPD;

2373 bool IsT1PushPop = MI->getOpcode() == ARM::tPUSH ||

2374 MI->getOpcode() == ARM::tPOP ||

2375 MI->getOpcode() == ARM::tPOP_RET;

2376

2377 assert((IsT1PushPop || (MI->getOperand(0).getReg() == ARM::SP &&

2378 MI->getOperand(1).getReg() == ARM::SP)) &&

2379 "trying to fold sp update into non-sp-updating push/pop");

2380

2381

2382

2383

2384 if (NumBytes % (IsVFPPushPop ? 8 : 4) != 0)

2385 return false;

2386

2387

2388

2389 int RegListIdx = IsT1PushPop ? 2 : 4;

2390

2391

2392 unsigned RegsNeeded;

2394 if (IsVFPPushPop) {

2395 RegsNeeded = NumBytes / 8;

2396 RegClass = &ARM::DPRRegClass;

2397 } else {

2398 RegsNeeded = NumBytes / 4;

2399 RegClass = &ARM::GPRRegClass;

2400 }

2401

2402

2403

2404

2406

2407

2408

2409 unsigned FirstRegEnc = -1;

2410

2412 for (int i = MI->getNumOperands() - 1; i >= RegListIdx; --i) {

2415

2417 TRI->getEncodingValue(MO.getReg()) < FirstRegEnc)

2418 FirstRegEnc = TRI->getEncodingValue(MO.getReg());

2419 }

2420

2421 const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF);

2422

2423

2424 for (int CurRegEnc = FirstRegEnc - 1; CurRegEnc >= 0 && RegsNeeded;

2425 --CurRegEnc) {

2427 if (IsT1PushPop && CurRegEnc > TRI->getEncodingValue(ARM::R7))

2428 continue;

2429 if (!IsPop) {

2430

2431

2432

2434 false, false, true));

2435 --RegsNeeded;

2436 continue;

2437 }

2438

2439

2440

2441

2442

2444 MI->getParent()->computeRegisterLiveness(TRI, CurReg, MI) !=

2446

2447

2448 if (IsVFPPushPop)

2449 return false;

2450 else

2451 continue;

2452 }

2453

2454

2456 true));

2457 --RegsNeeded;

2458 }

2459

2460 if (RegsNeeded > 0)

2461 return false;

2462

2463

2464

2465

2466 for (int i = MI->getNumOperands() - 1; i >= RegListIdx; --i)

2467 MI->removeOperand(i);

2468

2469

2472 MIB.add(MO);

2473

2474 return true;

2475}

2476

2480 unsigned Opcode = MI.getOpcode();

2483 bool isSub = false;

2484

2485

2486 if (Opcode == ARM::INLINEASM || Opcode == ARM::INLINEASM_BR)

2488

2489 if (Opcode == ARM::ADDri) {

2490 Offset += MI.getOperand(FrameRegIdx+1).getImm();

2492

2493 MI.setDesc(TII.get(ARM::MOVr));

2494 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);

2495 MI.removeOperand(FrameRegIdx+1);

2497 return true;

2498 } else if (Offset < 0) {

2500 isSub = true;

2501 MI.setDesc(TII.get(ARM::SUBri));

2502 }

2503

2504

2506

2507 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);

2508 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);

2510 return true;

2511 }

2512

2513

2514

2517

2518

2519 Offset &= ~ThisImmVal;

2520

2521

2523 "Bit extraction didn't work?");

2524 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);

2525 } else {

2526 unsigned ImmIdx = 0;

2527 int InstrOffs = 0;

2528 unsigned NumBits = 0;

2529 unsigned Scale = 1;

2532 ImmIdx = FrameRegIdx + 1;

2533 InstrOffs = MI.getOperand(ImmIdx).getImm();

2534 NumBits = 12;

2535 break;

2537 ImmIdx = FrameRegIdx+2;

2540 InstrOffs *= -1;

2541 NumBits = 12;

2542 break;

2544 ImmIdx = FrameRegIdx+2;

2547 InstrOffs *= -1;

2548 NumBits = 8;

2549 break;

2552

2553 return false;

2555 ImmIdx = FrameRegIdx+1;

2558 InstrOffs *= -1;

2559 NumBits = 8;

2560 Scale = 4;

2561 break;

2563 ImmIdx = FrameRegIdx+1;

2566 InstrOffs *= -1;

2567 NumBits = 8;

2568 Scale = 2;

2569 break;

2573 ImmIdx = FrameRegIdx+1;

2574 InstrOffs = MI.getOperand(ImmIdx).getImm();

2575 NumBits = 7;

2578 break;

2579 default:

2581 }

2582

2583 Offset += InstrOffs * Scale;

2584 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");

2587 isSub = true;

2588 }

2589

2590

2591 if (NumBits > 0) {

2592

2594 int ImmedOffset = Offset / Scale;

2595 unsigned Mask = (1 << NumBits) - 1;

2596 if ((unsigned)Offset <= Mask * Scale) {

2597

2598 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);

2599

2600

2601

2602 if (isSub) {

2604 ImmedOffset = -ImmedOffset;

2605 else

2606 ImmedOffset |= 1 << NumBits;

2607 }

2610 return true;

2611 }

2612

2613

2614 ImmedOffset = ImmedOffset & Mask;

2615 if (isSub) {

2617 ImmedOffset = -ImmedOffset;

2618 else

2619 ImmedOffset |= 1 << NumBits;

2620 }

2622 Offset &= ~(Mask*Scale);

2623 }

2624 }

2625

2628}

2629

2630

2631

2632

2633

2635 Register &SrcReg2, int64_t &CmpMask,

2636 int64_t &CmpValue) const {

2637 switch (MI.getOpcode()) {

2638 default: break;

2639 case ARM::CMPri:

2640 case ARM::t2CMPri:

2641 case ARM::tCMPi8:

2642 SrcReg = MI.getOperand(0).getReg();

2643 SrcReg2 = 0;

2644 CmpMask = ~0;

2645 CmpValue = MI.getOperand(1).getImm();

2646 return true;

2647 case ARM::CMPrr:

2648 case ARM::t2CMPrr:

2649 case ARM::tCMPr:

2650 SrcReg = MI.getOperand(0).getReg();

2651 SrcReg2 = MI.getOperand(1).getReg();

2652 CmpMask = ~0;

2653 CmpValue = 0;

2654 return true;

2655 case ARM::TSTri:

2656 case ARM::t2TSTri:

2657 SrcReg = MI.getOperand(0).getReg();

2658 SrcReg2 = 0;

2659 CmpMask = MI.getOperand(1).getImm();

2660 CmpValue = 0;

2661 return true;

2662 }

2663

2664 return false;

2665}

2666

2667

2668

2669

2670

2672 int CmpMask, bool CommonUse) {

2673 switch (MI->getOpcode()) {

2674 case ARM::ANDri:

2675 case ARM::t2ANDri:

2676 if (CmpMask != MI->getOperand(2).getImm())

2677 return false;

2678 if (SrcReg == MI->getOperand(CommonUse ? 1 : 0).getReg())

2679 return true;

2680 break;

2681 }

2682

2683 return false;

2684}

2685

2686

2687

2688

2690 switch (CC) {

2696 }

2697}

2698

2699

2700

2701

2702

2703

2704

2707 int64_t ImmValue,

2709 bool &IsThumb1) {

2710 if ((CmpI->getOpcode() == ARM::CMPrr || CmpI->getOpcode() == ARM::t2CMPrr) &&

2711 (OI->getOpcode() == ARM::SUBrr || OI->getOpcode() == ARM::t2SUBrr) &&

2716 IsThumb1 = false;

2717 return true;

2718 }

2719

2720 if (CmpI->getOpcode() == ARM::tCMPr && OI->getOpcode() == ARM::tSUBrr &&

2725 IsThumb1 = true;

2726 return true;

2727 }

2728

2729 if ((CmpI->getOpcode() == ARM::CMPri || CmpI->getOpcode() == ARM::t2CMPri) &&

2730 (OI->getOpcode() == ARM::SUBri || OI->getOpcode() == ARM::t2SUBri) &&

2733 IsThumb1 = false;

2734 return true;

2735 }

2736

2737 if (CmpI->getOpcode() == ARM::tCMPi8 &&

2738 (OI->getOpcode() == ARM::tSUBi8 || OI->getOpcode() == ARM::tSUBi3) &&

2741 IsThumb1 = true;

2742 return true;

2743 }

2744

2745 if ((CmpI->getOpcode() == ARM::CMPrr || CmpI->getOpcode() == ARM::t2CMPrr) &&

2746 (OI->getOpcode() == ARM::ADDrr || OI->getOpcode() == ARM::t2ADDrr ||

2747 OI->getOpcode() == ARM::ADDri || OI->getOpcode() == ARM::t2ADDri) &&

2751 IsThumb1 = false;

2752 return true;

2753 }

2754

2755 if (CmpI->getOpcode() == ARM::tCMPr &&

2756 (OI->getOpcode() == ARM::tADDi3 || OI->getOpcode() == ARM::tADDi8 ||

2757 OI->getOpcode() == ARM::tADDrr) &&

2760 IsThumb1 = true;

2761 return true;

2762 }

2763

2764 return false;

2765}

2766

2768 switch (MI->getOpcode()) {

2769 default: return false;

2770 case ARM::tLSLri:

2771 case ARM::tLSRri:

2772 case ARM::tLSLrr:

2773 case ARM::tLSRrr:

2774 case ARM::tSUBrr:

2775 case ARM::tADDrr:

2776 case ARM::tADDi3:

2777 case ARM::tADDi8:

2778 case ARM::tSUBi3:

2779 case ARM::tSUBi8:

2780 case ARM::tMUL:

2781 case ARM::tADC:

2782 case ARM::tSBC:

2783 case ARM::tRSB:

2784 case ARM::tAND:

2785 case ARM::tORR:

2786 case ARM::tEOR:

2787 case ARM::tBIC:

2788 case ARM::tMVN:

2789 case ARM::tASRri:

2790 case ARM::tASRrr:

2791 case ARM::tROR:

2792 IsThumb1 = true;

2793 [[fallthrough]];

2794 case ARM::RSBrr:

2795 case ARM::RSBri:

2796 case ARM::RSCrr:

2797 case ARM::RSCri:

2798 case ARM::ADDrr:

2799 case ARM::ADDri:

2800 case ARM::ADCrr:

2801 case ARM::ADCri:

2802 case ARM::SUBrr:

2803 case ARM::SUBri:

2804 case ARM::SBCrr:

2805 case ARM::SBCri:

2806 case ARM::t2RSBri:

2807 case ARM::t2ADDrr:

2808 case ARM::t2ADDri:

2809 case ARM::t2ADCrr:

2810 case ARM::t2ADCri:

2811 case ARM::t2SUBrr:

2812 case ARM::t2SUBri:

2813 case ARM::t2SBCrr:

2814 case ARM::t2SBCri:

2815 case ARM::ANDrr:

2816 case ARM::ANDri:

2817 case ARM::ANDrsr:

2818 case ARM::ANDrsi:

2819 case ARM::t2ANDrr:

2820 case ARM::t2ANDri:

2821 case ARM::t2ANDrs:

2822 case ARM::ORRrr:

2823 case ARM::ORRri:

2824 case ARM::ORRrsr:

2825 case ARM::ORRrsi:

2826 case ARM::t2ORRrr:

2827 case ARM::t2ORRri:

2828 case ARM::t2ORRrs:

2829 case ARM::EORrr:

2830 case ARM::EORri:

2831 case ARM::EORrsr:

2832 case ARM::EORrsi:

2833 case ARM::t2EORrr:

2834 case ARM::t2EORri:

2835 case ARM::t2EORrs:

2836 case ARM::BICri:

2837 case ARM::BICrr:

2838 case ARM::BICrsi:

2839 case ARM::BICrsr:

2840 case ARM::t2BICri:

2841 case ARM::t2BICrr:

2842 case ARM::t2BICrs:

2843 case ARM::t2LSRri:

2844 case ARM::t2LSRrr:

2845 case ARM::t2LSLri:

2846 case ARM::t2LSLrr:

2847 case ARM::MOVsr:

2848 case ARM::MOVsi:

2849 return true;

2850 }

2851}

2852

2853

2854

2855

2856

2857

2858

2859

2863

2865 if (MI) return false;

2866

2867

2868 if (CmpMask != ~0) {

2870 MI = nullptr;

2872 UI = MRI->use_instr_begin(SrcReg), UE = MRI->use_instr_end();

2873 UI != UE; ++UI) {

2874 if (UI->getParent() != CmpInstr.getParent())

2875 continue;

2879 continue;

2880 MI = PotentialAND;

2881 break;

2882 }

2883 if (MI) return false;

2884 }

2885 }

2886

2887

2890

2891

2892 if (I == B) return false;

2893

2894

2895

2896

2897

2898

2900 if (SrcReg2 != 0)

2901

2902 MI = nullptr;

2903 else if (MI->getParent() != CmpInstr.getParent() || CmpValue != 0) {

2904

2905

2906

2907

2908 if (CmpInstr.getOpcode() == ARM::CMPri ||

2909 CmpInstr.getOpcode() == ARM::t2CMPri ||

2910 CmpInstr.getOpcode() == ARM::tCMPi8)

2911 MI = nullptr;

2912 else

2913 return false;

2914 }

2915

2916 bool IsThumb1 = false;

2918 return false;

2919

2920

2921

2922

2923

2924

2925

2926

2927

2928

2929

2930

2931

2933 if (MI && IsThumb1) {

2934 --I;

2935 if (I != E && MI->readsRegister(ARM::CPSR, TRI)) {

2936 bool CanReorder = true;

2937 for (; I != E; --I) {

2938 if (I->getOpcode() != ARM::tMOVi8) {

2939 CanReorder = false;

2940 break;

2941 }

2942 }

2943 if (CanReorder) {

2944 MI = MI->removeFromParent();

2945 E = CmpInstr;

2947 }

2948 }

2949 I = CmpInstr;

2950 E = MI;

2951 }

2952

2953

2954

2955 bool SubAddIsThumb1 = false;

2956 do {

2958

2959

2961 SubAddIsThumb1)) {

2962 SubAdd = &*I;

2963 break;

2964 }

2965

2966

2967 if (I == E)

2968 break;

2969

2970 if (Instr.modifiesRegister(ARM::CPSR, TRI) ||

2971 Instr.readsRegister(ARM::CPSR, TRI))

2972

2973

2974 return false;

2975

2976 if (I == B) {

2977

2978

2979

2980

2981

2982 return false;

2983 }

2984 } while (true);

2985

2986

2987 if (MI && !SubAdd)

2988 return false;

2989

2990

2991 if (SubAdd) {

2992 MI = SubAdd;

2993 IsThumb1 = SubAddIsThumb1;

2994 }

2995

2996

2998 return false;

2999

3000

3001

3002

3003

3004

3005

3007 OperandsToUpdate;

3008 bool isSafe = false;

3009 I = CmpInstr;

3011 while (!isSafe && ++I != E) {

3013 for (unsigned IO = 0, EO = Instr.getNumOperands();

3014 !isSafe && IO != EO; ++IO) {

3017 isSafe = true;

3018 break;

3019 }

3020 if (!MO.isReg() || MO.getReg() != ARM::CPSR)

3021 continue;

3022 if (MO.isDef()) {

3023 isSafe = true;

3024 break;

3025 }

3026

3028 bool IsInstrVSel = true;

3029 switch (Instr.getOpcode()) {

3030 default:

3031 IsInstrVSel = false;

3033 break;

3034 case ARM::VSELEQD:

3035 case ARM::VSELEQS:

3036 case ARM::VSELEQH:

3038 break;

3039 case ARM::VSELGTD:

3040 case ARM::VSELGTS:

3041 case ARM::VSELGTH:

3043 break;

3044 case ARM::VSELGED:

3045 case ARM::VSELGES:

3046 case ARM::VSELGEH:

3048 break;

3049 case ARM::VSELVSD:

3050 case ARM::VSELVSS:

3051 case ARM::VSELVSH:

3053 break;

3054 }

3055

3056 if (SubAdd) {

3057

3058

3059

3060

3061

3062

3063

3065 bool IsSub = Opc == ARM::SUBrr || Opc == ARM::t2SUBrr ||

3066 Opc == ARM::SUBri || Opc == ARM::t2SUBri ||

3067 Opc == ARM::tSUBrr || Opc == ARM::tSUBi3 ||

3068 Opc == ARM::tSUBi8;

3069 unsigned OpI = Opc != ARM::tSUBrr ? 1 : 2;

3070 if (!IsSub ||

3071 (SrcReg2 != 0 && SubAdd->getOperand(OpI).getReg() == SrcReg2 &&

3073

3074 if (IsInstrVSel)

3075 return false;

3076

3079 return false;

3081 std::make_pair(&((*I).getOperand(IO - 1)), NewCC));

3082 }

3083 } else {

3084

3085 switch (CC) {

3091

3092 break;

3103

3104 return false;

3105 }

3106 }

3107 }

3108 }

3109

3110

3111

3112 if (!isSafe) {

3115 if (Succ->isLiveIn(ARM::CPSR))

3116 return false;

3117 }

3118

3119

3120

3121 if (!IsThumb1) {

3122 unsigned CPSRRegNum = MI->getNumExplicitOperands() - 1;

3123 MI->getOperand(CPSRRegNum).setReg(ARM::CPSR);

3124 MI->getOperand(CPSRRegNum).setIsDef(true);

3125 }

3126 assert(isPredicated(*MI) && "Can't use flags from predicated instruction");

3128

3129

3130

3131

3132 for (auto &[MO, Cond] : OperandsToUpdate)

3133 MO->setImm(Cond);

3134

3135 MI->clearRegisterDeads(ARM::CPSR);

3136

3137 return true;

3138}

3139

3141

3142

3143

3145 return true;

3149 int64_t CmpMask, CmpValue;

3150 bool IsThumb1;

3151 if (Next != MI.getParent()->end() &&

3154 return false;

3155 return true;

3156}

3157

3161

3162 unsigned DefOpc = DefMI.getOpcode();

3163 if (DefOpc != ARM::t2MOVi32imm && DefOpc != ARM::MOVi32imm &&

3164 DefOpc != ARM::tMOVi32imm)

3165 return false;

3166 if (DefMI.getOperand(1).isImm())

3167

3168 return false;

3169

3170 if (MRI->hasOneNonDBGUse(Reg))

3171 return false;

3172

3177 if (MO.getReg() == ARM::CPSR && !MO.isDead())

3178

3179

3180 return false;

3181 }

3182

3186 if (UseMI.getOperand(NumOps - 1).getReg() == ARM::CPSR)

3187

3188

3189 return false;

3190 }

3191

3192 unsigned UseOpc = UseMI.getOpcode();

3193 unsigned NewUseOpc = 0;

3195 uint32_t SOImmValV1 = 0, SOImmValV2 = 0;

3196 bool Commute = false;

3197 switch (UseOpc) {

3198 default: return false;

3199 case ARM::SUBrr:

3200 case ARM::ADDrr:

3201 case ARM::ORRrr:

3202 case ARM::EORrr:

3203 case ARM::t2SUBrr:

3204 case ARM::t2ADDrr:

3205 case ARM::t2ORRrr:

3206 case ARM::t2EORrr: {

3207 Commute = UseMI.getOperand(2).getReg() != Reg;

3208 switch (UseOpc) {

3209 default: break;

3210 case ARM::ADDrr:

3211 case ARM::SUBrr:

3212 if (UseOpc == ARM::SUBrr && Commute)

3213 return false;

3214

3215

3216

3218 NewUseOpc = UseOpc == ARM::ADDrr ? ARM::ADDri : ARM::SUBri;

3220 ImmVal = -ImmVal;

3221 NewUseOpc = UseOpc == ARM::ADDrr ? ARM::SUBri : ARM::ADDri;

3222 } else

3223 return false;

3226 break;

3227 case ARM::ORRrr:

3228 case ARM::EORrr:

3230 return false;

3233 switch (UseOpc) {

3234 default: break;

3235 case ARM::ORRrr: NewUseOpc = ARM::ORRri; break;

3236 case ARM::EORrr: NewUseOpc = ARM::EORri; break;

3237 }

3238 break;

3239 case ARM::t2ADDrr:

3240 case ARM::t2SUBrr: {

3241 if (UseOpc == ARM::t2SUBrr && Commute)

3242 return false;

3243

3244

3245

3246 const bool ToSP = DefMI.getOperand(0).getReg() == ARM::SP;

3247 const unsigned t2ADD = ToSP ? ARM::t2ADDspImm : ARM::t2ADDri;

3248 const unsigned t2SUB = ToSP ? ARM::t2SUBspImm : ARM::t2SUBri;

3250 NewUseOpc = UseOpc == ARM::t2ADDrr ? t2ADD : t2SUB;

3252 ImmVal = -ImmVal;

3253 NewUseOpc = UseOpc == ARM::t2ADDrr ? t2SUB : t2ADD;

3254 } else

3255 return false;

3258 break;

3259 }

3260 case ARM::t2ORRrr:

3261 case ARM::t2EORrr:

3263 return false;

3266 switch (UseOpc) {

3267 default: break;

3268 case ARM::t2ORRrr: NewUseOpc = ARM::t2ORRri; break;

3269 case ARM::t2EORrr: NewUseOpc = ARM::t2EORri; break;

3270 }

3271 break;

3272 }

3273 }

3274 }

3275

3276 unsigned OpIdx = Commute ? 2 : 1;

3278 bool isKill = UseMI.getOperand(OpIdx).isKill();

3280 Register NewReg = MRI->createVirtualRegister(TRC);

3282 NewReg)

3287 UseMI.setDesc(get(NewUseOpc));

3288 UseMI.getOperand(1).setReg(NewReg);

3289 UseMI.getOperand(1).setIsKill();

3290 UseMI.getOperand(2).ChangeToImmediate(SOImmValV2);

3291 DefMI.eraseFromParent();

3292

3293

3294

3295

3296

3297 switch(NewUseOpc){

3298 case ARM::t2ADDspImm:

3299 case ARM::t2SUBspImm:

3300 case ARM::t2ADDri:

3301 case ARM::t2SUBri:

3302 MRI->constrainRegClass(UseMI.getOperand(0).getReg(), TRC);

3303 }

3304 return true;

3305}

3306

3309 switch (MI.getOpcode()) {

3310 default: {

3313 assert(UOps >= 0 && "bad # UOps");

3314 return UOps;

3315 }

3316

3317 case ARM::LDRrs:

3318 case ARM::LDRBrs:

3319 case ARM::STRrs:

3320 case ARM::STRBrs: {

3321 unsigned ShOpVal = MI.getOperand(3).getImm();

3324 if (!isSub &&

3325 (ShImm == 0 ||

3326 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&

3328 return 1;

3329 return 2;

3330 }

3331

3332 case ARM::LDRH:

3333 case ARM::STRH: {

3334 if (MI.getOperand(2).getReg())

3335 return 1;

3336

3337 unsigned ShOpVal = MI.getOperand(3).getImm();

3340 if (!isSub &&

3341 (ShImm == 0 ||

3342 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&

3344 return 1;

3345 return 2;

3346 }

3347

3348 case ARM::LDRSB:

3349 case ARM::LDRSH:

3351

3352 case ARM::LDRSB_POST:

3353 case ARM::LDRSH_POST: {

3354 Register Rt = MI.getOperand(0).getReg();

3355 Register Rm = MI.getOperand(3).getReg();

3356 return (Rt == Rm) ? 4 : 3;

3357 }

3358

3359 case ARM::LDR_PRE_REG:

3360 case ARM::LDRB_PRE_REG: {

3361 Register Rt = MI.getOperand(0).getReg();

3362 Register Rm = MI.getOperand(3).getReg();

3363 if (Rt == Rm)

3364 return 3;

3365 unsigned ShOpVal = MI.getOperand(4).getImm();

3368 if (!isSub &&

3369 (ShImm == 0 ||

3370 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&

3372 return 2;

3373 return 3;

3374 }

3375

3376 case ARM::STR_PRE_REG:

3377 case ARM::STRB_PRE_REG: {

3378 unsigned ShOpVal = MI.getOperand(4).getImm();

3381 if (!isSub &&

3382 (ShImm == 0 ||

3383 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&

3385 return 2;

3386 return 3;

3387 }

3388

3389 case ARM::LDRH_PRE:

3390 case ARM::STRH_PRE: {

3391 Register Rt = MI.getOperand(0).getReg();

3392 Register Rm = MI.getOperand(3).getReg();

3393 if (!Rm)

3394 return 2;

3395 if (Rt == Rm)

3396 return 3;

3398 }

3399

3400 case ARM::LDR_POST_REG:

3401 case ARM::LDRB_POST_REG:

3402 case ARM::LDRH_POST: {

3403 Register Rt = MI.getOperand(0).getReg();

3404 Register Rm = MI.getOperand(3).getReg();

3405 return (Rt == Rm) ? 3 : 2;

3406 }

3407

3408 case ARM::LDR_PRE_IMM:

3409 case ARM::LDRB_PRE_IMM:

3410 case ARM::LDR_POST_IMM:

3411 case ARM::LDRB_POST_IMM:

3412 case ARM::STRB_POST_IMM:

3413 case ARM::STRB_POST_REG:

3414 case ARM::STRB_PRE_IMM:

3415 case ARM::STRH_POST:

3416 case ARM::STR_POST_IMM:

3417 case ARM::STR_POST_REG:

3418 case ARM::STR_PRE_IMM:

3419 return 2;

3420

3421 case ARM::LDRSB_PRE:

3422 case ARM::LDRSH_PRE: {

3423 Register Rm = MI.getOperand(3).getReg();

3424 if (Rm == 0)

3425 return 3;

3426 Register Rt = MI.getOperand(0).getReg();

3427 if (Rt == Rm)

3428 return 4;

3429 unsigned ShOpVal = MI.getOperand(4).getImm();

3432 if (!isSub &&

3433 (ShImm == 0 ||

3434 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&

3436 return 3;

3437 return 4;

3438 }

3439

3440 case ARM::LDRD: {

3441 Register Rt = MI.getOperand(0).getReg();

3442 Register Rn = MI.getOperand(2).getReg();

3443 Register Rm = MI.getOperand(3).getReg();

3444 if (Rm)

3446 : 3;

3447 return (Rt == Rn) ? 3 : 2;

3448 }

3449

3450 case ARM::STRD: {

3451 Register Rm = MI.getOperand(3).getReg();

3452 if (Rm)

3454 : 3;

3455 return 2;

3456 }

3457

3458 case ARM::LDRD_POST:

3459 case ARM::t2LDRD_POST:

3460 return 3;

3461

3462 case ARM::STRD_POST:

3463 case ARM::t2STRD_POST:

3464 return 4;

3465

3466 case ARM::LDRD_PRE: {

3467 Register Rt = MI.getOperand(0).getReg();

3468 Register Rn = MI.getOperand(3).getReg();

3469 Register Rm = MI.getOperand(4).getReg();

3470 if (Rm)

3472 : 4;

3473 return (Rt == Rn) ? 4 : 3;

3474 }

3475

3476 case ARM::t2LDRD_PRE: {

3477 Register Rt = MI.getOperand(0).getReg();

3478 Register Rn = MI.getOperand(3).getReg();

3479 return (Rt == Rn) ? 4 : 3;

3480 }

3481

3482 case ARM::STRD_PRE: {

3483 Register Rm = MI.getOperand(4).getReg();

3484 if (Rm)

3486 : 4;

3487 return 3;

3488 }

3489

3490 case ARM::t2STRD_PRE:

3491 return 3;

3492

3493 case ARM::t2LDR_POST:

3494 case ARM::t2LDRB_POST:

3495 case ARM::t2LDRB_PRE:

3496 case ARM::t2LDRSBi12:

3497 case ARM::t2LDRSBi8:

3498 case ARM::t2LDRSBpci:

3499 case ARM::t2LDRSBs:

3500 case ARM::t2LDRH_POST:

3501 case ARM::t2LDRH_PRE:

3502 case ARM::t2LDRSBT:

3503 case ARM::t2LDRSB_POST:

3504 case ARM::t2LDRSB_PRE:

3505 case ARM::t2LDRSH_POST:

3506 case ARM::t2LDRSH_PRE:

3507 case ARM::t2LDRSHi12:

3508 case ARM::t2LDRSHi8:

3509 case ARM::t2LDRSHpci:

3510 case ARM::t2LDRSHs:

3511 return 2;

3512

3513 case ARM::t2LDRDi8: {

3514 Register Rt = MI.getOperand(0).getReg();

3515 Register Rn = MI.getOperand(2).getReg();

3516 return (Rt == Rn) ? 3 : 2;

3517 }

3518

3519 case ARM::t2STRB_POST:

3520 case ARM::t2STRB_PRE:

3521 case ARM::t2STRBs:

3522 case ARM::t2STRDi8:

3523 case ARM::t2STRH_POST:

3524 case ARM::t2STRH_PRE:

3525 case ARM::t2STRHs:

3526 case ARM::t2STR_POST:

3527 case ARM::t2STR_PRE:

3528 case ARM::t2STRs:

3529 return 2;

3530 }

3531}

3532

3533

3534

3535

3536

3537

3538

3539

3540

3541

3542

3543

3544

3545

3546

3547

3548

3549

3550

3551

3552

3553

3554

3556 unsigned Size = 0;

3558 E = MI.memoperands_end();

3559 I != E; ++I) {

3560 Size += (*I)->getSize().getValue();

3561 }

3562

3563

3564

3565

3566

3567 return std::min(Size / 4, 16U);

3568}

3569

3571 unsigned NumRegs) {

3572 unsigned UOps = 1 + NumRegs;

3573 switch (Opc) {

3574 default:

3575 break;

3576 case ARM::VLDMDIA_UPD:

3577 case ARM::VLDMDDB_UPD:

3578 case ARM::VLDMSIA_UPD:

3579 case ARM::VLDMSDB_UPD:

3580 case ARM::VSTMDIA_UPD:

3581 case ARM::VSTMDDB_UPD:

3582 case ARM::VSTMSIA_UPD:

3583 case ARM::VSTMSDB_UPD:

3584 case ARM::LDMIA_UPD:

3585 case ARM::LDMDA_UPD:

3586 case ARM::LDMDB_UPD:

3587 case ARM::LDMIB_UPD:

3588 case ARM::STMIA_UPD:

3589 case ARM::STMDA_UPD:

3590 case ARM::STMDB_UPD:

3591 case ARM::STMIB_UPD:

3592 case ARM::tLDMIA_UPD:

3593 case ARM::tSTMIA_UPD:

3594 case ARM::t2LDMIA_UPD:

3595 case ARM::t2LDMDB_UPD:

3596 case ARM::t2STMIA_UPD:

3597 case ARM::t2STMDB_UPD:

3598 ++UOps;

3599 break;

3600 case ARM::LDMIA_RET:

3601 case ARM::tPOP_RET:

3602 case ARM::t2LDMIA_RET:

3603 UOps += 2;

3604 break;

3605 }

3606 return UOps;

3607}

3608

3611 if (!ItinData || ItinData->isEmpty())

3612 return 1;

3613

3615 unsigned Class = Desc.getSchedClass();

3617 if (ItinUOps >= 0) {

3618 if (Subtarget.isSwift() && (Desc.mayLoad() || Desc.mayStore()))

3620

3621 return ItinUOps;

3622 }

3623

3624 unsigned Opc = MI.getOpcode();

3625 switch (Opc) {

3626 default:

3628 case ARM::VLDMQIA:

3629 case ARM::VSTMQIA:

3630 return 2;

3631

3632

3633

3634

3635

3636

3637

3638

3639

3640

3641

3642 case ARM::VLDMDIA:

3643 case ARM::VLDMDIA_UPD:

3644 case ARM::VLDMDDB_UPD:

3645 case ARM::VLDMSIA:

3646 case ARM::VLDMSIA_UPD:

3647 case ARM::VLDMSDB_UPD:

3648 case ARM::VSTMDIA:

3649 case ARM::VSTMDIA_UPD:

3650 case ARM::VSTMDDB_UPD:

3651 case ARM::VSTMSIA:

3652 case ARM::VSTMSIA_UPD:

3653 case ARM::VSTMSDB_UPD: {

3654 unsigned NumRegs = MI.getNumOperands() - Desc.getNumOperands();

3655 return (NumRegs / 2) + (NumRegs % 2) + 1;

3656 }

3657

3658 case ARM::LDMIA_RET:

3659 case ARM::LDMIA:

3660 case ARM::LDMDA:

3661 case ARM::LDMDB:

3662 case ARM::LDMIB:

3663 case ARM::LDMIA_UPD:

3664 case ARM::LDMDA_UPD:

3665 case ARM::LDMDB_UPD:

3666 case ARM::LDMIB_UPD:

3667 case ARM::STMIA:

3668 case ARM::STMDA:

3669 case ARM::STMDB:

3670 case ARM::STMIB:

3671 case ARM::STMIA_UPD:

3672 case ARM::STMDA_UPD:

3673 case ARM::STMDB_UPD:

3674 case ARM::STMIB_UPD:

3675 case ARM::tLDMIA:

3676 case ARM::tLDMIA_UPD:

3677 case ARM::tSTMIA_UPD:

3678 case ARM::tPOP_RET:

3679 case ARM::tPOP:

3680 case ARM::tPUSH:

3681 case ARM::t2LDMIA_RET:

3682 case ARM::t2LDMIA:

3683 case ARM::t2LDMDB:

3684 case ARM::t2LDMIA_UPD:

3685 case ARM::t2LDMDB_UPD:

3686 case ARM::t2STMIA:

3687 case ARM::t2STMDB:

3688 case ARM::t2STMIA_UPD:

3689 case ARM::t2STMDB_UPD: {

3690 unsigned NumRegs = MI.getNumOperands() - Desc.getNumOperands() + 1;

3691 switch (Subtarget.getLdStMultipleTiming()) {

3695

3696 return NumRegs;

3698 if (NumRegs < 4)

3699 return 2;

3700

3701

3702 unsigned UOps = (NumRegs / 2);

3703 if (NumRegs % 2)

3704 ++UOps;

3705 return UOps;

3706 }

3708 unsigned UOps = (NumRegs / 2);

3709

3710

3711 if ((NumRegs % 2) || MI.hasOneMemOperand() ||

3712 (*MI.memoperands_begin())->getAlign() < Align(8))

3713 ++UOps;

3714 return UOps;

3715 }

3716 }

3717 }

3718 }

3720}

3721

3722std::optional

3723ARMBaseInstrInfo::getVLDMDefCycle(const InstrItineraryData *ItinData,

3724 const MCInstrDesc &DefMCID, unsigned DefClass,

3725 unsigned DefIdx, unsigned DefAlign) const {

3726 int RegNo = (int)(DefIdx+1) - DefMCID.getNumOperands() + 1;

3727 if (RegNo <= 0)

3728

3730

3731 unsigned DefCycle;

3733

3734 DefCycle = RegNo / 2 + 1;

3735 if (RegNo % 2)

3736 ++DefCycle;

3737 } else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {

3738 DefCycle = RegNo;

3739 bool isSLoad = false;

3740

3742 default: break;

3743 case ARM::VLDMSIA:

3744 case ARM::VLDMSIA_UPD:

3745 case ARM::VLDMSDB_UPD:

3746 isSLoad = true;

3747 break;

3748 }

3749

3750

3751

3752 if ((isSLoad && (RegNo % 2)) || DefAlign < 8)

3753 ++DefCycle;

3754 } else {

3755

3756 DefCycle = RegNo + 2;

3757 }

3758

3759 return DefCycle;

3760}

3761

3762std::optional

3764 const MCInstrDesc &DefMCID, unsigned DefClass,

3765 unsigned DefIdx, unsigned DefAlign) const {

3766 int RegNo = (int)(DefIdx+1) - DefMCID.getNumOperands() + 1;

3767 if (RegNo <= 0)

3768

3770

3771 unsigned DefCycle;

3772 if (Subtarget.isCortexA8() || Subtarget.isCortexA7()) {

3773

3774

3775 DefCycle = RegNo / 2;

3776 if (DefCycle < 1)

3777 DefCycle = 1;

3778

3779 DefCycle += 2;

3780 } else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {

3781 DefCycle = (RegNo / 2);

3782

3783

3784 if ((RegNo % 2) || DefAlign < 8)

3785 ++DefCycle;

3786

3787 DefCycle += 2;

3788 } else {

3789

3790 DefCycle = RegNo + 2;

3791 }

3792

3793 return DefCycle;

3794}

3795

3796std::optional

3797ARMBaseInstrInfo::getVSTMUseCycle(const InstrItineraryData *ItinData,

3798 const MCInstrDesc &UseMCID, unsigned UseClass,

3799 unsigned UseIdx, unsigned UseAlign) const {

3800 int RegNo = (int)(UseIdx+1) - UseMCID.getNumOperands() + 1;

3801 if (RegNo <= 0)

3803

3804 unsigned UseCycle;

3805 if (Subtarget.isCortexA8() || Subtarget.isCortexA7()) {

3806

3807 UseCycle = RegNo / 2 + 1;

3808 if (RegNo % 2)

3809 ++UseCycle;

3810 } else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {

3811 UseCycle = RegNo;

3812 bool isSStore = false;

3813

3815 default: break;

3816 case ARM::VSTMSIA:

3817 case ARM::VSTMSIA_UPD:

3818 case ARM::VSTMSDB_UPD:

3819 isSStore = true;

3820 break;

3821 }

3822

3823

3824

3825 if ((isSStore && (RegNo % 2)) || UseAlign < 8)

3826 ++UseCycle;

3827 } else {

3828

3829 UseCycle = RegNo + 2;

3830 }

3831

3832 return UseCycle;

3833}

3834

3835std::optional

3837 const MCInstrDesc &UseMCID, unsigned UseClass,

3838 unsigned UseIdx, unsigned UseAlign) const {

3839 int RegNo = (int)(UseIdx+1) - UseMCID.getNumOperands() + 1;

3840 if (RegNo <= 0)

3842

3843 unsigned UseCycle;

3844 if (Subtarget.isCortexA8() || Subtarget.isCortexA7()) {

3845 UseCycle = RegNo / 2;

3846 if (UseCycle < 2)

3847 UseCycle = 2;

3848

3849 UseCycle += 2;

3850 } else if (Subtarget.isLikeA9() || Subtarget.isSwift()) {

3851 UseCycle = (RegNo / 2);

3852

3853

3854 if ((RegNo % 2) || UseAlign < 8)

3855 ++UseCycle;

3856 } else {

3857

3858 UseCycle = 1;

3859 }

3860 return UseCycle;

3861}

3862

3865 unsigned DefIdx, unsigned DefAlign, const MCInstrDesc &UseMCID,

3866 unsigned UseIdx, unsigned UseAlign) const {

3869

3871 return ItinData->getOperandLatency(DefClass, DefIdx, UseClass, UseIdx);

3872

3873

3874

3875

3876 std::optional DefCycle;

3877 bool LdmBypass = false;

3879 default:

3881 break;

3882

3883 case ARM::VLDMDIA:

3884 case ARM::VLDMDIA_UPD:

3885 case ARM::VLDMDDB_UPD:

3886 case ARM::VLDMSIA:

3887 case ARM::VLDMSIA_UPD:

3888 case ARM::VLDMSDB_UPD:

3889 DefCycle = getVLDMDefCycle(ItinData, DefMCID, DefClass, DefIdx, DefAlign);

3890 break;

3891

3892 case ARM::LDMIA_RET:

3893 case ARM::LDMIA:

3894 case ARM::LDMDA:

3895 case ARM::LDMDB:

3896 case ARM::LDMIB:

3897 case ARM::LDMIA_UPD:

3898 case ARM::LDMDA_UPD:

3899 case ARM::LDMDB_UPD:

3900 case ARM::LDMIB_UPD:

3901 case ARM::tLDMIA:

3902 case ARM::tLDMIA_UPD:

3903 case ARM::tPUSH:

3904 case ARM::t2LDMIA_RET:

3905 case ARM::t2LDMIA:

3906 case ARM::t2LDMDB:

3907 case ARM::t2LDMIA_UPD:

3908 case ARM::t2LDMDB_UPD:

3909 LdmBypass = true;

3910 DefCycle = getLDMDefCycle(ItinData, DefMCID, DefClass, DefIdx, DefAlign);

3911 break;

3912 }

3913

3914 if (!DefCycle)

3915

3916 DefCycle = 2;

3917

3918 std::optional UseCycle;

3920 default:

3922 break;

3923

3924 case ARM::VSTMDIA:

3925 case ARM::VSTMDIA_UPD:

3926 case ARM::VSTMDDB_UPD:

3927 case ARM::VSTMSIA:

3928 case ARM::VSTMSIA_UPD:

3929 case ARM::VSTMSDB_UPD:

3930 UseCycle = getVSTMUseCycle(ItinData, UseMCID, UseClass, UseIdx, UseAlign);

3931 break;

3932

3933 case ARM::STMIA:

3934 case ARM::STMDA:

3935 case ARM::STMDB:

3936 case ARM::STMIB:

3937 case ARM::STMIA_UPD:

3938 case ARM::STMDA_UPD:

3939 case ARM::STMDB_UPD:

3940 case ARM::STMIB_UPD:

3941 case ARM::tSTMIA_UPD:

3942 case ARM::tPOP_RET:

3943 case ARM::tPOP:

3944 case ARM::t2STMIA:

3945 case ARM::t2STMDB:

3946 case ARM::t2STMIA_UPD:

3947 case ARM::t2STMDB_UPD:

3948 UseCycle = getSTMUseCycle(ItinData, UseMCID, UseClass, UseIdx, UseAlign);

3949 break;

3950 }

3951

3952 if (!UseCycle)

3953

3954 UseCycle = 1;

3955

3956 if (UseCycle > *DefCycle + 1)

3957 return std::nullopt;

3958

3959 UseCycle = *DefCycle - *UseCycle + 1;

3960 if (UseCycle > 0u) {

3961 if (LdmBypass) {

3962

3963

3965 UseClass, UseIdx))

3966 UseCycle = *UseCycle - 1;

3968 UseClass, UseIdx)) {

3969 UseCycle = *UseCycle - 1;

3970 }

3971 }

3972

3973 return UseCycle;

3974}

3975

3978 unsigned &DefIdx, unsigned &Dist) {

3979 Dist = 0;

3980

3983 assert(II->isInsideBundle() && "Empty bundle?");

3984

3985 int Idx = -1;

3986 while (II->isInsideBundle()) {

3987 Idx = II->findRegisterDefOperandIdx(Reg, TRI, false, true);

3988 if (Idx != -1)

3989 break;

3990 --II;

3991 ++Dist;

3992 }

3993

3994 assert(Idx != -1 && "Cannot find bundled definition!");

3995 DefIdx = Idx;

3996 return &*II;

3997}

3998

4001 unsigned &UseIdx, unsigned &Dist) {

4002 Dist = 0;

4003

4005 assert(II->isInsideBundle() && "Empty bundle?");

4007

4008

4009 int Idx = -1;

4010 while (II != E && II->isInsideBundle()) {

4011 Idx = II->findRegisterUseOperandIdx(Reg, TRI, false);

4012 if (Idx != -1)

4013 break;

4014 if (II->getOpcode() != ARM::t2IT)

4015 ++Dist;

4016 ++II;

4017 }

4018

4019 if (Idx == -1) {

4020 Dist = 0;

4021 return nullptr;

4022 }

4023

4024 UseIdx = Idx;

4025 return &*II;

4026}

4027

4028

4029

4030

4033 const MCInstrDesc &DefMCID, unsigned DefAlign) {

4034 int Adjust = 0;

4036

4037

4039 default: break;

4040 case ARM::LDRrs:

4041 case ARM::LDRBrs: {

4042 unsigned ShOpVal = DefMI.getOperand(3).getImm();

4044 if (ShImm == 0 ||

4046 --Adjust;

4047 break;

4048 }

4049 case ARM::t2LDRs:

4050 case ARM::t2LDRBs:

4051 case ARM::t2LDRHs:

4052 case ARM::t2LDRSHs: {

4053

4054 unsigned ShAmt = DefMI.getOperand(3).getImm();

4055 if (ShAmt == 0 || ShAmt == 2)

4056 --Adjust;

4057 break;

4058 }

4059 }

4060 } else if (Subtarget.isSwift()) {

4061

4062

4064 default: break;

4065 case ARM::LDRrs:

4066 case ARM::LDRBrs: {

4067 unsigned ShOpVal = DefMI.getOperand(3).getImm();

4070 if (!isSub &&

4071 (ShImm == 0 ||

4072 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&

4074 Adjust -= 2;

4075 else if (!isSub &&

4077 --Adjust;

4078 break;

4079 }

4080 case ARM::t2LDRs:

4081 case ARM::t2LDRBs:

4082 case ARM::t2LDRHs:

4083 case ARM::t2LDRSHs: {

4084

4085 unsigned ShAmt = DefMI.getOperand(3).getImm();

4086 if (ShAmt == 0 || ShAmt == 1 || ShAmt == 2 || ShAmt == 3)

4087 Adjust -= 2;

4088 break;

4089 }

4090 }

4091 }

4092

4093 if (DefAlign < 8 && Subtarget.checkVLDnAccessAlignment()) {

4095 default: break;

4096 case ARM::VLD1q8:

4097 case ARM::VLD1q16:

4098 case ARM::VLD1q32:

4099 case ARM::VLD1q64:

4100 case ARM::VLD1q8wb_fixed:

4101 case ARM::VLD1q16wb_fixed:

4102 case ARM::VLD1q32wb_fixed:

4103 case ARM::VLD1q64wb_fixed:

4104 case ARM::VLD1q8wb_register:

4105 case ARM::VLD1q16wb_register:

4106 case ARM::VLD1q32wb_register:

4107 case ARM::VLD1q64wb_register:

4108 case ARM::VLD2d8:

4109 case ARM::VLD2d16:

4110 case ARM::VLD2d32:

4111 case ARM::VLD2q8:

4112 case ARM::VLD2q16:

4113 case ARM::VLD2q32:

4114 case ARM::VLD2d8wb_fixed:

4115 case ARM::VLD2d16wb_fixed:

4116 case ARM::VLD2d32wb_fixed:

4117 case ARM::VLD2q8wb_fixed:

4118 case ARM::VLD2q16wb_fixed:

4119 case ARM::VLD2q32wb_fixed:

4120 case ARM::VLD2d8wb_register:

4121 case ARM::VLD2d16wb_register:

4122 case ARM::VLD2d32wb_register:

4123 case ARM::VLD2q8wb_register:

4124 case ARM::VLD2q16wb_register:

4125 case ARM::VLD2q32wb_register:

4126 case ARM::VLD3d8:

4127 case ARM::VLD3d16:

4128 case ARM::VLD3d32:

4129 case ARM::VLD1d64T:

4130 case ARM::VLD3d8_UPD:

4131 case ARM::VLD3d16_UPD:

4132 case ARM::VLD3d32_UPD:

4133 case ARM::VLD1d64Twb_fixed:

4134 case ARM::VLD1d64Twb_register:

4135 case ARM::VLD3q8_UPD:

4136 case ARM::VLD3q16_UPD:

4137 case ARM::VLD3q32_UPD:

4138 case ARM::VLD4d8:

4139 case ARM::VLD4d16:

4140 case ARM::VLD4d32:

4141 case ARM::VLD1d64Q:

4142 case ARM::VLD4d8_UPD:

4143 case ARM::VLD4d16_UPD:

4144 case ARM::VLD4d32_UPD:

4145 case ARM::VLD1d64Qwb_fixed:

4146 case ARM::VLD1d64Qwb_register:

4147 case ARM::VLD4q8_UPD:

4148 case ARM::VLD4q16_UPD:

4149 case ARM::VLD4q32_UPD:

4150 case ARM::VLD1DUPq8:

4151 case ARM::VLD1DUPq16:

4152 case ARM::VLD1DUPq32:

4153 case ARM::VLD1DUPq8wb_fixed:

4154 case ARM::VLD1DUPq16wb_fixed:

4155 case ARM::VLD1DUPq32wb_fixed:

4156 case ARM::VLD1DUPq8wb_register:

4157 case ARM::VLD1DUPq16wb_register:

4158 case ARM::VLD1DUPq32wb_register:

4159 case ARM::VLD2DUPd8:

4160 case ARM::VLD2DUPd16:

4161 case ARM::VLD2DUPd32:

4162 case ARM::VLD2DUPd8wb_fixed:

4163 case ARM::VLD2DUPd16wb_fixed:

4164 case ARM::VLD2DUPd32wb_fixed:

4165 case ARM::VLD2DUPd8wb_register:

4166 case ARM::VLD2DUPd16wb_register:

4167 case ARM::VLD2DUPd32wb_register:

4168 case ARM::VLD4DUPd8:

4169 case ARM::VLD4DUPd16:

4170 case ARM::VLD4DUPd32:

4171 case ARM::VLD4DUPd8_UPD:

4172 case ARM::VLD4DUPd16_UPD:

4173 case ARM::VLD4DUPd32_UPD:

4174 case ARM::VLD1LNd8:

4175 case ARM::VLD1LNd16:

4176 case ARM::VLD1LNd32:

4177 case ARM::VLD1LNd8_UPD:

4178 case ARM::VLD1LNd16_UPD:

4179 case ARM::VLD1LNd32_UPD:

4180 case ARM::VLD2LNd8:

4181 case ARM::VLD2LNd16:

4182 case ARM::VLD2LNd32:

4183 case ARM::VLD2LNq16:

4184 case ARM::VLD2LNq32:

4185 case ARM::VLD2LNd8_UPD:

4186 case ARM::VLD2LNd16_UPD:

4187 case ARM::VLD2LNd32_UPD:

4188 case ARM::VLD2LNq16_UPD:

4189 case ARM::VLD2LNq32_UPD:

4190 case ARM::VLD4LNd8:

4191 case ARM::VLD4LNd16:

4192 case ARM::VLD4LNd32:

4193 case ARM::VLD4LNq16:

4194 case ARM::VLD4LNq32:

4195 case ARM::VLD4LNd8_UPD:

4196 case ARM::VLD4LNd16_UPD:

4197 case ARM::VLD4LNd32_UPD:

4198 case ARM::VLD4LNq16_UPD:

4199 case ARM::VLD4LNq32_UPD:

4200

4201

4202 ++Adjust;

4203 break;

4204 }

4205 }

4206 return Adjust;

4207}

4208

4211 unsigned DefIdx, const MachineInstr &UseMI, unsigned UseIdx) const {

4212

4213 if (!ItinData || ItinData->isEmpty())

4214 return std::nullopt;

4215

4218

4220 unsigned DefAdj = 0;

4221 if (DefMI.isBundle())

4222 ResolvedDefMI =

4226 return 1;

4227 }

4228

4230 unsigned UseAdj = 0;

4231 if (UseMI.isBundle()) {

4232 ResolvedUseMI =

4234 if (!ResolvedUseMI)

4235 return std::nullopt;

4236 }

4237

4238 return getOperandLatencyImpl(

4239 ItinData, *ResolvedDefMI, DefIdx, ResolvedDefMI->getDesc(), DefAdj, DefMO,

4240 Reg, *ResolvedUseMI, UseIdx, ResolvedUseMI->getDesc(), UseAdj);

4241}

4242

4243std::optional ARMBaseInstrInfo::getOperandLatencyImpl(

4245 unsigned DefIdx, const MCInstrDesc &DefMCID, unsigned DefAdj,

4247 unsigned UseIdx, const MCInstrDesc &UseMCID, unsigned UseAdj) const {

4248 if (Reg == ARM::CPSR) {

4249 if (DefMI.getOpcode() == ARM::FMSTAT) {

4250

4251 return Subtarget.isLikeA9() ? 1 : 20;

4252 }

4253

4254

4255 if (UseMI.isBranch())

4256 return 0;

4257

4258

4259 unsigned Latency = getInstrLatency(ItinData, DefMI);

4260

4261

4262

4263

4264

4269 }

4271 }

4272

4273 if (DefMO.isImplicit() || UseMI.getOperand(UseIdx).isImplicit())

4274 return std::nullopt;

4275

4276 unsigned DefAlign = DefMI.hasOneMemOperand()

4277 ? (*DefMI.memoperands_begin())->getAlign().value()

4278 : 0;

4279 unsigned UseAlign = UseMI.hasOneMemOperand()

4280 ? (*UseMI.memoperands_begin())->getAlign().value()

4281 : 0;

4282

4283

4285 ItinData, DefMCID, DefIdx, DefAlign, UseMCID, UseIdx, UseAlign);

4286

4288 return std::nullopt;

4289

4290

4291 int Adj = DefAdj + UseAdj;

4292

4293

4295 if (Adj >= 0 || (int)*Latency > -Adj) {

4297 }

4298

4300}

4301

4302std::optional

4304 SDNode *DefNode, unsigned DefIdx,

4305 SDNode *UseNode, unsigned UseIdx) const {

4307 return 1;

4308

4310

4311 if (isZeroCost(DefMCID.Opcode))

4312 return 0;

4313

4314 if (!ItinData || ItinData->isEmpty())

4315 return DefMCID.mayLoad() ? 3 : 1;

4316

4318 std::optional Latency =

4320 int Adj = Subtarget.getPreISelOperandLatencyAdjustment();

4321 int Threshold = 1 + Adj;

4323 }

4324

4327 unsigned DefAlign = !DefMN->memoperands_empty()

4328 ? (*DefMN->memoperands_begin())->getAlign().value()

4329 : 0;

4331 unsigned UseAlign = !UseMN->memoperands_empty()

4332 ? (*UseMN->memoperands_begin())->getAlign().value()

4333 : 0;

4335 ItinData, DefMCID, DefIdx, DefAlign, UseMCID, UseIdx, UseAlign);

4337 return std::nullopt;

4338

4340 (Subtarget.isCortexA8() || Subtarget.isLikeA9() ||

4341 Subtarget.isCortexA7())) {

4342

4343

4345 default: break;

4346 case ARM::LDRrs:

4347 case ARM::LDRBrs: {

4350 if (ShImm == 0 ||

4353 break;

4354 }

4355 case ARM::t2LDRs:

4356 case ARM::t2LDRBs:

4357 case ARM::t2LDRHs:

4358 case ARM::t2LDRSHs: {

4359

4361 if (ShAmt == 0 || ShAmt == 2)

4363 break;

4364 }

4365 }

4366 } else if (DefIdx == 0 && Latency > 2U && Subtarget.isSwift()) {

4367

4368

4370 default: break;

4371 case ARM::LDRrs:

4372 case ARM::LDRBrs: {

4375 if (ShImm == 0 ||

4376 ((ShImm == 1 || ShImm == 2 || ShImm == 3) &&

4381 break;

4382 }

4383 case ARM::t2LDRs:

4384 case ARM::t2LDRBs:

4385 case ARM::t2LDRHs:

4386 case ARM::t2LDRSHs:

4387

4389 break;

4390 }

4391 }

4392

4393 if (DefAlign < 8 && Subtarget.checkVLDnAccessAlignment())

4395 default: break;

4396 case ARM::VLD1q8:

4397 case ARM::VLD1q16:

4398 case ARM::VLD1q32:

4399 case ARM::VLD1q64:

4400 case ARM::VLD1q8wb_register:

4401 case ARM::VLD1q16wb_register:

4402 case ARM::VLD1q32wb_register:

4403 case ARM::VLD1q64wb_register:

4404 case ARM::VLD1q8wb_fixed:

4405 case ARM::VLD1q16wb_fixed:

4406 case ARM::VLD1q32wb_fixed:

4407 case ARM::VLD1q64wb_fixed:

4408 case ARM::VLD2d8:

4409 case ARM::VLD2d16:

4410 case ARM::VLD2d32:

4411 case ARM::VLD2q8Pseudo:

4412 case ARM::VLD2q16Pseudo:

4413 case ARM::VLD2q32Pseudo:

4414 case ARM::VLD2d8wb_fixed:

4415 case ARM::VLD2d16wb_fixed:

4416 case ARM::VLD2d32wb_fixed:

4417 case ARM::VLD2q8PseudoWB_fixed:

4418 case ARM::VLD2q16PseudoWB_fixed:

4419 case ARM::VLD2q32PseudoWB_fixed:

4420 case ARM::VLD2d8wb_register:

4421 case ARM::VLD2d16wb_register:

4422 case ARM::VLD2d32wb_register:

4423 case ARM::VLD2q8PseudoWB_register:

4424 case ARM::VLD2q16PseudoWB_register:

4425 case ARM::VLD2q32PseudoWB_register:

4426 case ARM::VLD3d8Pseudo:

4427 case ARM::VLD3d16Pseudo:

4428 case ARM::VLD3d32Pseudo:

4429 case ARM::VLD1d8TPseudo:

4430 case ARM::VLD1d16TPseudo:

4431 case ARM::VLD1d32TPseudo:

4432 case ARM::VLD1d64TPseudo:

4433 case ARM::VLD1d64TPseudoWB_fixed:

4434 case ARM::VLD1d64TPseudoWB_register:

4435 case ARM::VLD3d8Pseudo_UPD:

4436 case ARM::VLD3d16Pseudo_UPD:

4437 case ARM::VLD3d32Pseudo_UPD:

4438 case ARM::VLD3q8Pseudo_UPD:

4439 case ARM::VLD3q16Pseudo_UPD:

4440 case ARM::VLD3q32Pseudo_UPD:

4441 case ARM::VLD3q8oddPseudo:

4442 case ARM::VLD3q16oddPseudo:

4443 case ARM::VLD3q32oddPseudo:

4444 case ARM::VLD3q8oddPseudo_UPD:

4445 case ARM::VLD3q16oddPseudo_UPD:

4446 case ARM::VLD3q32oddPseudo_UPD:

4447 case ARM::VLD4d8Pseudo:

4448 case ARM::VLD4d16Pseudo:

4449 case ARM::VLD4d32Pseudo:

4450 case ARM::VLD1d8QPseudo:

4451 case ARM::VLD1d16QPseudo:

4452 case ARM::VLD1d32QPseudo:

4453 case ARM::VLD1d64QPseudo:

4454 case ARM::VLD1d64QPseudoWB_fixed:

4455 case ARM::VLD1d64QPseudoWB_register:

4456 case ARM::VLD1q8HighQPseudo:

4457 case ARM::VLD1q8LowQPseudo_UPD:

4458 case ARM::VLD1q8HighTPseudo:

4459 case ARM::VLD1q8LowTPseudo_UPD:

4460 case ARM::VLD1q16HighQPseudo:

4461 case ARM::VLD1q16LowQPseudo_UPD:

4462 case ARM::VLD1q16HighTPseudo:

4463 case ARM::VLD1q16LowTPseudo_UPD:

4464 case ARM::VLD1q32HighQPseudo:

4465 case ARM::VLD1q32LowQPseudo_UPD:

4466 case ARM::VLD1q32HighTPseudo:

4467 case ARM::VLD1q32LowTPseudo_UPD:

4468 case ARM::VLD1q64HighQPseudo:

4469 case ARM::VLD1q64LowQPseudo_UPD:

4470 case ARM::VLD1q64HighTPseudo:

4471 case ARM::VLD1q64LowTPseudo_UPD:

4472 case ARM::VLD4d8Pseudo_UPD:

4473 case ARM::VLD4d16Pseudo_UPD:

4474 case ARM::VLD4d32Pseudo_UPD:

4475 case ARM::VLD4q8Pseudo_UPD:

4476 case ARM::VLD4q16Pseudo_UPD:

4477 case ARM::VLD4q32Pseudo_UPD:

4478 case ARM::VLD4q8oddPseudo:

4479 case ARM::VLD4q16oddPseudo:

4480 case ARM::VLD4q32oddPseudo:

4481 case ARM::VLD4q8oddPseudo_UPD:

4482 case ARM::VLD4q16oddPseudo_UPD:

4483 case ARM::VLD4q32oddPseudo_UPD:

4484 case ARM::VLD1DUPq8:

4485 case ARM::VLD1DUPq16:

4486 case ARM::VLD1DUPq32:

4487 case ARM::VLD1DUPq8wb_fixed:

4488 case ARM::VLD1DUPq16wb_fixed:

4489 case ARM::VLD1DUPq32wb_fixed:

4490 case ARM::VLD1DUPq8wb_register:

4491 case ARM::VLD1DUPq16wb_register:

4492 case ARM::VLD1DUPq32wb_register:

4493 case ARM::VLD2DUPd8:

4494 case ARM::VLD2DUPd16:

4495 case ARM::VLD2DUPd32:

4496 case ARM::VLD2DUPd8wb_fixed:

4497 case ARM::VLD2DUPd16wb_fixed:

4498 case ARM::VLD2DUPd32wb_fixed:

4499 case ARM::VLD2DUPd8wb_register:

4500 case ARM::VLD2DUPd16wb_register:

4501 case ARM::VLD2DUPd32wb_register:

4502 case ARM::VLD2DUPq8EvenPseudo:

4503 case ARM::VLD2DUPq8OddPseudo:

4504 case ARM::VLD2DUPq16EvenPseudo:

4505 case ARM::VLD2DUPq16OddPseudo:

4506 case ARM::VLD2DUPq32EvenPseudo:

4507 case ARM::VLD2DUPq32OddPseudo:

4508 case ARM::VLD3DUPq8EvenPseudo:

4509 case ARM::VLD3DUPq8OddPseudo:

4510 case ARM::VLD3DUPq16EvenPseudo:

4511 case ARM::VLD3DUPq16OddPseudo:

4512 case ARM::VLD3DUPq32EvenPseudo:

4513 case ARM::VLD3DUPq32OddPseudo:

4514 case ARM::VLD4DUPd8Pseudo:

4515 case ARM::VLD4DUPd16Pseudo:

4516 case ARM::VLD4DUPd32Pseudo:

4517 case ARM::VLD4DUPd8Pseudo_UPD:

4518 case ARM::VLD4DUPd16Pseudo_UPD:

4519 case ARM::VLD4DUPd32Pseudo_UPD:

4520 case ARM::VLD4DUPq8EvenPseudo:

4521 case ARM::VLD4DUPq8OddPseudo:

4522 case ARM::VLD4DUPq16EvenPseudo:

4523 case ARM::VLD4DUPq16OddPseudo:

4524 case ARM::VLD4DUPq32EvenPseudo:

4525 case ARM::VLD4DUPq32OddPseudo:

4526 case ARM::VLD1LNq8Pseudo:

4527 case ARM::VLD1LNq16Pseudo:

4528 case ARM::VLD1LNq32Pseudo:

4529 case ARM::VLD1LNq8Pseudo_UPD:

4530 case ARM::VLD1LNq16Pseudo_UPD:

4531 case ARM::VLD1LNq32Pseudo_UPD:

4532 case ARM::VLD2LNd8Pseudo:

4533 case ARM::VLD2LNd16Pseudo:

4534 case ARM::VLD2LNd32Pseudo:

4535 case ARM::VLD2LNq16Pseudo:

4536 case ARM::VLD2LNq32Pseudo:

4537 case ARM::VLD2LNd8Pseudo_UPD:

4538 case ARM::VLD2LNd16Pseudo_UPD:

4539 case ARM::VLD2LNd32Pseudo_UPD:

4540 case ARM::VLD2LNq16Pseudo_UPD:

4541 case ARM::VLD2LNq32Pseudo_UPD:

4542 case ARM::VLD4LNd8Pseudo:

4543 case ARM::VLD4LNd16Pseudo:

4544 case ARM::VLD4LNd32Pseudo:

4545 case ARM::VLD4LNq16Pseudo:

4546 case ARM::VLD4LNq32Pseudo:

4547 case ARM::VLD4LNd8Pseudo_UPD:

4548 case ARM::VLD4LNd16Pseudo_UPD:

4549 case ARM::VLD4LNd32Pseudo_UPD:

4550 case ARM::VLD4LNq16Pseudo_UPD:

4551 case ARM::VLD4LNq32Pseudo_UPD:

4552

4553

4555 break;

4556 }

4557

4559}

4560

4561unsigned ARMBaseInstrInfo::getPredicationCost(const MachineInstr &MI) const {

4562 if (MI.isCopyLike() || MI.isInsertSubreg() || MI.isRegSequence() ||

4563 MI.isImplicitDef())

4564 return 0;

4565

4566 if (MI.isBundle())

4567 return 0;

4568

4570

4571 if (MCID.isCall() || (MCID.hasImplicitDefOfPhysReg(ARM::CPSR) &&

4572 !Subtarget.cheapPredicableCPSRDef())) {

4573

4574

4575 return 1;

4576 }

4577 return 0;

4578}

4579

4580unsigned ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData,

4582 unsigned *PredCost) const {

4583 if (MI.isCopyLike() || MI.isInsertSubreg() || MI.isRegSequence() ||

4584 MI.isImplicitDef())

4585 return 1;

4586

4587

4588

4589 if (MI.isBundle()) {

4593 while (++I != E && I->isInsideBundle()) {

4594 if (I->getOpcode() != ARM::t2IT)

4595 Latency += getInstrLatency(ItinData, *I, PredCost);

4596 }

4598 }

4599

4600 const MCInstrDesc &MCID = MI.getDesc();

4602 !Subtarget.cheapPredicableCPSRDef()))) {

4603

4604

4605 *PredCost = 1;

4606 }

4607

4608

4609 if (!ItinData)

4610 return MI.mayLoad() ? 3 : 1;

4611

4613

4614

4617

4618

4620

4621

4622 unsigned DefAlign =

4623 MI.hasOneMemOperand() ? (*MI.memoperands_begin())->getAlign().value() : 0;

4625 if (Adj >= 0 || (int)Latency > -Adj) {

4627 }

4629}

4630

4631unsigned ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData,

4632 SDNode *Node) const {

4633 if (Node->isMachineOpcode())

4634 return 1;

4635

4636 if (!ItinData || ItinData->isEmpty())

4637 return 1;

4638

4639 unsigned Opcode = Node->getMachineOpcode();

4640 switch (Opcode) {

4641 default:

4643 case ARM::VLDMQIA:

4644 case ARM::VSTMQIA:

4645 return 2;

4646 }

4647}

4648

4649bool ARMBaseInstrInfo::hasHighOperandLatency(const TargetSchedModel &SchedModel,

4652 unsigned DefIdx,

4654 unsigned UseIdx) const {

4657 if (Subtarget.nonpipelinedVFP() &&

4659 return true;

4660

4661

4665 return false;

4668}

4669

4670bool ARMBaseInstrInfo::hasLowDefLatency(const TargetSchedModel &SchedModel,

4672 unsigned DefIdx) const {

4674 if (!ItinData || ItinData->isEmpty())

4675 return false;

4676

4679 unsigned DefClass = DefMI.getDesc().getSchedClass();

4680 std::optional DefCycle =

4682 return DefCycle && DefCycle <= 2U;

4683 }

4684 return false;

4685}

4686

4687bool ARMBaseInstrInfo::verifyInstruction(const MachineInstr &MI,

4690 ErrInfo = "Pseudo flag setting opcodes only exist in Selection DAG";

4691 return false;

4692 }

4693 if (MI.getOpcode() == ARM::tMOVr && !Subtarget.hasV6Ops()) {

4694

4695 if (!ARM::hGPRRegClass.contains(MI.getOperand(0).getReg()) &&

4696 !ARM::hGPRRegClass.contains(MI.getOperand(1).getReg())) {

4697 ErrInfo = "Non-flag-setting Thumb1 mov is v6-only";

4698 return false;

4699 }

4700 }

4701 if (MI.getOpcode() == ARM::tPUSH ||

4702 MI.getOpcode() == ARM::tPOP ||

4703 MI.getOpcode() == ARM::tPOP_RET) {

4704 for (const MachineOperand &MO : llvm::drop_begin(MI.operands(), 2)) {

4705 if (MO.isImplicit() || !MO.isReg())

4706 continue;

4709 if (!(MI.getOpcode() == ARM::tPUSH && Reg == ARM::LR) &&

4710 !(MI.getOpcode() == ARM::tPOP_RET && Reg == ARM::PC)) {

4711 ErrInfo = "Unsupported register in Thumb1 push/pop";

4712 return false;

4713 }

4714 }

4715 }

4716 }

4717 if (MI.getOpcode() == ARM::MVE_VMOV_q_rr) {

4718 assert(MI.getOperand(4).isImm() && MI.getOperand(5).isImm());

4719 if ((MI.getOperand(4).getImm() != 2 && MI.getOperand(4).getImm() != 3) ||

4720 MI.getOperand(4).getImm() != MI.getOperand(5).getImm() + 2) {

4721 ErrInfo = "Incorrect array index for MVE_VMOV_q_rr";

4722 return false;

4723 }

4724 }

4725

4726

4727

4731 default:

4732 break;

4741 uint32_t Imm = 0;

4742 for (auto Op : MI.operands()) {

4743 if (Op.isImm()) {

4744 Imm = Op.getImm();

4745 break;

4746 }

4747 }

4749 ErrInfo = "Incorrect AddrMode Imm for instruction";

4750 return false;

4751 }

4752 break;

4753 }

4754 }

4755 return true;

4756}

4757

4759 unsigned LoadImmOpc,

4760 unsigned LoadOpc) const {

4761 assert(!Subtarget.isROPI() && !Subtarget.isRWPI() &&

4762 "ROPI/RWPI not currently supported with stack guard");

4763

4766 Register Reg = MI->getOperand(0).getReg();

4768 unsigned int Offset = 0;

4769

4770 if (LoadImmOpc == ARM::MRC || LoadImmOpc == ARM::t2MRC) {

4771 assert(!Subtarget.isReadTPSoft() &&

4772 "TLS stack protector requires hardware TLS register");

4773

4781

4782 Module &M = *MBB.getParent()->getFunction().getParent();

4783 Offset = M.getStackProtectorGuardOffset();

4784 if (Offset & ~0xfffU) {

4785

4786

4787

4788 unsigned AddOpc = (LoadImmOpc == ARM::MRC) ? ARM::ADDri : ARM::t2ADDri;

4795 }

4796 } else {

4799 bool IsIndirect = Subtarget.isGVIndirectSymbol(GV);

4800

4802 if (Subtarget.isTargetMachO()) {

4804 } else if (Subtarget.isTargetCOFF()) {

4807 else if (IsIndirect)

4809 } else if (IsIndirect) {

4811 }

4812

4813 if (LoadImmOpc == ARM::tMOVi32imm) {

4814 Register CPSRSaveReg = ARM::R12;

4815 auto APSREncoding =

4816 ARMSysReg::lookupMClassSysRegByName("apsr_nzcvq")->Encoding;

4818 .addImm(APSREncoding)

4823 .addImm(APSREncoding)

4826 } else {

4829 }

4830

4831 if (IsIndirect) {

4840 }

4841 }

4842

4848}

4849

4850bool

4852 unsigned &AddSubOpc,

4853 bool &NegAcc, bool &HasLane) const {

4855 if (I == MLxEntryMap.end())

4856 return false;

4857

4859 MulOpc = Entry.MulOpc;

4860 AddSubOpc = Entry.AddSubOpc;

4861 NegAcc = Entry.NegAcc;

4862 HasLane = Entry.HasLane;

4863 return true;

4864}

4865

4866

4867

4868

4869

4870

4871

4872

4873

4874

4875

4876

4882

4883

4884

4885

4886std::pair<uint16_t, uint16_t>

4888

4889

4890 if (Subtarget.hasNEON()) {

4891

4892

4895

4896

4897

4898 if (Subtarget.useNEONForFPMovs() && isPredicated(MI) &&

4899 (MI.getOpcode() == ARM::VMOVRS || MI.getOpcode() == ARM::VMOVSR ||

4900 MI.getOpcode() == ARM::VMOVS))

4902 }

4903

4905

4907 return std::make_pair(ExeNEON, 0);

4908

4909

4910

4912 return std::make_pair(ExeNEON, 0);

4913

4915 return std::make_pair(ExeVFP, 0);

4916

4917 return std::make_pair(ExeGeneric, 0);

4918}

4919

4921 unsigned SReg, unsigned &Lane) {

4923 TRI->getMatchingSuperReg(SReg, ARM::ssub_0, &ARM::DPRRegClass);

4924 Lane = 0;

4925

4926 if (DReg)

4927 return DReg;

4928

4929 Lane = 1;

4930 DReg = TRI->getMatchingSuperReg(SReg, ARM::ssub_1, &ARM::DPRRegClass);

4931

4932 assert(DReg && "S-register with no D super-register?");

4933 return DReg;

4934}

4935

4936

4937

4938

4939

4940

4941

4942

4943

4944

4945

4946

4947

4948

4949

4950

4953 unsigned Lane,

4955

4956

4957 if (MI.definesRegister(DReg, TRI) || MI.readsRegister(DReg, TRI)) {

4959 return true;

4960 }

4961

4962

4963 ImplicitSReg = TRI->getSubReg(DReg,

4964 (Lane & 1) ? ARM::ssub_0 : ARM::ssub_1);

4966 MI.getParent()->computeRegisterLiveness(TRI, ImplicitSReg, MI);

4967

4969 return true;

4971 return false;

4972

4973

4974

4976 return true;

4977}

4978

4980 unsigned Domain) const {

4981 unsigned DstReg, SrcReg;

4983 unsigned Lane;

4986 switch (MI.getOpcode()) {

4987 default:

4989 break;

4990 case ARM::VMOVD:

4992 break;

4993

4994

4996

4997

4998 assert(Subtarget.hasNEON() && "VORRd requires NEON");

4999

5000

5001 DstReg = MI.getOperand(0).getReg();

5002 SrcReg = MI.getOperand(1).getReg();

5003

5004 for (unsigned i = MI.getDesc().getNumOperands(); i; --i)

5005 MI.removeOperand(i - 1);

5006

5007

5008 MI.setDesc(get(ARM::VORRd));

5013 break;

5014 case ARM::VMOVRS:

5016 break;

5018

5019

5020 DstReg = MI.getOperand(0).getReg();

5021 SrcReg = MI.getOperand(1).getReg();

5022

5023 for (unsigned i = MI.getDesc().getNumOperands(); i; --i)

5024 MI.removeOperand(i - 1);

5025

5027

5028

5029

5030

5031 MI.setDesc(get(ARM::VGETLNi32));

5036

5037

5038

5040 break;

5041 case ARM::VMOVSR: {

5043 break;

5045

5046

5047 DstReg = MI.getOperand(0).getReg();

5048 SrcReg = MI.getOperand(1).getReg();

5049

5051

5054 break;

5055

5056 for (unsigned i = MI.getDesc().getNumOperands(); i; --i)

5057 MI.removeOperand(i - 1);

5058

5059

5060

5061 MI.setDesc(get(ARM::VSETLNi32));

5067

5068

5069

5071 if (ImplicitSReg)

5073 break;

5074 }

5075 case ARM::VMOVS: {

5077 break;

5078

5079

5080 DstReg = MI.getOperand(0).getReg();

5081 SrcReg = MI.getOperand(1).getReg();

5082

5083 unsigned DstLane = 0, SrcLane = 0;

5087

5090 break;

5091

5092 for (unsigned i = MI.getDesc().getNumOperands(); i; --i)

5093 MI.removeOperand(i - 1);

5094

5095 if (DSrc == DDst) {

5096

5097

5098 MI.setDesc(get(ARM::VDUPLN32d));

5103

5104

5105

5108 if (ImplicitSReg)

5110 break;

5111 }

5112

5113

5114

5115

5116

5117

5118

5119

5120

5121

5122

5123

5124

5126 NewMIB = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), get(ARM::VEXTd32),

5127 DDst);

5128

5129

5130

5131

5132 MCRegister CurReg = SrcLane == 1 && DstLane == 1 ? DSrc : DDst;

5133 bool CurUndef = MI.readsRegister(CurReg, TRI);

5135

5136 CurReg = SrcLane == 0 && DstLane == 0 ? DSrc : DDst;

5137 CurUndef = MI.readsRegister(CurReg, TRI);

5141

5142 if (SrcLane == DstLane)

5144

5145 MI.setDesc(get(ARM::VEXTd32));

5147

5148

5149

5150 CurReg = SrcLane == 1 && DstLane == 0 ? DSrc : DDst;

5151 CurUndef = CurReg == DSrc && MI.readsRegister(CurReg, TRI);

5153

5154 CurReg = SrcLane == 0 && DstLane == 1 ? DSrc : DDst;

5155 CurUndef = CurReg == DSrc && MI.readsRegister(CurReg, TRI);

5159

5160 if (SrcLane != DstLane)

5162

5163

5164

5166 if (ImplicitSReg != 0)

5168 break;

5169 }

5170 }

5171}

5172

5173

5174

5175

5176

5177

5178

5179

5180

5181

5182

5183

5184

5185

5186

5187

5188

5192 auto PartialUpdateClearance = Subtarget.getPartialUpdateClearance();

5193 if (!PartialUpdateClearance)

5194 return 0;

5195

5196 assert(TRI && "Need TRI instance");

5197

5200 return 0;

5202 int UseOp = -1;

5203

5204 switch (MI.getOpcode()) {

5205

5206 case ARM::VLDRS:

5207 case ARM::FCONSTS:

5208 case ARM::VMOVSR:

5209 case ARM::VMOVv8i8:

5210 case ARM::VMOVv4i16:

5211 case ARM::VMOVv2i32:

5212 case ARM::VMOVv2f32:

5213 case ARM::VMOVv1i64:

5214 UseOp = MI.findRegisterUseOperandIdx(Reg, TRI, false);

5215 break;

5216

5217

5218 case ARM::VLD1LNd32:

5219 UseOp = 3;

5220 break;

5221 default:

5222 return 0;

5223 }

5224

5225

5226

5227 if (UseOp != -1 && MI.getOperand(UseOp).readsReg())

5228 return 0;

5229

5230

5231 if (Reg.isVirtual()) {

5232

5233 if (!MO.getSubReg() || MI.readsVirtualRegister(Reg))

5234 return 0;

5235 } else if (ARM::SPRRegClass.contains(Reg)) {

5236

5238 TRI->getMatchingSuperReg(Reg, ARM::ssub_0, &ARM::DPRRegClass);

5239 if (!DReg || MI.definesRegister(DReg, TRI))

5240 return 0;

5241 }

5242

5243

5244

5245 return PartialUpdateClearance;

5246}

5247

5248

5249

5252 assert(OpNum < MI.getDesc().getNumDefs() && "OpNum is not a def");

5253 assert(TRI && "Need TRI instance");

5254

5257 assert(Reg.isPhysical() && "Can't break virtual register dependencies.");

5258 unsigned DReg = Reg;

5259

5260

5261 if (ARM::SPRRegClass.contains(Reg)) {

5262 DReg = ARM::D0 + (Reg - ARM::S0) / 2;

5263 assert(TRI->isSuperRegister(Reg, DReg) && "Register enums broken");

5264 }

5265

5266 assert(ARM::DPRRegClass.contains(DReg) && "Can only break D-reg deps");

5267 assert(MI.definesRegister(DReg, TRI) && "MI doesn't clobber full D-reg");

5268

5269

5270

5271

5272

5273

5274

5275

5276

5277 BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), get(ARM::FCONSTD), DReg)

5280 MI.addRegisterKilled(DReg, TRI, true);

5281}

5282

5284 return Subtarget.hasFeature(ARM::HasV6KOps);

5285}

5286

5288 if (MI->getNumOperands() < 4)

5289 return true;

5290 unsigned ShOpVal = MI->getOperand(3).getImm();

5292

5294 ((ShImm == 1 || ShImm == 2) &&

5296 return true;

5297

5298 return false;

5299}

5300

5304 assert(DefIdx < MI.getDesc().getNumDefs() && "Invalid definition index");

5305 assert(MI.isRegSequenceLike() && "Invalid kind of instruction");

5306

5307 switch (MI.getOpcode()) {

5308 case ARM::VMOVDRR:

5309

5310

5311

5312

5313

5317 MOReg->getSubReg(), ARM::ssub_0));

5318

5319 MOReg = &MI.getOperand(2);

5322 MOReg->getSubReg(), ARM::ssub_1));

5323 return true;

5324 }

5326}

5327

5331 assert(DefIdx < MI.getDesc().getNumDefs() && "Invalid definition index");

5332 assert(MI.isExtractSubregLike() && "Invalid kind of instruction");

5333

5334 switch (MI.getOpcode()) {

5335 case ARM::VMOVRRD:

5336

5337

5338

5339

5342 return false;

5345 InputReg.SubIdx = DefIdx == 0 ? ARM::ssub_0 : ARM::ssub_1;

5346 return true;

5347 }

5349}

5350

5354 assert(DefIdx < MI.getDesc().getNumDefs() && "Invalid definition index");

5355 assert(MI.isInsertSubregLike() && "Invalid kind of instruction");

5356

5357 switch (MI.getOpcode()) {

5358 case ARM::VSETLNi32:

5359 case ARM::MVE_VMOV_to_lane_32:

5360

5361

5364 if (MOInsertedReg.isUndef())

5365 return false;

5367 BaseReg.Reg = MOBaseReg.getReg();

5368 BaseReg.SubReg = MOBaseReg.getSubReg();

5369

5370 InsertedReg.Reg = MOInsertedReg.getReg();

5372 InsertedReg.SubIdx = ARM::ssub_0 + MOIndex.getImm();

5373 return true;

5374 }

5376}

5377

5378std::pair<unsigned, unsigned>

5381 return std::make_pair(TF & Mask, TF & ~Mask);

5382}

5383

5386 using namespace ARMII;

5387

5388 static const std::pair<unsigned, const char *> TargetFlags[] = {

5389 {MO_LO16, "arm-lo16"}, {MO_HI16, "arm-hi16"},

5390 {MO_LO_0_7, "arm-lo-0-7"}, {MO_HI_0_7, "arm-hi-0-7"},

5391 {MO_LO_8_15, "arm-lo-8-15"}, {MO_HI_8_15, "arm-hi-8-15"},

5392 };

5393 return ArrayRef(TargetFlags);

5394}

5395

5398 using namespace ARMII;

5399

5400 static const std::pair<unsigned, const char *> TargetFlags[] = {

5401 {MO_COFFSTUB, "arm-coffstub"},

5402 {MO_GOT, "arm-got"},

5403 {MO_SBREL, "arm-sbrel"},

5404 {MO_DLLIMPORT, "arm-dllimport"},

5405 {MO_SECREL, "arm-secrel"},

5406 {MO_NONLAZY, "arm-nonlazy"}};

5407 return ArrayRef(TargetFlags);

5408}

5409

5410std::optional

5412 int Sign = 1;

5413 unsigned Opcode = MI.getOpcode();

5415

5416

5417

5419 if (!Op0.isReg() || Reg != Op0.getReg())

5420 return std::nullopt;

5421

5422

5423 if (Opcode == ARM::SUBri)

5424 Sign = -1;

5425 else if (Opcode != ARM::ADDri)

5426 return std::nullopt;

5427

5428

5429

5430

5431 if (MI.getOperand(1).isReg() || MI.getOperand(2).isImm())

5432 return std::nullopt;

5433

5434 Offset = MI.getOperand(2).getImm() * Sign;

5436}

5437

5442 for (auto I = From; I != To; ++I)

5443 if (I->modifiesRegister(Reg, TRI))

5444 return true;

5445 return false;

5446}

5447

5450

5451

5452

5455 --CmpMI;

5456 if (CmpMI->modifiesRegister(ARM::CPSR, TRI))

5457 break;

5458 if (CmpMI->readsRegister(ARM::CPSR, TRI))

5459 break;

5460 }

5461

5462

5463

5464 if (CmpMI->getOpcode() != ARM::tCMPi8 && CmpMI->getOpcode() != ARM::t2CMPri)

5465 return nullptr;

5466 Register Reg = CmpMI->getOperand(0).getReg();

5469 if (Pred != ARMCC::AL || CmpMI->getOperand(1).getImm() != 0)

5470 return nullptr;

5472 return nullptr;

5474 return nullptr;

5475

5476 return &*CmpMI;

5477}

5478

5481 bool ForCodesize) {

5482 if (Subtarget->isThumb()) {

5483 if (Val <= 255)

5484 return ForCodesize ? 2 : 1;

5485 if (Subtarget->hasV6T2Ops() && (Val <= 0xffff ||

5488 return ForCodesize ? 4 : 1;

5489 if (Val <= 510)

5490 return ForCodesize ? 4 : 2;

5491 if (~Val <= 255)

5492 return ForCodesize ? 4 : 2;

5494 return ForCodesize ? 4 : 2;

5495 } else {

5497 return ForCodesize ? 4 : 1;

5499 return ForCodesize ? 4 : 1;

5500 if (Subtarget->hasV6T2Ops() && Val <= 0xffff)

5501 return ForCodesize ? 4 : 1;

5503 return ForCodesize ? 8 : 2;

5505 return ForCodesize ? 8 : 2;

5506 }

5507 if (Subtarget->useMovt())

5508 return ForCodesize ? 8 : 2;

5509 return ForCodesize ? 8 : 3;

5510}

5511

5514 bool ForCodesize) {

5515

5518 if (Cost1 < Cost2)

5519 return true;

5520 if (Cost1 > Cost2)

5521 return false;

5522

5523

5526}

5527

5528

5529

5530

5531

5532

5533

5534

5535

5536

5537

5538

5539

5540

5541

5542

5543

5544

5545

5546

5547

5548

5549

5550

5551

5552

5553

5554

5555

5556

5557

5558

5559

5560

5561

5562

5563

5564

5565

5566

5567

5568

5569

5570

5571

5572

5573

5574

5575

5576

5577

5578

5579

5580

5581

5582

5583

5584

5585

5586

5587

5588

5589

5590

5591

5592

5593

5594

5595

5596

5597

5598

5599

5600

5601

5602

5603

5604

5605

5606

5607

5608

5609

5610

5611

5612

5613

5614

5615

5616

5617

5618

5619

5620

5621

5622

5623

5624

5625

5626

5627

5628

5629

5637

5643

5670

5673 MachineFunction *MF = C.getMF();

5675 const ARMBaseRegisterInfo *ARI =

5676 static_cast<const ARMBaseRegisterInfo *>(&TRI);

5677

5679

5680

5681 for (Register Reg : ARM::rGPRRegClass) {

5682 if (!(Reg < regsReserved.size() && regsReserved.test(Reg)) &&

5683 Reg != ARM::LR &&

5684 Reg != ARM::R12 &&

5685 C.isAvailableAcrossAndOutOfSeq(Reg, TRI) &&

5686 C.isAvailableInsideSeq(Reg, TRI))

5687 return Reg;

5688 }

5690}

5691

5692

5693

5694

5698

5699 bool Live = false;

5700 for (; I != E; ++I) {

5702

5703

5704 if (MI.modifiesRegister(ARM::LR, &TRI))

5705 Live = false;

5706

5707

5708 unsigned Opcode = MI.getOpcode();

5709 if (Opcode == ARM::BX_RET || Opcode == ARM::MOVPCLR ||

5710 Opcode == ARM::SUBS_PC_LR || Opcode == ARM::tBX_RET ||

5711 Opcode == ARM::tBXNS_RET) {

5712

5713

5714 Live = true;

5715 continue;

5716 }

5717 if (MI.readsRegister(ARM::LR, &TRI))

5718 Live = true;

5719 }

5720 return !Live;

5721}

5722

5723std::optional<std::unique_ptroutliner::OutlinedFunction>

5726 std::vectoroutliner::Candidate &RepeatedSequenceLocs,

5727 unsigned MinRepeats) const {

5728 unsigned SequenceSize = 0;

5729 for (auto &MI : RepeatedSequenceLocs[0])

5731

5732

5733 unsigned FlagsSetInAll = 0xF;

5734

5735

5738 FlagsSetInAll &= C.Flags;

5739

5740

5741

5742

5743

5744

5745

5746

5747

5748

5749

5750

5751

5753

5754

5756 return false;

5757 return C.isAnyUnavailableAcrossOrOutOfSeq({ARM::R12, ARM::CPSR}, TRI);

5758 };

5759

5760

5762

5763

5764

5765 llvm::erase_if(RepeatedSequenceLocs, CantGuaranteeValueAcrossCall);

5766

5767

5768 if (RepeatedSequenceLocs.size() < MinRepeats)

5769 return std::nullopt;

5770 }

5771

5772

5773

5774

5775

5776

5777

5778

5779

5780

5781

5782

5783 auto NoBTI =

5787 });

5788 if (std::distance(RepeatedSequenceLocs.begin(), NoBTI) >

5789 std::distance(NoBTI, RepeatedSequenceLocs.end()))

5790 RepeatedSequenceLocs.erase(NoBTI, RepeatedSequenceLocs.end());

5791 else

5792 RepeatedSequenceLocs.erase(RepeatedSequenceLocs.begin(), NoBTI);

5793

5794 if (RepeatedSequenceLocs.size() < MinRepeats)

5795 return std::nullopt;

5796

5797

5798 auto NoPAC =

5801

5802

5804 });

5805 if (std::distance(RepeatedSequenceLocs.begin(), NoPAC) >

5806 std::distance(NoPAC, RepeatedSequenceLocs.end()))

5807 RepeatedSequenceLocs.erase(NoPAC, RepeatedSequenceLocs.end());

5808 else

5809 RepeatedSequenceLocs.erase(RepeatedSequenceLocs.begin(), NoPAC);

5810

5811 if (RepeatedSequenceLocs.size() < MinRepeats)

5812 return std::nullopt;

5813

5814

5815

5816

5817 unsigned LastInstrOpcode = RepeatedSequenceLocs[0].back().getOpcode();

5818

5819

5820 auto SetCandidateCallInfo =

5821 [&RepeatedSequenceLocs](unsigned CallID, unsigned NumBytesForCall) {

5823 C.setCallInfo(CallID, NumBytesForCall);

5824 };

5825

5827

5828 const auto &SomeMFI =

5829 *RepeatedSequenceLocs.front().getMF()->getInfo<ARMFunctionInfo>();

5830

5831 if (SomeMFI.branchTargetEnforcement()) {

5837 }

5838

5839

5840 if (SomeMFI.shouldSignReturnAddress(true)) {

5841 Costs.CallDefault += 8;

5843 }

5844

5846 unsigned NumBytesToCreateFrame = Costs.FrameDefault;

5847

5848

5849

5850 if (RepeatedSequenceLocs[0].back().isTerminator()) {

5854 } else if (LastInstrOpcode == ARM::BL || LastInstrOpcode == ARM::BLX ||

5855 LastInstrOpcode == ARM::BLX_noip || LastInstrOpcode == ARM::tBL ||

5856 LastInstrOpcode == ARM::tBLXr ||

5857 LastInstrOpcode == ARM::tBLXr_noip ||

5858 LastInstrOpcode == ARM::tBLXi) {

5860 NumBytesToCreateFrame = Costs.FrameThunk;

5862 } else {

5863

5864

5865

5866 unsigned NumBytesNoStackCalls = 0;

5867 std::vectoroutliner::Candidate CandidatesWithoutStackFixups;

5868

5870

5871

5872 const auto Last = C.getMBB()->rbegin();

5873 const bool LRIsAvailable =

5874 C.getMBB()->isReturnBlock() && Last->isCall()

5877 : C.isAvailableAcrossAndOutOfSeq(ARM::LR, TRI);

5878 if (LRIsAvailable) {

5882 CandidatesWithoutStackFixups.push_back(C);

5883 }

5884

5885

5886

5887 else if (findRegisterToSaveLRTo(C)) {

5889 NumBytesNoStackCalls += Costs.CallRegSave;

5891 CandidatesWithoutStackFixups.push_back(C);

5892 }

5893

5894

5895

5896 else if (C.isAvailableInsideSeq(ARM::SP, TRI)) {

5897 NumBytesNoStackCalls += Costs.CallDefault;

5899 CandidatesWithoutStackFixups.push_back(C);

5900 }

5901

5902

5903

5904 else

5905 NumBytesNoStackCalls += SequenceSize;

5906 }

5907

5908

5909

5910

5911 if (NumBytesNoStackCalls <=

5912 RepeatedSequenceLocs.size() * Costs.CallDefault) {

5913 RepeatedSequenceLocs = CandidatesWithoutStackFixups;

5915 if (RepeatedSequenceLocs.size() < MinRepeats)

5916 return std::nullopt;

5917 } else

5919 }

5920

5921

5922

5924

5925

5930

5931

5932

5933

5934

5935

5939 }

5940

5941 return std::make_uniqueoutliner::OutlinedFunction(

5942 RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID);

5943}

5944

5945bool ARMBaseInstrInfo::checkAndUpdateStackOffset(MachineInstr *MI,

5947 bool Updt) const {

5948 int SPIdx = MI->findRegisterUseOperandIdx(ARM::SP, nullptr);

5950 if (SPIdx < 0)

5951

5952 return true;

5954

5955 return false;

5956

5957

5958

5971 return false;

5972

5973 unsigned NumOps = MI->getDesc().getNumOperands();

5974 unsigned ImmIdx = NumOps - 3;

5975

5977 assert(Offset.isImm() && "Is not an immediate");

5978 int64_t OffVal = Offset.getImm();

5979

5980 if (OffVal < 0)

5981

5982 return false;

5983

5984 unsigned NumBits = 0;

5985 unsigned Scale = 1;

5986

5990 return false;

5992 NumBits = 8;

5993 break;

5996 return false;

5998 NumBits = 8;

5999 Scale = 4;

6000 break;

6003 return false;

6005 NumBits = 8;

6006 Scale = 2;

6007 break;

6009 NumBits = 8;

6010 break;

6012

6013 assert((Fixup & 3) == 0 && "Can't encode this offset!");

6014 NumBits = 10;

6015 break;

6017 NumBits = 8;

6018 Scale = 4;

6019 break;

6022 NumBits = 12;

6023 break;

6025 NumBits = 8;

6026 Scale = 4;

6027 break;

6028 default:

6030 }

6031

6032

6033 assert(((OffVal * Scale + Fixup) & (Scale - 1)) == 0 &&

6034 "Can't encode this offset!");

6035 OffVal += Fixup / Scale;

6036

6037 unsigned Mask = (1 << NumBits) - 1;

6038

6039 if (OffVal <= Mask) {

6040 if (Updt)

6041 MI->getOperand(ImmIdx).setImm(OffVal);

6042 return true;

6043 }

6044

6045 return false;

6046}

6047

6049 Function &F, std::vectoroutliner::Candidate &Candidates) const {

6051

6052

6053 const Function &CFn = C.getMF()->getFunction();

6054 if (CFn.hasFnAttribute("branch-target-enforcement"))

6055 F.addFnAttr(CFn.getFnAttribute("branch-target-enforcement"));

6056

6059

6060 ARMGenInstrInfo::mergeOutliningCandidateAttributes(F, Candidates);

6061}

6062

6064 MachineFunction &MF, bool OutlineFromLinkOnceODRs) const {

6066

6067

6068 if (!OutlineFromLinkOnceODRs && F.hasLinkOnceODRLinkage())

6069 return false;

6070

6071

6072

6073

6074

6075 if (F.hasSection())

6076 return false;

6077

6078

6080 return false;

6081

6082

6083 return true;

6084}

6085

6087 unsigned &Flags) const {

6088

6089

6090 assert(MBB.getParent()->getRegInfo().tracksLiveness() &&

6091 "Suitable Machine Function for outlining must track liveness");

6092

6094

6097

6098

6099 bool R12AvailableInBlock = LRU.available(ARM::R12);

6100 bool CPSRAvailableInBlock = LRU.available(ARM::CPSR);

6101

6102

6103

6104 if (R12AvailableInBlock && CPSRAvailableInBlock)

6106

6107

6109

6110

6111

6112 if (R12AvailableInBlock && !LRU.available(ARM::R12))

6113 return false;

6114 if (CPSRAvailableInBlock && !LRU.available(ARM::CPSR))

6115 return false;

6116

6117

6118

6121

6122

6123

6124 bool LRIsAvailable =

6125 MBB.isReturnBlock() && MBB.back().isCall()

6128 if (!LRIsAvailable)

6130

6131 return true;

6132}

6133

6137 unsigned Flags) const {

6140

6141

6142

6143 unsigned Opc = MI.getOpcode();

6144 if (Opc == ARM::tPICADD || Opc == ARM::PICADD || Opc == ARM::PICSTR ||

6145 Opc == ARM::PICSTRB || Opc == ARM::PICSTRH || Opc == ARM::PICLDR ||

6146 Opc == ARM::PICLDRB || Opc == ARM::PICLDRH || Opc == ARM::PICLDRSB ||

6147 Opc == ARM::PICLDRSH || Opc == ARM::t2LDRpci_pic ||

6148 Opc == ARM::t2MOVi16_ga_pcrel || Opc == ARM::t2MOVTi16_ga_pcrel ||

6149 Opc == ARM::t2MOV_ga_pcrel)

6151

6152

6153 if (Opc == ARM::t2BF_LabelPseudo || Opc == ARM::t2DoLoopStart ||

6154 Opc == ARM::t2DoLoopStartTP || Opc == ARM::t2WhileLoopStart ||

6155 Opc == ARM::t2WhileLoopStartLR || Opc == ARM::t2WhileLoopStartTP ||

6156 Opc == ARM::t2LoopDec || Opc == ARM::t2LoopEnd ||

6157 Opc == ARM::t2LoopEndDec)

6159

6164

6165

6166 if (MI.isTerminator())

6167

6168

6170

6171

6172 if (MI.readsRegister(ARM::LR, TRI) || MI.readsRegister(ARM::PC, TRI))

6174

6175 if (MI.isCall()) {

6176

6177

6178 const Function *Callee = nullptr;

6180 if (MOP.isGlobal()) {

6182 break;

6183 }

6184 }

6185

6186

6187

6188 if (Callee &&

6189 (Callee->getName() == "\01__gnu_mcount_nc" ||

6190 Callee->getName() == "\01mcount" || Callee->getName() == "__mcount"))

6192

6193

6194

6195

6196

6198 if (Opc == ARM::BL || Opc == ARM::tBL || Opc == ARM::BLX ||

6199 Opc == ARM::BLX_noip || Opc == ARM::tBLXr || Opc == ARM::tBLXr_noip ||

6200 Opc == ARM::tBLXi)

6202

6203 if (!Callee)

6204 return UnknownCallOutlineType;

6205

6206

6207

6209

6210

6211 if (!CalleeMF)

6212 return UnknownCallOutlineType;

6213

6214

6215

6216

6220 return UnknownCallOutlineType;

6221

6222

6223

6225 }

6226

6227

6228 if (MI.modifiesRegister(ARM::LR, TRI) || MI.modifiesRegister(ARM::PC, TRI))

6230

6231

6232 if (MI.modifiesRegister(ARM::SP, TRI) || MI.readsRegister(ARM::SP, TRI)) {

6233

6234

6235

6236

6237

6238

6239

6240

6241

6242

6243

6244

6245 bool MightNeedStackFixUp =

6248

6249 if (!MightNeedStackFixUp)

6251

6252

6253

6254

6255 if (MI.modifiesRegister(ARM::SP, TRI))

6257

6258

6259

6260 if (checkAndUpdateStackOffset(&MI, Subtarget.getStackAlignment().value(),

6261 false))

6263

6264

6266 }

6267

6268

6269 if (MI.readsRegister(ARM::ITSTATE, TRI) ||

6270 MI.modifiesRegister(ARM::ITSTATE, TRI))

6272

6273

6274 if (MI.isCFIInstruction())

6276

6278}

6279

6283 }

6284}

6285

6288 bool Auth) const {

6289 int Align = std::max(Subtarget.getStackAlignment().value(), uint64_t(8));

6291 assert(Align >= 8 && Align <= 256);

6292 if (Auth) {

6293 assert(Subtarget.isThumb2());

6294

6295

6304 } else {

6305 unsigned Opc = Subtarget.isThumb() ? ARM::t2STR_PRE : ARM::STR_PRE_IMM;

6312 }

6313

6314 if (!CFI)

6315 return;

6316

6317

6319 CFIBuilder.buildDefCFAOffset(Align);

6320

6321

6322

6323 int LROffset = Auth ? Align - 4 : Align;

6324 CFIBuilder.buildOffset(ARM::LR, -LROffset);

6325 if (Auth) {

6326

6327 CFIBuilder.buildOffset(ARM::RA_AUTH_CODE, -Align);

6328 }

6329}

6330

6333 bool CFI, bool Auth) const {

6334 int Align = Subtarget.getStackAlignment().value();

6336 if (Auth) {

6337 assert(Subtarget.isThumb2());

6338

6347

6348 } else {

6349 unsigned Opc = Subtarget.isThumb() ? ARM::t2LDR_POST : ARM::LDR_POST_IMM;

6353 if (!Subtarget.isThumb())

6355 MIB.addImm(Subtarget.getStackAlignment().value())

6358 }

6359

6360 if (CFI) {

6361

6363 CFIBuilder.buildDefCFAOffset(0);

6364 CFIBuilder.buildRestore(ARM::LR);

6365 if (Auth)

6366 CFIBuilder.buildUndefined(ARM::RA_AUTH_CODE);

6367 }

6368

6369 if (Auth)

6371}

6372

6376

6377

6380 bool isThumb = Subtarget.isThumb();

6381 unsigned FuncOp = isThumb ? 2 : 0;

6382 unsigned Opc = Call->getOperand(FuncOp).isReg()

6383 ? isThumb ? ARM::tTAILJMPr : ARM::TAILJMPr

6384 : isThumb ? Subtarget.isTargetMachO() ? ARM::tTAILJMPd

6385 : ARM::tTAILJMPdND

6386 : ARM::TAILJMPd;

6388 .add(Call->getOperand(FuncOp));

6389 if (isThumb && Call->getOperand(FuncOp).isReg())

6391 Call->eraseFromParent();

6392 }

6393

6394

6396 return MI.isCall() && MI.isReturn();

6397 };

6401

6404 Et = std::prev(MBB.end());

6405

6406

6407

6408

6409 if (MBB.isLiveIn(ARM::LR))

6410 MBB.addLiveIn(ARM::LR);

6411

6412

6414 saveLROnStack(MBB, It, true, Auth);

6415

6416

6417

6419 "Can only fix up stack references once");

6420 fixupPostOutline(MBB);

6421

6422

6423 restoreLRFromStack(MBB, Et, true, Auth);

6424 }

6425

6426

6429 return;

6430

6431

6432

6435

6436

6439 return;

6440

6441

6442

6443 fixupPostOutline(MBB);

6444}

6445

6451 unsigned Opc;

6452 bool isThumb = Subtarget.isThumb();

6453

6454

6456

6458 ? Subtarget.isTargetMachO() ? ARM::tTAILJMPd : ARM::tTAILJMPdND

6459 : ARM::TAILJMPd;

6464 It = MBB.insert(It, MIB);

6465 return It;

6466 }

6467

6468

6474

6477

6478 It = MBB.insert(It, CallMIB);

6479 return It;

6480 }

6481

6483

6485 Register Reg = findRegisterToSaveLRTo(C);

6486 assert(Reg != 0 && "No callee-saved register available?");

6487

6488

6493 CallPt = MBB.insert(It, CallMIB);

6497 It--;

6498 return CallPt;

6499 }

6500

6501 if (MBB.isLiveIn(ARM::LR))

6502 MBB.addLiveIn(ARM::LR);

6505 CallPt = MBB.insert(It, CallMIB);

6506 restoreLRFromStack(MBB, It, !AFI.isLRSpilled(), Auth);

6507 It--;

6508 return CallPt;

6509}

6510

6515

6516bool ARMBaseInstrInfo::isReMaterializableImpl(

6518

6519

6520

6521

6524}

6525

6530

6535

6538 : ARM::BLX_pred;

6539}

6540

6541namespace {

6546

6547

6548

6549

6550 static int constexpr MAX_STAGES = 30;

6551 static int constexpr LAST_IS_USE = MAX_STAGES;

6552 static int constexpr SEEN_AS_LIVE = MAX_STAGES + 1;

6553 typedef std::bitset<MAX_STAGES + 2> IterNeed;

6554 typedef std::map<Register, IterNeed> IterNeeds;

6555

6557 const IterNeeds &CIN);

6559

6560

6561

6562

6563

6564

6565

6566

6567public:

6569 : EndLoop(EndLoop), LoopCount(LoopCount),

6571 TII(MF->getSubtarget().getInstrInfo()) {}

6572

6573 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {

6574

6575 return MI == EndLoop || MI == LoopCount;

6576 }

6577

6578 bool shouldUseSchedule(SwingSchedulerDAG &SSD, SMSchedule &SMS) override {

6579 if (tooMuchRegisterPressure(SSD, SMS))

6580 return false;

6581

6582 return true;

6583 }

6584

6585 std::optional createTripCountGreaterCondition(

6586 int TC, MachineBasicBlock &MBB,

6587 SmallVectorImpl &Cond) override {

6588

6594 }

6595 return {};

6596 } else if (EndLoop->getOpcode() == ARM::t2LoopEnd) {

6597

6598

6599 MachineInstr *LoopDec = nullptr;

6601 if (I.getOpcode() == ARM::t2LoopDec)

6602 LoopDec = &I;

6603 assert(LoopDec && "Unable to find copied LoopDec");

6604

6609 .addReg(ARM::NoRegister);

6612 return {};

6613 } else

6615 }

6616

6617 void setPreheader(MachineBasicBlock *NewPreheader) override {}

6618

6619 void adjustTripCount(int TripCountAdjust) override {}

6620};

6621

6622void ARMPipelinerLoopInfo::bumpCrossIterationPressure(RegPressureTracker &RPT,

6623 const IterNeeds &CIN) {

6624

6625 for (const auto &N : CIN) {

6626 int Cnt = N.second.count() - N.second[SEEN_AS_LIVE] * 2;

6627 for (int I = 0; I < Cnt; ++I)

6630 }

6631

6632 for (const auto &N : CIN) {

6633 int Cnt = N.second.count() - N.second[SEEN_AS_LIVE] * 2;

6634 for (int I = 0; I < Cnt; ++I)

6637 }

6638}

6639

6640bool ARMPipelinerLoopInfo::tooMuchRegisterPressure(SwingSchedulerDAG &SSD,

6642 IterNeeds CrossIterationNeeds;

6643

6644

6645

6646

6647 for (auto &SU : SSD.SUnits) {

6650 for (auto &S : SU.Succs)

6651 if (MI->isPHI() && S.getKind() == SDep::Anti) {

6654 CrossIterationNeeds[Reg.id()].set(0);

6655 } else if (S.isAssignedRegDep()) {

6657 if (OStg >= 0 && OStg != Stg) {

6660 CrossIterationNeeds[Reg.id()] |= ((1 << (OStg - Stg)) - 1);

6661 }

6662 }

6663 }

6664

6665

6666

6667

6668

6669 std::vector<SUnit *> ProposedSchedule;

6671 for (int Stage = 0, StageEnd = SMS.getMaxStageCount(); Stage <= StageEnd;

6672 ++Stage) {

6673 std::deque<SUnit *> Instrs =

6675 std::sort(Instrs.begin(), Instrs.end(),

6676 [](SUnit *A, SUnit *B) { return A->NodeNum > B->NodeNum; });

6678 }

6679

6680

6681

6682

6683 for (auto *SU : ProposedSchedule)

6685 ++OperI) {

6686 auto MO = *OperI;

6687 if (!MO.isReg() || !MO.getReg())

6688 continue;

6690 auto CIter = CrossIterationNeeds.find(Reg.id());

6691 if (CIter == CrossIterationNeeds.end() || CIter->second[LAST_IS_USE] ||

6692 CIter->second[SEEN_AS_LIVE])

6693 continue;

6694 if (MO.isDef() && !MO.isDead())

6695 CIter->second.set(SEEN_AS_LIVE);

6696 else if (MO.isUse())

6697 CIter->second.set(LAST_IS_USE);

6698 }

6699 for (auto &CI : CrossIterationNeeds)

6700 CI.second.reset(LAST_IS_USE);

6701

6706 RPTracker.init(MF, &RegClassInfo, nullptr, EndLoop->getParent(),

6708

6709 bumpCrossIterationPressure(RPTracker, CrossIterationNeeds);

6710

6711 for (auto *SU : ProposedSchedule) {

6713 RPTracker.setPos(std::next(CurInstI));

6714 RPTracker.recede();

6715

6716

6718 auto MO = *OperI;

6719 if (!MO.isReg() || !MO.getReg())

6720 continue;

6722 if (MO.isDef() && !MO.isDead()) {

6723 auto CIter = CrossIterationNeeds.find(Reg.id());

6724 if (CIter != CrossIterationNeeds.end()) {

6725 CIter->second.reset(0);

6726 CIter->second.reset(SEEN_AS_LIVE);

6727 }

6728 }

6729 }

6730 for (auto &S : SU->Preds) {

6732 if (S.isAssignedRegDep()) {

6734 auto CIter = CrossIterationNeeds.find(Reg.id());

6735 if (CIter != CrossIterationNeeds.end()) {

6737 assert(Stg2 <= Stg && "Data dependence upon earlier stage");

6738 if (Stg - Stg2 < MAX_STAGES)

6739 CIter->second.set(Stg - Stg2);

6740 CIter->second.set(SEEN_AS_LIVE);

6741 }

6742 }

6743 }

6744

6745 bumpCrossIterationPressure(RPTracker, CrossIterationNeeds);

6746 }

6747

6748 auto &P = RPTracker.getPressure().MaxSetPressure;

6749 for (unsigned I = 0, E = P.size(); I < E; ++I) {

6750

6751 if (I == ARM::DQuad_with_ssub_0 || I == ARM::DTripleSpc_with_ssub_0 ||

6752 I == ARM::DTriple_with_qsub_0_in_QPR)

6753 continue;

6754

6756 return true;

6757 }

6758 }

6759 return false;

6760}

6761

6762}

6763

6764std::unique_ptrTargetInstrInfo::PipelinerLoopInfo

6768 if (Preheader == LoopBB)

6769 Preheader = *std::next(LoopBB->pred_begin());

6770

6771 if (I != LoopBB->end() && I->getOpcode() == ARM::t2Bcc) {

6772

6773

6774

6775

6777 for (auto &L : LoopBB->instrs()) {

6778 if (L.isCall())

6779 return nullptr;

6781 CCSetter = &L;

6782 }

6783 if (CCSetter)

6784 return std::make_unique(&*I, CCSetter);

6785 else

6786 return nullptr;

6787

6788 }

6789

6790

6791

6792

6793

6794

6795

6796

6797

6798 if (I != LoopBB->end() && I->getOpcode() == ARM::t2LoopEnd) {

6799 for (auto &L : LoopBB->instrs())

6800 if (L.isCall())

6801 return nullptr;

6802 else if (isVCTP(&L))

6803 return nullptr;

6804 Register LoopDecResult = I->getOperand(0).getReg();

6806 MachineInstr *LoopDec = MRI.getUniqueVRegDef(LoopDecResult);

6807 if (!LoopDec || LoopDec->getOpcode() != ARM::t2LoopDec)

6808 return nullptr;

6810 for (auto &J : Preheader->instrs())

6811 if (J.getOpcode() == ARM::t2DoLoopStart)

6812 LoopStart = &J;

6813 if (!LoopStart)

6814 return nullptr;

6815 return std::make_unique(&*I, LoopDec);

6816 }

6817 return nullptr;

6818}

unsigned const MachineRegisterInfo * MRI

MachineInstrBuilder & UseMI

MachineInstrBuilder MachineInstrBuilder & DefMI

MachineOutlinerClass

Constants defining how certain sequences should be outlined.

@ MachineOutlinerTailCall

Emit a save, restore, call, and return.

@ MachineOutlinerRegSave

Emit a call and tail-call.

@ MachineOutlinerNoLRSave

Only emit a branch.

@ MachineOutlinerThunk

Emit a call and return.

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

static bool isThumb(const MCSubtargetInfo &STI)

static bool getImplicitSPRUseForDPRUse(const TargetRegisterInfo *TRI, MachineInstr &MI, MCRegister DReg, unsigned Lane, MCRegister &ImplicitSReg)

getImplicitSPRUseForDPRUse - Given a use of a DPR register and lane, set ImplicitSReg to a register n...

Definition ARMBaseInstrInfo.cpp:4951

static const MachineInstr * getBundledUseMI(const TargetRegisterInfo *TRI, const MachineInstr &MI, unsigned Reg, unsigned &UseIdx, unsigned &Dist)

Definition ARMBaseInstrInfo.cpp:3999

static unsigned duplicateCPV(MachineFunction &MF, unsigned &CPI)

Create a copy of a const pool value.

Definition ARMBaseInstrInfo.cpp:1613

static bool isSuitableForMask(MachineInstr *&MI, Register SrcReg, int CmpMask, bool CommonUse)

isSuitableForMask - Identify a suitable 'and' instruction that operates on the given source register ...

Definition ARMBaseInstrInfo.cpp:2671

static int adjustDefLatency(const ARMSubtarget &Subtarget, const MachineInstr &DefMI, const MCInstrDesc &DefMCID, unsigned DefAlign)

Return the number of cycles to add to (or subtract from) the static itinerary based on the def opcode...

Definition ARMBaseInstrInfo.cpp:4031

static unsigned getNumMicroOpsSwiftLdSt(const InstrItineraryData *ItinData, const MachineInstr &MI)

Definition ARMBaseInstrInfo.cpp:3307

static MCRegister getCorrespondingDRegAndLane(const TargetRegisterInfo *TRI, unsigned SReg, unsigned &Lane)

Definition ARMBaseInstrInfo.cpp:4920

static const AddSubFlagsOpcodePair AddSubFlagsOpcodeMap[]

Definition ARMBaseInstrInfo.cpp:2268

static bool isEligibleForITBlock(const MachineInstr *MI)

Definition ARMBaseInstrInfo.cpp:519

static ARMCC::CondCodes getCmpToAddCondition(ARMCC::CondCodes CC)

getCmpToAddCondition - assume the flags are set by CMP(a,b), return the condition code if we modify t...

Definition ARMBaseInstrInfo.cpp:2689

static bool isOptimizeCompareCandidate(MachineInstr *MI, bool &IsThumb1)

Definition ARMBaseInstrInfo.cpp:2767

static bool isLRAvailable(const TargetRegisterInfo &TRI, MachineBasicBlock::reverse_iterator I, MachineBasicBlock::reverse_iterator E)

Definition ARMBaseInstrInfo.cpp:5695

ARMExeDomain

Definition ARMBaseInstrInfo.cpp:4877

@ ExeVFP

Definition ARMBaseInstrInfo.cpp:4879

@ ExeNEON

Definition ARMBaseInstrInfo.cpp:4880

@ ExeGeneric

Definition ARMBaseInstrInfo.cpp:4878

static const ARM_MLxEntry ARM_MLxTable[]

Definition ARMBaseInstrInfo.cpp:87

static bool isRedundantFlagInstr(const MachineInstr *CmpI, Register SrcReg, Register SrcReg2, int64_t ImmValue, const MachineInstr *OI, bool &IsThumb1)

isRedundantFlagInstr - check whether the first instruction, whose only purpose is to update flags,...

Definition ARMBaseInstrInfo.cpp:2705

static unsigned getNumMicroOpsSingleIssuePlusExtras(unsigned Opc, unsigned NumRegs)

Definition ARMBaseInstrInfo.cpp:3570

static const MachineInstr * getBundledDefMI(const TargetRegisterInfo *TRI, const MachineInstr *MI, unsigned Reg, unsigned &DefIdx, unsigned &Dist)

Definition ARMBaseInstrInfo.cpp:3976

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

MachineBasicBlock MachineBasicBlock::iterator MBBI

This file contains the simple types necessary to represent the attributes associated with functions a...

static const Function * getParent(const Value *V)

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

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

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

DXIL Forward Handle Accesses

This file defines the DenseMap class.

const HexagonInstrInfo * TII

Module.h This file contains the declarations for the Module class.

const size_t AbstractManglingParser< Derived, Alloc >::NumOps

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

TargetInstrInfo::RegSubRegPair RegSubRegPair

Register const TargetRegisterInfo * TRI

Promote Memory to Register

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

MachineInstr unsigned OpIdx

uint64_t IntrinsicInst * II

PowerPC TLS Dynamic Call Fixup

TargetInstrInfo::RegSubRegPairAndIdx RegSubRegPairAndIdx

const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB

const SmallVectorImpl< MachineOperand > & Cond

static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)

This file defines the SmallSet class.

This file defines the SmallVector class.

static X86::CondCode getSwappedCondition(X86::CondCode CC)

Assuming the flags are set by MI(a,b), return the condition code if we modify the instructions such t...

static bool isCPSRDefined(const MachineInstr &MI)

Definition ARMBaseInstrInfo.cpp:512

bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override

optimizeCompareInstr - Convert the instruction to set the zero flag so that we can remove a "comparis...

Definition ARMBaseInstrInfo.cpp:2860

bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override

Definition ARMBaseInstrInfo.cpp:378

ScheduleHazardRecognizer * CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, const ScheduleDAG *DAG) const override

Definition ARMBaseInstrInfo.cpp:125

void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override

Definition ARMBaseInstrInfo.cpp:718

bool foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, MachineRegisterInfo *MRI) const override

foldImmediate - 'Reg' is known to be defined by a move immediate instruction, try to fold the immedia...

Definition ARMBaseInstrInfo.cpp:3158

std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override

Definition ARMBaseInstrInfo.cpp:5379

bool hasNOP() const

Definition ARMBaseInstrInfo.cpp:5283

bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, unsigned ExtraPredCycles, BranchProbability Probability) const override

Definition ARMBaseInstrInfo.cpp:1942

bool ClobbersPredicate(MachineInstr &MI, std::vector< MachineOperand > &Pred, bool SkipDead) const override

Definition ARMBaseInstrInfo.cpp:488

void copyFromCPSR(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MCRegister DestReg, bool KillSrc, const ARMSubtarget &Subtarget) const

Definition ARMBaseInstrInfo.cpp:654

unsigned getNumMicroOps(const InstrItineraryData *ItinData, const MachineInstr &MI) const override

Definition ARMBaseInstrInfo.cpp:3609

std::optional< RegImmPair > isAddImmediate(const MachineInstr &MI, Register Reg) const override

Definition ARMBaseInstrInfo.cpp:5411

unsigned getPartialRegUpdateClearance(const MachineInstr &, unsigned, const TargetRegisterInfo *) const override

Definition ARMBaseInstrInfo.cpp:5189

unsigned getNumLDMAddresses(const MachineInstr &MI) const

Get the number of addresses by LDM or VLDM or zero for unknown.

Definition ARMBaseInstrInfo.cpp:3555

MachineInstr * optimizeSelect(MachineInstr &MI, SmallPtrSetImpl< MachineInstr * > &SeenMIs, bool) const override

Definition ARMBaseInstrInfo.cpp:2187

const MachineInstrBuilder & AddDReg(MachineInstrBuilder &MIB, unsigned Reg, unsigned SubIdx, unsigned State) const

Definition ARMBaseInstrInfo.cpp:932

bool produceSameValue(const MachineInstr &MI0, const MachineInstr &MI1, const MachineRegisterInfo *MRI) const override

Definition ARMBaseInstrInfo.cpp:1707

void setExecutionDomain(MachineInstr &MI, unsigned Domain) const override

Definition ARMBaseInstrInfo.cpp:4979

ArrayRef< std::pair< unsigned, const char * > > getSerializableBitmaskMachineOperandTargetFlags() const override

Definition ARMBaseInstrInfo.cpp:5397

ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, const ScheduleDAG *DAG) const override

Definition ARMBaseInstrInfo.cpp:161

std::unique_ptr< TargetInstrInfo::PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override

Analyze loop L, which must be a single-basic-block loop, and if the conditions can be understood enou...

Definition ARMBaseInstrInfo.cpp:6765

unsigned getInstSizeInBytes(const MachineInstr &MI) const override

GetInstSize - Returns the size of the specified MachineInstr.

Definition ARMBaseInstrInfo.cpp:605

void copyToCPSR(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MCRegister SrcReg, bool KillSrc, const ARMSubtarget &Subtarget) const

Definition ARMBaseInstrInfo.cpp:674

void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override

Definition ARMBaseInstrInfo.cpp:1211

unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override

Definition ARMBaseInstrInfo.cpp:298

void mergeOutliningCandidateAttributes(Function &F, std::vector< outliner::Candidate > &Candidates) const override

Definition ARMBaseInstrInfo.cpp:6048

bool isFunctionSafeToOutlineFrom(MachineFunction &MF, bool OutlineFromLinkOnceODRs) const override

ARM supports the MachineOutliner.

Definition ARMBaseInstrInfo.cpp:6063

bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override

Enable outlining by default at -Oz.

Definition ARMBaseInstrInfo.cpp:6511

std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override

If the specific machine instruction is an instruction that moves/copies value from one register to an...

Definition ARMBaseInstrInfo.cpp:887

MachineInstr & duplicate(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MachineInstr &Orig) const override

Definition ARMBaseInstrInfo.cpp:1683

ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *II, const ScheduleDAGMI *DAG) const override

Definition ARMBaseInstrInfo.cpp:138

MachineBasicBlock::iterator insertOutlinedCall(Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It, MachineFunction &MF, outliner::Candidate &C) const override

Definition ARMBaseInstrInfo.cpp:6446

std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx, const TargetRegisterInfo *TRI) const override

Definition ARMBaseInstrInfo.cpp:403

bool isPredicated(const MachineInstr &MI) const override

Definition ARMBaseInstrInfo.cpp:387

bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override

Definition ARMBaseInstrInfo.cpp:1891

void expandLoadStackGuardBase(MachineBasicBlock::iterator MI, unsigned LoadImmOpc, unsigned LoadOpc) const

Definition ARMBaseInstrInfo.cpp:4758

bool isPredicable(const MachineInstr &MI) const override

isPredicable - Return true if the specified instruction can be predicated.

Definition ARMBaseInstrInfo.cpp:551

Register isLoadFromStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override

Definition ARMBaseInstrInfo.cpp:1464

std::optional< ParamLoadedValue > describeLoadedValue(const MachineInstr &MI, Register Reg) const override

Specialization of TargetInstrInfo::describeLoadedValue, used to enhance debug entry value description...

Definition ARMBaseInstrInfo.cpp:903

std::optional< std::unique_ptr< outliner::OutlinedFunction > > getOutliningCandidateInfo(const MachineModuleInfo &MMI, std::vector< outliner::Candidate > &RepeatedSequenceLocs, unsigned MinRepeats) const override

Definition ARMBaseInstrInfo.cpp:5724

bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override

Definition ARMBaseInstrInfo.cpp:182

unsigned extraSizeToPredicateInstructions(const MachineFunction &MF, unsigned NumInsts) const override

Definition ARMBaseInstrInfo.cpp:2032

unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override

Definition ARMBaseInstrInfo.cpp:325

const ARMBaseRegisterInfo & getRegisterInfo() const

void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg, unsigned SubIdx, const MachineInstr &Orig) const override

Definition ARMBaseInstrInfo.cpp:1656

bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, int64_t &Offset1, int64_t &Offset2) const override

areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler to determine if two loads are lo...

Definition ARMBaseInstrInfo.cpp:1794

std::optional< unsigned > getOperandLatency(const InstrItineraryData *ItinData, const MachineInstr &DefMI, unsigned DefIdx, const MachineInstr &UseMI, unsigned UseIdx) const override

Definition ARMBaseInstrInfo.cpp:4209

bool getRegSequenceLikeInputs(const MachineInstr &MI, unsigned DefIdx, SmallVectorImpl< RegSubRegPairAndIdx > &InputRegs) const override

Build the equivalent inputs of a REG_SEQUENCE for the given MI and DefIdx.

Definition ARMBaseInstrInfo.cpp:5301

unsigned predictBranchSizeForIfCvt(MachineInstr &MI) const override

Definition ARMBaseInstrInfo.cpp:2046

bool getInsertSubregLikeInputs(const MachineInstr &MI, unsigned DefIdx, RegSubRegPair &BaseReg, RegSubRegPairAndIdx &InsertedReg) const override

Build the equivalent inputs of a INSERT_SUBREG for the given MI and DefIdx.

Definition ARMBaseInstrInfo.cpp:5351

bool expandPostRAPseudo(MachineInstr &MI) const override

Definition ARMBaseInstrInfo.cpp:1533

outliner::InstrType getOutliningTypeImpl(const MachineModuleInfo &MMI, MachineBasicBlock::iterator &MIT, unsigned Flags) const override

Definition ARMBaseInstrInfo.cpp:6135

bool SubsumesPredicate(ArrayRef< MachineOperand > Pred1, ArrayRef< MachineOperand > Pred2) const override

Definition ARMBaseInstrInfo.cpp:462

bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, int64_t Offset1, int64_t Offset2, unsigned NumLoads) const override

shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to determine (in conjunction w...

Definition ARMBaseInstrInfo.cpp:1861

bool PredicateInstruction(MachineInstr &MI, ArrayRef< MachineOperand > Pred) const override

Definition ARMBaseInstrInfo.cpp:428

std::pair< uint16_t, uint16_t > getExecutionDomain(const MachineInstr &MI) const override

VFP/NEON execution domains.

Definition ARMBaseInstrInfo.cpp:4887

bool isProfitableToUnpredicate(MachineBasicBlock &TMBB, MachineBasicBlock &FMBB) const override

Definition ARMBaseInstrInfo.cpp:2069

void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override

Definition ARMBaseInstrInfo.cpp:944

bool isFpMLxInstruction(unsigned Opcode) const

isFpMLxInstruction - Return true if the specified opcode is a fp MLA / MLS instruction.

bool isSwiftFastImmShift(const MachineInstr *MI) const

Returns true if the instruction has a shift by immediate that can be executed in one cycle less.

Definition ARMBaseInstrInfo.cpp:5287

ARMBaseInstrInfo(const ARMSubtarget &STI, const ARMBaseRegisterInfo &TRI)

Definition ARMBaseInstrInfo.cpp:110

ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override

Definition ARMBaseInstrInfo.cpp:5385

Register isStoreToStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override

Definition ARMBaseInstrInfo.cpp:1198

bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override

analyzeCompare - For a comparison instruction, return the source registers in SrcReg and SrcReg2 if h...

Definition ARMBaseInstrInfo.cpp:2634

Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override

Definition ARMBaseInstrInfo.cpp:1144

void breakPartialRegDependency(MachineInstr &, unsigned, const TargetRegisterInfo *TRI) const override

Definition ARMBaseInstrInfo.cpp:5250

bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, unsigned &Flags) const override

Definition ARMBaseInstrInfo.cpp:6086

void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF, const outliner::OutlinedFunction &OF) const override

Definition ARMBaseInstrInfo.cpp:6373

Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override

Definition ARMBaseInstrInfo.cpp:1404

const ARMSubtarget & getSubtarget() const

MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const override

Commutes the operands in the given instruction.

Definition ARMBaseInstrInfo.cpp:2102

bool analyzeSelect(const MachineInstr &MI, SmallVectorImpl< MachineOperand > &Cond, unsigned &TrueOp, unsigned &FalseOp, bool &Optimizable) const override

Definition ARMBaseInstrInfo.cpp:2165

bool getExtractSubregLikeInputs(const MachineInstr &MI, unsigned DefIdx, RegSubRegPairAndIdx &InputReg) const override

Build the equivalent inputs of a EXTRACT_SUBREG for the given MI and DefIdx.

Definition ARMBaseInstrInfo.cpp:5328

bool shouldSink(const MachineInstr &MI) const override

Definition ARMBaseInstrInfo.cpp:3140

BitVector getReservedRegs(const MachineFunction &MF) const override

static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)

static ARMConstantPoolMBB * Create(LLVMContext &C, const MachineBasicBlock *mbb, unsigned ID, unsigned char PCAdj)

static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)

ARMConstantPoolValue - ARM specific constantpool value.

bool isMachineBasicBlock() const

bool isGlobalValue() const

ARMCP::ARMCPModifier getModifier() const

bool mustAddCurrentAddress() const

virtual bool hasSameValue(ARMConstantPoolValue *ACPV)

hasSameValue - Return true if this ARM constpool value can share the same constantpool entry as anoth...

bool isBlockAddress() const

ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...

bool isThumb2Function() const

bool branchTargetEnforcement() const

unsigned createPICLabelUId()

bool isThumb1OnlyFunction() const

bool isThumbFunction() const

bool shouldSignReturnAddress() const

const ARMBaseInstrInfo * getInstrInfo() const override

bool isThumb1Only() const

Align getStackAlignment() const

getStackAlignment - Returns the minimum alignment known to hold of the stack frame on entry to the fu...

bool enableMachinePipeliner() const override

Returns true if machine pipeliner should be enabled.

@ DoubleIssueCheckUnalignedAccess

Can load/store 2 registers/cycle, but needs an extra cycle if the access is not 64-bit aligned.

@ SingleIssue

Can load/store 1 register/cycle.

@ DoubleIssue

Can load/store 2 registers/cycle.

@ SingleIssuePlusExtras

Can load/store 1 register/cycle, but needs an extra cycle for address computation and potentially als...

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

size_t size() const

size - Get the array size.

bool test(unsigned Idx) const

size_type size() const

size - Returns the number of bits in this bitvector.

LLVM_ABI uint64_t scale(uint64_t Num) const

Scale a large integer.

BranchProbability getCompl() const

Helper class for creating CFI instructions and inserting them into MIR.

void buildRegister(MCRegister Reg1, MCRegister Reg2) const

void buildRestore(MCRegister Reg) const

ConstMIBundleOperands - Iterate over all operands in a const bundle of machine instructions.

DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator

bool hasOptSize() const

Optimize this function for size (-Os) or minimum size (-Oz).

Attribute getFnAttribute(Attribute::AttrKind Kind) const

Return the attribute for the given attribute kind.

bool hasMinSize() const

Optimize this function for minimum size (-Oz).

LLVMContext & getContext() const

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

bool hasFnAttribute(Attribute::AttrKind Kind) const

Return true if the function has the attribute.

bool hasDLLImportStorageClass() const

bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override

Reverses the branch condition of the specified condition list, returning false on success and true if...

Itinerary data supplied by a subtarget to be used by a target.

int getNumMicroOps(unsigned ItinClassIndx) const

Return the number of micro-ops that the given class decodes to.

std::optional< unsigned > getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const

Return the cycle for the given class and operand.

unsigned getStageLatency(unsigned ItinClassIndx) const

Return the total stage latency of the given class.

std::optional< unsigned > getOperandLatency(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const

Compute and return the use operand latency of a given itinerary class and operand index if the value ...

bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const

Return true if there is a pipeline forwarding between instructions of itinerary classes DefClass and ...

bool isEmpty() const

Returns true if there are no itineraries.

A set of register units used to track register liveness.

bool available(MCRegister Reg) const

Returns true if no part of physical register Reg is live.

LLVM_ABI void addLiveOuts(const MachineBasicBlock &MBB)

Adds registers living out of block MBB.

LLVM_ABI void accumulate(const MachineInstr &MI)

Adds all register units used, defined or clobbered in MI.

This class is intended to be used as a base class for asm properties and features specific to the tar...

Describe properties that are true of each instruction in the target description file.

unsigned getSchedClass() const

Return the scheduling class for this instruction.

unsigned getNumOperands() const

Return the number of declared MachineOperands for this MachineInstruction.

ArrayRef< MCOperandInfo > operands() const

bool mayLoad() const

Return true if this instruction could possibly read memory.

bool hasOptionalDef() const

Set if this instruction has an optional definition, e.g.

unsigned getNumDefs() const

Return the number of MachineOperands that are register definitions.

bool isCall() const

Return true if the instruction is a call.

unsigned getOpcode() const

Return the opcode number for this descriptor.

LLVM_ABI bool hasImplicitDefOfPhysReg(MCRegister Reg, const MCRegisterInfo *MRI=nullptr) const

Return true if this instruction implicitly defines the specified physical register.

Wrapper class representing physical registers. Should be passed by value.

bool isValid() const

isValid - Returns true until all the operands have been visited.

unsigned pred_size() const

MachineInstrBundleIterator< const MachineInstr > const_iterator

LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)

Insert MI into the instruction list before I, possibly inside a bundle.

LLVM_ABI iterator getFirstTerminator()

Returns an iterator to the first terminator instruction of this basic block.

Instructions::iterator instr_iterator

pred_iterator pred_begin()

MachineInstrBundleIterator< MachineInstr, true > reverse_iterator

Instructions::const_iterator const_instr_iterator

const MachineFunction * getParent() const

Return the MachineFunction containing this basic block.

LLVM_ABI instr_iterator erase(instr_iterator I)

Remove an instruction from the instruction list and delete it.

MachineInstrBundleIterator< MachineInstr > iterator

LivenessQueryResult

Possible outcome of a register liveness query to computeRegisterLiveness()

@ LQR_Dead

Register is known to be fully dead.

@ LQR_Live

Register is known to be (at least partially) live.

@ LQR_Unknown

Register liveness not decidable from local neighborhood.

This class is a data container for one entry in a MachineConstantPool.

union llvm::MachineConstantPoolEntry::@004270020304201266316354007027341142157160323045 Val

The constant itself.

bool isMachineConstantPoolEntry() const

isMachineConstantPoolEntry - Return true if the MachineConstantPoolEntry is indeed a target specific ...

MachineConstantPoolValue * MachineCPVal

const Constant * ConstVal

The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...

const std::vector< MachineConstantPoolEntry > & getConstants() const

unsigned getConstantPoolIndex(const Constant *C, Align Alignment)

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

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

uint64_t getStackSize() const

Return the number of bytes that must be allocated to hold all of the fixed size frame objects.

bool isCalleeSavedInfoValid() const

Has the callee saved info been calculated yet?

Align getObjectAlign(int ObjectIdx) const

Return the alignment of the specified stack object.

int64_t getObjectSize(int ObjectIdx) const

Return the size of the specified object.

unsigned getNumObjects() const

Return the number of objects.

const TargetSubtargetInfo & getSubtarget() const

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

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

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.

MachineFrameInfo & getFrameInfo()

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

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

Function & getFunction()

Return the LLVM function that this machine code represents.

Ty * getInfo()

getInfo - Keep track of various per-function pieces of information for backends that would like to do...

MachineConstantPool * getConstantPool()

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

const TargetMachine & getTarget() const

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

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & add(const MachineOperand &MO) const

const MachineInstrBuilder & addFrameIndex(int Idx) const

const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const

const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const

const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const

const MachineInstrBuilder & setMIFlags(unsigned Flags) const

const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const

Representation of each machine instruction.

ArrayRef< MachineMemOperand * >::iterator mmo_iterator

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

bool isImplicitDef() const

const MachineBasicBlock * getParent() const

bool isCopyLike() const

Return true if the instruction behaves like a copy.

bool isCall(QueryType Type=AnyInBundle) const

unsigned getNumOperands() const

Retuns the total number of operands.

LLVM_ABI int findFirstPredOperandIdx() const

Find the index of the first operand in the operand list that is used to represent the predicate.

const MCInstrDesc & getDesc() const

Returns the target instruction descriptor of this MachineInstr.

bool isRegSequence() const

bool isInsertSubreg() const

LLVM_ABI void tieOperands(unsigned DefIdx, unsigned UseIdx)

Add a tie between the register operands at DefIdx and UseIdx.

LLVM_ABI bool isIdenticalTo(const MachineInstr &Other, MICheckType Check=CheckDefs) const

Return true if this instruction is identical to Other.

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

LLVM_ABI void eraseFromParent()

Unlink 'this' from the containing basic block and delete it.

LLVM_ABI bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)

We have determined MI kills a register.

bool hasOptionalDef(QueryType Type=IgnoreBundle) const

Set if this instruction has an optional definition, e.g.

LLVM_ABI void addRegisterDefined(Register Reg, const TargetRegisterInfo *RegInfo=nullptr)

We have determined MI defines a register.

const MachineOperand & getOperand(unsigned i) const

LLVM_ABI void clearKillInfo()

Clears kill flags on all operands.

A description of a memory reference used in the backend.

@ MODereferenceable

The memory access is dereferenceable (i.e., doesn't trap).

@ MOLoad

The memory access reads data.

@ MOInvariant

The memory access always returns the same value (or traps).

@ MOStore

The memory access writes data.

This class contains meta information specific to a module.

LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const

Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.

MachineOperand class - Representation of each machine instruction operand.

unsigned getSubReg() const

const GlobalValue * getGlobal() const

void setImplicit(bool Val=true)

void setImm(int64_t immVal)

bool readsReg() const

readsReg - Returns true if this operand reads the previous value of its register.

bool isReg() const

isReg - Tests if this is a MO_Register operand.

bool isRegMask() const

isRegMask - Tests if this is a MO_RegisterMask operand.

MachineBasicBlock * getMBB() const

LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)

ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.

static MachineOperand CreateImm(int64_t Val)

Register getReg() const

getReg - Returns the register number.

LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const

Returns true if this operand is identical to the specified operand except for liveness related flags ...

static bool clobbersPhysReg(const uint32_t *RegMask, MCRegister PhysReg)

clobbersPhysReg - Returns true if this RegMask clobbers PhysReg.

static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)

int64_t getOffset() const

Return the offset from the symbol in this operand.

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

defusechain_instr_iterator< true, false, false, true > use_instr_iterator

use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the specified register,...

const TargetRegisterInfo * getTargetRegisterInfo() const

A Module instance is used to store all the information related to an LLVM module.

void AddHazardRecognizer(std::unique_ptr< ScheduleHazardRecognizer > &&)

Track the current register pressure at some position in the instruction stream, and remember the high...

LLVM_ABI void increaseRegPressure(VirtRegOrUnit VRegOrUnit, LaneBitmask PreviousMask, LaneBitmask NewMask)

LLVM_ABI void decreaseRegPressure(VirtRegOrUnit VRegOrUnit, LaneBitmask PreviousMask, LaneBitmask NewMask)

unsigned getRegPressureSetLimit(unsigned Idx) const

Get the register unit limit for the given pressure set index.

LLVM_ABI void runOnMachineFunction(const MachineFunction &MF, bool Rev=false)

runOnFunction - Prepare to answer questions about MF.

Wrapper class representing virtual and physical registers.

constexpr bool isVirtual() const

Return true if the specified register number is in the virtual register namespace.

static constexpr bool isPhysicalRegister(unsigned Reg)

Return true if the specified register number is in the physical register namespace.

constexpr unsigned id() const

constexpr bool isPhysical() const

Return true if the specified register number is in the physical register namespace.

Represents one node in the SelectionDAG.

bool isMachineOpcode() const

Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.

unsigned getMachineOpcode() const

This may only be called if isMachineOpcode returns true.

const SDValue & getOperand(unsigned Num) const

uint64_t getConstantOperandVal(unsigned Num) const

Helper method returns the integer value of a ConstantSDNode operand.

@ Anti

A register anti-dependence (aka WAR).

This class represents the scheduled code.

unsigned getMaxStageCount()

Return the maximum stage count needed for this schedule.

int stageScheduled(SUnit *SU) const

Return the stage for a scheduled instruction.

int getInitiationInterval() const

Return the initiation interval for this schedule.

std::deque< SUnit * > & getInstructions(int cycle)

Return the instructions that are scheduled at the specified cycle.

int getFirstCycle() const

Return the first cycle in the completed schedule.

int getFinalCycle() const

Return the last cycle in the finalized schedule.

Scheduling unit. This is a node in the scheduling DAG.

ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply schedules machine instructions ac...

virtual bool hasVRegLiveness() const

Return true if this DAG supports VReg liveness and RegPressure.

std::vector< SUnit > SUnits

The scheduling units.

HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...

A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...

bool erase(PtrType Ptr)

Remove pointer from the set.

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...

size_type count(const T &V) const

count - Return 1 if the element is in the set, 0 otherwise.

std::pair< const_iterator, bool > insert(const T &V)

insert - Insert an element into the set if it isn't already there.

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.

StringRef - Represent a constant reference to a string, i.e.

This class builds the dependence graph for the instructions in a loop, and attempts to schedule the i...

Object returned by analyzeLoopForPipelining.

TargetInstrInfo - Interface to description of machine instruction set.

virtual ScheduleHazardRecognizer * CreateTargetPostRAHazardRecognizer(const InstrItineraryData *, const ScheduleDAG *DAG) const

Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...

virtual ScheduleHazardRecognizer * CreateTargetMIHazardRecognizer(const InstrItineraryData *, const ScheduleDAGMI *DAG) const

Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...

virtual std::optional< ParamLoadedValue > describeLoadedValue(const MachineInstr &MI, Register Reg) const

Produce the expression describing the MI loading a value into the physical register Reg.

virtual ScheduleHazardRecognizer * CreateTargetHazardRecognizer(const TargetSubtargetInfo *STI, const ScheduleDAG *DAG) const

Allocate and return a hazard recognizer to use for this target when scheduling the machine instructio...

virtual bool isReMaterializableImpl(const MachineInstr &MI) const

For instructions with opcodes for which the M_REMATERIALIZABLE flag is set, this hook lets the target...

virtual MachineInstr & duplicate(MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MachineInstr &Orig) const

Clones instruction or the whole instruction bundle Orig and insert into MBB before InsertBefore.

virtual MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const

This method commutes the operands of the given machine instruction MI.

virtual std::string createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, unsigned OpIdx, const TargetRegisterInfo *TRI) const

const MCAsmInfo * getMCAsmInfo() const

Return target specific asm information.

MCRegister getRegister(unsigned i) const

Return the specified register in the class.

TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...

Provide an instruction scheduling machine model to CodeGen passes.

LLVM_ABI unsigned computeOperandLatency(const MachineInstr *DefMI, unsigned DefOperIdx, const MachineInstr *UseMI, unsigned UseOperIdx) const

Compute operand latency based on the available machine model.

const InstrItineraryData * getInstrItineraries() const

TargetSubtargetInfo - Generic base class for all target subtargets.

virtual const TargetRegisterInfo * getRegisterInfo() const =0

Return the target's register information.

Wrapper class representing a virtual register or register unit.

self_iterator getIterator()

#define llvm_unreachable(msg)

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

constexpr char Align[]

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

static CondCodes getOppositeCondition(CondCodes CC)

ARMII - This namespace holds all of the target specific flags that instruction info tracks.

@ MO_OPTION_MASK

MO_OPTION_MASK - Most flags are mutually exclusive; this mask selects just that part of the flag set.

@ MO_NONLAZY

MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...

@ MO_DLLIMPORT

MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...

@ MO_GOT

MO_GOT - On a symbol operand, this represents a GOT relative relocation.

@ MO_COFFSTUB

MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....

AddrMode

ARM Addressing Modes.

unsigned char getAM3Offset(unsigned AM3Opc)

unsigned char getAM5FP16Offset(unsigned AM5Opc)

unsigned getSORegOffset(unsigned Op)

int getSOImmVal(unsigned Arg)

getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...

ShiftOpc getAM2ShiftOpc(unsigned AM2Opc)

unsigned getAM2Offset(unsigned AM2Opc)

unsigned getSOImmValRotate(unsigned Imm)

getSOImmValRotate - Try to handle Imm with an immediate shifter operand, computing the rotate amount ...

bool isThumbImmShiftedVal(unsigned V)

isThumbImmShiftedVal - Return true if the specified value can be obtained by left shifting a 8-bit im...

int getT2SOImmVal(unsigned Arg)

getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...

ShiftOpc getSORegShOp(unsigned Op)

AddrOpc getAM5Op(unsigned AM5Opc)

bool isSOImmTwoPartValNeg(unsigned V)

isSOImmTwoPartValNeg - Return true if the specified value can be obtained by two SOImmVal,...

unsigned getSOImmTwoPartSecond(unsigned V)

getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, return the second chunk of ...

bool isSOImmTwoPartVal(unsigned V)

isSOImmTwoPartVal - Return true if the specified value can be obtained by or'ing together two SOImmVa...

AddrOpc getAM5FP16Op(unsigned AM5Opc)

unsigned getT2SOImmTwoPartSecond(unsigned Imm)

unsigned getT2SOImmTwoPartFirst(unsigned Imm)

bool isT2SOImmTwoPartVal(unsigned Imm)

unsigned char getAM5Offset(unsigned AM5Opc)

unsigned getSOImmTwoPartFirst(unsigned V)

getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, return the first chunk of it...

AddrOpc getAM2Op(unsigned AM2Opc)

AddrOpc getAM3Op(unsigned AM3Opc)

Define some predicates that are used for node matching.

@ C

The default llvm calling convention, compatible with C.

@ Implicit

Not emitted register (e.g. carry, or temporary result).

@ Define

Register definition.

@ Kill

The last use of a register.

@ Undef

Value of the register doesn't matter.

InstrType

Represents how an instruction should be mapped by the outliner.

NodeAddr< NodeBase * > Node

This is an optimization pass for GlobalISel generic memory operations.

auto drop_begin(T &&RangeOrContainer, size_t N=1)

Return a range covering RangeOrContainer with the first N elements excluded.

constexpr T rotr(T V, int R)

static bool isIndirectCall(const MachineInstr &MI)

MachineInstr * findCMPToFoldIntoCBZ(MachineInstr *Br, const TargetRegisterInfo *TRI)

Search backwards from a tBcc to find a tCMPi8 against 0, meaning we can convert them to a tCBZ or tCB...

Definition ARMBaseInstrInfo.cpp:5448

static bool isCondBranchOpcode(int Opc)

bool HasLowerConstantMaterializationCost(unsigned Val1, unsigned Val2, const ARMSubtarget *Subtarget, bool ForCodesize=false)

Returns true if Val1 has a lower Constant Materialization Cost than Val2.

Definition ARMBaseInstrInfo.cpp:5512

static bool isPushOpcode(int Opc)

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

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

void addPredicatedMveVpredNOp(MachineInstrBuilder &MIB, unsigned Cond)

Definition ARMBaseInstrInfo.cpp:706

static bool isVCTP(const MachineInstr *MI)

bool IsCPSRDead< MachineInstr >(const MachineInstr *MI)

Definition ARMBaseInstrInfo.cpp:588

unsigned getBLXpredOpcode(const MachineFunction &MF)

Definition ARMBaseInstrInfo.cpp:6536

decltype(auto) dyn_cast(const From &Val)

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

static bool isARMLowRegister(MCRegister Reg)

isARMLowRegister - Returns true if the register is a low register (r0-r7).

static bool isIndirectBranchOpcode(int Opc)

bool isLegalAddressImm(unsigned Opcode, int Imm, const TargetInstrInfo *TII)

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

Wrapper function to append range R to container C.

bool registerDefinedBetween(unsigned Reg, MachineBasicBlock::iterator From, MachineBasicBlock::iterator To, const TargetRegisterInfo *TRI)

Return true if Reg is defd between From and To.

Definition ARMBaseInstrInfo.cpp:5438

static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)

Get the operands corresponding to the given Pred value.

static bool isSEHInstruction(const MachineInstr &MI)

static bool isCalleeSavedRegister(MCRegister Reg, const MCPhysReg *CSRegs)

bool any_of(R &&range, UnaryPredicate P)

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

bool tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget, MachineFunction &MF, MachineInstr *MI, unsigned NumBytes)

Tries to add registers to the reglist of a given base-updating push/pop instruction to adjust the sta...

Definition ARMBaseInstrInfo.cpp:2355

auto reverse(ContainerTy &&C)

static bool isJumpTableBranchOpcode(int Opc)

MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)

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

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI raw_ostream & dbgs()

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

static bool isPopOpcode(int Opc)

class LLVM_GSL_OWNER SmallVector

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

bool isa(const From &Val)

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

void addPredicatedMveVpredROp(MachineInstrBuilder &MIB, unsigned Cond, unsigned Inactive)

Definition ARMBaseInstrInfo.cpp:712

auto drop_end(T &&RangeOrContainer, size_t N=1)

Return a range covering RangeOrContainer with the last N elements excluded.

constexpr T divideCeil(U Numerator, V Denominator)

Returns the integer ceil(Numerator / Denominator).

unsigned getUndefRegState(bool B)

void addUnpredicatedMveVpredROp(MachineInstrBuilder &MIB, Register DestReg)

Definition ARMBaseInstrInfo.cpp:700

unsigned ConstantMaterializationCost(unsigned Val, const ARMSubtarget *Subtarget, bool ForCodesize=false)

Returns the number of instructions required to materialize the given constant in a register,...

Definition ARMBaseInstrInfo.cpp:5479

unsigned getKillRegState(bool B)

uint16_t MCPhysReg

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

bool rewriteARMFrameIndex(MachineInstr &MI, unsigned FrameRegIdx, Register FrameReg, int &Offset, const ARMBaseInstrInfo &TII)

rewriteARMFrameIndex / rewriteT2FrameIndex - Rewrite MI to access 'Offset' bytes from the FP.

Definition ARMBaseInstrInfo.cpp:2477

static bool isIndirectControlFlowNotComingBack(const MachineInstr &MI)

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

FunctionAddr VTableAddr Next

ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, Register &PredReg)

getInstrPredicate - If instruction is predicated, returns its predicate condition,...

Definition ARMBaseInstrInfo.cpp:2079

unsigned getMatchingCondBranchOpcode(unsigned Opc)

Definition ARMBaseInstrInfo.cpp:2091

DWARFExpression::Operation Op

ArrayRef(const T &OneElt) -> ArrayRef< T >

static bool isUncondBranchOpcode(int Opc)

auto partition(R &&Range, UnaryPredicate P)

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

decltype(auto) cast(const From &Val)

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

void erase_if(Container &C, UnaryPredicate P)

Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...

static const char * ARMCondCodeToString(ARMCC::CondCodes CC)

static MachineOperand condCodeOp(unsigned CCReg=0)

Get the operand corresponding to the conditional code result.

unsigned gettBLXrOpcode(const MachineFunction &MF)

Definition ARMBaseInstrInfo.cpp:6531

static bool isSpeculationBarrierEndBBOpcode(int Opc)

unsigned getBLXOpcode(const MachineFunction &MF)

Definition ARMBaseInstrInfo.cpp:6526

void addUnpredicatedMveVpredNOp(MachineInstrBuilder &MIB)

Definition ARMBaseInstrInfo.cpp:694

bool isV8EligibleForIT(const InstrType *Instr)

void emitARMRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, ARMCC::CondCodes Pred, Register PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)

emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of instructions to materializea des...

Definition ARMBaseInstrInfo.cpp:2314

unsigned convertAddSubFlagsOpcode(unsigned OldOpc)

Map pseudo instructions that imply an 'S' bit onto real opcodes.

Definition ARMBaseInstrInfo.cpp:2307

ARM_MLxEntry - Record information about MLA / MLS instructions.

Definition ARMBaseInstrInfo.cpp:79

bool NegAcc

Definition ARMBaseInstrInfo.cpp:83

uint16_t MulOpc

Definition ARMBaseInstrInfo.cpp:81

uint16_t AddSubOpc

Definition ARMBaseInstrInfo.cpp:82

uint16_t MLxOpc

Definition ARMBaseInstrInfo.cpp:80

bool HasLane

Definition ARMBaseInstrInfo.cpp:84

Map pseudo instructions that imply an 'S' bit onto real opcodes.

Definition ARMBaseInstrInfo.cpp:2263

uint16_t MachineOpc

Definition ARMBaseInstrInfo.cpp:2265

uint16_t PseudoOpc

Definition ARMBaseInstrInfo.cpp:2264

int CallDefault

Definition ARMBaseInstrInfo.cpp:5653

int CallTailCall

Definition ARMBaseInstrInfo.cpp:5645

int FrameTailCall

Definition ARMBaseInstrInfo.cpp:5646

int FrameThunk

Definition ARMBaseInstrInfo.cpp:5648

int CallRegSave

Definition ARMBaseInstrInfo.cpp:5651

int FrameDefault

Definition ARMBaseInstrInfo.cpp:5654

int CallNoLRSave

Definition ARMBaseInstrInfo.cpp:5649

int FrameNoLRSave

Definition ARMBaseInstrInfo.cpp:5650

int SaveRestoreLROnStack

Definition ARMBaseInstrInfo.cpp:5655

int CallThunk

Definition ARMBaseInstrInfo.cpp:5647

int FrameRegSave

Definition ARMBaseInstrInfo.cpp:5652

OutlinerCosts(const ARMSubtarget &target)

Definition ARMBaseInstrInfo.cpp:5657

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

constexpr uint64_t value() const

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

static constexpr LaneBitmask getAll()

static constexpr LaneBitmask getNone()

static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)

Return a MachinePointerInfo record that refers to a GOT entry.

static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)

Return a MachinePointerInfo record that refers to the specified FrameIndex.

Used to describe a register and immediate addition.

RegisterPressure computed within a region of instructions delimited by TopPos and BottomPos.

An individual sequence of instructions to be replaced with a call to an outlined function.

The information necessary to create an outlined function for some class of candidate.