LLVM 24.0.0git
ThumbRegisterInfo.cpp
Go to the documentation of this file.
1//===-- ThumbRegisterInfo.cpp - Thumb-1 Register Information -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the Thumb-1 implementation of the TargetRegisterInfo
10// class.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ThumbRegisterInfo.h"
15#include "ARMBaseInstrInfo.h"
17#include "ARMSubtarget.h"
25#include "llvm/IR/Constants.h"
26#include "llvm/IR/Function.h"
27#include "llvm/IR/LLVMContext.h"
31
32namespace llvm {
34}
35
36using namespace llvm;
37
39 : IsThumb1Only(STI.isThumb1Only()) {}
40
43 const MachineFunction &MF) const {
44 if (!IsThumb1Only)
46
47 if (ARM::tGPRRegClass.hasSubClassEq(RC))
48 return &ARM::tGPRRegClass;
50}
51
54 const DebugLoc &dl, unsigned DestReg,
55 unsigned SubIdx, int Val,
56 ARMCC::CondCodes Pred, unsigned PredReg,
57 unsigned MIFlags) {
58 MachineFunction &MF = *MBB.getParent();
59 const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
60 const TargetInstrInfo &TII = *STI.getInstrInfo();
63 Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), Val);
64 unsigned Idx = ConstantPool->getConstantPoolIndex(C, Align(4));
65
66 BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRpci))
67 .addReg(DestReg, getDefRegState(true), SubIdx)
68 .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg)
69 .setMIFlags(MIFlags);
70}
71
74 const DebugLoc &dl, unsigned DestReg,
75 unsigned SubIdx, int Val,
76 ARMCC::CondCodes Pred, unsigned PredReg,
77 unsigned MIFlags) {
78 MachineFunction &MF = *MBB.getParent();
82 Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), Val);
83 unsigned Idx = ConstantPool->getConstantPoolIndex(C, Align(4));
84
85 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2LDRpci))
86 .addReg(DestReg, getDefRegState(true), SubIdx)
89 .setMIFlags(MIFlags);
90}
91
92/// emitLoadConstPool - Emits a load from constpool to materialize the
93/// specified immediate.
96 const DebugLoc &dl, Register DestReg, unsigned SubIdx, int Val,
97 ARMCC::CondCodes Pred, Register PredReg, unsigned MIFlags) const {
98 MachineFunction &MF = *MBB.getParent();
99 const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
100 if (STI.isThumb1Only()) {
101 assert((DestReg.isVirtual() || isARMLowRegister(DestReg)) &&
102 "Thumb1 does not have ldr to high register");
103 return emitThumb1LoadConstPool(MBB, MBBI, dl, DestReg, SubIdx, Val, Pred,
104 PredReg, MIFlags);
105 }
106 return emitThumb2LoadConstPool(MBB, MBBI, dl, DestReg, SubIdx, Val, Pred,
107 PredReg, MIFlags);
108}
109
110/// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize a
111/// destreg = basereg + immediate in Thumb code. Materialize the immediate in a
112/// register using mov / mvn (armv6-M >) sequences, movs / lsls / adds / lsls /
113/// adds / lsls / adds sequences (armv6-M) or load the immediate from a
114/// constpool entry.
117 const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes,
118 bool CanChangeCC, const TargetInstrInfo &TII,
119 const ARMBaseRegisterInfo &MRI, unsigned MIFlags = MachineInstr::NoFlags) {
120 MachineFunction &MF = *MBB.getParent();
121 const ARMSubtarget &ST = MF.getSubtarget<ARMSubtarget>();
122
123 // Use a single sp-relative add if the immediate is small enough.
124 if (BaseReg == ARM::SP &&
125 (DestReg.isVirtual() || isARMLowRegister(DestReg)) && NumBytes >= 0 &&
126 NumBytes <= 1020 && (NumBytes % 4) == 0) {
127 BuildMI(MBB, MBBI, dl, TII.get(ARM::tADDrSPi), DestReg)
128 .addReg(ARM::SP)
129 .addImm(NumBytes / 4)
131 .setMIFlags(MIFlags);
132 return;
133 }
134
135 bool isHigh = DestReg.isVirtual() || !isARMLowRegister(DestReg) ||
136 (BaseReg != 0 && !isARMLowRegister(BaseReg));
137 bool isSub = false;
138 // Subtract doesn't have high register version. Load the negative value
139 // if either base or dest register is a high register. Also, if do not
140 // issue sub as part of the sequence if condition register is to be
141 // preserved.
142 if (NumBytes < 0 && !isHigh && CanChangeCC) {
143 isSub = true;
144 NumBytes = -NumBytes;
145 }
146 Register LdReg = DestReg;
147 if (DestReg == ARM::SP)
148 assert(BaseReg == ARM::SP && "Unexpected!");
149 if (!DestReg.isVirtual() && !isARMLowRegister(DestReg))
150 LdReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass);
151
152 if (NumBytes <= 255 && NumBytes >= 0 && CanChangeCC) {
153 BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)
154 .add(t1CondCodeOp())
155 .addImm(NumBytes)
156 .setMIFlags(MIFlags);
157 } else if (NumBytes < 0 && NumBytes >= -255 && CanChangeCC) {
158 BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg)
159 .add(t1CondCodeOp())
160 .addImm(NumBytes)
161 .setMIFlags(MIFlags);
162 BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg)
163 .add(t1CondCodeOp())
164 .addReg(LdReg, RegState::Kill)
165 .setMIFlags(MIFlags);
166 } else if (ST.genExecuteOnly()) {
167 if (ST.useMovt()) {
168 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi32imm ), LdReg)
169 .addImm(NumBytes)
170 .setMIFlags(MIFlags);
171 } else if (!CanChangeCC) {
172 // tMOVi32imm is lowered to a sequence of flag-setting instructions, so
173 // if CPSR is live we need to save and restore CPSR around it.
174 // TODO Try inserting the tMOVi32imm at an earlier point, where CPSR is
175 // dead.
176 bool LiveCpsr = false, CpsrWrite = false;
177 auto isCpsr = [](auto &MO) { return MO.getReg() == ARM::CPSR; };
178 for (auto Iter = MBBI; Iter != MBB.instr_end(); ++Iter) {
179 // If CPSR is used after this instruction (and there's not a def before
180 // that) then CPSR is live.
181 if (any_of(Iter->all_uses(), isCpsr)) {
182 LiveCpsr = true;
183 break;
184 }
185 if (any_of(Iter->all_defs(), isCpsr)) {
186 CpsrWrite = true;
187 break;
188 }
189 }
190 // If there's no use or def of CPSR then it may be live if it's a
191 // live-out value.
192 auto liveOutIsCpsr = [](auto &Out) { return Out.PhysReg == ARM::CPSR; };
193 if (!LiveCpsr && !CpsrWrite)
194 LiveCpsr = any_of(MBB.liveouts(), liveOutIsCpsr);
195
196 Register CPSRSaveReg;
197 unsigned APSREncoding;
198 if (LiveCpsr) {
199 CPSRSaveReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass);
200 APSREncoding =
201 ARMSysReg::lookupMClassSysRegByName("apsr_nzcvq")->Encoding;
202 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MRS_M), CPSRSaveReg)
203 .addImm(APSREncoding)
205 .addReg(ARM::CPSR, RegState::Implicit);
206 }
207 BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi32imm), LdReg)
208 .addImm(NumBytes)
209 .setMIFlags(MIFlags);
210 if (LiveCpsr) {
211 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MSR_M))
212 .addImm(APSREncoding)
213 .addReg(CPSRSaveReg, RegState::Kill)
215 }
216 } else {
217 BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi32imm), LdReg)
218 .addImm(NumBytes)
219 .setMIFlags(MIFlags);
220 }
221 } else
222 MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes, ARMCC::AL, 0,
223 MIFlags);
224
225 // Emit add / sub.
226 int Opc = (isSub) ? ARM::tSUBrr
227 : ((isHigh || !CanChangeCC) ? ARM::tADDhirr : ARM::tADDrr);
228 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
229 if (Opc != ARM::tADDhirr)
230 MIB = MIB.add(t1CondCodeOp());
231 if (DestReg == ARM::SP || isSub)
232 MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill);
233 else
234 MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill);
235 MIB.add(predOps(ARMCC::AL));
236}
237
238/// emitThumbRegPlusImmediate - Emits a series of instructions to materialize
239/// a destreg = basereg + immediate in Thumb code. Tries a series of ADDs or
240/// SUBs first, and uses a constant pool value if the instruction sequence would
241/// be too long. This is allowed to modify the condition flags.
244 const DebugLoc &dl, Register DestReg,
245 Register BaseReg, int NumBytes,
246 const TargetInstrInfo &TII,
247 const ARMBaseRegisterInfo &MRI,
248 unsigned MIFlags) {
249 bool isSub = NumBytes < 0;
250 unsigned Bytes = (unsigned)NumBytes;
251 if (isSub) Bytes = -NumBytes;
252
253 int CopyOpc = 0;
254 unsigned CopyBits = 0;
255 unsigned CopyScale = 1;
256 bool CopyNeedsCC = false;
257 int ExtraOpc = 0;
258 unsigned ExtraBits = 0;
259 unsigned ExtraScale = 1;
260 bool ExtraNeedsCC = false;
261
262 // Strategy:
263 // We need to select two types of instruction, maximizing the available
264 // immediate range of each. The instructions we use will depend on whether
265 // DestReg and BaseReg are low, high or the stack pointer.
266 // * CopyOpc - DestReg = BaseReg + imm
267 // This will be emitted once if DestReg != BaseReg, and never if
268 // DestReg == BaseReg.
269 // * ExtraOpc - DestReg = DestReg + imm
270 // This will be emitted as many times as necessary to add the
271 // full immediate.
272 // If the immediate ranges of these instructions are not large enough to cover
273 // NumBytes with a reasonable number of instructions, we fall back to using a
274 // value loaded from a constant pool.
275 if (DestReg == ARM::SP) {
276 if (BaseReg == ARM::SP) {
277 // sp -> sp
278 // Already in right reg, no copy needed
279 } else {
280 // low -> sp or high -> sp
281 CopyOpc = ARM::tMOVr;
282 CopyBits = 0;
283 }
284 ExtraOpc = isSub ? ARM::tSUBspi : ARM::tADDspi;
285 ExtraBits = 7;
286 ExtraScale = 4;
287 } else if (isARMLowRegister(DestReg)) {
288 if (BaseReg == ARM::SP) {
289 // sp -> low
290 assert(!isSub && "Thumb1 does not have tSUBrSPi");
291 CopyOpc = ARM::tADDrSPi;
292 CopyBits = 8;
293 CopyScale = 4;
294 } else if (DestReg == BaseReg) {
295 // low -> same low
296 // Already in right reg, no copy needed
297 } else if (isARMLowRegister(BaseReg)) {
298 // low -> different low
299 CopyOpc = isSub ? ARM::tSUBi3 : ARM::tADDi3;
300 CopyBits = 3;
301 CopyNeedsCC = true;
302 } else {
303 // high -> low
304 CopyOpc = ARM::tMOVr;
305 CopyBits = 0;
306 }
307 ExtraOpc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
308 ExtraBits = 8;
309 ExtraNeedsCC = true;
310 } else /* DestReg is high */ {
311 if (DestReg == BaseReg) {
312 // high -> same high
313 // Already in right reg, no copy needed
314 } else {
315 // {low,high,sp} -> high
316 CopyOpc = ARM::tMOVr;
317 CopyBits = 0;
318 }
319 ExtraOpc = 0;
320 }
321
322 // We could handle an unaligned immediate with an unaligned copy instruction
323 // and an aligned extra instruction, but this case is not currently needed.
324 assert(((Bytes & 3) == 0 || ExtraScale == 1) &&
325 "Unaligned offset, but all instructions require alignment");
326
327 unsigned CopyRange = ((1 << CopyBits) - 1) * CopyScale;
328 // If we would emit the copy with an immediate of 0, just use tMOVr.
329 if (CopyOpc && Bytes < CopyScale) {
330 CopyOpc = ARM::tMOVr;
331 CopyScale = 1;
332 CopyNeedsCC = false;
333 CopyRange = 0;
334 }
335 unsigned ExtraRange = ((1 << ExtraBits) - 1) * ExtraScale; // per instruction
336 unsigned RequiredCopyInstrs = CopyOpc ? 1 : 0;
337 unsigned RangeAfterCopy = (CopyRange > Bytes) ? 0 : (Bytes - CopyRange);
338
339 // We could handle this case when the copy instruction does not require an
340 // aligned immediate, but we do not currently do this.
341 assert(RangeAfterCopy % ExtraScale == 0 &&
342 "Extra instruction requires immediate to be aligned");
343
344 unsigned RequiredExtraInstrs;
345 if (ExtraRange)
346 RequiredExtraInstrs = alignTo(RangeAfterCopy, ExtraRange) / ExtraRange;
347 else if (RangeAfterCopy > 0)
348 // We need an extra instruction but none is available
349 RequiredExtraInstrs = 1000000;
350 else
351 RequiredExtraInstrs = 0;
352 unsigned RequiredInstrs = RequiredCopyInstrs + RequiredExtraInstrs;
353 unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2;
354
355 // Use a constant pool, if the sequence of ADDs/SUBs is too expensive.
356 if (RequiredInstrs > Threshold) {
358 DestReg, BaseReg, NumBytes, true,
359 TII, MRI, MIFlags);
360 return;
361 }
362
363 // Emit zero or one copy instructions
364 if (CopyOpc) {
365 unsigned CopyImm = std::min(Bytes, CopyRange) / CopyScale;
366 Bytes -= CopyImm * CopyScale;
367
368 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(CopyOpc), DestReg);
369 if (CopyNeedsCC)
370 MIB = MIB.add(t1CondCodeOp());
371 MIB.addReg(BaseReg, RegState::Kill);
372 if (CopyOpc != ARM::tMOVr) {
373 MIB.addImm(CopyImm);
374 }
375 MIB.setMIFlags(MIFlags).add(predOps(ARMCC::AL));
376
377 BaseReg = DestReg;
378 }
379
380 // Emit zero or more in-place add/sub instructions
381 while (Bytes) {
382 unsigned ExtraImm = std::min(Bytes, ExtraRange) / ExtraScale;
383 Bytes -= ExtraImm * ExtraScale;
384
385 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(ExtraOpc), DestReg);
386 if (ExtraNeedsCC)
387 MIB = MIB.add(t1CondCodeOp());
388 MIB.addReg(BaseReg)
389 .addImm(ExtraImm)
391 .setMIFlags(MIFlags);
392 }
393}
394
395static void removeOperands(MachineInstr &MI, unsigned i) {
396 unsigned Op = i;
397 for (unsigned e = MI.getNumOperands(); i != e; ++i)
398 MI.removeOperand(Op);
399}
400
401/// convertToNonSPOpcode - Change the opcode to the non-SP version, because
402/// we're replacing the frame index with a non-SP register.
403static unsigned convertToNonSPOpcode(unsigned Opcode) {
404 switch (Opcode) {
405 case ARM::tLDRspi:
406 return ARM::tLDRi;
407
408 case ARM::tSTRspi:
409 return ARM::tSTRi;
410 }
411
412 return Opcode;
413}
414
416 unsigned FrameRegIdx,
417 Register FrameReg, int &Offset,
418 const ARMBaseInstrInfo &TII) const {
419 MachineInstr &MI = *II;
420 MachineBasicBlock &MBB = *MI.getParent();
421 MachineFunction &MF = *MBB.getParent();
422 assert(MBB.getParent()->getSubtarget<ARMSubtarget>().isThumb1Only() &&
423 "This isn't needed for thumb2!");
424 DebugLoc dl = MI.getDebugLoc();
425 MachineInstrBuilder MIB(*MBB.getParent(), &MI);
426 unsigned Opcode = MI.getOpcode();
427 const MCInstrDesc &Desc = MI.getDesc();
428 unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
429
430 if (Opcode == ARM::tADDframe) {
431 Offset += MI.getOperand(FrameRegIdx+1).getImm();
432 Register DestReg = MI.getOperand(0).getReg();
433
434 emitThumbRegPlusImmediate(MBB, II, dl, DestReg, FrameReg, Offset, TII,
435 *this);
436 MBB.erase(II);
437 return true;
438 } else {
440 llvm_unreachable("Unsupported addressing mode!");
441
442 unsigned ImmIdx = FrameRegIdx + 1;
443 int InstrOffs = MI.getOperand(ImmIdx).getImm();
444 unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5;
445 unsigned Scale = 4;
446
447 Offset += InstrOffs * Scale;
448 assert((Offset & (Scale - 1)) == 0 && "Can't encode this offset!");
449
450 // Common case: small offset, fits into instruction.
451 MachineOperand &ImmOp = MI.getOperand(ImmIdx);
452 int ImmedOffset = Offset / Scale;
453 unsigned Mask = (1 << NumBits) - 1;
454
455 if ((unsigned)Offset <= Mask * Scale) {
456 // Replace the FrameIndex with the frame register (e.g., sp).
457 Register DestReg = FrameReg;
458
459 // In case FrameReg is a high register, move it to a low reg to ensure it
460 // can be used as an operand.
461 if (ARM::hGPRRegClass.contains(FrameReg) && FrameReg != ARM::SP) {
462 DestReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass);
463 BuildMI(MBB, II, dl, TII.get(ARM::tMOVr), DestReg)
464 .addReg(FrameReg)
466 }
467
468 MI.getOperand(FrameRegIdx).ChangeToRegister(DestReg, false);
469 ImmOp.ChangeToImmediate(ImmedOffset);
470
471 // If we're using a register where sp was stored, convert the instruction
472 // to the non-SP version.
473 unsigned NewOpc = convertToNonSPOpcode(Opcode);
474 if (NewOpc != Opcode && FrameReg != ARM::SP)
475 MI.setDesc(TII.get(NewOpc));
476
477 return true;
478 }
479
480 // The offset doesn't fit, but we may be able to put some of the offset into
481 // the ldr to simplify the generation of the rest of it.
482 NumBits = 5;
483 Mask = (1 << NumBits) - 1;
484 InstrOffs = 0;
485 auto &ST = MF.getSubtarget<ARMSubtarget>();
486 // If using the maximum ldr offset will put the rest into the range of a
487 // single sp-relative add then do so.
488 if (FrameReg == ARM::SP && Offset - (Mask * Scale) <= 1020) {
489 InstrOffs = Mask;
490 } else if (ST.genExecuteOnly()) {
491 // With execute-only the offset is generated either with movw+movt or an
492 // add+lsl sequence. If subtracting an offset will make the top half zero
493 // then that saves a movt or lsl+add. Otherwise if we don't have movw then
494 // we may be able to subtract a value such that it makes the bottom byte
495 // zero, saving an add.
496 unsigned BottomBits = (Offset / Scale) & Mask;
497 bool CanMakeBottomByteZero = ((Offset - BottomBits * Scale) & 0xff) == 0;
498 bool TopHalfZero = (Offset & 0xffff0000) == 0;
499 bool CanMakeTopHalfZero = ((Offset - Mask * Scale) & 0xffff0000) == 0;
500 if (!TopHalfZero && CanMakeTopHalfZero)
501 InstrOffs = Mask;
502 else if (!ST.useMovt() && CanMakeBottomByteZero)
503 InstrOffs = BottomBits;
504 }
505 ImmOp.ChangeToImmediate(InstrOffs);
506 Offset -= InstrOffs * Scale;
507 }
508
509 return Offset == 0;
510}
511
513 int64_t Offset) const {
514 const MachineFunction &MF = *MI.getParent()->getParent();
515 const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
516 if (!STI.isThumb1Only())
518
519 const ARMBaseInstrInfo &TII = *STI.getInstrInfo();
520 int Off = Offset; // ARM doesn't need the general 64-bit offsets
521 unsigned i = 0;
522
523 while (!MI.getOperand(i).isFI()) {
524 ++i;
525 assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
526 }
527 bool Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII);
528 assert (Done && "Unable to resolve frame index!");
529 (void)Done;
530}
531
533 int SPAdj, unsigned FIOperandNum,
534 RegScavenger *RS) const {
535 MachineInstr &MI = *II;
536 MachineBasicBlock &MBB = *MI.getParent();
537 MachineFunction &MF = *MBB.getParent();
538 const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
539 if (!STI.isThumb1Only())
540 return ARMBaseRegisterInfo::eliminateFrameIndex(II, SPAdj, FIOperandNum,
541 RS);
542
543 Register VReg;
544 const ARMBaseInstrInfo &TII = *STI.getInstrInfo();
545 DebugLoc dl = MI.getDebugLoc();
546 MachineInstrBuilder MIB(*MBB.getParent(), &MI);
547
548 Register FrameReg;
549 int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
550 const ARMFrameLowering *TFI = getFrameLowering(MF);
551 int Offset = TFI->ResolveFrameIndexReference(MF, FrameIndex, FrameReg, SPAdj);
552
553 // PEI::scavengeFrameVirtualRegs() cannot accurately track SPAdj because the
554 // call frame setup/destroy instructions have already been eliminated. That
555 // means the stack pointer cannot be used to access the emergency spill slot
556 // when !hasReservedCallFrame().
557#ifndef NDEBUG
558 if (RS && FrameReg == ARM::SP && RS->isScavengingFrameIndex(FrameIndex)){
560 "Cannot use SP to access the emergency spill slot in "
561 "functions without a reserved call frame");
563 "Cannot use SP to access the emergency spill slot in "
564 "functions with variable sized frame objects");
565 }
566#endif // NDEBUG
567
568 // Special handling of dbg_value instructions.
569 if (MI.isDebugValue()) {
570 MI.getOperand(FIOperandNum). ChangeToRegister(FrameReg, false /*isDef*/);
571 MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
572 return false;
573 }
574
575 // Modify MI as necessary to handle as much of 'Offset' as possible
577 "This eliminateFrameIndex only supports Thumb1!");
578 if (rewriteFrameIndex(MI, FIOperandNum, FrameReg, Offset, TII))
579 return true;
580
581 // If we get here, the immediate doesn't fit into the instruction. We folded
582 // as much as possible above, handle the rest, providing a register that is
583 // SP+LargeImm.
584 assert(Offset && "This code isn't needed if offset already handled!");
585
586 unsigned Opcode = MI.getOpcode();
587
588 // Remove predicate first.
589 int PIdx = MI.findFirstPredOperandIdx();
590 if (PIdx != -1)
591 removeOperands(MI, PIdx);
592
593 if (MI.mayLoad()) {
594 // Use the destination register to materialize sp + offset.
595 Register TmpReg = MI.getOperand(0).getReg();
596 bool UseRR = false;
597 if (Opcode == ARM::tLDRspi) {
598 if (FrameReg == ARM::SP || STI.genExecuteOnly())
599 emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg,
600 Offset, false, TII, *this);
601 else {
602 emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset);
603 if (!ARM::hGPRRegClass.contains(FrameReg)) {
604 UseRR = true;
605 } else {
606 // If FrameReg is a high register, add the reg values in a separate
607 // instruction as the load won't be able to access it.
608 BuildMI(MBB, II, dl, TII.get(ARM::tADDhirr), TmpReg)
609 .addReg(TmpReg)
610 .addReg(FrameReg)
612 }
613 }
614 } else {
615 emitThumbRegPlusImmediate(MBB, II, dl, TmpReg, FrameReg, Offset, TII,
616 *this);
617 }
618
619 MI.setDesc(TII.get(UseRR ? ARM::tLDRr : ARM::tLDRi));
620 MI.getOperand(FIOperandNum).ChangeToRegister(TmpReg, false, false, true);
621 if (UseRR) {
622 assert(!ARM::hGPRRegClass.contains(FrameReg) &&
623 "Thumb1 loads can't use high register");
624 // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame
625 // register. The offset is already handled in the vreg value.
626 MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false,
627 false);
628 }
629 } else if (MI.mayStore()) {
630 VReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass);
631 bool UseRR = false;
632
633 if (Opcode == ARM::tSTRspi) {
634 if (FrameReg == ARM::SP || STI.genExecuteOnly())
635 emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg,
636 Offset, false, TII, *this);
637 else {
638 emitLoadConstPool(MBB, II, dl, VReg, 0, Offset);
639 if (!ARM::hGPRRegClass.contains(FrameReg)) {
640 UseRR = true;
641 } else {
642 // If FrameReg is a high register, add the reg values in a separate
643 // instruction as the load won't be able to access it.
644 BuildMI(MBB, II, dl, TII.get(ARM::tADDhirr), VReg)
645 .addReg(VReg)
646 .addReg(FrameReg)
648 }
649 }
650 } else
651 emitThumbRegPlusImmediate(MBB, II, dl, VReg, FrameReg, Offset, TII,
652 *this);
653 MI.setDesc(TII.get(UseRR ? ARM::tSTRr : ARM::tSTRi));
654 MI.getOperand(FIOperandNum).ChangeToRegister(VReg, false, false, true);
655 if (UseRR) {
656 assert(!ARM::hGPRRegClass.contains(FrameReg) &&
657 "Thumb1 stores can't use high register");
658 // Use [reg, reg] addrmode. Replace the immediate operand w/ the frame
659 // register. The offset is already handled in the vreg value.
660 MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false,
661 false);
662 }
663 } else {
664 llvm_unreachable("Unexpected opcode!");
665 }
666
667 // Add predicate back if it's needed.
668 if (MI.isPredicable())
669 MIB.add(predOps(ARMCC::AL));
670 return false;
671}
672
673bool
676 // For Thumb1, the emergency spill slot must be some small positive
677 // offset from the base/stack pointer.
678 return false;
679 }
680 // For Thumb2, put the emergency spill slot next to FP.
681 return true;
682}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
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)
Definition Value.cpp:484
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...
static void removeOperands(MachineInstr &MI, unsigned i)
static void emitThumb1LoadConstPool(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, unsigned DestReg, unsigned SubIdx, int Val, ARMCC::CondCodes Pred, unsigned PredReg, unsigned MIFlags)
static void emitThumb2LoadConstPool(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, unsigned DestReg, unsigned SubIdx, int Val, ARMCC::CondCodes Pred, unsigned PredReg, unsigned MIFlags)
static unsigned convertToNonSPOpcode(unsigned Opcode)
convertToNonSPOpcode - Change the opcode to the non-SP version, because we're replacing the frame ind...
virtual 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
emitLoadConstPool - Emits a load from constpool to materialize the specified immediate.
bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS=nullptr) 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...
const ARMBaseInstrInfo * getInstrInfo() const override
bool isThumb1Only() const
const ARMFrameLowering * getFrameLowering() const override
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
Definition Constants.h:135
This is an important base class in LLVM.
Definition Constant.h:43
A debug info location.
Definition DebugLoc.h:126
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 & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
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 & 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.
Definition Register.h:20
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
TargetInstrInfo - Interface to description of machine instruction set.
virtual const TargetInstrInfo * getInstrInfo() const
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
cl::opt< bool > ReuseFrameIndexVals
@ Offset
Definition DWP.cpp:577
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
@ Done
Definition Threading.h:60
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.
Op::Description Desc
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
constexpr RegState 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...
DWARFExpression::Operation Op
static MachineOperand t1CondCodeOp(bool isDead=false)
Get the operand corresponding to the conditional code result for Thumb1.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
bool useFPForScavengingIndex(const MachineFunction &MF) const override
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.
bool eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS=nullptr) const override
const TargetRegisterClass * getLargestLegalSuperClass(const TargetRegisterClass *RC, const MachineFunction &MF) const override
ThumbRegisterInfo(const ARMSubtarget &STI)
void resolveFrameIndex(MachineInstr &MI, Register BaseReg, int64_t Offset) const override
bool rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, Register FrameReg, int &Offset, const ARMBaseInstrInfo &TII) const