LLVM 23.0.0git
Thumb2InstrInfo.cpp
Go to the documentation of this file.
1//===- Thumb2InstrInfo.cpp - Thumb-2 Instruction 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-2 implementation of the TargetInstrInfo class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "Thumb2InstrInfo.h"
15#include "ARMSubtarget.h"
26#include "llvm/IR/DebugLoc.h"
27#include "llvm/IR/Module.h"
28#include "llvm/MC/MCInst.h"
30#include "llvm/MC/MCInstrDesc.h"
34#include <cassert>
35
36using namespace llvm;
37
38static cl::opt<bool>
39OldT2IfCvt("old-thumb2-ifcvt", cl::Hidden,
40 cl::desc("Use old-style Thumb2 if-conversion heuristics"),
41 cl::init(false));
42
43static cl::opt<bool>
44PreferNoCSEL("prefer-no-csel", cl::Hidden,
45 cl::desc("Prefer predicated Move to CSEL"),
46 cl::init(false));
47
50
51/// Return the noop instruction to use for a noop.
53 return MCInstBuilder(ARM::tHINT).addImm(0).addImm(ARMCC::AL).addReg(0);
54}
55
56unsigned Thumb2InstrInfo::getUnindexedOpcode(unsigned Opc) const {
57 // FIXME
58 return 0;
59}
60
61void
63 MachineBasicBlock *NewDest) const {
64 MachineBasicBlock *MBB = Tail->getParent();
65 ARMFunctionInfo *AFI = MBB->getParent()->getInfo<ARMFunctionInfo>();
66 if (!AFI->hasITBlocks() || Tail->isBranch()) {
68 return;
69 }
70
71 // If the first instruction of Tail is predicated, we may have to update
72 // the IT instruction.
73 Register PredReg;
76 if (CC != ARMCC::AL)
77 // Expecting at least the t2IT instruction before it.
78 --MBBI;
79
80 // Actually replace the tail.
82
83 // Fix up IT.
84 if (CC != ARMCC::AL) {
86 unsigned Count = 4; // At most 4 instructions in an IT block.
87 while (Count && MBBI != E) {
88 if (MBBI->isDebugInstr()) {
89 --MBBI;
90 continue;
91 }
92 if (MBBI->getOpcode() == ARM::t2IT) {
93 unsigned Mask = MBBI->getOperand(1).getImm();
94 if (Count == 4)
95 MBBI->eraseFromParent();
96 else {
97 unsigned MaskOn = 1 << Count;
98 unsigned MaskOff = ~(MaskOn - 1);
99 MBBI->getOperand(1).setImm((Mask & MaskOff) | MaskOn);
100 }
101 return;
102 }
103 --MBBI;
104 --Count;
105 }
106
107 // Ctrl flow can reach here if branch folding is run before IT block
108 // formation pass.
109 }
110}
111
112bool
115 while (MBBI->isDebugInstr()) {
116 ++MBBI;
117 if (MBBI == MBB.end())
118 return false;
119 }
120
121 Register PredReg;
122 return getITInstrPredicate(*MBBI, PredReg) == ARMCC::AL;
123}
124
128 bool PreferFalse) const {
129 // Try to use the base optimizeSelect, which uses canFoldIntoMOVCC to fold the
130 // MOVCC into another instruction. If that fails on 8.1-M fall back to using a
131 // CSEL.
132 MachineInstr *RV = ARMBaseInstrInfo::optimizeSelect(MI, SeenMIs, PreferFalse);
133 if (!RV && getSubtarget().hasV8_1MMainlineOps() && !PreferNoCSEL) {
134 Register DestReg = MI.getOperand(0).getReg();
135
136 if (!DestReg.isVirtual())
137 return nullptr;
138
139 MachineInstrBuilder NewMI = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
140 get(ARM::t2CSEL), DestReg)
141 .add(MI.getOperand(2))
142 .add(MI.getOperand(1))
143 .add(MI.getOperand(3));
144 SeenMIs.insert(NewMI);
145 return NewMI;
146 }
147 return RV;
148}
149
152 const DebugLoc &DL, Register DestReg,
153 Register SrcReg, bool KillSrc,
154 bool RenamableDest, bool RenamableSrc) const {
155 // Handle SPR, DPR, and QPR copies.
156 if (!ARM::GPRRegClass.contains(DestReg, SrcReg))
157 return ARMBaseInstrInfo::copyPhysReg(MBB, I, DL, DestReg, SrcReg, KillSrc);
158
159 BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg)
160 .addReg(SrcReg, getKillRegState(KillSrc))
162}
163
166 Register SrcReg, bool isKill, int FI,
167 const TargetRegisterClass *RC,
168 Register VReg,
169 MachineInstr::MIFlag Flags) const {
170 DebugLoc DL;
171 if (I != MBB.end()) DL = I->getDebugLoc();
172
173 MachineFunction &MF = *MBB.getParent();
174 MachineFrameInfo &MFI = MF.getFrameInfo();
177 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
178
179 if (ARM::GPRRegClass.hasSubClassEq(RC)) {
180 BuildMI(MBB, I, DL, get(ARM::t2STRi12))
181 .addReg(SrcReg, getKillRegState(isKill))
182 .addFrameIndex(FI)
183 .addImm(0)
184 .addMemOperand(MMO)
186 return;
187 }
188
189 if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {
190 // Thumb2 STRD expects its dest-registers to be in rGPR. Not a problem for
191 // gsub_0, but needs an extra constraint for gsub_1 (which could be sp
192 // otherwise).
193 if (SrcReg.isVirtual()) {
194 MachineRegisterInfo *MRI = &MF.getRegInfo();
195 MRI->constrainRegClass(SrcReg, &ARM::GPRPairnospRegClass);
196 }
197
198 MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(ARM::t2STRDi8));
199 AddDReg(MIB, SrcReg, ARM::gsub_0, getKillRegState(isKill));
200 AddDReg(MIB, SrcReg, ARM::gsub_1, {});
202 return;
203 }
204
205 ARMBaseInstrInfo::storeRegToStackSlot(MBB, I, SrcReg, isKill, FI, RC,
206 Register());
207}
208
211 Register DestReg, int FI,
212 const TargetRegisterClass *RC,
213 Register VReg, unsigned SubReg,
214 MachineInstr::MIFlag Flags) const {
215 MachineFunction &MF = *MBB.getParent();
216 MachineFrameInfo &MFI = MF.getFrameInfo();
219 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
220 DebugLoc DL;
221 if (I != MBB.end()) DL = I->getDebugLoc();
222
223 if (ARM::GPRRegClass.hasSubClassEq(RC)) {
224 BuildMI(MBB, I, DL, get(ARM::t2LDRi12), DestReg)
225 .addFrameIndex(FI)
226 .addImm(0)
227 .addMemOperand(MMO)
229 return;
230 }
231
232 if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {
233 // Thumb2 LDRD expects its dest-registers to be in rGPR. Not a problem for
234 // gsub_0, but needs an extra constraint for gsub_1 (which could be sp
235 // otherwise).
236 if (DestReg.isVirtual()) {
237 MachineRegisterInfo *MRI = &MF.getRegInfo();
238 MRI->constrainRegClass(DestReg, &ARM::GPRPairnospRegClass);
239 }
240
241 MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(ARM::t2LDRDi8));
242 AddDReg(MIB, DestReg, ARM::gsub_0, RegState::DefineNoRead);
243 AddDReg(MIB, DestReg, ARM::gsub_1, RegState::DefineNoRead);
245
246 if (DestReg.isPhysical())
247 MIB.addReg(DestReg, RegState::ImplicitDefine);
248 return;
249 }
250
252}
253
254void Thumb2InstrInfo::expandLoadStackGuard(
256 MachineFunction &MF = *MI->getParent()->getParent();
257 Module &M = *MF.getFunction().getParent();
258
259 if (M.getStackProtectorGuard() == "tls") {
260 expandLoadStackGuardBase(MI, ARM::t2MRC, ARM::t2LDRi12);
261 return;
262 }
263
264 const auto *GV = cast<GlobalValue>((*MI->memoperands_begin())->getValue());
265 const ARMSubtarget &Subtarget = MF.getSubtarget<ARMSubtarget>();
266 bool IsPIC = MF.getTarget().isPositionIndependent();
267 if (Subtarget.isTargetELF() && !GV->isDSOLocal())
268 expandLoadStackGuardBase(MI, ARM::t2LDRLIT_ga_pcrel, ARM::t2LDRi12);
269 else if (!Subtarget.useMovt())
271 MI, IsPIC ? ARM::t2LDRLIT_ga_pcrel : ARM::tLDRLIT_ga_abs,
272 ARM::t2LDRi12);
273 else if (IsPIC)
274 expandLoadStackGuardBase(MI, ARM::t2MOV_ga_pcrel, ARM::t2LDRi12);
275 else
276 expandLoadStackGuardBase(MI, ARM::t2MOVi32imm, ARM::t2LDRi12);
277}
278
280 bool NewMI,
281 unsigned OpIdx1,
282 unsigned OpIdx2) const {
283 switch (MI.getOpcode()) {
284 case ARM::MVE_VMAXNMAf16:
285 case ARM::MVE_VMAXNMAf32:
286 case ARM::MVE_VMINNMAf16:
287 case ARM::MVE_VMINNMAf32:
288 // Don't allow predicated instructions to be commuted.
290 return nullptr;
291 }
292 return ARMBaseInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
293}
294
296 const MachineBasicBlock *MBB,
297 const MachineFunction &MF) const {
298 // BTI clearing instructions shall not take part in scheduling regions as
299 // they must stay in their intended place. Although PAC isn't BTI clearing,
300 // it can be transformed into PACBTI after the pre-RA Machine Scheduling
301 // has taken place, so its movement must also be restricted.
302 switch (MI.getOpcode()) {
303 case ARM::t2BTI:
304 case ARM::t2PAC:
305 case ARM::t2PACBTI:
306 case ARM::t2SG:
307 return true;
308 default:
309 break;
310 }
312}
313
316 const DebugLoc &dl, Register DestReg,
317 Register BaseReg, int NumBytes,
318 ARMCC::CondCodes Pred, Register PredReg,
319 const ARMBaseInstrInfo &TII,
320 unsigned MIFlags) {
321 if (NumBytes == 0 && DestReg != BaseReg) {
322 BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)
323 .addReg(BaseReg, RegState::Kill)
324 .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);
325 return;
326 }
327
328 bool isSub = NumBytes < 0;
329 if (isSub) NumBytes = -NumBytes;
330
331 // If profitable, use a movw or movt to materialize the offset.
332 // FIXME: Use the scavenger to grab a scratch register.
333 if (DestReg != ARM::SP && DestReg != BaseReg &&
334 NumBytes >= 4096 &&
335 ARM_AM::getT2SOImmVal(NumBytes) == -1) {
336 bool Fits = false;
337 if (NumBytes < 65536) {
338 // Use a movw to materialize the 16-bit constant.
339 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), DestReg)
340 .addImm(NumBytes)
341 .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);
342 Fits = true;
343 } else if ((NumBytes & 0xffff) == 0) {
344 // Use a movt to materialize the 32-bit constant.
345 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVTi16), DestReg)
346 .addReg(DestReg)
347 .addImm(NumBytes >> 16)
348 .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);
349 Fits = true;
350 }
351
352 if (Fits) {
353 if (isSub) {
354 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2SUBrr), DestReg)
355 .addReg(BaseReg)
356 .addReg(DestReg, RegState::Kill)
357 .add(predOps(Pred, PredReg))
358 .add(condCodeOp())
359 .setMIFlags(MIFlags);
360 } else {
361 // Here we know that DestReg is not SP but we do not
362 // know anything about BaseReg. t2ADDrr is an invalid
363 // instruction is SP is used as the second argument, but
364 // is fine if SP is the first argument. To be sure we
365 // do not generate invalid encoding, put BaseReg first.
366 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2ADDrr), DestReg)
367 .addReg(BaseReg)
368 .addReg(DestReg, RegState::Kill)
369 .add(predOps(Pred, PredReg))
370 .add(condCodeOp())
371 .setMIFlags(MIFlags);
372 }
373 return;
374 }
375 }
376
377 while (NumBytes) {
378 unsigned ThisVal = NumBytes;
379 unsigned Opc = 0;
380 if (DestReg == ARM::SP && BaseReg != ARM::SP) {
381 // mov sp, rn. Note t2MOVr cannot be used.
382 BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)
383 .addReg(BaseReg)
384 .setMIFlags(MIFlags)
386 BaseReg = ARM::SP;
387 continue;
388 }
389
390 assert((DestReg != ARM::SP || BaseReg == ARM::SP) &&
391 "Writing to SP, from other register.");
392
393 // Try to use T1, as it smaller
394 if ((DestReg == ARM::SP) && (ThisVal < ((1 << 7) - 1) * 4)) {
395 assert((ThisVal & 3) == 0 && "Stack update is not multiple of 4?");
396 Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;
397 BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
398 .addReg(BaseReg)
399 .addImm(ThisVal / 4)
400 .setMIFlags(MIFlags)
402 break;
403 }
404 bool HasCCOut = true;
405 int ImmIsT2SO = ARM_AM::getT2SOImmVal(ThisVal);
406 bool ToSP = DestReg == ARM::SP;
407 unsigned t2SUB = ToSP ? ARM::t2SUBspImm : ARM::t2SUBri;
408 unsigned t2ADD = ToSP ? ARM::t2ADDspImm : ARM::t2ADDri;
409 unsigned t2SUBi12 = ToSP ? ARM::t2SUBspImm12 : ARM::t2SUBri12;
410 unsigned t2ADDi12 = ToSP ? ARM::t2ADDspImm12 : ARM::t2ADDri12;
411 Opc = isSub ? t2SUB : t2ADD;
412 // Prefer T2: sub rd, rn, so_imm | sub sp, sp, so_imm
413 if (ImmIsT2SO != -1) {
414 NumBytes = 0;
415 } else if (ThisVal < 4096) {
416 // Prefer T3 if can make it in a single go: subw rd, rn, imm12 | subw sp,
417 // sp, imm12
418 Opc = isSub ? t2SUBi12 : t2ADDi12;
419 HasCCOut = false;
420 NumBytes = 0;
421 } else {
422 // Use one T2 instruction to reduce NumBytes
423 // FIXME: Move this to ARMAddressingModes.h?
424 unsigned RotAmt = llvm::countl_zero(ThisVal);
425 ThisVal = ThisVal & llvm::rotr<uint32_t>(0xff000000U, RotAmt);
426 NumBytes &= ~ThisVal;
427 assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 &&
428 "Bit extraction didn't work?");
429 }
430
431 // Build the new ADD / SUB.
432 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
433 .addReg(BaseReg, RegState::Kill)
434 .addImm(ThisVal)
436 .setMIFlags(MIFlags);
437 if (HasCCOut)
438 MIB.add(condCodeOp());
439
440 BaseReg = DestReg;
441 }
442}
443
444static unsigned
445negativeOffsetOpcode(unsigned opcode)
446{
447 switch (opcode) {
448 case ARM::t2LDRi12: return ARM::t2LDRi8;
449 case ARM::t2LDRHi12: return ARM::t2LDRHi8;
450 case ARM::t2LDRBi12: return ARM::t2LDRBi8;
451 case ARM::t2LDRSHi12: return ARM::t2LDRSHi8;
452 case ARM::t2LDRSBi12: return ARM::t2LDRSBi8;
453 case ARM::t2STRi12: return ARM::t2STRi8;
454 case ARM::t2STRBi12: return ARM::t2STRBi8;
455 case ARM::t2STRHi12: return ARM::t2STRHi8;
456 case ARM::t2PLDi12: return ARM::t2PLDi8;
457 case ARM::t2PLDWi12: return ARM::t2PLDWi8;
458 case ARM::t2PLIi12: return ARM::t2PLIi8;
459
460 case ARM::t2LDRi8:
461 case ARM::t2LDRHi8:
462 case ARM::t2LDRBi8:
463 case ARM::t2LDRSHi8:
464 case ARM::t2LDRSBi8:
465 case ARM::t2STRi8:
466 case ARM::t2STRBi8:
467 case ARM::t2STRHi8:
468 case ARM::t2PLDi8:
469 case ARM::t2PLDWi8:
470 case ARM::t2PLIi8:
471 return opcode;
472
473 default:
474 llvm_unreachable("unknown thumb2 opcode.");
475 }
476}
477
478static unsigned
479positiveOffsetOpcode(unsigned opcode)
480{
481 switch (opcode) {
482 case ARM::t2LDRi8: return ARM::t2LDRi12;
483 case ARM::t2LDRHi8: return ARM::t2LDRHi12;
484 case ARM::t2LDRBi8: return ARM::t2LDRBi12;
485 case ARM::t2LDRSHi8: return ARM::t2LDRSHi12;
486 case ARM::t2LDRSBi8: return ARM::t2LDRSBi12;
487 case ARM::t2STRi8: return ARM::t2STRi12;
488 case ARM::t2STRBi8: return ARM::t2STRBi12;
489 case ARM::t2STRHi8: return ARM::t2STRHi12;
490 case ARM::t2PLDi8: return ARM::t2PLDi12;
491 case ARM::t2PLDWi8: return ARM::t2PLDWi12;
492 case ARM::t2PLIi8: return ARM::t2PLIi12;
493
494 case ARM::t2LDRi12:
495 case ARM::t2LDRHi12:
496 case ARM::t2LDRBi12:
497 case ARM::t2LDRSHi12:
498 case ARM::t2LDRSBi12:
499 case ARM::t2STRi12:
500 case ARM::t2STRBi12:
501 case ARM::t2STRHi12:
502 case ARM::t2PLDi12:
503 case ARM::t2PLDWi12:
504 case ARM::t2PLIi12:
505 return opcode;
506
507 default:
508 llvm_unreachable("unknown thumb2 opcode.");
509 }
510}
511
512static unsigned
513immediateOffsetOpcode(unsigned opcode)
514{
515 switch (opcode) {
516 case ARM::t2LDRs: return ARM::t2LDRi12;
517 case ARM::t2LDRHs: return ARM::t2LDRHi12;
518 case ARM::t2LDRBs: return ARM::t2LDRBi12;
519 case ARM::t2LDRSHs: return ARM::t2LDRSHi12;
520 case ARM::t2LDRSBs: return ARM::t2LDRSBi12;
521 case ARM::t2STRs: return ARM::t2STRi12;
522 case ARM::t2STRBs: return ARM::t2STRBi12;
523 case ARM::t2STRHs: return ARM::t2STRHi12;
524 case ARM::t2PLDs: return ARM::t2PLDi12;
525 case ARM::t2PLDWs: return ARM::t2PLDWi12;
526 case ARM::t2PLIs: return ARM::t2PLIi12;
527
528 case ARM::t2LDRi12:
529 case ARM::t2LDRHi12:
530 case ARM::t2LDRBi12:
531 case ARM::t2LDRSHi12:
532 case ARM::t2LDRSBi12:
533 case ARM::t2STRi12:
534 case ARM::t2STRBi12:
535 case ARM::t2STRHi12:
536 case ARM::t2PLDi12:
537 case ARM::t2PLDWi12:
538 case ARM::t2PLIi12:
539 case ARM::t2LDRi8:
540 case ARM::t2LDRHi8:
541 case ARM::t2LDRBi8:
542 case ARM::t2LDRSHi8:
543 case ARM::t2LDRSBi8:
544 case ARM::t2STRi8:
545 case ARM::t2STRBi8:
546 case ARM::t2STRHi8:
547 case ARM::t2PLDi8:
548 case ARM::t2PLDWi8:
549 case ARM::t2PLIi8:
550 return opcode;
551
552 default:
553 llvm_unreachable("unknown thumb2 opcode.");
554 }
555}
556
557bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
558 Register FrameReg, int &Offset,
559 const ARMBaseInstrInfo &TII,
560 const TargetRegisterInfo *TRI) {
561 unsigned Opcode = MI.getOpcode();
562 const MCInstrDesc &Desc = MI.getDesc();
563 unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
564 bool isSub = false;
565
566 MachineFunction &MF = *MI.getParent()->getParent();
567 const TargetRegisterClass *RegClass = TII.getRegClass(Desc, FrameRegIdx);
568
569 // Memory operands in inline assembly always use AddrModeT2_i12.
570 if (Opcode == ARM::INLINEASM || Opcode == ARM::INLINEASM_BR)
571 AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2?
572
573 const bool IsSP = Opcode == ARM::t2ADDspImm12 || Opcode == ARM::t2ADDspImm;
574 if (IsSP || Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) {
575 Offset += MI.getOperand(FrameRegIdx+1).getImm();
576
577 Register PredReg;
578 if (Offset == 0 && getInstrPredicate(MI, PredReg) == ARMCC::AL &&
579 !MI.definesRegister(ARM::CPSR, /*TRI=*/nullptr)) {
580 // Turn it into a move.
581 MI.setDesc(TII.get(ARM::tMOVr));
582 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
583 // Remove offset and remaining explicit predicate operands.
584 do MI.removeOperand(FrameRegIdx+1);
585 while (MI.getNumOperands() > FrameRegIdx+1);
586 MachineInstrBuilder MIB(*MI.getParent()->getParent(), &MI);
587 MIB.add(predOps(ARMCC::AL));
588 return true;
589 }
590
591 bool HasCCOut = (Opcode != ARM::t2ADDspImm12 && Opcode != ARM::t2ADDri12);
592
593 if (Offset < 0) {
594 Offset = -Offset;
595 isSub = true;
596 MI.setDesc(IsSP ? TII.get(ARM::t2SUBspImm) : TII.get(ARM::t2SUBri));
597 } else {
598 MI.setDesc(IsSP ? TII.get(ARM::t2ADDspImm) : TII.get(ARM::t2ADDri));
599 }
600
601 // Common case: small offset, fits into instruction.
602 if (ARM_AM::getT2SOImmVal(Offset) != -1) {
603 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
604 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
605 // Add cc_out operand if the original instruction did not have one.
606 if (!HasCCOut)
607 MI.addOperand(MachineOperand::CreateReg(0, false));
608 Offset = 0;
609 return true;
610 }
611 // Another common case: imm12.
612 if (Offset < 4096 &&
613 (!HasCCOut || MI.getOperand(MI.getNumOperands()-1).getReg() == 0)) {
614 unsigned NewOpc = isSub ? IsSP ? ARM::t2SUBspImm12 : ARM::t2SUBri12
615 : IsSP ? ARM::t2ADDspImm12 : ARM::t2ADDri12;
616 MI.setDesc(TII.get(NewOpc));
617 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
618 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
619 // Remove the cc_out operand.
620 if (HasCCOut)
621 MI.removeOperand(MI.getNumOperands()-1);
622 Offset = 0;
623 return true;
624 }
625
626 // Otherwise, extract 8 adjacent bits from the immediate into this
627 // t2ADDri/t2SUBri.
628 unsigned RotAmt = llvm::countl_zero<unsigned>(Offset);
629 unsigned ThisImmVal = Offset & llvm::rotr<uint32_t>(0xff000000U, RotAmt);
630
631 // We will handle these bits from offset, clear them.
632 Offset &= ~ThisImmVal;
633
634 assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 &&
635 "Bit extraction didn't work?");
636 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
637 // Add cc_out operand if the original instruction did not have one.
638 if (!HasCCOut)
639 MI.addOperand(MachineOperand::CreateReg(0, false));
640 } else {
641 // AddrMode4 and AddrMode6 cannot handle any offset.
643 return false;
644
645 // AddrModeT2_so cannot handle any offset. If there is no offset
646 // register then we change to an immediate version.
647 unsigned NewOpc = Opcode;
649 Register OffsetReg = MI.getOperand(FrameRegIdx + 1).getReg();
650 if (OffsetReg != 0) {
651 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
652 return Offset == 0;
653 }
654
655 MI.removeOperand(FrameRegIdx+1);
656 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0);
657 NewOpc = immediateOffsetOpcode(Opcode);
659 }
660
661 unsigned NumBits = 0;
662 unsigned Scale = 1;
665 // i8 supports only negative, and i12 supports only positive, so
666 // based on Offset sign convert Opcode to the appropriate
667 // instruction
668 Offset += MI.getOperand(FrameRegIdx+1).getImm();
669 if (Offset < 0) {
670 NewOpc = negativeOffsetOpcode(Opcode);
671 NumBits = 8;
672 isSub = true;
673 Offset = -Offset;
674 } else {
675 NewOpc = positiveOffsetOpcode(Opcode);
676 NumBits = 12;
677 }
678 } else if (AddrMode == ARMII::AddrMode5) {
679 // VFP address mode.
680 const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1);
681 int InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm());
682 if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub)
683 InstrOffs *= -1;
684 NumBits = 8;
685 Scale = 4;
686 Offset += InstrOffs * 4;
687 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
688 if (Offset < 0) {
689 Offset = -Offset;
690 isSub = true;
691 }
692 } else if (AddrMode == ARMII::AddrMode5FP16) {
693 // VFP address mode.
694 const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1);
695 int InstrOffs = ARM_AM::getAM5FP16Offset(OffOp.getImm());
697 InstrOffs *= -1;
698 NumBits = 8;
699 Scale = 2;
700 Offset += InstrOffs * 2;
701 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
702 if (Offset < 0) {
703 Offset = -Offset;
704 isSub = true;
705 }
706 } else if (AddrMode == ARMII::AddrModeT2_i7s4 ||
709 Offset += MI.getOperand(FrameRegIdx + 1).getImm();
710 unsigned OffsetMask;
711 switch (AddrMode) {
712 case ARMII::AddrModeT2_i7s4: NumBits = 9; OffsetMask = 0x3; break;
713 case ARMII::AddrModeT2_i7s2: NumBits = 8; OffsetMask = 0x1; break;
714 default: NumBits = 7; OffsetMask = 0x0; break;
715 }
716 // MCInst operand expects already scaled value.
717 Scale = 1;
718 assert((Offset & OffsetMask) == 0 && "Can't encode this offset!");
719 (void)OffsetMask; // squash unused-variable warning at -NDEBUG
720 } else if (AddrMode == ARMII::AddrModeT2_i8s4) {
721 Offset += MI.getOperand(FrameRegIdx + 1).getImm();
722 NumBits = 8 + 2;
723 // MCInst operand expects already scaled value.
724 Scale = 1;
725 assert((Offset & 3) == 0 && "Can't encode this offset!");
726 } else if (AddrMode == ARMII::AddrModeT2_ldrex) {
727 Offset += MI.getOperand(FrameRegIdx + 1).getImm() * 4;
728 NumBits = 8; // 8 bits scaled by 4
729 Scale = 4;
730 assert((Offset & 3) == 0 && "Can't encode this offset!");
731 } else {
732 llvm_unreachable("Unsupported addressing mode!");
733 }
734
735 if (NewOpc != Opcode)
736 MI.setDesc(TII.get(NewOpc));
737
738 MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1);
739
740 // Attempt to fold address computation
741 // Common case: small offset, fits into instruction. We need to make sure
742 // the register class is correct too, for instructions like the MVE
743 // VLDRH.32, which only accepts low tGPR registers.
744 int ImmedOffset = Offset / Scale;
745 unsigned Mask = (1 << NumBits) - 1;
746 if ((unsigned)Offset <= Mask * Scale &&
747 (FrameReg.isVirtual() || RegClass->contains(FrameReg))) {
748 if (FrameReg.isVirtual()) {
749 // Make sure the register class for the virtual register is correct
750 MachineRegisterInfo *MRI = &MF.getRegInfo();
751 if (!MRI->constrainRegClass(FrameReg, RegClass))
752 llvm_unreachable("Unable to constrain virtual register class.");
753 }
754
755 // Replace the FrameIndex with fp/sp
756 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
757 if (isSub) {
759 // FIXME: Not consistent.
760 ImmedOffset |= 1 << NumBits;
761 else
762 ImmedOffset = -ImmedOffset;
763 }
764 ImmOp.ChangeToImmediate(ImmedOffset);
765 Offset = 0;
766 return true;
767 }
768
769 // Otherwise, offset doesn't fit. Pull in what we can to simplify
770 ImmedOffset = ImmedOffset & Mask;
771 if (isSub) {
773 // FIXME: Not consistent.
774 ImmedOffset |= 1 << NumBits;
775 else {
776 ImmedOffset = -ImmedOffset;
777 if (ImmedOffset == 0)
778 // Change the opcode back if the encoded offset is zero.
779 MI.setDesc(TII.get(positiveOffsetOpcode(NewOpc)));
780 }
781 }
782 ImmOp.ChangeToImmediate(ImmedOffset);
783 Offset &= ~(Mask*Scale);
784 }
785
786 Offset = (isSub) ? -Offset : Offset;
787 return Offset == 0 && (FrameReg.isVirtual() || RegClass->contains(FrameReg));
788}
789
791 Register &PredReg) {
792 unsigned Opc = MI.getOpcode();
793 if (Opc == ARM::tBcc || Opc == ARM::t2Bcc)
794 return ARMCC::AL;
795 return getInstrPredicate(MI, PredReg);
796}
797
799 const MCInstrDesc &MCID = MI.getDesc();
800
801 for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i)
802 if (ARM::isVpred(MCID.operands()[i].OperandType))
803 return i;
804
805 return -1;
806}
807
809 const MCInstrDesc &MCID = MI.getDesc();
810
811 for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i)
812 if (MCID.operands()[i].OperandType == ARM::OPERAND_VPRED_R)
813 return i + ARM::SUBOP_vpred_r_inactive;
814
815 return -1;
816}
817
819 Register &PredReg) {
820 int PIdx = findFirstVPTPredOperandIdx(MI);
821 if (PIdx == -1) {
822 PredReg = 0;
823 return ARMVCC::None;
824 }
825
826 PredReg = MI.getOperand(PIdx+1).getReg();
827 return (ARMVCC::VPTCodes)MI.getOperand(PIdx).getImm();
828}
829
831 assert(isVPTOpcode(Instr.getOpcode()) && "Not a VPST or VPT Instruction!");
832
833 MachineOperand &MaskOp = Instr.getOperand(0);
834 assert(MaskOp.isImm() && "Operand 0 is not the block mask of the VPT/VPST?!");
835
836 MachineBasicBlock::iterator Iter = ++Instr.getIterator(),
837 End = Instr.getParent()->end();
838
839 while (Iter != End && Iter->isDebugInstr())
840 ++Iter;
841
842 // Verify that the instruction after the VPT/VPST is predicated (it should
843 // be), and skip it.
844 assert(Iter != End && "Expected some instructions in any VPT block");
845 assert(
847 "VPT/VPST should be followed by an instruction with a 'then' predicate!");
848 ++Iter;
849
850 // Iterate over the predicated instructions, updating the BlockMask as we go.
852 while (Iter != End) {
853 if (Iter->isDebugInstr()) {
854 ++Iter;
855 continue;
856 }
858 if (Pred == ARMVCC::None)
859 break;
860 BlockMask = expandPredBlockMask(BlockMask, Pred);
861 ++Iter;
862 }
863
864 // Rewrite the BlockMask.
865 MaskOp.setImm((int64_t)(BlockMask));
866}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
#define I(x, y, z)
Definition MD5.cpp:57
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
static unsigned negativeOffsetOpcode(unsigned opcode)
static unsigned positiveOffsetOpcode(unsigned opcode)
static cl::opt< bool > OldT2IfCvt("old-thumb2-ifcvt", cl::Hidden, cl::desc("Use old-style Thumb2 if-conversion heuristics"), cl::init(false))
static cl::opt< bool > PreferNoCSEL("prefer-no-csel", cl::Hidden, cl::desc("Prefer predicated Move to CSEL"), cl::init(false))
static unsigned immediateOffsetOpcode(unsigned opcode)
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
MachineInstr * optimizeSelect(MachineInstr &MI, SmallPtrSetImpl< MachineInstr * > &SeenMIs, bool) const override
const MachineInstrBuilder & AddDReg(MachineInstrBuilder &MIB, unsigned Reg, unsigned SubIdx, RegState State) const
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
void expandLoadStackGuardBase(MachineBasicBlock::iterator MI, unsigned LoadImmOpc, unsigned LoadOpc) const
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
ARMBaseInstrInfo(const ARMSubtarget &STI, const ARMBaseRegisterInfo &TRI)
const ARMSubtarget & getSubtarget() const
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const override
Commutes the operands in the given instruction.
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
bool isTargetELF() const
A debug info location.
Definition DebugLoc.h:126
Module * getParent()
Get the module that this global value is contained inside of...
MCInstBuilder & addReg(MCRegister Reg)
Add a new register operand.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
Describe properties that are true of each instruction in the target description file.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
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.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
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 & addFrameIndex(int Idx) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
void setImm(int64_t immVal)
int64_t getImm() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
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 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)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
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
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
virtual void ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, MachineBasicBlock *NewDest) const
Delete the instruction OldInst and everything after it, replacing it with an unconditional branch to ...
bool isPositionIndependent() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
bool isLegalToSplitMBBAt(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const override
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
unsigned getUnindexedOpcode(unsigned Opc) const override
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const override
void ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, MachineBasicBlock *NewDest) const override
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
MachineInstr * optimizeSelect(MachineInstr &MI, SmallPtrSetImpl< MachineInstr * > &SeenMIs, bool) const override
Thumb2InstrInfo(const ARMSubtarget &STI)
MCInst getNop() const override
Return the noop instruction to use for a noop.
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
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned char getAM5FP16Offset(unsigned AM5Opc)
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
AddrOpc getAM5Op(unsigned AM5Opc)
AddrOpc getAM5FP16Op(unsigned AM5Opc)
unsigned char getAM5Offset(unsigned AM5Opc)
PredBlockMask
Mask values for IT and VPT Blocks, to be used by MCOperands.
bool isVpred(OperandType op)
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
Definition CallingConv.h:76
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
int findVPTInactiveOperandIdx(const MachineInstr &MI)
@ Offset
Definition DWP.cpp:573
constexpr T rotr(T V, int R)
Definition bit.h:399
int findFirstVPTPredOperandIdx(const MachineInstr &MI)
ARMVCC::VPTCodes getVPTInstrPredicate(const MachineInstr &MI, Register &PredReg)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Kill
The last use of a register.
constexpr RegState getKillRegState(bool B)
static bool isVPTOpcode(int Opc)
bool rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx, Register FrameReg, int &Offset, const ARMBaseInstrInfo &TII, const TargetRegisterInfo *TRI)
static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)
Get the operands corresponding to the given Pred value.
Op::Description Desc
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
Definition bit.h:263
ARMCC::CondCodes getITInstrPredicate(const MachineInstr &MI, Register &PredReg)
getITInstrPredicate - Valid only in Thumb2 mode.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
ARM::PredBlockMask expandPredBlockMask(ARM::PredBlockMask BlockMask, ARMVCC::VPTCodes Kind)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, Register &PredReg)
getInstrPredicate - If instruction is predicated, returns its predicate condition,...
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
void recomputeVPTBlockMask(MachineInstr &Instr)
void emitT2RegPlusImmediate(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)
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.