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