LLVM 22.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, 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 const TargetRegisterInfo *TRI,
169 Register VReg,
170 MachineInstr::MIFlag Flags) const {
171 DebugLoc DL;
172 if (I != MBB.end()) DL = I->getDebugLoc();
173
175 MachineFrameInfo &MFI = MF.getFrameInfo();
178 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
179
180 if (ARM::GPRRegClass.hasSubClassEq(RC)) {
181 BuildMI(MBB, I, DL, get(ARM::t2STRi12))
182 .addReg(SrcReg, getKillRegState(isKill))
183 .addFrameIndex(FI)
184 .addImm(0)
185 .addMemOperand(MMO)
187 return;
188 }
189
190 if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {
191 // Thumb2 STRD expects its dest-registers to be in rGPR. Not a problem for
192 // gsub_0, but needs an extra constraint for gsub_1 (which could be sp
193 // otherwise).
194 if (SrcReg.isVirtual()) {
196 MRI->constrainRegClass(SrcReg, &ARM::GPRPairnospRegClass);
197 }
198
199 MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(ARM::t2STRDi8));
200 AddDReg(MIB, SrcReg, ARM::gsub_0, getKillRegState(isKill), TRI);
201 AddDReg(MIB, SrcReg, ARM::gsub_1, 0, TRI);
203 return;
204 }
205
206 ARMBaseInstrInfo::storeRegToStackSlot(MBB, I, SrcReg, isKill, FI, RC, TRI,
207 Register());
208}
209
212 int FI, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI,
213 Register VReg, MachineInstr::MIFlag Flags) const {
215 MachineFrameInfo &MFI = MF.getFrameInfo();
218 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
219 DebugLoc DL;
220 if (I != MBB.end()) DL = I->getDebugLoc();
221
222 if (ARM::GPRRegClass.hasSubClassEq(RC)) {
223 BuildMI(MBB, I, DL, get(ARM::t2LDRi12), DestReg)
224 .addFrameIndex(FI)
225 .addImm(0)
226 .addMemOperand(MMO)
228 return;
229 }
230
231 if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {
232 // Thumb2 LDRD expects its dest-registers to be in rGPR. Not a problem for
233 // gsub_0, but needs an extra constraint for gsub_1 (which could be sp
234 // otherwise).
235 if (DestReg.isVirtual()) {
237 MRI->constrainRegClass(DestReg, &ARM::GPRPairnospRegClass);
238 }
239
240 MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(ARM::t2LDRDi8));
241 AddDReg(MIB, DestReg, ARM::gsub_0, RegState::DefineNoRead, TRI);
242 AddDReg(MIB, DestReg, ARM::gsub_1, RegState::DefineNoRead, TRI);
244
245 if (DestReg.isPhysical())
246 MIB.addReg(DestReg, RegState::ImplicitDefine);
247 return;
248 }
249
251 Register());
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 =
568 TII.getRegClass(Desc, FrameRegIdx, TRI, MF);
569
570 // Memory operands in inline assembly always use AddrModeT2_i12.
571 if (Opcode == ARM::INLINEASM || Opcode == ARM::INLINEASM_BR)
572 AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2?
573
574 const bool IsSP = Opcode == ARM::t2ADDspImm12 || Opcode == ARM::t2ADDspImm;
575 if (IsSP || Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) {
576 Offset += MI.getOperand(FrameRegIdx+1).getImm();
577
578 Register PredReg;
579 if (Offset == 0 && getInstrPredicate(MI, PredReg) == ARMCC::AL &&
580 !MI.definesRegister(ARM::CPSR, /*TRI=*/nullptr)) {
581 // Turn it into a move.
582 MI.setDesc(TII.get(ARM::tMOVr));
583 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
584 // Remove offset and remaining explicit predicate operands.
585 do MI.removeOperand(FrameRegIdx+1);
586 while (MI.getNumOperands() > FrameRegIdx+1);
587 MachineInstrBuilder MIB(*MI.getParent()->getParent(), &MI);
588 MIB.add(predOps(ARMCC::AL));
589 return true;
590 }
591
592 bool HasCCOut = (Opcode != ARM::t2ADDspImm12 && Opcode != ARM::t2ADDri12);
593
594 if (Offset < 0) {
595 Offset = -Offset;
596 isSub = true;
597 MI.setDesc(IsSP ? TII.get(ARM::t2SUBspImm) : TII.get(ARM::t2SUBri));
598 } else {
599 MI.setDesc(IsSP ? TII.get(ARM::t2ADDspImm) : TII.get(ARM::t2ADDri));
600 }
601
602 // Common case: small offset, fits into instruction.
603 if (ARM_AM::getT2SOImmVal(Offset) != -1) {
604 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
605 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
606 // Add cc_out operand if the original instruction did not have one.
607 if (!HasCCOut)
608 MI.addOperand(MachineOperand::CreateReg(0, false));
609 Offset = 0;
610 return true;
611 }
612 // Another common case: imm12.
613 if (Offset < 4096 &&
614 (!HasCCOut || MI.getOperand(MI.getNumOperands()-1).getReg() == 0)) {
615 unsigned NewOpc = isSub ? IsSP ? ARM::t2SUBspImm12 : ARM::t2SUBri12
616 : IsSP ? ARM::t2ADDspImm12 : ARM::t2ADDri12;
617 MI.setDesc(TII.get(NewOpc));
618 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
619 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
620 // Remove the cc_out operand.
621 if (HasCCOut)
622 MI.removeOperand(MI.getNumOperands()-1);
623 Offset = 0;
624 return true;
625 }
626
627 // Otherwise, extract 8 adjacent bits from the immediate into this
628 // t2ADDri/t2SUBri.
629 unsigned RotAmt = llvm::countl_zero<unsigned>(Offset);
630 unsigned ThisImmVal = Offset & llvm::rotr<uint32_t>(0xff000000U, RotAmt);
631
632 // We will handle these bits from offset, clear them.
633 Offset &= ~ThisImmVal;
634
635 assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 &&
636 "Bit extraction didn't work?");
637 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
638 // Add cc_out operand if the original instruction did not have one.
639 if (!HasCCOut)
640 MI.addOperand(MachineOperand::CreateReg(0, false));
641 } else {
642 // AddrMode4 and AddrMode6 cannot handle any offset.
644 return false;
645
646 // AddrModeT2_so cannot handle any offset. If there is no offset
647 // register then we change to an immediate version.
648 unsigned NewOpc = Opcode;
650 Register OffsetReg = MI.getOperand(FrameRegIdx + 1).getReg();
651 if (OffsetReg != 0) {
652 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
653 return Offset == 0;
654 }
655
656 MI.removeOperand(FrameRegIdx+1);
657 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0);
658 NewOpc = immediateOffsetOpcode(Opcode);
660 }
661
662 unsigned NumBits = 0;
663 unsigned Scale = 1;
666 // i8 supports only negative, and i12 supports only positive, so
667 // based on Offset sign convert Opcode to the appropriate
668 // instruction
669 Offset += MI.getOperand(FrameRegIdx+1).getImm();
670 if (Offset < 0) {
671 NewOpc = negativeOffsetOpcode(Opcode);
672 NumBits = 8;
673 isSub = true;
674 Offset = -Offset;
675 } else {
676 NewOpc = positiveOffsetOpcode(Opcode);
677 NumBits = 12;
678 }
679 } else if (AddrMode == ARMII::AddrMode5) {
680 // VFP address mode.
681 const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1);
682 int InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm());
683 if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub)
684 InstrOffs *= -1;
685 NumBits = 8;
686 Scale = 4;
687 Offset += InstrOffs * 4;
688 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
689 if (Offset < 0) {
690 Offset = -Offset;
691 isSub = true;
692 }
693 } else if (AddrMode == ARMII::AddrMode5FP16) {
694 // VFP address mode.
695 const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1);
696 int InstrOffs = ARM_AM::getAM5FP16Offset(OffOp.getImm());
698 InstrOffs *= -1;
699 NumBits = 8;
700 Scale = 2;
701 Offset += InstrOffs * 2;
702 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
703 if (Offset < 0) {
704 Offset = -Offset;
705 isSub = true;
706 }
707 } else if (AddrMode == ARMII::AddrModeT2_i7s4 ||
710 Offset += MI.getOperand(FrameRegIdx + 1).getImm();
711 unsigned OffsetMask;
712 switch (AddrMode) {
713 case ARMII::AddrModeT2_i7s4: NumBits = 9; OffsetMask = 0x3; break;
714 case ARMII::AddrModeT2_i7s2: NumBits = 8; OffsetMask = 0x1; break;
715 default: NumBits = 7; OffsetMask = 0x0; break;
716 }
717 // MCInst operand expects already scaled value.
718 Scale = 1;
719 assert((Offset & OffsetMask) == 0 && "Can't encode this offset!");
720 (void)OffsetMask; // squash unused-variable warning at -NDEBUG
721 } else if (AddrMode == ARMII::AddrModeT2_i8s4) {
722 Offset += MI.getOperand(FrameRegIdx + 1).getImm();
723 NumBits = 8 + 2;
724 // MCInst operand expects already scaled value.
725 Scale = 1;
726 assert((Offset & 3) == 0 && "Can't encode this offset!");
727 } else if (AddrMode == ARMII::AddrModeT2_ldrex) {
728 Offset += MI.getOperand(FrameRegIdx + 1).getImm() * 4;
729 NumBits = 8; // 8 bits scaled by 4
730 Scale = 4;
731 assert((Offset & 3) == 0 && "Can't encode this offset!");
732 } else {
733 llvm_unreachable("Unsupported addressing mode!");
734 }
735
736 if (NewOpc != Opcode)
737 MI.setDesc(TII.get(NewOpc));
738
739 MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1);
740
741 // Attempt to fold address computation
742 // Common case: small offset, fits into instruction. We need to make sure
743 // the register class is correct too, for instructions like the MVE
744 // VLDRH.32, which only accepts low tGPR registers.
745 int ImmedOffset = Offset / Scale;
746 unsigned Mask = (1 << NumBits) - 1;
747 if ((unsigned)Offset <= Mask * Scale &&
748 (FrameReg.isVirtual() || RegClass->contains(FrameReg))) {
749 if (FrameReg.isVirtual()) {
750 // Make sure the register class for the virtual register is correct
752 if (!MRI->constrainRegClass(FrameReg, RegClass))
753 llvm_unreachable("Unable to constrain virtual register class.");
754 }
755
756 // Replace the FrameIndex with fp/sp
757 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
758 if (isSub) {
760 // FIXME: Not consistent.
761 ImmedOffset |= 1 << NumBits;
762 else
763 ImmedOffset = -ImmedOffset;
764 }
765 ImmOp.ChangeToImmediate(ImmedOffset);
766 Offset = 0;
767 return true;
768 }
769
770 // Otherwise, offset doesn't fit. Pull in what we can to simplify
771 ImmedOffset = ImmedOffset & Mask;
772 if (isSub) {
774 // FIXME: Not consistent.
775 ImmedOffset |= 1 << NumBits;
776 else {
777 ImmedOffset = -ImmedOffset;
778 if (ImmedOffset == 0)
779 // Change the opcode back if the encoded offset is zero.
780 MI.setDesc(TII.get(positiveOffsetOpcode(NewOpc)));
781 }
782 }
783 ImmOp.ChangeToImmediate(ImmedOffset);
784 Offset &= ~(Mask*Scale);
785 }
786
787 Offset = (isSub) ? -Offset : Offset;
788 return Offset == 0 && (FrameReg.isVirtual() || RegClass->contains(FrameReg));
789}
790
792 Register &PredReg) {
793 unsigned Opc = MI.getOpcode();
794 if (Opc == ARM::tBcc || Opc == ARM::t2Bcc)
795 return ARMCC::AL;
796 return getInstrPredicate(MI, PredReg);
797}
798
800 const MCInstrDesc &MCID = MI.getDesc();
801
802 for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i)
803 if (ARM::isVpred(MCID.operands()[i].OperandType))
804 return i;
805
806 return -1;
807}
808
810 Register &PredReg) {
811 int PIdx = findFirstVPTPredOperandIdx(MI);
812 if (PIdx == -1) {
813 PredReg = 0;
814 return ARMVCC::None;
815 }
816
817 PredReg = MI.getOperand(PIdx+1).getReg();
818 return (ARMVCC::VPTCodes)MI.getOperand(PIdx).getImm();
819}
820
822 assert(isVPTOpcode(Instr.getOpcode()) && "Not a VPST or VPT Instruction!");
823
824 MachineOperand &MaskOp = Instr.getOperand(0);
825 assert(MaskOp.isImm() && "Operand 0 is not the block mask of the VPT/VPST?!");
826
827 MachineBasicBlock::iterator Iter = ++Instr.getIterator(),
828 End = Instr.getParent()->end();
829
830 while (Iter != End && Iter->isDebugInstr())
831 ++Iter;
832
833 // Verify that the instruction after the VPT/VPST is predicated (it should
834 // be), and skip it.
835 assert(Iter != End && "Expected some instructions in any VPT block");
836 assert(
838 "VPT/VPST should be followed by an instruction with a 'then' predicate!");
839 ++Iter;
840
841 // Iterate over the predicated instructions, updating the BlockMask as we go.
843 while (Iter != End) {
844 if (Iter->isDebugInstr()) {
845 ++Iter;
846 continue;
847 }
849 if (Pred == ARMVCC::None)
850 break;
851 BlockMask = expandPredBlockMask(BlockMask, Pred);
852 ++Iter;
853 }
854
855 // Rewrite the BlockMask.
856 MaskOp.setImm((int64_t)(BlockMask));
857}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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
Register const TargetRegisterInfo * TRI
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:480
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
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, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) 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, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) 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:345
A debug info location.
Definition: DebugLoc.h:124
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:663
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:188
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:199
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:238
ArrayRef< MCOperandInfo > operands() const
Definition: MCInstrDesc.h:240
LLVM_ABI 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:72
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,...
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:19
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition: Register.h:74
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition: Register.h:78
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
Definition: SmallPtrSet.h:380
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:401
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 storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) 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.
#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:444
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:477
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:203
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 LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.