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

1

2

3

4

5

6

7

8

9

10

11

12

13

31

32namespace llvm {

34}

35

36using namespace llvm;

37

39 : IsThumb1Only(STI.isThumb1Only()) {}

40

44 if (!IsThumb1Only)

46

47 if (ARM::tGPRRegClass.hasSubClassEq(RC))

48 return &ARM::tGPRRegClass;

50}

51

54 if (!IsThumb1Only)

56 return &ARM::tGPRRegClass;

57}

58

61 const DebugLoc &dl, unsigned DestReg,

62 unsigned SubIdx, int Val,

64 unsigned MIFlags) {

69 const Constant *C = ConstantInt::get(

72

77}

78

81 const DebugLoc &dl, unsigned DestReg,

82 unsigned SubIdx, int Val,

84 unsigned MIFlags) {

88 const Constant *C = ConstantInt::get(

91

97}

98

99

100

103 const DebugLoc &dl, Register DestReg, unsigned SubIdx, int Val,

109 "Thumb1 does not have ldr to high register");

111 PredReg, MIFlags);

112 }

114 PredReg, MIFlags);

115}

116

117

118

119

120

121

129

130

131 if (BaseReg == ARM::SP &&

133 NumBytes <= 1020 && (NumBytes % 4) == 0) {

136 .addImm(NumBytes / 4)

139 return;

140 }

141

144 bool isSub = false;

145

146

147

148

149 if (NumBytes < 0 && !isHigh && CanChangeCC) {

150 isSub = true;

151 NumBytes = -NumBytes;

152 }

154 if (DestReg == ARM::SP)

155 assert(BaseReg == ARM::SP && "Unexpected!");

158

159 if (NumBytes <= 255 && NumBytes >= 0 && CanChangeCC) {

164 } else if (NumBytes < 0 && NumBytes >= -255 && CanChangeCC) {

173 } else if (ST.genExecuteOnly()) {

174 if (ST.useMovt()) {

178 } else if (!CanChangeCC) {

179

180

181

182

183 bool LiveCpsr = false, CpsrWrite = false;

184 auto isCpsr = [](auto &MO) { return MO.getReg() == ARM::CPSR; };

185 for (auto Iter = MBBI; Iter != MBB.instr_end(); ++Iter) {

186

187

188 if (any_of(Iter->all_uses(), isCpsr)) {

189 LiveCpsr = true;

190 break;

191 }

192 if (any_of(Iter->all_defs(), isCpsr)) {

193 CpsrWrite = true;

194 break;

195 }

196 }

197

198

199 auto liveOutIsCpsr = [](auto &Out) { return Out.PhysReg == ARM::CPSR; };

200 if (!LiveCpsr && !CpsrWrite)

201 LiveCpsr = any_of(MBB.liveouts(), liveOutIsCpsr);

202

204 unsigned APSREncoding;

205 if (LiveCpsr) {

207 APSREncoding =

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

210 .addImm(APSREncoding)

213 }

217 if (LiveCpsr) {

219 .addImm(APSREncoding)

222 }

223 } else {

227 }

228 } else

230 MIFlags);

231

232

233 int Opc = (isSub) ? ARM::tSUBrr

234 : ((isHigh || !CanChangeCC) ? ARM::tADDhirr : ARM::tADDrr);

236 if (Opc != ARM::tADDhirr)

238 if (DestReg == ARM::SP || isSub)

240 else

243}

244

245

246

247

248

252 Register BaseReg, int NumBytes,

255 unsigned MIFlags) {

256 bool isSub = NumBytes < 0;

257 unsigned Bytes = (unsigned)NumBytes;

258 if (isSub) Bytes = -NumBytes;

259

260 int CopyOpc = 0;

261 unsigned CopyBits = 0;

262 unsigned CopyScale = 1;

263 bool CopyNeedsCC = false;

264 int ExtraOpc = 0;

265 unsigned ExtraBits = 0;

266 unsigned ExtraScale = 1;

267 bool ExtraNeedsCC = false;

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282 if (DestReg == ARM::SP) {

283 if (BaseReg == ARM::SP) {

284

285

286 } else {

287

288 CopyOpc = ARM::tMOVr;

289 CopyBits = 0;

290 }

291 ExtraOpc = isSub ? ARM::tSUBspi : ARM::tADDspi;

292 ExtraBits = 7;

293 ExtraScale = 4;

295 if (BaseReg == ARM::SP) {

296

297 assert(!isSub && "Thumb1 does not have tSUBrSPi");

298 CopyOpc = ARM::tADDrSPi;

299 CopyBits = 8;

300 CopyScale = 4;

301 } else if (DestReg == BaseReg) {

302

303

305

306 CopyOpc = isSub ? ARM::tSUBi3 : ARM::tADDi3;

307 CopyBits = 3;

308 CopyNeedsCC = true;

309 } else {

310

311 CopyOpc = ARM::tMOVr;

312 CopyBits = 0;

313 }

314 ExtraOpc = isSub ? ARM::tSUBi8 : ARM::tADDi8;

315 ExtraBits = 8;

316 ExtraNeedsCC = true;

317 } else {

318 if (DestReg == BaseReg) {

319

320

321 } else {

322

323 CopyOpc = ARM::tMOVr;

324 CopyBits = 0;

325 }

326 ExtraOpc = 0;

327 }

328

329

330

331 assert(((Bytes & 3) == 0 || ExtraScale == 1) &&

332 "Unaligned offset, but all instructions require alignment");

333

334 unsigned CopyRange = ((1 << CopyBits) - 1) * CopyScale;

335

336 if (CopyOpc && Bytes < CopyScale) {

337 CopyOpc = ARM::tMOVr;

338 CopyScale = 1;

339 CopyNeedsCC = false;

340 CopyRange = 0;

341 }

342 unsigned ExtraRange = ((1 << ExtraBits) - 1) * ExtraScale;

343 unsigned RequiredCopyInstrs = CopyOpc ? 1 : 0;

344 unsigned RangeAfterCopy = (CopyRange > Bytes) ? 0 : (Bytes - CopyRange);

345

346

347

348 assert(RangeAfterCopy % ExtraScale == 0 &&

349 "Extra instruction requires immediate to be aligned");

350

351 unsigned RequiredExtraInstrs;

352 if (ExtraRange)

353 RequiredExtraInstrs = alignTo(RangeAfterCopy, ExtraRange) / ExtraRange;

354 else if (RangeAfterCopy > 0)

355

356 RequiredExtraInstrs = 1000000;

357 else

358 RequiredExtraInstrs = 0;

359 unsigned RequiredInstrs = RequiredCopyInstrs + RequiredExtraInstrs;

360 unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2;

361

362

363 if (RequiredInstrs > Threshold) {

365 DestReg, BaseReg, NumBytes, true,

367 return;

368 }

369

370

371 if (CopyOpc) {

372 unsigned CopyImm = std::min(Bytes, CopyRange) / CopyScale;

373 Bytes -= CopyImm * CopyScale;

374

376 if (CopyNeedsCC)

379 if (CopyOpc != ARM::tMOVr) {

381 }

383

384 BaseReg = DestReg;

385 }

386

387

388 while (Bytes) {

389 unsigned ExtraImm = std::min(Bytes, ExtraRange) / ExtraScale;

390 Bytes -= ExtraImm * ExtraScale;

391

393 if (ExtraNeedsCC)

399 }

400}

401

403 unsigned Op = i;

404 for (unsigned e = MI.getNumOperands(); i != e; ++i)

405 MI.removeOperand(Op);

406}

407

408

409

411 switch (Opcode) {

412 case ARM::tLDRspi:

413 return ARM::tLDRi;

414

415 case ARM::tSTRspi:

416 return ARM::tSTRi;

417 }

418

419 return Opcode;

420}

421

423 unsigned FrameRegIdx,

430 "This isn't needed for thumb2!");

433 unsigned Opcode = MI.getOpcode();

436

437 if (Opcode == ARM::tADDframe) {

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

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

440

442 *this);

444 return true;

445 } else {

448

449 unsigned ImmIdx = FrameRegIdx + 1;

450 int InstrOffs = MI.getOperand(ImmIdx).getImm();

451 unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5;

452 unsigned Scale = 4;

453

454 Offset += InstrOffs * Scale;

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

456

457

459 int ImmedOffset = Offset / Scale;

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

461

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

463

465

466

467

468 if (ARM::hGPRRegClass.contains(FrameReg) && FrameReg != ARM::SP) {

473 }

474

475 MI.getOperand(FrameRegIdx).ChangeToRegister(DestReg, false);

477

478

479

481 if (NewOpc != Opcode && FrameReg != ARM::SP)

482 MI.setDesc(TII.get(NewOpc));

483

484 return true;

485 }

486

487

488

489 NumBits = 5;

490 Mask = (1 << NumBits) - 1;

491 InstrOffs = 0;

493

494

495 if (FrameReg == ARM::SP && Offset - (Mask * Scale) <= 1020) {

496 InstrOffs = Mask;

497 } else if (ST.genExecuteOnly()) {

498

499

500

501

502

503 unsigned BottomBits = (Offset / Scale) & Mask;

504 bool CanMakeBottomByteZero = ((Offset - BottomBits * Scale) & 0xff) == 0;

505 bool TopHalfZero = (Offset & 0xffff0000) == 0;

506 bool CanMakeTopHalfZero = ((Offset - Mask * Scale) & 0xffff0000) == 0;

507 if (!TopHalfZero && CanMakeTopHalfZero)

508 InstrOffs = Mask;

509 else if (!ST.useMovt() && CanMakeBottomByteZero)

510 InstrOffs = BottomBits;

511 }

513 Offset -= InstrOffs * Scale;

514 }

515

517}

518

520 int64_t Offset) const {

525

527 int Off = Offset;

528 unsigned i = 0;

529

530 while (MI.getOperand(i).isFI()) {

531 ++i;

532 assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");

533 }

535 assert (Done && "Unable to resolve frame index!");

537}

538

540 int SPAdj, unsigned FIOperandNum,

548 RS);

549

554

556 int FrameIndex = MI.getOperand(FIOperandNum).getIndex();

559

560

561

562

563

564#ifndef NDEBUG

565 if (RS && FrameReg == ARM::SP && RS->isScavengingFrameIndex(FrameIndex)){

567 "Cannot use SP to access the emergency spill slot in "

568 "functions without a reserved call frame");

570 "Cannot use SP to access the emergency spill slot in "

571 "functions with variable sized frame objects");

572 }

573#endif

574

575

576 if (MI.isDebugValue()) {

577 MI.getOperand(FIOperandNum). ChangeToRegister(FrameReg, false );

578 MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);

579 return false;

580 }

581

582

584 "This eliminateFrameIndex only supports Thumb1!");

586 return true;

587

588

589

590

591 assert(Offset && "This code isn't needed if offset already handled!");

592

593 unsigned Opcode = MI.getOpcode();

594

595

596 int PIdx = MI.findFirstPredOperandIdx();

597 if (PIdx != -1)

599

600 if (MI.mayLoad()) {

601

602 Register TmpReg = MI.getOperand(0).getReg();

603 bool UseRR = false;

604 if (Opcode == ARM::tLDRspi) {

605 if (FrameReg == ARM::SP || STI.genExecuteOnly())

608 else {

610 if (!ARM::hGPRRegClass.contains(FrameReg)) {

611 UseRR = true;

612 } else {

613

614

619 }

620 }

621 } else {

623 *this);

624 }

625

626 MI.setDesc(TII.get(UseRR ? ARM::tLDRr : ARM::tLDRi));

627 MI.getOperand(FIOperandNum).ChangeToRegister(TmpReg, false, false, true);

628 if (UseRR) {

630 "Thumb1 loads can't use high register");

631

632

633 MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false,

634 false);

635 }

636 } else if (MI.mayStore()) {

638 bool UseRR = false;

639

640 if (Opcode == ARM::tSTRspi) {

641 if (FrameReg == ARM::SP || STI.genExecuteOnly())

644 else {

646 if (!ARM::hGPRRegClass.contains(FrameReg)) {

647 UseRR = true;

648 } else {

649

650

655 }

656 }

657 } else

659 *this);

660 MI.setDesc(TII.get(UseRR ? ARM::tSTRr : ARM::tSTRi));

661 MI.getOperand(FIOperandNum).ChangeToRegister(VReg, false, false, true);

662 if (UseRR) {

664 "Thumb1 stores can't use high register");

665

666

667 MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false,

668 false);

669 }

670 } else {

672 }

673

674

675 if (MI.isPredicable())

677 return false;

678}

679

680bool

683

684

685 return false;

686 }

687

688 return true;

689}

unsigned const MachineRegisterInfo * MRI

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

const TargetInstrInfo & TII

MachineBasicBlock MachineBasicBlock::iterator MBBI

This file contains the declarations for the subclasses of Constant, which represent the different fla...

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

uint64_t IntrinsicInst * II

This file declares the machine register scavenger class.

static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)

static void emitThumbRegPlusImmInReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, bool CanChangeCC, const TargetInstrInfo &TII, const ARMBaseRegisterInfo &MRI, unsigned MIFlags=MachineInstr::NoFlags)

emitThumbRegPlusImmInReg - Emits a series of instructions to materialize a destreg = basereg + immedi...

Definition ThumbRegisterInfo.cpp:122

static void removeOperands(MachineInstr &MI, unsigned i)

Definition ThumbRegisterInfo.cpp:402

static void emitThumb1LoadConstPool(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, unsigned DestReg, unsigned SubIdx, int Val, ARMCC::CondCodes Pred, unsigned PredReg, unsigned MIFlags)

Definition ThumbRegisterInfo.cpp:59

static void emitThumb2LoadConstPool(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, unsigned DestReg, unsigned SubIdx, int Val, ARMCC::CondCodes Pred, unsigned PredReg, unsigned MIFlags)

Definition ThumbRegisterInfo.cpp:79

static unsigned convertToNonSPOpcode(unsigned Opcode)

convertToNonSPOpcode - Change the opcode to the non-SP version, because we're replacing the frame ind...

Definition ThumbRegisterInfo.cpp:410

bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS=nullptr) const override

const TargetRegisterClass * getPointerRegClass(unsigned Kind=0) const override

const TargetRegisterClass * getLargestLegalSuperClass(const TargetRegisterClass *RC, const MachineFunction &MF) const override

void resolveFrameIndex(MachineInstr &MI, Register BaseReg, int64_t Offset) const override

bool hasReservedCallFrame(const MachineFunction &MF) const override

hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...

int ResolveFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg, int SPAdj) const

ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...

bool isThumbFunction() const

const ARMBaseInstrInfo * getInstrInfo() const override

bool isThumb1Only() const

const ARMFrameLowering * getFrameLowering() const override

This is an important base class in LLVM.

Describe properties that are true of each instruction in the target description file.

MachineInstrBundleIterator< MachineInstr > iterator

The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...

bool hasVarSizedObjects() const

This method may be called any time after instruction selection is complete to determine if the stack ...

const TargetSubtargetInfo & getSubtarget() const

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

MachineFrameInfo & getFrameInfo()

getFrameInfo - Return the frame info object for the current function.

MachineRegisterInfo & getRegInfo()

getRegInfo - Return information about the registers currently in use.

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 MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & add(const MachineOperand &MO) const

const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int 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 & setMIFlags(unsigned Flags) const

Representation of each machine instruction.

MachineOperand class - Representation of each machine instruction operand.

LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)

ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.

LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")

createVirtualRegister - Create and return a new virtual register in the function with the specified r...

Wrapper class representing virtual and physical registers.

constexpr bool isVirtual() const

Return true if the specified register number is in the virtual register namespace.

TargetInstrInfo - Interface to description of machine instruction set.

virtual const TargetInstrInfo * getInstrInfo() const

static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)

#define llvm_unreachable(msg)

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

@ C

The default llvm calling convention, compatible with C.

@ Implicit

Not emitted register (e.g. carry, or temporary result).

@ Kill

The last use of a register.

This is an optimization pass for GlobalISel generic memory operations.

cl::opt< bool > ReuseFrameIndexVals

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

static bool isARMLowRegister(MCRegister Reg)

isARMLowRegister - Returns true if the register is a low register (r0-r7).

static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)

Get the operands corresponding to the given Pred value.

bool any_of(R &&range, UnaryPredicate P)

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

unsigned getDefRegState(bool B)

void emitThumbRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, const TargetInstrInfo &TII, const ARMBaseRegisterInfo &MRI, unsigned MIFlags=0)

emitThumbRegPlusImmediate - Emits a series of instructions to materialize a destreg = basereg + immed...

Definition ThumbRegisterInfo.cpp:249

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

DWARFExpression::Operation Op

static MachineOperand t1CondCodeOp(bool isDead=false)

Get the operand corresponding to the conditional code result for Thumb1.

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

const TargetRegisterClass * getPointerRegClass(unsigned Kind=0) const override

Definition ThumbRegisterInfo.cpp:53

bool useFPForScavengingIndex(const MachineFunction &MF) const override

Definition ThumbRegisterInfo.cpp:681

void emitLoadConstPool(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, unsigned SubIdx, int Val, ARMCC::CondCodes Pred=ARMCC::AL, Register PredReg=Register(), unsigned MIFlags=MachineInstr::NoFlags) const override

emitLoadConstPool - Emits a load from constpool to materialize the specified immediate.

Definition ThumbRegisterInfo.cpp:101

bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS=nullptr) const override

Definition ThumbRegisterInfo.cpp:539

const TargetRegisterClass * getLargestLegalSuperClass(const TargetRegisterClass *RC, const MachineFunction &MF) const override

Definition ThumbRegisterInfo.cpp:42

ThumbRegisterInfo(const ARMSubtarget &STI)

Definition ThumbRegisterInfo.cpp:38

void resolveFrameIndex(MachineInstr &MI, Register BaseReg, int64_t Offset) const override

Definition ThumbRegisterInfo.cpp:519

bool rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, Register FrameReg, int &Offset, const ARMBaseInstrInfo &TII) const

Definition ThumbRegisterInfo.cpp:422