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"
35#include <cassert>
36
37using namespace llvm;
38
39static cl::opt<bool>
40OldT2IfCvt("old-thumb2-ifcvt", cl::Hidden,
41 cl::desc("Use old-style Thumb2 if-conversion heuristics"),
42 cl::init(false));
43
44static cl::opt<bool>
45PreferNoCSEL("prefer-no-csel", cl::Hidden,
46 cl::desc("Prefer predicated Move to CSEL"),
47 cl::init(false));
48
50 : ARMBaseInstrInfo(STI) {}
51
52/// Return the noop instruction to use for a noop.
54 return MCInstBuilder(ARM::tHINT).addImm(0).addImm(ARMCC::AL).addReg(0);
55}
56
57unsigned Thumb2InstrInfo::getUnindexedOpcode(unsigned Opc) const {
58 // FIXME
59 return 0;
60}
61
62void
64 MachineBasicBlock *NewDest) const {
65 MachineBasicBlock *MBB = Tail->getParent();
67 if (!AFI->hasITBlocks() || Tail->isBranch()) {
69 return;
70 }
71
72 // If the first instruction of Tail is predicated, we may have to update
73 // the IT instruction.
74 Register PredReg;
77 if (CC != ARMCC::AL)
78 // Expecting at least the t2IT instruction before it.
79 --MBBI;
80
81 // Actually replace the tail.
83
84 // Fix up IT.
85 if (CC != ARMCC::AL) {
87 unsigned Count = 4; // At most 4 instructions in an IT block.
88 while (Count && MBBI != E) {
89 if (MBBI->isDebugInstr()) {
90 --MBBI;
91 continue;
92 }
93 if (MBBI->getOpcode() == ARM::t2IT) {
94 unsigned Mask = MBBI->getOperand(1).getImm();
95 if (Count == 4)
97 else {
98 unsigned MaskOn = 1 << Count;
99 unsigned MaskOff = ~(MaskOn - 1);
100 MBBI->getOperand(1).setImm((Mask & MaskOff) | MaskOn);
101 }
102 return;
103 }
104 --MBBI;
105 --Count;
106 }
107
108 // Ctrl flow can reach here if branch folding is run before IT block
109 // formation pass.
110 }
111}
112
113bool
116 while (MBBI->isDebugInstr()) {
117 ++MBBI;
118 if (MBBI == MBB.end())
119 return false;
120 }
121
122 Register PredReg;
123 return getITInstrPredicate(*MBBI, PredReg) == ARMCC::AL;
124}
125
129 bool PreferFalse) const {
130 // Try to use the base optimizeSelect, which uses canFoldIntoMOVCC to fold the
131 // MOVCC into another instruction. If that fails on 8.1-M fall back to using a
132 // CSEL.
133 MachineInstr *RV = ARMBaseInstrInfo::optimizeSelect(MI, SeenMIs, PreferFalse);
134 if (!RV && getSubtarget().hasV8_1MMainlineOps() && !PreferNoCSEL) {
135 Register DestReg = MI.getOperand(0).getReg();
136
137 if (!DestReg.isVirtual())
138 return nullptr;
139
140 MachineInstrBuilder NewMI = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(),
141 get(ARM::t2CSEL), DestReg)
142 .add(MI.getOperand(2))
143 .add(MI.getOperand(1))
144 .add(MI.getOperand(3));
145 SeenMIs.insert(NewMI);
146 return NewMI;
147 }
148 return RV;
149}
150
153 const DebugLoc &DL, MCRegister DestReg,
154 MCRegister SrcReg, bool KillSrc) 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 if (MF.getSubtarget<ARMSubtarget>().isTargetELF() && !GV->isDSOLocal())
267 expandLoadStackGuardBase(MI, ARM::t2LDRLIT_ga_pcrel, ARM::t2LDRi12);
268 else if (MF.getTarget().isPositionIndependent())
269 expandLoadStackGuardBase(MI, ARM::t2MOV_ga_pcrel, ARM::t2LDRi12);
270 else
271 expandLoadStackGuardBase(MI, ARM::t2MOVi32imm, ARM::t2LDRi12);
272}
273
275 bool NewMI,
276 unsigned OpIdx1,
277 unsigned OpIdx2) const {
278 switch (MI.getOpcode()) {
279 case ARM::MVE_VMAXNMAf16:
280 case ARM::MVE_VMAXNMAf32:
281 case ARM::MVE_VMINNMAf16:
282 case ARM::MVE_VMINNMAf32:
283 // Don't allow predicated instructions to be commuted.
285 return nullptr;
286 }
287 return ARMBaseInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
288}
289
291 const MachineBasicBlock *MBB,
292 const MachineFunction &MF) const {
293 // BTI clearing instructions shall not take part in scheduling regions as
294 // they must stay in their intended place. Although PAC isn't BTI clearing,
295 // it can be transformed into PACBTI after the pre-RA Machine Scheduling
296 // has taken place, so its movement must also be restricted.
297 switch (MI.getOpcode()) {
298 case ARM::t2BTI:
299 case ARM::t2PAC:
300 case ARM::t2PACBTI:
301 case ARM::t2SG:
302 return true;
303 default:
304 break;
305 }
307}
308
311 const DebugLoc &dl, Register DestReg,
312 Register BaseReg, int NumBytes,
313 ARMCC::CondCodes Pred, Register PredReg,
314 const ARMBaseInstrInfo &TII,
315 unsigned MIFlags) {
316 if (NumBytes == 0 && DestReg != BaseReg) {
317 BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)
318 .addReg(BaseReg, RegState::Kill)
319 .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);
320 return;
321 }
322
323 bool isSub = NumBytes < 0;
324 if (isSub) NumBytes = -NumBytes;
325
326 // If profitable, use a movw or movt to materialize the offset.
327 // FIXME: Use the scavenger to grab a scratch register.
328 if (DestReg != ARM::SP && DestReg != BaseReg &&
329 NumBytes >= 4096 &&
330 ARM_AM::getT2SOImmVal(NumBytes) == -1) {
331 bool Fits = false;
332 if (NumBytes < 65536) {
333 // Use a movw to materialize the 16-bit constant.
334 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), DestReg)
335 .addImm(NumBytes)
336 .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);
337 Fits = true;
338 } else if ((NumBytes & 0xffff) == 0) {
339 // Use a movt to materialize the 32-bit constant.
340 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVTi16), DestReg)
341 .addReg(DestReg)
342 .addImm(NumBytes >> 16)
343 .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);
344 Fits = true;
345 }
346
347 if (Fits) {
348 if (isSub) {
349 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2SUBrr), DestReg)
350 .addReg(BaseReg)
351 .addReg(DestReg, RegState::Kill)
352 .add(predOps(Pred, PredReg))
353 .add(condCodeOp())
354 .setMIFlags(MIFlags);
355 } else {
356 // Here we know that DestReg is not SP but we do not
357 // know anything about BaseReg. t2ADDrr is an invalid
358 // instruction is SP is used as the second argument, but
359 // is fine if SP is the first argument. To be sure we
360 // do not generate invalid encoding, put BaseReg first.
361 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2ADDrr), DestReg)
362 .addReg(BaseReg)
363 .addReg(DestReg, RegState::Kill)
364 .add(predOps(Pred, PredReg))
365 .add(condCodeOp())
366 .setMIFlags(MIFlags);
367 }
368 return;
369 }
370 }
371
372 while (NumBytes) {
373 unsigned ThisVal = NumBytes;
374 unsigned Opc = 0;
375 if (DestReg == ARM::SP && BaseReg != ARM::SP) {
376 // mov sp, rn. Note t2MOVr cannot be used.
377 BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)
378 .addReg(BaseReg)
379 .setMIFlags(MIFlags)
381 BaseReg = ARM::SP;
382 continue;
383 }
384
385 assert((DestReg != ARM::SP || BaseReg == ARM::SP) &&
386 "Writing to SP, from other register.");
387
388 // Try to use T1, as it smaller
389 if ((DestReg == ARM::SP) && (ThisVal < ((1 << 7) - 1) * 4)) {
390 assert((ThisVal & 3) == 0 && "Stack update is not multiple of 4?");
391 Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;
392 BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
393 .addReg(BaseReg)
394 .addImm(ThisVal / 4)
395 .setMIFlags(MIFlags)
397 break;
398 }
399 bool HasCCOut = true;
400 int ImmIsT2SO = ARM_AM::getT2SOImmVal(ThisVal);
401 bool ToSP = DestReg == ARM::SP;
402 unsigned t2SUB = ToSP ? ARM::t2SUBspImm : ARM::t2SUBri;
403 unsigned t2ADD = ToSP ? ARM::t2ADDspImm : ARM::t2ADDri;
404 unsigned t2SUBi12 = ToSP ? ARM::t2SUBspImm12 : ARM::t2SUBri12;
405 unsigned t2ADDi12 = ToSP ? ARM::t2ADDspImm12 : ARM::t2ADDri12;
406 Opc = isSub ? t2SUB : t2ADD;
407 // Prefer T2: sub rd, rn, so_imm | sub sp, sp, so_imm
408 if (ImmIsT2SO != -1) {
409 NumBytes = 0;
410 } else if (ThisVal < 4096) {
411 // Prefer T3 if can make it in a single go: subw rd, rn, imm12 | subw sp,
412 // sp, imm12
413 Opc = isSub ? t2SUBi12 : t2ADDi12;
414 HasCCOut = false;
415 NumBytes = 0;
416 } else {
417 // Use one T2 instruction to reduce NumBytes
418 // FIXME: Move this to ARMAddressingModes.h?
419 unsigned RotAmt = llvm::countl_zero(ThisVal);
420 ThisVal = ThisVal & llvm::rotr<uint32_t>(0xff000000U, RotAmt);
421 NumBytes &= ~ThisVal;
422 assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 &&
423 "Bit extraction didn't work?");
424 }
425
426 // Build the new ADD / SUB.
427 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
428 .addReg(BaseReg, RegState::Kill)
429 .addImm(ThisVal)
431 .setMIFlags(MIFlags);
432 if (HasCCOut)
433 MIB.add(condCodeOp());
434
435 BaseReg = DestReg;
436 }
437}
438
439static unsigned
440negativeOffsetOpcode(unsigned opcode)
441{
442 switch (opcode) {
443 case ARM::t2LDRi12: return ARM::t2LDRi8;
444 case ARM::t2LDRHi12: return ARM::t2LDRHi8;
445 case ARM::t2LDRBi12: return ARM::t2LDRBi8;
446 case ARM::t2LDRSHi12: return ARM::t2LDRSHi8;
447 case ARM::t2LDRSBi12: return ARM::t2LDRSBi8;
448 case ARM::t2STRi12: return ARM::t2STRi8;
449 case ARM::t2STRBi12: return ARM::t2STRBi8;
450 case ARM::t2STRHi12: return ARM::t2STRHi8;
451 case ARM::t2PLDi12: return ARM::t2PLDi8;
452 case ARM::t2PLDWi12: return ARM::t2PLDWi8;
453 case ARM::t2PLIi12: return ARM::t2PLIi8;
454
455 case ARM::t2LDRi8:
456 case ARM::t2LDRHi8:
457 case ARM::t2LDRBi8:
458 case ARM::t2LDRSHi8:
459 case ARM::t2LDRSBi8:
460 case ARM::t2STRi8:
461 case ARM::t2STRBi8:
462 case ARM::t2STRHi8:
463 case ARM::t2PLDi8:
464 case ARM::t2PLDWi8:
465 case ARM::t2PLIi8:
466 return opcode;
467
468 default:
469 llvm_unreachable("unknown thumb2 opcode.");
470 }
471}
472
473static unsigned
474positiveOffsetOpcode(unsigned opcode)
475{
476 switch (opcode) {
477 case ARM::t2LDRi8: return ARM::t2LDRi12;
478 case ARM::t2LDRHi8: return ARM::t2LDRHi12;
479 case ARM::t2LDRBi8: return ARM::t2LDRBi12;
480 case ARM::t2LDRSHi8: return ARM::t2LDRSHi12;
481 case ARM::t2LDRSBi8: return ARM::t2LDRSBi12;
482 case ARM::t2STRi8: return ARM::t2STRi12;
483 case ARM::t2STRBi8: return ARM::t2STRBi12;
484 case ARM::t2STRHi8: return ARM::t2STRHi12;
485 case ARM::t2PLDi8: return ARM::t2PLDi12;
486 case ARM::t2PLDWi8: return ARM::t2PLDWi12;
487 case ARM::t2PLIi8: return ARM::t2PLIi12;
488
489 case ARM::t2LDRi12:
490 case ARM::t2LDRHi12:
491 case ARM::t2LDRBi12:
492 case ARM::t2LDRSHi12:
493 case ARM::t2LDRSBi12:
494 case ARM::t2STRi12:
495 case ARM::t2STRBi12:
496 case ARM::t2STRHi12:
497 case ARM::t2PLDi12:
498 case ARM::t2PLDWi12:
499 case ARM::t2PLIi12:
500 return opcode;
501
502 default:
503 llvm_unreachable("unknown thumb2 opcode.");
504 }
505}
506
507static unsigned
508immediateOffsetOpcode(unsigned opcode)
509{
510 switch (opcode) {
511 case ARM::t2LDRs: return ARM::t2LDRi12;
512 case ARM::t2LDRHs: return ARM::t2LDRHi12;
513 case ARM::t2LDRBs: return ARM::t2LDRBi12;
514 case ARM::t2LDRSHs: return ARM::t2LDRSHi12;
515 case ARM::t2LDRSBs: return ARM::t2LDRSBi12;
516 case ARM::t2STRs: return ARM::t2STRi12;
517 case ARM::t2STRBs: return ARM::t2STRBi12;
518 case ARM::t2STRHs: return ARM::t2STRHi12;
519 case ARM::t2PLDs: return ARM::t2PLDi12;
520 case ARM::t2PLDWs: return ARM::t2PLDWi12;
521 case ARM::t2PLIs: return ARM::t2PLIi12;
522
523 case ARM::t2LDRi12:
524 case ARM::t2LDRHi12:
525 case ARM::t2LDRBi12:
526 case ARM::t2LDRSHi12:
527 case ARM::t2LDRSBi12:
528 case ARM::t2STRi12:
529 case ARM::t2STRBi12:
530 case ARM::t2STRHi12:
531 case ARM::t2PLDi12:
532 case ARM::t2PLDWi12:
533 case ARM::t2PLIi12:
534 case ARM::t2LDRi8:
535 case ARM::t2LDRHi8:
536 case ARM::t2LDRBi8:
537 case ARM::t2LDRSHi8:
538 case ARM::t2LDRSBi8:
539 case ARM::t2STRi8:
540 case ARM::t2STRBi8:
541 case ARM::t2STRHi8:
542 case ARM::t2PLDi8:
543 case ARM::t2PLDWi8:
544 case ARM::t2PLIi8:
545 return opcode;
546
547 default:
548 llvm_unreachable("unknown thumb2 opcode.");
549 }
550}
551
552bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
553 Register FrameReg, int &Offset,
554 const ARMBaseInstrInfo &TII,
555 const TargetRegisterInfo *TRI) {
556 unsigned Opcode = MI.getOpcode();
557 const MCInstrDesc &Desc = MI.getDesc();
558 unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
559 bool isSub = false;
560
561 MachineFunction &MF = *MI.getParent()->getParent();
562 const TargetRegisterClass *RegClass =
563 TII.getRegClass(Desc, FrameRegIdx, TRI, MF);
564
565 // Memory operands in inline assembly always use AddrModeT2_i12.
566 if (Opcode == ARM::INLINEASM || Opcode == ARM::INLINEASM_BR)
567 AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2?
568
569 const bool IsSP = Opcode == ARM::t2ADDspImm12 || Opcode == ARM::t2ADDspImm;
570 if (IsSP || Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) {
571 Offset += MI.getOperand(FrameRegIdx+1).getImm();
572
573 Register PredReg;
574 if (Offset == 0 && getInstrPredicate(MI, PredReg) == ARMCC::AL &&
575 !MI.definesRegister(ARM::CPSR, /*TRI=*/nullptr)) {
576 // Turn it into a move.
577 MI.setDesc(TII.get(ARM::tMOVr));
578 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
579 // Remove offset and remaining explicit predicate operands.
580 do MI.removeOperand(FrameRegIdx+1);
581 while (MI.getNumOperands() > FrameRegIdx+1);
582 MachineInstrBuilder MIB(*MI.getParent()->getParent(), &MI);
583 MIB.add(predOps(ARMCC::AL));
584 return true;
585 }
586
587 bool HasCCOut = (Opcode != ARM::t2ADDspImm12 && Opcode != ARM::t2ADDri12);
588
589 if (Offset < 0) {
590 Offset = -Offset;
591 isSub = true;
592 MI.setDesc(IsSP ? TII.get(ARM::t2SUBspImm) : TII.get(ARM::t2SUBri));
593 } else {
594 MI.setDesc(IsSP ? TII.get(ARM::t2ADDspImm) : TII.get(ARM::t2ADDri));
595 }
596
597 // Common case: small offset, fits into instruction.
598 if (ARM_AM::getT2SOImmVal(Offset) != -1) {
599 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
600 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
601 // Add cc_out operand if the original instruction did not have one.
602 if (!HasCCOut)
603 MI.addOperand(MachineOperand::CreateReg(0, false));
604 Offset = 0;
605 return true;
606 }
607 // Another common case: imm12.
608 if (Offset < 4096 &&
609 (!HasCCOut || MI.getOperand(MI.getNumOperands()-1).getReg() == 0)) {
610 unsigned NewOpc = isSub ? IsSP ? ARM::t2SUBspImm12 : ARM::t2SUBri12
611 : IsSP ? ARM::t2ADDspImm12 : ARM::t2ADDri12;
612 MI.setDesc(TII.get(NewOpc));
613 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
614 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
615 // Remove the cc_out operand.
616 if (HasCCOut)
617 MI.removeOperand(MI.getNumOperands()-1);
618 Offset = 0;
619 return true;
620 }
621
622 // Otherwise, extract 8 adjacent bits from the immediate into this
623 // t2ADDri/t2SUBri.
624 unsigned RotAmt = llvm::countl_zero<unsigned>(Offset);
625 unsigned ThisImmVal = Offset & llvm::rotr<uint32_t>(0xff000000U, RotAmt);
626
627 // We will handle these bits from offset, clear them.
628 Offset &= ~ThisImmVal;
629
630 assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 &&
631 "Bit extraction didn't work?");
632 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
633 // Add cc_out operand if the original instruction did not have one.
634 if (!HasCCOut)
635 MI.addOperand(MachineOperand::CreateReg(0, false));
636 } else {
637 // AddrMode4 and AddrMode6 cannot handle any offset.
639 return false;
640
641 // AddrModeT2_so cannot handle any offset. If there is no offset
642 // register then we change to an immediate version.
643 unsigned NewOpc = Opcode;
645 Register OffsetReg = MI.getOperand(FrameRegIdx + 1).getReg();
646 if (OffsetReg != 0) {
647 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
648 return Offset == 0;
649 }
650
651 MI.removeOperand(FrameRegIdx+1);
652 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0);
653 NewOpc = immediateOffsetOpcode(Opcode);
655 }
656
657 unsigned NumBits = 0;
658 unsigned Scale = 1;
661 // i8 supports only negative, and i12 supports only positive, so
662 // based on Offset sign convert Opcode to the appropriate
663 // instruction
664 Offset += MI.getOperand(FrameRegIdx+1).getImm();
665 if (Offset < 0) {
666 NewOpc = negativeOffsetOpcode(Opcode);
667 NumBits = 8;
668 isSub = true;
669 Offset = -Offset;
670 } else {
671 NewOpc = positiveOffsetOpcode(Opcode);
672 NumBits = 12;
673 }
674 } else if (AddrMode == ARMII::AddrMode5) {
675 // VFP address mode.
676 const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1);
677 int InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm());
678 if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub)
679 InstrOffs *= -1;
680 NumBits = 8;
681 Scale = 4;
682 Offset += InstrOffs * 4;
683 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
684 if (Offset < 0) {
685 Offset = -Offset;
686 isSub = true;
687 }
688 } else if (AddrMode == ARMII::AddrMode5FP16) {
689 // VFP address mode.
690 const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1);
691 int InstrOffs = ARM_AM::getAM5FP16Offset(OffOp.getImm());
693 InstrOffs *= -1;
694 NumBits = 8;
695 Scale = 2;
696 Offset += InstrOffs * 2;
697 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
698 if (Offset < 0) {
699 Offset = -Offset;
700 isSub = true;
701 }
702 } else if (AddrMode == ARMII::AddrModeT2_i7s4 ||
705 Offset += MI.getOperand(FrameRegIdx + 1).getImm();
706 unsigned OffsetMask;
707 switch (AddrMode) {
708 case ARMII::AddrModeT2_i7s4: NumBits = 9; OffsetMask = 0x3; break;
709 case ARMII::AddrModeT2_i7s2: NumBits = 8; OffsetMask = 0x1; break;
710 default: NumBits = 7; OffsetMask = 0x0; break;
711 }
712 // MCInst operand expects already scaled value.
713 Scale = 1;
714 assert((Offset & OffsetMask) == 0 && "Can't encode this offset!");
715 (void)OffsetMask; // squash unused-variable warning at -NDEBUG
716 } else if (AddrMode == ARMII::AddrModeT2_i8s4) {
717 Offset += MI.getOperand(FrameRegIdx + 1).getImm();
718 NumBits = 8 + 2;
719 // MCInst operand expects already scaled value.
720 Scale = 1;
721 assert((Offset & 3) == 0 && "Can't encode this offset!");
722 } else if (AddrMode == ARMII::AddrModeT2_ldrex) {
723 Offset += MI.getOperand(FrameRegIdx + 1).getImm() * 4;
724 NumBits = 8; // 8 bits scaled by 4
725 Scale = 4;
726 assert((Offset & 3) == 0 && "Can't encode this offset!");
727 } else {
728 llvm_unreachable("Unsupported addressing mode!");
729 }
730
731 if (NewOpc != Opcode)
732 MI.setDesc(TII.get(NewOpc));
733
734 MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1);
735
736 // Attempt to fold address computation
737 // Common case: small offset, fits into instruction. We need to make sure
738 // the register class is correct too, for instructions like the MVE
739 // VLDRH.32, which only accepts low tGPR registers.
740 int ImmedOffset = Offset / Scale;
741 unsigned Mask = (1 << NumBits) - 1;
742 if ((unsigned)Offset <= Mask * Scale &&
743 (FrameReg.isVirtual() || RegClass->contains(FrameReg))) {
744 if (FrameReg.isVirtual()) {
745 // Make sure the register class for the virtual register is correct
747 if (!MRI->constrainRegClass(FrameReg, RegClass))
748 llvm_unreachable("Unable to constrain virtual register class.");
749 }
750
751 // Replace the FrameIndex with fp/sp
752 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
753 if (isSub) {
755 // FIXME: Not consistent.
756 ImmedOffset |= 1 << NumBits;
757 else
758 ImmedOffset = -ImmedOffset;
759 }
760 ImmOp.ChangeToImmediate(ImmedOffset);
761 Offset = 0;
762 return true;
763 }
764
765 // Otherwise, offset doesn't fit. Pull in what we can to simplify
766 ImmedOffset = ImmedOffset & Mask;
767 if (isSub) {
769 // FIXME: Not consistent.
770 ImmedOffset |= 1 << NumBits;
771 else {
772 ImmedOffset = -ImmedOffset;
773 if (ImmedOffset == 0)
774 // Change the opcode back if the encoded offset is zero.
775 MI.setDesc(TII.get(positiveOffsetOpcode(NewOpc)));
776 }
777 }
778 ImmOp.ChangeToImmediate(ImmedOffset);
779 Offset &= ~(Mask*Scale);
780 }
781
782 Offset = (isSub) ? -Offset : Offset;
783 return Offset == 0 && (FrameReg.isVirtual() || RegClass->contains(FrameReg));
784}
785
787 Register &PredReg) {
788 unsigned Opc = MI.getOpcode();
789 if (Opc == ARM::tBcc || Opc == ARM::t2Bcc)
790 return ARMCC::AL;
791 return getInstrPredicate(MI, PredReg);
792}
793
795 const MCInstrDesc &MCID = MI.getDesc();
796
797 for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i)
798 if (ARM::isVpred(MCID.operands()[i].OperandType))
799 return i;
800
801 return -1;
802}
803
805 Register &PredReg) {
806 int PIdx = findFirstVPTPredOperandIdx(MI);
807 if (PIdx == -1) {
808 PredReg = 0;
809 return ARMVCC::None;
810 }
811
812 PredReg = MI.getOperand(PIdx+1).getReg();
813 return (ARMVCC::VPTCodes)MI.getOperand(PIdx).getImm();
814}
815
817 assert(isVPTOpcode(Instr.getOpcode()) && "Not a VPST or VPT Instruction!");
818
819 MachineOperand &MaskOp = Instr.getOperand(0);
820 assert(MaskOp.isImm() && "Operand 0 is not the block mask of the VPT/VPST?!");
821
822 MachineBasicBlock::iterator Iter = ++Instr.getIterator(),
823 End = Instr.getParent()->end();
824
825 while (Iter != End && Iter->isDebugInstr())
826 ++Iter;
827
828 // Verify that the instruction after the VPT/VPST is predicated (it should
829 // be), and skip it.
830 assert(Iter != End && "Expected some instructions in any VPT block");
831 assert(
833 "VPT/VPST should be followed by an instruction with a 'then' predicate!");
834 ++Iter;
835
836 // Iterate over the predicated instructions, updating the BlockMask as we go.
838 while (Iter != End) {
839 if (Iter->isDebugInstr()) {
840 ++Iter;
841 continue;
842 }
844 if (Pred == ARMVCC::None)
845 break;
846 BlockMask = expandPredBlockMask(BlockMask, Pred);
847 ++Iter;
848 }
849
850 // Rewrite the BlockMask.
851 MaskOp.setImm((int64_t)(BlockMask));
852}
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
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
Module.h This file contains the declarations for the Module class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc) 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) 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
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
Definition: ARMSubtarget.h:311
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(unsigned 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:184
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.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
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:346
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:367
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 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.
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc) 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.
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:18
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.