LLVM 19.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/MC/MCInst.h"
29#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) const {
154 // Handle SPR, DPR, and QPR copies.
155 if (!ARM::GPRRegClass.contains(DestReg, SrcReg))
156 return ARMBaseInstrInfo::copyPhysReg(MBB, I, DL, DestReg, SrcReg, KillSrc);
157
158 BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg)
159 .addReg(SrcReg, getKillRegState(KillSrc))
161}
162
165 Register SrcReg, bool isKill, int FI,
166 const TargetRegisterClass *RC,
167 const TargetRegisterInfo *TRI,
168 Register VReg) const {
169 DebugLoc DL;
170 if (I != MBB.end()) DL = I->getDebugLoc();
171
173 MachineFrameInfo &MFI = MF.getFrameInfo();
176 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
177
178 if (ARM::GPRRegClass.hasSubClassEq(RC)) {
179 BuildMI(MBB, I, DL, get(ARM::t2STRi12))
180 .addReg(SrcReg, getKillRegState(isKill))
181 .addFrameIndex(FI)
182 .addImm(0)
183 .addMemOperand(MMO)
185 return;
186 }
187
188 if (ARM::GPRPairRegClass.hasSubClassEq(RC)) {
189 // Thumb2 STRD expects its dest-registers to be in rGPR. Not a problem for
190 // gsub_0, but needs an extra constraint for gsub_1 (which could be sp
191 // otherwise).
192 if (SrcReg.isVirtual()) {
194 MRI->constrainRegClass(SrcReg, &ARM::GPRPairnospRegClass);
195 }
196
197 MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(ARM::t2STRDi8));
198 AddDReg(MIB, SrcReg, ARM::gsub_0, getKillRegState(isKill), TRI);
199 AddDReg(MIB, SrcReg, ARM::gsub_1, 0, TRI);
201 return;
202 }
203
204 ARMBaseInstrInfo::storeRegToStackSlot(MBB, I, SrcReg, isKill, FI, RC, TRI,
205 Register());
206}
207
210 Register DestReg, int FI,
211 const TargetRegisterClass *RC,
212 const TargetRegisterInfo *TRI,
213 Register VReg) 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 if (MF.getSubtarget<ARMSubtarget>().isTargetELF() && !GV->isDSOLocal())
266 expandLoadStackGuardBase(MI, ARM::t2LDRLIT_ga_pcrel, ARM::t2LDRi12);
267 else if (MF.getTarget().isPositionIndependent())
268 expandLoadStackGuardBase(MI, ARM::t2MOV_ga_pcrel, ARM::t2LDRi12);
269 else
270 expandLoadStackGuardBase(MI, ARM::t2MOVi32imm, ARM::t2LDRi12);
271}
272
274 bool NewMI,
275 unsigned OpIdx1,
276 unsigned OpIdx2) const {
277 switch (MI.getOpcode()) {
278 case ARM::MVE_VMAXNMAf16:
279 case ARM::MVE_VMAXNMAf32:
280 case ARM::MVE_VMINNMAf16:
281 case ARM::MVE_VMINNMAf32:
282 // Don't allow predicated instructions to be commuted.
284 return nullptr;
285 }
286 return ARMBaseInstrInfo::commuteInstructionImpl(MI, NewMI, OpIdx1, OpIdx2);
287}
288
290 const MachineBasicBlock *MBB,
291 const MachineFunction &MF) const {
292 // BTI clearing instructions shall not take part in scheduling regions as
293 // they must stay in their intended place. Although PAC isn't BTI clearing,
294 // it can be transformed into PACBTI after the pre-RA Machine Scheduling
295 // has taken place, so its movement must also be restricted.
296 switch (MI.getOpcode()) {
297 case ARM::t2BTI:
298 case ARM::t2PAC:
299 case ARM::t2PACBTI:
300 case ARM::t2SG:
301 return true;
302 default:
303 break;
304 }
306}
307
310 const DebugLoc &dl, Register DestReg,
311 Register BaseReg, int NumBytes,
312 ARMCC::CondCodes Pred, Register PredReg,
313 const ARMBaseInstrInfo &TII,
314 unsigned MIFlags) {
315 if (NumBytes == 0 && DestReg != BaseReg) {
316 BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)
317 .addReg(BaseReg, RegState::Kill)
318 .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);
319 return;
320 }
321
322 bool isSub = NumBytes < 0;
323 if (isSub) NumBytes = -NumBytes;
324
325 // If profitable, use a movw or movt to materialize the offset.
326 // FIXME: Use the scavenger to grab a scratch register.
327 if (DestReg != ARM::SP && DestReg != BaseReg &&
328 NumBytes >= 4096 &&
329 ARM_AM::getT2SOImmVal(NumBytes) == -1) {
330 bool Fits = false;
331 if (NumBytes < 65536) {
332 // Use a movw to materialize the 16-bit constant.
333 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVi16), DestReg)
334 .addImm(NumBytes)
335 .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);
336 Fits = true;
337 } else if ((NumBytes & 0xffff) == 0) {
338 // Use a movt to materialize the 32-bit constant.
339 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2MOVTi16), DestReg)
340 .addReg(DestReg)
341 .addImm(NumBytes >> 16)
342 .addImm((unsigned)Pred).addReg(PredReg).setMIFlags(MIFlags);
343 Fits = true;
344 }
345
346 if (Fits) {
347 if (isSub) {
348 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2SUBrr), DestReg)
349 .addReg(BaseReg)
350 .addReg(DestReg, RegState::Kill)
351 .add(predOps(Pred, PredReg))
352 .add(condCodeOp())
353 .setMIFlags(MIFlags);
354 } else {
355 // Here we know that DestReg is not SP but we do not
356 // know anything about BaseReg. t2ADDrr is an invalid
357 // instruction is SP is used as the second argument, but
358 // is fine if SP is the first argument. To be sure we
359 // do not generate invalid encoding, put BaseReg first.
360 BuildMI(MBB, MBBI, dl, TII.get(ARM::t2ADDrr), DestReg)
361 .addReg(BaseReg)
362 .addReg(DestReg, RegState::Kill)
363 .add(predOps(Pred, PredReg))
364 .add(condCodeOp())
365 .setMIFlags(MIFlags);
366 }
367 return;
368 }
369 }
370
371 while (NumBytes) {
372 unsigned ThisVal = NumBytes;
373 unsigned Opc = 0;
374 if (DestReg == ARM::SP && BaseReg != ARM::SP) {
375 // mov sp, rn. Note t2MOVr cannot be used.
376 BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), DestReg)
377 .addReg(BaseReg)
378 .setMIFlags(MIFlags)
380 BaseReg = ARM::SP;
381 continue;
382 }
383
384 assert((DestReg != ARM::SP || BaseReg == ARM::SP) &&
385 "Writing to SP, from other register.");
386
387 // Try to use T1, as it smaller
388 if ((DestReg == ARM::SP) && (ThisVal < ((1 << 7) - 1) * 4)) {
389 assert((ThisVal & 3) == 0 && "Stack update is not multiple of 4?");
390 Opc = isSub ? ARM::tSUBspi : ARM::tADDspi;
391 BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
392 .addReg(BaseReg)
393 .addImm(ThisVal / 4)
394 .setMIFlags(MIFlags)
396 break;
397 }
398 bool HasCCOut = true;
399 int ImmIsT2SO = ARM_AM::getT2SOImmVal(ThisVal);
400 bool ToSP = DestReg == ARM::SP;
401 unsigned t2SUB = ToSP ? ARM::t2SUBspImm : ARM::t2SUBri;
402 unsigned t2ADD = ToSP ? ARM::t2ADDspImm : ARM::t2ADDri;
403 unsigned t2SUBi12 = ToSP ? ARM::t2SUBspImm12 : ARM::t2SUBri12;
404 unsigned t2ADDi12 = ToSP ? ARM::t2ADDspImm12 : ARM::t2ADDri12;
405 Opc = isSub ? t2SUB : t2ADD;
406 // Prefer T2: sub rd, rn, so_imm | sub sp, sp, so_imm
407 if (ImmIsT2SO != -1) {
408 NumBytes = 0;
409 } else if (ThisVal < 4096) {
410 // Prefer T3 if can make it in a single go: subw rd, rn, imm12 | subw sp,
411 // sp, imm12
412 Opc = isSub ? t2SUBi12 : t2ADDi12;
413 HasCCOut = false;
414 NumBytes = 0;
415 } else {
416 // Use one T2 instruction to reduce NumBytes
417 // FIXME: Move this to ARMAddressingModes.h?
418 unsigned RotAmt = llvm::countl_zero(ThisVal);
419 ThisVal = ThisVal & llvm::rotr<uint32_t>(0xff000000U, RotAmt);
420 NumBytes &= ~ThisVal;
421 assert(ARM_AM::getT2SOImmVal(ThisVal) != -1 &&
422 "Bit extraction didn't work?");
423 }
424
425 // Build the new ADD / SUB.
426 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg)
427 .addReg(BaseReg, RegState::Kill)
428 .addImm(ThisVal)
430 .setMIFlags(MIFlags);
431 if (HasCCOut)
432 MIB.add(condCodeOp());
433
434 BaseReg = DestReg;
435 }
436}
437
438static unsigned
439negativeOffsetOpcode(unsigned opcode)
440{
441 switch (opcode) {
442 case ARM::t2LDRi12: return ARM::t2LDRi8;
443 case ARM::t2LDRHi12: return ARM::t2LDRHi8;
444 case ARM::t2LDRBi12: return ARM::t2LDRBi8;
445 case ARM::t2LDRSHi12: return ARM::t2LDRSHi8;
446 case ARM::t2LDRSBi12: return ARM::t2LDRSBi8;
447 case ARM::t2STRi12: return ARM::t2STRi8;
448 case ARM::t2STRBi12: return ARM::t2STRBi8;
449 case ARM::t2STRHi12: return ARM::t2STRHi8;
450 case ARM::t2PLDi12: return ARM::t2PLDi8;
451 case ARM::t2PLDWi12: return ARM::t2PLDWi8;
452 case ARM::t2PLIi12: return ARM::t2PLIi8;
453
454 case ARM::t2LDRi8:
455 case ARM::t2LDRHi8:
456 case ARM::t2LDRBi8:
457 case ARM::t2LDRSHi8:
458 case ARM::t2LDRSBi8:
459 case ARM::t2STRi8:
460 case ARM::t2STRBi8:
461 case ARM::t2STRHi8:
462 case ARM::t2PLDi8:
463 case ARM::t2PLDWi8:
464 case ARM::t2PLIi8:
465 return opcode;
466
467 default:
468 llvm_unreachable("unknown thumb2 opcode.");
469 }
470}
471
472static unsigned
473positiveOffsetOpcode(unsigned opcode)
474{
475 switch (opcode) {
476 case ARM::t2LDRi8: return ARM::t2LDRi12;
477 case ARM::t2LDRHi8: return ARM::t2LDRHi12;
478 case ARM::t2LDRBi8: return ARM::t2LDRBi12;
479 case ARM::t2LDRSHi8: return ARM::t2LDRSHi12;
480 case ARM::t2LDRSBi8: return ARM::t2LDRSBi12;
481 case ARM::t2STRi8: return ARM::t2STRi12;
482 case ARM::t2STRBi8: return ARM::t2STRBi12;
483 case ARM::t2STRHi8: return ARM::t2STRHi12;
484 case ARM::t2PLDi8: return ARM::t2PLDi12;
485 case ARM::t2PLDWi8: return ARM::t2PLDWi12;
486 case ARM::t2PLIi8: return ARM::t2PLIi12;
487
488 case ARM::t2LDRi12:
489 case ARM::t2LDRHi12:
490 case ARM::t2LDRBi12:
491 case ARM::t2LDRSHi12:
492 case ARM::t2LDRSBi12:
493 case ARM::t2STRi12:
494 case ARM::t2STRBi12:
495 case ARM::t2STRHi12:
496 case ARM::t2PLDi12:
497 case ARM::t2PLDWi12:
498 case ARM::t2PLIi12:
499 return opcode;
500
501 default:
502 llvm_unreachable("unknown thumb2 opcode.");
503 }
504}
505
506static unsigned
507immediateOffsetOpcode(unsigned opcode)
508{
509 switch (opcode) {
510 case ARM::t2LDRs: return ARM::t2LDRi12;
511 case ARM::t2LDRHs: return ARM::t2LDRHi12;
512 case ARM::t2LDRBs: return ARM::t2LDRBi12;
513 case ARM::t2LDRSHs: return ARM::t2LDRSHi12;
514 case ARM::t2LDRSBs: return ARM::t2LDRSBi12;
515 case ARM::t2STRs: return ARM::t2STRi12;
516 case ARM::t2STRBs: return ARM::t2STRBi12;
517 case ARM::t2STRHs: return ARM::t2STRHi12;
518 case ARM::t2PLDs: return ARM::t2PLDi12;
519 case ARM::t2PLDWs: return ARM::t2PLDWi12;
520 case ARM::t2PLIs: return ARM::t2PLIi12;
521
522 case ARM::t2LDRi12:
523 case ARM::t2LDRHi12:
524 case ARM::t2LDRBi12:
525 case ARM::t2LDRSHi12:
526 case ARM::t2LDRSBi12:
527 case ARM::t2STRi12:
528 case ARM::t2STRBi12:
529 case ARM::t2STRHi12:
530 case ARM::t2PLDi12:
531 case ARM::t2PLDWi12:
532 case ARM::t2PLIi12:
533 case ARM::t2LDRi8:
534 case ARM::t2LDRHi8:
535 case ARM::t2LDRBi8:
536 case ARM::t2LDRSHi8:
537 case ARM::t2LDRSBi8:
538 case ARM::t2STRi8:
539 case ARM::t2STRBi8:
540 case ARM::t2STRHi8:
541 case ARM::t2PLDi8:
542 case ARM::t2PLDWi8:
543 case ARM::t2PLIi8:
544 return opcode;
545
546 default:
547 llvm_unreachable("unknown thumb2 opcode.");
548 }
549}
550
551bool llvm::rewriteT2FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
552 Register FrameReg, int &Offset,
553 const ARMBaseInstrInfo &TII,
554 const TargetRegisterInfo *TRI) {
555 unsigned Opcode = MI.getOpcode();
556 const MCInstrDesc &Desc = MI.getDesc();
557 unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
558 bool isSub = false;
559
560 MachineFunction &MF = *MI.getParent()->getParent();
561 const TargetRegisterClass *RegClass =
562 TII.getRegClass(Desc, FrameRegIdx, TRI, MF);
563
564 // Memory operands in inline assembly always use AddrModeT2_i12.
565 if (Opcode == ARM::INLINEASM || Opcode == ARM::INLINEASM_BR)
566 AddrMode = ARMII::AddrModeT2_i12; // FIXME. mode for thumb2?
567
568 const bool IsSP = Opcode == ARM::t2ADDspImm12 || Opcode == ARM::t2ADDspImm;
569 if (IsSP || Opcode == ARM::t2ADDri || Opcode == ARM::t2ADDri12) {
570 Offset += MI.getOperand(FrameRegIdx+1).getImm();
571
572 Register PredReg;
573 if (Offset == 0 && getInstrPredicate(MI, PredReg) == ARMCC::AL &&
574 !MI.definesRegister(ARM::CPSR)) {
575 // Turn it into a move.
576 MI.setDesc(TII.get(ARM::tMOVr));
577 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
578 // Remove offset and remaining explicit predicate operands.
579 do MI.removeOperand(FrameRegIdx+1);
580 while (MI.getNumOperands() > FrameRegIdx+1);
581 MachineInstrBuilder MIB(*MI.getParent()->getParent(), &MI);
582 MIB.add(predOps(ARMCC::AL));
583 return true;
584 }
585
586 bool HasCCOut = (Opcode != ARM::t2ADDspImm12 && Opcode != ARM::t2ADDri12);
587
588 if (Offset < 0) {
589 Offset = -Offset;
590 isSub = true;
591 MI.setDesc(IsSP ? TII.get(ARM::t2SUBspImm) : TII.get(ARM::t2SUBri));
592 } else {
593 MI.setDesc(IsSP ? TII.get(ARM::t2ADDspImm) : TII.get(ARM::t2ADDri));
594 }
595
596 // Common case: small offset, fits into instruction.
597 if (ARM_AM::getT2SOImmVal(Offset) != -1) {
598 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
599 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
600 // Add cc_out operand if the original instruction did not have one.
601 if (!HasCCOut)
602 MI.addOperand(MachineOperand::CreateReg(0, false));
603 Offset = 0;
604 return true;
605 }
606 // Another common case: imm12.
607 if (Offset < 4096 &&
608 (!HasCCOut || MI.getOperand(MI.getNumOperands()-1).getReg() == 0)) {
609 unsigned NewOpc = isSub ? IsSP ? ARM::t2SUBspImm12 : ARM::t2SUBri12
610 : IsSP ? ARM::t2ADDspImm12 : ARM::t2ADDri12;
611 MI.setDesc(TII.get(NewOpc));
612 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
613 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(Offset);
614 // Remove the cc_out operand.
615 if (HasCCOut)
616 MI.removeOperand(MI.getNumOperands()-1);
617 Offset = 0;
618 return true;
619 }
620
621 // Otherwise, extract 8 adjacent bits from the immediate into this
622 // t2ADDri/t2SUBri.
623 unsigned RotAmt = llvm::countl_zero<unsigned>(Offset);
624 unsigned ThisImmVal = Offset & llvm::rotr<uint32_t>(0xff000000U, RotAmt);
625
626 // We will handle these bits from offset, clear them.
627 Offset &= ~ThisImmVal;
628
629 assert(ARM_AM::getT2SOImmVal(ThisImmVal) != -1 &&
630 "Bit extraction didn't work?");
631 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(ThisImmVal);
632 // Add cc_out operand if the original instruction did not have one.
633 if (!HasCCOut)
634 MI.addOperand(MachineOperand::CreateReg(0, false));
635 } else {
636 // AddrMode4 and AddrMode6 cannot handle any offset.
638 return false;
639
640 // AddrModeT2_so cannot handle any offset. If there is no offset
641 // register then we change to an immediate version.
642 unsigned NewOpc = Opcode;
644 Register OffsetReg = MI.getOperand(FrameRegIdx + 1).getReg();
645 if (OffsetReg != 0) {
646 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
647 return Offset == 0;
648 }
649
650 MI.removeOperand(FrameRegIdx+1);
651 MI.getOperand(FrameRegIdx+1).ChangeToImmediate(0);
652 NewOpc = immediateOffsetOpcode(Opcode);
654 }
655
656 unsigned NumBits = 0;
657 unsigned Scale = 1;
660 // i8 supports only negative, and i12 supports only positive, so
661 // based on Offset sign convert Opcode to the appropriate
662 // instruction
663 Offset += MI.getOperand(FrameRegIdx+1).getImm();
664 if (Offset < 0) {
665 NewOpc = negativeOffsetOpcode(Opcode);
666 NumBits = 8;
667 isSub = true;
668 Offset = -Offset;
669 } else {
670 NewOpc = positiveOffsetOpcode(Opcode);
671 NumBits = 12;
672 }
673 } else if (AddrMode == ARMII::AddrMode5) {
674 // VFP address mode.
675 const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1);
676 int InstrOffs = ARM_AM::getAM5Offset(OffOp.getImm());
677 if (ARM_AM::getAM5Op(OffOp.getImm()) == ARM_AM::sub)
678 InstrOffs *= -1;
679 NumBits = 8;
680 Scale = 4;
681 Offset += InstrOffs * 4;
682 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
683 if (Offset < 0) {
684 Offset = -Offset;
685 isSub = true;
686 }
687 } else if (AddrMode == ARMII::AddrMode5FP16) {
688 // VFP address mode.
689 const MachineOperand &OffOp = MI.getOperand(FrameRegIdx+1);
690 int InstrOffs = ARM_AM::getAM5FP16Offset(OffOp.getImm());
692 InstrOffs *= -1;
693 NumBits = 8;
694 Scale = 2;
695 Offset += InstrOffs * 2;
696 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
697 if (Offset < 0) {
698 Offset = -Offset;
699 isSub = true;
700 }
701 } else if (AddrMode == ARMII::AddrModeT2_i7s4 ||
704 Offset += MI.getOperand(FrameRegIdx + 1).getImm();
705 unsigned OffsetMask;
706 switch (AddrMode) {
707 case ARMII::AddrModeT2_i7s4: NumBits = 9; OffsetMask = 0x3; break;
708 case ARMII::AddrModeT2_i7s2: NumBits = 8; OffsetMask = 0x1; break;
709 default: NumBits = 7; OffsetMask = 0x0; break;
710 }
711 // MCInst operand expects already scaled value.
712 Scale = 1;
713 assert((Offset & OffsetMask) == 0 && "Can't encode this offset!");
714 (void)OffsetMask; // squash unused-variable warning at -NDEBUG
715 } else if (AddrMode == ARMII::AddrModeT2_i8s4) {
716 Offset += MI.getOperand(FrameRegIdx + 1).getImm();
717 NumBits = 8 + 2;
718 // MCInst operand expects already scaled value.
719 Scale = 1;
720 assert((Offset & 3) == 0 && "Can't encode this offset!");
721 } else if (AddrMode == ARMII::AddrModeT2_ldrex) {
722 Offset += MI.getOperand(FrameRegIdx + 1).getImm() * 4;
723 NumBits = 8; // 8 bits scaled by 4
724 Scale = 4;
725 assert((Offset & 3) == 0 && "Can't encode this offset!");
726 } else {
727 llvm_unreachable("Unsupported addressing mode!");
728 }
729
730 if (NewOpc != Opcode)
731 MI.setDesc(TII.get(NewOpc));
732
733 MachineOperand &ImmOp = MI.getOperand(FrameRegIdx+1);
734
735 // Attempt to fold address computation
736 // Common case: small offset, fits into instruction. We need to make sure
737 // the register class is correct too, for instructions like the MVE
738 // VLDRH.32, which only accepts low tGPR registers.
739 int ImmedOffset = Offset / Scale;
740 unsigned Mask = (1 << NumBits) - 1;
741 if ((unsigned)Offset <= Mask * Scale &&
742 (FrameReg.isVirtual() || RegClass->contains(FrameReg))) {
743 if (FrameReg.isVirtual()) {
744 // Make sure the register class for the virtual register is correct
746 if (!MRI->constrainRegClass(FrameReg, RegClass))
747 llvm_unreachable("Unable to constrain virtual register class.");
748 }
749
750 // Replace the FrameIndex with fp/sp
751 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
752 if (isSub) {
754 // FIXME: Not consistent.
755 ImmedOffset |= 1 << NumBits;
756 else
757 ImmedOffset = -ImmedOffset;
758 }
759 ImmOp.ChangeToImmediate(ImmedOffset);
760 Offset = 0;
761 return true;
762 }
763
764 // Otherwise, offset doesn't fit. Pull in what we can to simplify
765 ImmedOffset = ImmedOffset & Mask;
766 if (isSub) {
768 // FIXME: Not consistent.
769 ImmedOffset |= 1 << NumBits;
770 else {
771 ImmedOffset = -ImmedOffset;
772 if (ImmedOffset == 0)
773 // Change the opcode back if the encoded offset is zero.
774 MI.setDesc(TII.get(positiveOffsetOpcode(NewOpc)));
775 }
776 }
777 ImmOp.ChangeToImmediate(ImmedOffset);
778 Offset &= ~(Mask*Scale);
779 }
780
781 Offset = (isSub) ? -Offset : Offset;
782 return Offset == 0 && (FrameReg.isVirtual() || RegClass->contains(FrameReg));
783}
784
786 Register &PredReg) {
787 unsigned Opc = MI.getOpcode();
788 if (Opc == ARM::tBcc || Opc == ARM::t2Bcc)
789 return ARMCC::AL;
790 return getInstrPredicate(MI, PredReg);
791}
792
794 const MCInstrDesc &MCID = MI.getDesc();
795
796 for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i)
797 if (ARM::isVpred(MCID.operands()[i].OperandType))
798 return i;
799
800 return -1;
801}
802
804 Register &PredReg) {
805 int PIdx = findFirstVPTPredOperandIdx(MI);
806 if (PIdx == -1) {
807 PredReg = 0;
808 return ARMVCC::None;
809 }
810
811 PredReg = MI.getOperand(PIdx+1).getReg();
812 return (ARMVCC::VPTCodes)MI.getOperand(PIdx).getImm();
813}
814
816 assert(isVPTOpcode(Instr.getOpcode()) && "Not a VPST or VPT Instruction!");
817
818 MachineOperand &MaskOp = Instr.getOperand(0);
819 assert(MaskOp.isImm() && "Operand 0 is not the block mask of the VPT/VPST?!");
820
821 MachineBasicBlock::iterator Iter = ++Instr.getIterator(),
822 End = Instr.getParent()->end();
823
824 while (Iter != End && Iter->isDebugInstr())
825 ++Iter;
826
827 // Verify that the instruction after the VPT/VPST is predicated (it should
828 // be), and skip it.
829 assert(Iter != End && "Expected some instructions in any VPT block");
830 assert(
832 "VPT/VPST should be followed by an instruction with a 'then' predicate!");
833 ++Iter;
834
835 // Iterate over the predicated instructions, updating the BlockMask as we go.
837 while (Iter != End) {
838 if (Iter->isDebugInstr()) {
839 ++Iter;
840 continue;
841 }
843 if (Pred == ARMVCC::None)
844 break;
845 BlockMask = expandPredBlockMask(BlockMask, Pred);
846 ++Iter;
847 }
848
849 // Rewrite the BlockMask.
850 MaskOp.setImm((int64_t)(BlockMask));
851}
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
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:381
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:321
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:342
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:450
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
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.