LLVM 20.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
49 : ARMBaseInstrInfo(STI) {}
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();
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)
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, MCRegister DestReg,
153 MCRegister 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 const TargetRegisterInfo *TRI,
169 Register VReg) const {
170 DebugLoc DL;
171 if (I != MBB.end()) DL = I->getDebugLoc();
172
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()) {
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), TRI);
200 AddDReg(MIB, SrcReg, ARM::gsub_1, 0, TRI);
202 return;
203 }
204
205 ARMBaseInstrInfo::storeRegToStackSlot(MBB, I, SrcReg, isKill, FI, RC, TRI,
206 Register());
207}
208
211 Register DestReg, int FI,
212 const TargetRegisterClass *RC,
213 const TargetRegisterInfo *TRI,
214 Register VReg) const {
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()) {
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, TRI);
243 AddDReg(MIB, DestReg, ARM::gsub_1, RegState::DefineNoRead, TRI);
245
246 if (DestReg.isPhysical())
247 MIB.addReg(DestReg, RegState::ImplicitDefine);
248 return;
249 }
250
252 Register());
253}
254
255void Thumb2InstrInfo::expandLoadStackGuard(
257 MachineFunction &MF = *MI->getParent()->getParent();
258 Module &M = *MF.getFunction().getParent();
259
260 if (M.getStackProtectorGuard() == "tls") {
261 expandLoadStackGuardBase(MI, ARM::t2MRC, ARM::t2LDRi12);
262 return;
263 }
264
265 const auto *GV = cast<GlobalValue>((*MI->memoperands_begin())->getValue());
266 const ARMSubtarget &Subtarget = MF.getSubtarget<ARMSubtarget>();
267 if (Subtarget.isTargetELF() && !GV->isDSOLocal())
268 expandLoadStackGuardBase(MI, ARM::t2LDRLIT_ga_pcrel, ARM::t2LDRi12);
269 else if (!Subtarget.useMovt())
270 expandLoadStackGuardBase(MI, ARM::tLDRLIT_ga_abs, ARM::t2LDRi12);
271 else if (MF.getTarget().isPositionIndependent())
272 expandLoadStackGuardBase(MI, ARM::t2MOV_ga_pcrel, ARM::t2LDRi12);
273 else
274 expandLoadStackGuardBase(MI, ARM::t2MOVi32imm, ARM::t2LDRi12);
275}
276
278 bool NewMI,
279 unsigned OpIdx1,
280 unsigned OpIdx2) const {
281 switch (MI.getOpcode()) {
282 case ARM::MVE_VMAXNMAf16:
283 case ARM::MVE_VMAXNMAf32:
284 case ARM::MVE_VMINNMAf16:
285 case ARM::MVE_VMINNMAf32:
286 // Don't allow predicated instructions to be commuted.
288 return nullptr;
289 }
290 return ARMBaseInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
291}
292
294 const MachineBasicBlock *MBB,
295 const MachineFunction &MF) const {
296 // BTI clearing instructions shall not take part in scheduling regions as
297 // they must stay in their intended place. Although PAC isn't BTI clearing,
298 // it can be transformed into PACBTI after the pre-RA Machine Scheduling
299 // has taken place, so its movement must also be restricted.
300 switch (MI.getOpcode()) {
301 case ARM::t2BTI:
302 case ARM::t2PAC:
303 case ARM::t2PACBTI:
304 case ARM::t2SG:
305 return true;
306 default:
307 break;
308 }
310}
311
314 const DebugLoc &dl, Register DestReg,
315 Register BaseReg, int NumBytes,
316 ARMCC::CondCodes Pred, Register PredReg,
317 const ARMBaseInstrInfo &TII,
318 unsigned MIFlags) {
319 if (NumBytes == 0 && DestReg != BaseReg) {
320 BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)
321 .addReg(BaseReg, RegState::Kill)
322 .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);
323 return;
324 }
325
326 bool isSub = NumBytes < 0;
327 if (isSub) NumBytes = -NumBytes;
328
329 // If profitable, use a movw or movt to materialize the offset.
330 // FIXME: Use the scavenger to grab a scratch register.
331 if (DestReg != ARM::SP && DestReg != BaseReg &&
332 NumBytes >= 4096 &&
333 ARM_AM::getT2SOImmVal(NumBytes) == -1) {
334 bool Fits = false;
335 if (NumBytes < 65536) {
336 // Use a movw to materialize the 16-bit constant.
337 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), DestReg)
338 .addImm(NumBytes)
339 .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);
340 Fits = true;
341 } else if ((NumBytes & 0xffff) == 0) {
342 // Use a movt to materialize the 32-bit constant.
343 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVTi16), DestReg)
344 .addReg(DestReg)
345 .addImm(NumBytes >> 16)
346 .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);
347 Fits = true;
348 }
349
350 if (Fits) {
351 if (isSub) {
352 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2SUBrr), DestReg)
353 .addReg(BaseReg)
354 .addReg(DestReg, RegState::Kill)
355 .add(predOps(Pred, PredReg))
356 .add(condCodeOp())
357 .setMIFlags(MIFlags);
358 } else {
359 // Here we know that DestReg is not SP but we do not
360 // know anything about BaseReg. t2ADDrr is an invalid
361 // instruction is SP is used as the second argument, but
362 // is fine if SP is the first argument. To be sure we
363 // do not generate invalid encoding, put BaseReg first.
364 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2ADDrr), DestReg)
365 .addReg(BaseReg)
366 .addReg(DestReg, RegState::Kill)
367 .add(predOps(Pred, PredReg))
368 .add(condCodeOp())
369 .setMIFlags(MIFlags);
370 }
371 return;
372 }
373 }
374
375 while (NumBytes) {
376 unsigned ThisVal = NumBytes;
377 unsigned Opc = 0;
378 if (DestReg == ARM::SP && BaseReg != ARM::SP) {
379 // mov sp, rn. Note t2MOVr cannot be used.
380 BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)
381 .addReg(BaseReg)
382 .setMIFlags(MIFlags)
384 BaseReg = ARM::SP;
385 continue;
386 }
387
388 assert((DestReg != ARM::SP || BaseReg == ARM::SP) &&
389 "Writing to SP, from other register.");
390
391 // Try to use T1, as it smaller
392 if ((DestReg == ARM::SP) && (ThisVal < ((1 << 7) - 1) * 4)) {
393 assert((ThisVal & 3) == 0 && "Stack update is not multiple of 4?");
394 Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;
395 BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
396 .addReg(BaseReg)
397 .addImm(ThisVal / 4)
398 .setMIFlags(MIFlags)
400 break;
401 }
402 bool HasCCOut = true;
403 int ImmIsT2SO = ARM_AM::getT2SOImmVal(ThisVal);
404 bool ToSP = DestReg == ARM::SP;
405 unsigned t2SUB = ToSP ? ARM::t2SUBspImm : ARM::t2SUBri;
406 unsigned t2ADD = ToSP ? ARM::t2ADDspImm : ARM::t2ADDri;
407 unsigned t2SUBi12 = ToSP ? ARM::t2SUBspImm12 : ARM::t2SUBri12;
408 unsigned t2ADDi12 = ToSP ? ARM::t2ADDspImm12 : ARM::t2ADDri12;
409 Opc = isSub ? t2SUB : t2ADD;
410 // Prefer T2: sub rd, rn, so_imm | sub sp, sp, so_imm
411 if (ImmIsT2SO != -1) {
412 NumBytes = 0;
413 } else if (ThisVal < 4096) {
414 // Prefer T3 if can make it in a single go: subw rd, rn, imm12 | subw sp,
415 // sp, imm12
416 Opc = isSub ? t2SUBi12 : t2ADDi12;
417 HasCCOut = false;
418 NumBytes = 0;
419 } else {
420 // Use one T2 instruction to reduce NumBytes
421 // FIXME: Move this to ARMAddressingModes.h?
422 unsigned RotAmt = llvm::countl_zero(ThisVal);
423 ThisVal = ThisVal & llvm::rotr<uint32_t>(0xff000000U, RotAmt);
424 NumBytes &= ~ThisVal;
425 assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 &&
426 "Bit extraction didn't work?");
427 }
428
429 // Build the new ADD / SUB.
430 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
431 .addReg(BaseReg, RegState::Kill)
432 .addImm(ThisVal)
434 .setMIFlags(MIFlags);
435 if (HasCCOut)
436 MIB.add(condCodeOp());
437
438 BaseReg = DestReg;
439 }
440}
441
442static unsigned
443negativeOffsetOpcode(unsigned opcode)
444{
445 switch (opcode) {
446 case ARM::t2LDRi12: return ARM::t2LDRi8;
447 case ARM::t2LDRHi12: return ARM::t2LDRHi8;
448 case ARM::t2LDRBi12: return ARM::t2LDRBi8;
449 case ARM::t2LDRSHi12: return ARM::t2LDRSHi8;
450 case ARM::t2LDRSBi12: return ARM::t2LDRSBi8;
451 case ARM::t2STRi12: return ARM::t2STRi8;
452 case ARM::t2STRBi12: return ARM::t2STRBi8;
453 case ARM::t2STRHi12: return ARM::t2STRHi8;
454 case ARM::t2PLDi12: return ARM::t2PLDi8;
455 case ARM::t2PLDWi12: return ARM::t2PLDWi8;
456 case ARM::t2PLIi12: return ARM::t2PLIi8;
457
458 case ARM::t2LDRi8:
459 case ARM::t2LDRHi8:
460 case ARM::t2LDRBi8:
461 case ARM::t2LDRSHi8:
462 case ARM::t2LDRSBi8:
463 case ARM::t2STRi8:
464 case ARM::t2STRBi8:
465 case ARM::t2STRHi8:
466 case ARM::t2PLDi8:
467 case ARM::t2PLDWi8:
468 case ARM::t2PLIi8:
469 return opcode;
470
471 default:
472 llvm_unreachable("unknown thumb2 opcode.");
473 }
474}
475
476static unsigned
477positiveOffsetOpcode(unsigned opcode)
478{
479 switch (opcode) {
480 case ARM::t2LDRi8: return ARM::t2LDRi12;
481 case ARM::t2LDRHi8: return ARM::t2LDRHi12;
482 case ARM::t2LDRBi8: return ARM::t2LDRBi12;
483 case ARM::t2LDRSHi8: return ARM::t2LDRSHi12;
484 case ARM::t2LDRSBi8: return ARM::t2LDRSBi12;
485 case ARM::t2STRi8: return ARM::t2STRi12;
486 case ARM::t2STRBi8: return ARM::t2STRBi12;
487 case ARM::t2STRHi8: return ARM::t2STRHi12;
488 case ARM::t2PLDi8: return ARM::t2PLDi12;
489 case ARM::t2PLDWi8: return ARM::t2PLDWi12;
490 case ARM::t2PLIi8: return ARM::t2PLIi12;
491
492 case ARM::t2LDRi12:
493 case ARM::t2LDRHi12:
494 case ARM::t2LDRBi12:
495 case ARM::t2LDRSHi12:
496 case ARM::t2LDRSBi12:
497 case ARM::t2STRi12:
498 case ARM::t2STRBi12:
499 case ARM::t2STRHi12:
500 case ARM::t2PLDi12:
501 case ARM::t2PLDWi12:
502 case ARM::t2PLIi12:
503 return opcode;
504
505 default:
506 llvm_unreachable("unknown thumb2 opcode.");
507 }
508}
509
510static unsigned
511immediateOffsetOpcode(unsigned opcode)
512{
513 switch (opcode) {
514 case ARM::t2LDRs: return ARM::t2LDRi12;
515 case ARM::t2LDRHs: return ARM::t2LDRHi12;
516 case ARM::t2LDRBs: return ARM::t2LDRBi12;
517 case ARM::t2LDRSHs: return ARM::t2LDRSHi12;
518 case ARM::t2LDRSBs: return ARM::t2LDRSBi12;
519 case ARM::t2STRs: return ARM::t2STRi12;
520 case ARM::t2STRBs: return ARM::t2STRBi12;
521 case ARM::t2STRHs: return ARM::t2STRHi12;
522 case ARM::t2PLDs: return ARM::t2PLDi12;
523 case ARM::t2PLDWs: return ARM::t2PLDWi12;
524 case ARM::t2PLIs: return ARM::t2PLIi12;
525
526 case ARM::t2LDRi12:
527 case ARM::t2LDRHi12:
528 case ARM::t2LDRBi12:
529 case ARM::t2LDRSHi12:
530 case ARM::t2LDRSBi12:
531 case ARM::t2STRi12:
532 case ARM::t2STRBi12:
533 case ARM::t2STRHi12:
534 case ARM::t2PLDi12:
535 case ARM::t2PLDWi12:
536 case ARM::t2PLIi12:
537 case ARM::t2LDRi8:
538 case ARM::t2LDRHi8:
539 case ARM::t2LDRBi8:
540 case ARM::t2LDRSHi8:
541 case ARM::t2LDRSBi8:
542 case ARM::t2STRi8:
543 case ARM::t2STRBi8:
544 case ARM::t2STRHi8:
545 case ARM::t2PLDi8:
546 case ARM::t2PLDWi8:
547 case ARM::t2PLIi8:
548 return opcode;
549
550 default:
551 llvm_unreachable("unknown thumb2 opcode.");
552 }
553}
554
555bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
556 Register FrameReg, int &Offset,
557 const ARMBaseInstrInfo &TII,
558 const TargetRegisterInfo *TRI) {
559 unsigned Opcode = MI.getOpcode();
560 const MCInstrDesc &Desc = MI.getDesc();
561 unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
562 bool isSub = false;
563
564 MachineFunction &MF = *MI.getParent()->getParent();
565 const TargetRegisterClass *RegClass =
566 TII.getRegClass(Desc, FrameRegIdx, TRI, MF);
567
568 // Memory operands in inline assembly always use AddrModeT2_i12.
569 if (Opcode == ARM::INLINEASM || Opcode == ARM::INLINEASM_BR)
570 AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2?
571
572 const bool IsSP = Opcode == ARM::t2ADDspImm12 || Opcode == ARM::t2ADDspImm;
573 if (IsSP || Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) {
574 Offset += MI.getOperand(FrameRegIdx+1).getImm();
575
576 Register PredReg;
577 if (Offset == 0 && getInstrPredicate(MI, PredReg) == ARMCC::AL &&
578 !MI.definesRegister(ARM::CPSR, /*TRI=*/nullptr)) {
579 // Turn it into a move.
580 MI.setDesc(TII.get(ARM::tMOVr));
581 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
582 // Remove offset and remaining explicit predicate operands.
583 do MI.removeOperand(FrameRegIdx+1);
584 while (MI.getNumOperands() > FrameRegIdx+1);
585 MachineInstrBuilder MIB(*MI.getParent()->getParent(), &MI);
586 MIB.add(predOps(ARMCC::AL));
587 return true;
588 }
589
590 bool HasCCOut = (Opcode != ARM::t2ADDspImm12 && Opcode != ARM::t2ADDri12);
591
592 if (Offset < 0) {
593 Offset = -Offset;
594 isSub = true;
595 MI.setDesc(IsSP ? TII.get(ARM::t2SUBspImm) : TII.get(ARM::t2SUBri));
596 } else {
597 MI.setDesc(IsSP ? TII.get(ARM::t2ADDspImm) : TII.get(ARM::t2ADDri));
598 }
599
600 // Common case: small offset, fits into instruction.
601 if (ARM_AM::getT2SOImmVal(Offset) != -1) {
602 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
603 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
604 // Add cc_out operand if the original instruction did not have one.
605 if (!HasCCOut)
606 MI.addOperand(MachineOperand::CreateReg(0, false));
607 Offset = 0;
608 return true;
609 }
610 // Another common case: imm12.
611 if (Offset < 4096 &&
612 (!HasCCOut || MI.getOperand(MI.getNumOperands()-1).getReg() == 0)) {
613 unsigned NewOpc = isSub ? IsSP ? ARM::t2SUBspImm12 : ARM::t2SUBri12
614 : IsSP ? ARM::t2ADDspImm12 : ARM::t2ADDri12;
615 MI.setDesc(TII.get(NewOpc));
616 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
617 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
618 // Remove the cc_out operand.
619 if (HasCCOut)
620 MI.removeOperand(MI.getNumOperands()-1);
621 Offset = 0;
622 return true;
623 }
624
625 // Otherwise, extract 8 adjacent bits from the immediate into this
626 // t2ADDri/t2SUBri.
627 unsigned RotAmt = llvm::countl_zero<unsigned>(Offset);
628 unsigned ThisImmVal = Offset & llvm::rotr<uint32_t>(0xff000000U, RotAmt);
629
630 // We will handle these bits from offset, clear them.
631 Offset &= ~ThisImmVal;
632
633 assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 &&
634 "Bit extraction didn't work?");
635 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
636 // Add cc_out operand if the original instruction did not have one.
637 if (!HasCCOut)
638 MI.addOperand(MachineOperand::CreateReg(0, false));
639 } else {
640 // AddrMode4 and AddrMode6 cannot handle any offset.
642 return false;
643
644 // AddrModeT2_so cannot handle any offset. If there is no offset
645 // register then we change to an immediate version.
646 unsigned NewOpc = Opcode;
648 Register OffsetReg = MI.getOperand(FrameRegIdx + 1).getReg();
649 if (OffsetReg != 0) {
650 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
651 return Offset == 0;
652 }
653
654 MI.removeOperand(FrameRegIdx+1);
655 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0);
656 NewOpc = immediateOffsetOpcode(Opcode);
658 }
659
660 unsigned NumBits = 0;
661 unsigned Scale = 1;
664 // i8 supports only negative, and i12 supports only positive, so
665 // based on Offset sign convert Opcode to the appropriate
666 // instruction
667 Offset += MI.getOperand(FrameRegIdx+1).getImm();
668 if (Offset < 0) {
669 NewOpc = negativeOffsetOpcode(Opcode);
670 NumBits = 8;
671 isSub = true;
672 Offset = -Offset;
673 } else {
674 NewOpc = positiveOffsetOpcode(Opcode);
675 NumBits = 12;
676 }
677 } else if (AddrMode == ARMII::AddrMode5) {
678 // VFP address mode.
679 const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1);
680 int InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm());
681 if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub)
682 InstrOffs *= -1;
683 NumBits = 8;
684 Scale = 4;
685 Offset += InstrOffs * 4;
686 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
687 if (Offset < 0) {
688 Offset = -Offset;
689 isSub = true;
690 }
691 } else if (AddrMode == ARMII::AddrMode5FP16) {
692 // VFP address mode.
693 const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1);
694 int InstrOffs = ARM_AM::getAM5FP16Offset(OffOp.getImm());
696 InstrOffs *= -1;
697 NumBits = 8;
698 Scale = 2;
699 Offset += InstrOffs * 2;
700 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
701 if (Offset < 0) {
702 Offset = -Offset;
703 isSub = true;
704 }
705 } else if (AddrMode == ARMII::AddrModeT2_i7s4 ||
708 Offset += MI.getOperand(FrameRegIdx + 1).getImm();
709 unsigned OffsetMask;
710 switch (AddrMode) {
711 case ARMII::AddrModeT2_i7s4: NumBits = 9; OffsetMask = 0x3; break;
712 case ARMII::AddrModeT2_i7s2: NumBits = 8; OffsetMask = 0x1; break;
713 default: NumBits = 7; OffsetMask = 0x0; break;
714 }
715 // MCInst operand expects already scaled value.
716 Scale = 1;
717 assert((Offset & OffsetMask) == 0 && "Can't encode this offset!");
718 (void)OffsetMask; // squash unused-variable warning at -NDEBUG
719 } else if (AddrMode == ARMII::AddrModeT2_i8s4) {
720 Offset += MI.getOperand(FrameRegIdx + 1).getImm();
721 NumBits = 8 + 2;
722 // MCInst operand expects already scaled value.
723 Scale = 1;
724 assert((Offset & 3) == 0 && "Can't encode this offset!");
725 } else if (AddrMode == ARMII::AddrModeT2_ldrex) {
726 Offset += MI.getOperand(FrameRegIdx + 1).getImm() * 4;
727 NumBits = 8; // 8 bits scaled by 4
728 Scale = 4;
729 assert((Offset & 3) == 0 && "Can't encode this offset!");
730 } else {
731 llvm_unreachable("Unsupported addressing mode!");
732 }
733
734 if (NewOpc != Opcode)
735 MI.setDesc(TII.get(NewOpc));
736
737 MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1);
738
739 // Attempt to fold address computation
740 // Common case: small offset, fits into instruction. We need to make sure
741 // the register class is correct too, for instructions like the MVE
742 // VLDRH.32, which only accepts low tGPR registers.
743 int ImmedOffset = Offset / Scale;
744 unsigned Mask = (1 << NumBits) - 1;
745 if ((unsigned)Offset <= Mask * Scale &&
746 (FrameReg.isVirtual() || RegClass->contains(FrameReg))) {
747 if (FrameReg.isVirtual()) {
748 // Make sure the register class for the virtual register is correct
750 if (!MRI->constrainRegClass(FrameReg, RegClass))
751 llvm_unreachable("Unable to constrain virtual register class.");
752 }
753
754 // Replace the FrameIndex with fp/sp
755 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
756 if (isSub) {
758 // FIXME: Not consistent.
759 ImmedOffset |= 1 << NumBits;
760 else
761 ImmedOffset = -ImmedOffset;
762 }
763 ImmOp.ChangeToImmediate(ImmedOffset);
764 Offset = 0;
765 return true;
766 }
767
768 // Otherwise, offset doesn't fit. Pull in what we can to simplify
769 ImmedOffset = ImmedOffset & Mask;
770 if (isSub) {
772 // FIXME: Not consistent.
773 ImmedOffset |= 1 << NumBits;
774 else {
775 ImmedOffset = -ImmedOffset;
776 if (ImmedOffset == 0)
777 // Change the opcode back if the encoded offset is zero.
778 MI.setDesc(TII.get(positiveOffsetOpcode(NewOpc)));
779 }
780 }
781 ImmOp.ChangeToImmediate(ImmedOffset);
782 Offset &= ~(Mask*Scale);
783 }
784
785 Offset = (isSub) ? -Offset : Offset;
786 return Offset == 0 && (FrameReg.isVirtual() || RegClass->contains(FrameReg));
787}
788
790 Register &PredReg) {
791 unsigned Opc = MI.getOpcode();
792 if (Opc == ARM::tBcc || Opc == ARM::t2Bcc)
793 return ARMCC::AL;
794 return getInstrPredicate(MI, PredReg);
795}
796
798 const MCInstrDesc &MCID = MI.getDesc();
799
800 for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i)
801 if (ARM::isVpred(MCID.operands()[i].OperandType))
802 return i;
803
804 return -1;
805}
806
808 Register &PredReg) {
809 int PIdx = findFirstVPTPredOperandIdx(MI);
810 if (PIdx == -1) {
811 PredReg = 0;
812 return ARMVCC::None;
813 }
814
815 PredReg = MI.getOperand(PIdx+1).getReg();
816 return (ARMVCC::VPTCodes)MI.getOperand(PIdx).getImm();
817}
818
820 assert(isVPTOpcode(Instr.getOpcode()) && "Not a VPST or VPT Instruction!");
821
822 MachineOperand &MaskOp = Instr.getOperand(0);
823 assert(MaskOp.isImm() && "Operand 0 is not the block mask of the VPT/VPST?!");
824
825 MachineBasicBlock::iterator Iter = ++Instr.getIterator(),
826 End = Instr.getParent()->end();
827
828 while (Iter != End && Iter->isDebugInstr())
829 ++Iter;
830
831 // Verify that the instruction after the VPT/VPST is predicated (it should
832 // be), and skip it.
833 assert(Iter != End && "Expected some instructions in any VPT block");
834 assert(
836 "VPT/VPST should be followed by an instruction with a 'then' predicate!");
837 ++Iter;
838
839 // Iterate over the predicated instructions, updating the BlockMask as we go.
841 while (Iter != End) {
842 if (Iter->isDebugInstr()) {
843 ++Iter;
844 continue;
845 }
847 if (Pred == ARMVCC::None)
848 break;
849 BlockMask = expandPredBlockMask(BlockMask, Pred);
850 ++Iter;
851 }
852
853 // Rewrite the BlockMask.
854 MaskOp.setImm((int64_t)(BlockMask));
855}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
bool End
Definition: ELF_riscv.cpp:480
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:58
unsigned const TargetRegisterInfo * TRI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
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)
const MachineInstrBuilder & AddDReg(MachineInstrBuilder &MIB, unsigned Reg, unsigned SubIdx, unsigned State, const TargetRegisterInfo *TRI) const
MachineInstr * optimizeSelect(MachineInstr &MI, SmallPtrSetImpl< MachineInstr * > &SeenMIs, bool) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
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, const TargetRegisterInfo *TRI, Register VReg) const override
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
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 useMovt() const
bool isTargetELF() const
Definition: ARMSubtarget.h:348
A debug info location.
Definition: DebugLoc.h:33
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:656
MCInstBuilder & addReg(MCRegister Reg)
Add a new register operand.
Definition: MCInstBuilder.h:37
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:43
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:185
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:198
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:237
ArrayRef< MCOperandInfo > operands() const
Definition: MCInstrDesc.h:239
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
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.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
Definition: MachineInstr.h:69
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.
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,...
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition: Register.h:91
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition: Register.h:95
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
Definition: SmallPtrSet.h:363
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:384
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
bool contains(Register Reg) const
Return true if the specified register is included in this register class.
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
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
MachineInstr * commuteInstructionImpl(MachineInstr &MI, bool NewMI, unsigned OpIdx1, unsigned OpIdx2) const override
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
void ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail, MachineBasicBlock *NewDest) const override
MachineInstr * optimizeSelect(MachineInstr &MI, SmallPtrSetImpl< MachineInstr * > &SeenMIs, bool) const override
Thumb2InstrInfo(const ARMSubtarget &STI)
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
MCInst getNop() const override
Return the noop instruction to use for a noop.
#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.
Definition: ARMBaseInfo.h:105
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
@ Kill
The last use of a register.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
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.
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.
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:281
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)
unsigned getKillRegState(bool B)
ARM::PredBlockMask expandPredBlockMask(ARM::PredBlockMask BlockMask, ARMVCC::VPTCodes Kind)
Definition: ARMBaseInfo.cpp:16
ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, Register &PredReg)
getInstrPredicate - If instruction is predicated, returns its predicate condition,...
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)
Description of the encoding of one expression Op.
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.