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