1 //===- Thumb2InstrInfo.cpp - Thumb-2 Instruction Information --------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains the Thumb-2 implementation of the TargetInstrInfo class.
11 //===----------------------------------------------------------------------===//
13 #include "Thumb2InstrInfo.h"
14 #include "ARMMachineFunctionInfo.h"
15 #include "ARMSubtarget.h"
16 #include "MCTargetDesc/ARMAddressingModes.h"
17 #include "llvm/CodeGen/MachineBasicBlock.h"
18 #include "llvm/CodeGen/MachineFrameInfo.h"
19 #include "llvm/CodeGen/MachineFunction.h"
20 #include "llvm/CodeGen/MachineInstr.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/CodeGen/MachineMemOperand.h"
23 #include "llvm/CodeGen/MachineOperand.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #include "llvm/CodeGen/TargetRegisterInfo.h"
26 #include "llvm/IR/DebugLoc.h"
27 #include "llvm/MC/MCInst.h"
28 #include "llvm/MC/MCInstBuilder.h"
29 #include "llvm/MC/MCInstrDesc.h"
30 #include "llvm/Support/CommandLine.h"
31 #include "llvm/Support/ErrorHandling.h"
32 #include "llvm/Support/MathExtras.h"
33 #include "llvm/Target/TargetMachine.h"
39 OldT2IfCvt("old-thumb2-ifcvt", cl::Hidden
,
40 cl::desc("Use old-style Thumb2 if-conversion heuristics"),
44 PreferNoCSEL("prefer-no-csel", cl::Hidden
,
45 cl::desc("Prefer predicated Move to CSEL"),
48 Thumb2InstrInfo::Thumb2InstrInfo(const ARMSubtarget
&STI
)
49 : ARMBaseInstrInfo(STI
) {}
51 /// Return the noop instruction to use for a noop.
52 MCInst
Thumb2InstrInfo::getNop() const {
53 return MCInstBuilder(ARM::tHINT
).addImm(0).addImm(ARMCC::AL
).addReg(0);
56 unsigned Thumb2InstrInfo::getUnindexedOpcode(unsigned Opc
) const {
62 Thumb2InstrInfo::ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail
,
63 MachineBasicBlock
*NewDest
) const {
64 MachineBasicBlock
*MBB
= Tail
->getParent();
65 ARMFunctionInfo
*AFI
= MBB
->getParent()->getInfo
<ARMFunctionInfo
>();
66 if (!AFI
->hasITBlocks() || Tail
->isBranch()) {
67 TargetInstrInfo::ReplaceTailWithBranchTo(Tail
, NewDest
);
71 // If the first instruction of Tail is predicated, we may have to update
72 // the IT instruction.
74 ARMCC::CondCodes CC
= getInstrPredicate(*Tail
, PredReg
);
75 MachineBasicBlock::iterator MBBI
= Tail
;
77 // Expecting at least the t2IT instruction before it.
80 // Actually replace the tail.
81 TargetInstrInfo::ReplaceTailWithBranchTo(Tail
, NewDest
);
84 if (CC
!= ARMCC::AL
) {
85 MachineBasicBlock::iterator E
= MBB
->begin();
86 unsigned Count
= 4; // At most 4 instructions in an IT block.
87 while (Count
&& MBBI
!= E
) {
88 if (MBBI
->isDebugInstr()) {
92 if (MBBI
->getOpcode() == ARM::t2IT
) {
93 unsigned Mask
= MBBI
->getOperand(1).getImm();
95 MBBI
->eraseFromParent();
97 unsigned MaskOn
= 1 << Count
;
98 unsigned MaskOff
= ~(MaskOn
- 1);
99 MBBI
->getOperand(1).setImm((Mask
& MaskOff
) | MaskOn
);
107 // Ctrl flow can reach here if branch folding is run before IT block
113 Thumb2InstrInfo::isLegalToSplitMBBAt(MachineBasicBlock
&MBB
,
114 MachineBasicBlock::iterator MBBI
) const {
115 while (MBBI
->isDebugInstr()) {
117 if (MBBI
== MBB
.end())
122 return getITInstrPredicate(*MBBI
, PredReg
) == ARMCC::AL
;
126 Thumb2InstrInfo::optimizeSelect(MachineInstr
&MI
,
127 SmallPtrSetImpl
<MachineInstr
*> &SeenMIs
,
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
132 MachineInstr
*RV
= ARMBaseInstrInfo::optimizeSelect(MI
, SeenMIs
, PreferFalse
);
133 if (!RV
&& getSubtarget().hasV8_1MMainlineOps() && !PreferNoCSEL
) {
134 Register DestReg
= MI
.getOperand(0).getReg();
136 if (!DestReg
.isVirtual())
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
);
150 void Thumb2InstrInfo::copyPhysReg(MachineBasicBlock
&MBB
,
151 MachineBasicBlock::iterator I
,
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
);
158 BuildMI(MBB
, I
, DL
, get(ARM::tMOVr
), DestReg
)
159 .addReg(SrcReg
, getKillRegState(KillSrc
))
160 .add(predOps(ARMCC::AL
));
163 void Thumb2InstrInfo::
164 storeRegToStackSlot(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator I
,
165 Register SrcReg
, bool isKill
, int FI
,
166 const TargetRegisterClass
*RC
,
167 const TargetRegisterInfo
*TRI
) const {
169 if (I
!= MBB
.end()) DL
= I
->getDebugLoc();
171 MachineFunction
&MF
= *MBB
.getParent();
172 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
173 MachineMemOperand
*MMO
= MF
.getMachineMemOperand(
174 MachinePointerInfo::getFixedStack(MF
, FI
), MachineMemOperand::MOStore
,
175 MFI
.getObjectSize(FI
), MFI
.getObjectAlign(FI
));
177 if (ARM::GPRRegClass
.hasSubClassEq(RC
)) {
178 BuildMI(MBB
, I
, DL
, get(ARM::t2STRi12
))
179 .addReg(SrcReg
, getKillRegState(isKill
))
183 .add(predOps(ARMCC::AL
));
187 if (ARM::GPRPairRegClass
.hasSubClassEq(RC
)) {
188 // Thumb2 STRD expects its dest-registers to be in rGPR. Not a problem for
189 // gsub_0, but needs an extra constraint for gsub_1 (which could be sp
191 if (Register::isVirtualRegister(SrcReg
)) {
192 MachineRegisterInfo
*MRI
= &MF
.getRegInfo();
193 MRI
->constrainRegClass(SrcReg
, &ARM::GPRPairnospRegClass
);
196 MachineInstrBuilder MIB
= BuildMI(MBB
, I
, DL
, get(ARM::t2STRDi8
));
197 AddDReg(MIB
, SrcReg
, ARM::gsub_0
, getKillRegState(isKill
), TRI
);
198 AddDReg(MIB
, SrcReg
, ARM::gsub_1
, 0, TRI
);
199 MIB
.addFrameIndex(FI
).addImm(0).addMemOperand(MMO
).add(predOps(ARMCC::AL
));
203 ARMBaseInstrInfo::storeRegToStackSlot(MBB
, I
, SrcReg
, isKill
, FI
, RC
, TRI
);
206 void Thumb2InstrInfo::
207 loadRegFromStackSlot(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator I
,
208 Register DestReg
, int FI
,
209 const TargetRegisterClass
*RC
,
210 const TargetRegisterInfo
*TRI
) const {
211 MachineFunction
&MF
= *MBB
.getParent();
212 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
213 MachineMemOperand
*MMO
= MF
.getMachineMemOperand(
214 MachinePointerInfo::getFixedStack(MF
, FI
), MachineMemOperand::MOLoad
,
215 MFI
.getObjectSize(FI
), MFI
.getObjectAlign(FI
));
217 if (I
!= MBB
.end()) DL
= I
->getDebugLoc();
219 if (ARM::GPRRegClass
.hasSubClassEq(RC
)) {
220 BuildMI(MBB
, I
, DL
, get(ARM::t2LDRi12
), DestReg
)
224 .add(predOps(ARMCC::AL
));
228 if (ARM::GPRPairRegClass
.hasSubClassEq(RC
)) {
229 // Thumb2 LDRD expects its dest-registers to be in rGPR. Not a problem for
230 // gsub_0, but needs an extra constraint for gsub_1 (which could be sp
232 if (Register::isVirtualRegister(DestReg
)) {
233 MachineRegisterInfo
*MRI
= &MF
.getRegInfo();
234 MRI
->constrainRegClass(DestReg
, &ARM::GPRPairnospRegClass
);
237 MachineInstrBuilder MIB
= BuildMI(MBB
, I
, DL
, get(ARM::t2LDRDi8
));
238 AddDReg(MIB
, DestReg
, ARM::gsub_0
, RegState::DefineNoRead
, TRI
);
239 AddDReg(MIB
, DestReg
, ARM::gsub_1
, RegState::DefineNoRead
, TRI
);
240 MIB
.addFrameIndex(FI
).addImm(0).addMemOperand(MMO
).add(predOps(ARMCC::AL
));
242 if (Register::isPhysicalRegister(DestReg
))
243 MIB
.addReg(DestReg
, RegState::ImplicitDefine
);
247 ARMBaseInstrInfo::loadRegFromStackSlot(MBB
, I
, DestReg
, FI
, RC
, TRI
);
250 void Thumb2InstrInfo::expandLoadStackGuard(
251 MachineBasicBlock::iterator MI
) const {
252 MachineFunction
&MF
= *MI
->getParent()->getParent();
253 if (MF
.getTarget().isPositionIndependent())
254 expandLoadStackGuardBase(MI
, ARM::t2MOV_ga_pcrel
, ARM::t2LDRi12
);
256 expandLoadStackGuardBase(MI
, ARM::t2MOVi32imm
, ARM::t2LDRi12
);
259 MachineInstr
*Thumb2InstrInfo::commuteInstructionImpl(MachineInstr
&MI
,
262 unsigned OpIdx2
) const {
263 switch (MI
.getOpcode()) {
264 case ARM::MVE_VMAXNMAf16
:
265 case ARM::MVE_VMAXNMAf32
:
266 case ARM::MVE_VMINNMAf16
:
267 case ARM::MVE_VMINNMAf32
:
268 // Don't allow predicated instructions to be commuted.
269 if (getVPTInstrPredicate(MI
) != ARMVCC::None
)
272 return ARMBaseInstrInfo::commuteInstructionImpl(MI
, NewMI
, OpIdx1
, OpIdx2
);
275 void llvm::emitT2RegPlusImmediate(MachineBasicBlock
&MBB
,
276 MachineBasicBlock::iterator
&MBBI
,
277 const DebugLoc
&dl
, Register DestReg
,
278 Register BaseReg
, int NumBytes
,
279 ARMCC::CondCodes Pred
, Register PredReg
,
280 const ARMBaseInstrInfo
&TII
,
282 if (NumBytes
== 0 && DestReg
!= BaseReg
) {
283 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::tMOVr
), DestReg
)
284 .addReg(BaseReg
, RegState::Kill
)
285 .addImm((unsigned)Pred
).addReg(PredReg
).setMIFlags(MIFlags
);
289 bool isSub
= NumBytes
< 0;
290 if (isSub
) NumBytes
= -NumBytes
;
292 // If profitable, use a movw or movt to materialize the offset.
293 // FIXME: Use the scavenger to grab a scratch register.
294 if (DestReg
!= ARM::SP
&& DestReg
!= BaseReg
&&
296 ARM_AM::getT2SOImmVal(NumBytes
) == -1) {
298 if (NumBytes
< 65536) {
299 // Use a movw to materialize the 16-bit constant.
300 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::t2MOVi16
), DestReg
)
302 .addImm((unsigned)Pred
).addReg(PredReg
).setMIFlags(MIFlags
);
304 } else if ((NumBytes
& 0xffff) == 0) {
305 // Use a movt to materialize the 32-bit constant.
306 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::t2MOVTi16
), DestReg
)
308 .addImm(NumBytes
>> 16)
309 .addImm((unsigned)Pred
).addReg(PredReg
).setMIFlags(MIFlags
);
315 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::t2SUBrr
), DestReg
)
317 .addReg(DestReg
, RegState::Kill
)
318 .add(predOps(Pred
, PredReg
))
320 .setMIFlags(MIFlags
);
322 // Here we know that DestReg is not SP but we do not
323 // know anything about BaseReg. t2ADDrr is an invalid
324 // instruction is SP is used as the second argument, but
325 // is fine if SP is the first argument. To be sure we
326 // do not generate invalid encoding, put BaseReg first.
327 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::t2ADDrr
), DestReg
)
329 .addReg(DestReg
, RegState::Kill
)
330 .add(predOps(Pred
, PredReg
))
332 .setMIFlags(MIFlags
);
339 unsigned ThisVal
= NumBytes
;
341 if (DestReg
== ARM::SP
&& BaseReg
!= ARM::SP
) {
342 // mov sp, rn. Note t2MOVr cannot be used.
343 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::tMOVr
), DestReg
)
346 .add(predOps(ARMCC::AL
));
351 assert((DestReg
!= ARM::SP
|| BaseReg
== ARM::SP
) &&
352 "Writing to SP, from other register.");
354 // Try to use T1, as it smaller
355 if ((DestReg
== ARM::SP
) && (ThisVal
< ((1 << 7) - 1) * 4)) {
356 assert((ThisVal
& 3) == 0 && "Stack update is not multiple of 4?");
357 Opc
= isSub
? ARM::tSUBspi
: ARM::tADDspi
;
358 BuildMI(MBB
, MBBI
, dl
, TII
.get(Opc
), DestReg
)
362 .add(predOps(ARMCC::AL
));
365 bool HasCCOut
= true;
366 int ImmIsT2SO
= ARM_AM::getT2SOImmVal(ThisVal
);
367 bool ToSP
= DestReg
== ARM::SP
;
368 unsigned t2SUB
= ToSP
? ARM::t2SUBspImm
: ARM::t2SUBri
;
369 unsigned t2ADD
= ToSP
? ARM::t2ADDspImm
: ARM::t2ADDri
;
370 unsigned t2SUBi12
= ToSP
? ARM::t2SUBspImm12
: ARM::t2SUBri12
;
371 unsigned t2ADDi12
= ToSP
? ARM::t2ADDspImm12
: ARM::t2ADDri12
;
372 Opc
= isSub
? t2SUB
: t2ADD
;
373 // Prefer T2: sub rd, rn, so_imm | sub sp, sp, so_imm
374 if (ImmIsT2SO
!= -1) {
376 } else if (ThisVal
< 4096) {
377 // Prefer T3 if can make it in a single go: subw rd, rn, imm12 | subw sp,
379 Opc
= isSub
? t2SUBi12
: t2ADDi12
;
383 // Use one T2 instruction to reduce NumBytes
384 // FIXME: Move this to ARMAddressingModes.h?
385 unsigned RotAmt
= countLeadingZeros(ThisVal
);
386 ThisVal
= ThisVal
& ARM_AM::rotr32(0xff000000U
, RotAmt
);
387 NumBytes
&= ~ThisVal
;
388 assert(ARM_AM::getT2SOImmVal(ThisVal
) != -1 &&
389 "Bit extraction didn't work?");
392 // Build the new ADD / SUB.
393 MachineInstrBuilder MIB
= BuildMI(MBB
, MBBI
, dl
, TII
.get(Opc
), DestReg
)
394 .addReg(BaseReg
, RegState::Kill
)
396 .add(predOps(ARMCC::AL
))
397 .setMIFlags(MIFlags
);
399 MIB
.add(condCodeOp());
406 negativeOffsetOpcode(unsigned opcode
)
409 case ARM::t2LDRi12
: return ARM::t2LDRi8
;
410 case ARM::t2LDRHi12
: return ARM::t2LDRHi8
;
411 case ARM::t2LDRBi12
: return ARM::t2LDRBi8
;
412 case ARM::t2LDRSHi12
: return ARM::t2LDRSHi8
;
413 case ARM::t2LDRSBi12
: return ARM::t2LDRSBi8
;
414 case ARM::t2STRi12
: return ARM::t2STRi8
;
415 case ARM::t2STRBi12
: return ARM::t2STRBi8
;
416 case ARM::t2STRHi12
: return ARM::t2STRHi8
;
417 case ARM::t2PLDi12
: return ARM::t2PLDi8
;
418 case ARM::t2PLDWi12
: return ARM::t2PLDWi8
;
419 case ARM::t2PLIi12
: return ARM::t2PLIi8
;
435 llvm_unreachable("unknown thumb2 opcode.");
440 positiveOffsetOpcode(unsigned opcode
)
443 case ARM::t2LDRi8
: return ARM::t2LDRi12
;
444 case ARM::t2LDRHi8
: return ARM::t2LDRHi12
;
445 case ARM::t2LDRBi8
: return ARM::t2LDRBi12
;
446 case ARM::t2LDRSHi8
: return ARM::t2LDRSHi12
;
447 case ARM::t2LDRSBi8
: return ARM::t2LDRSBi12
;
448 case ARM::t2STRi8
: return ARM::t2STRi12
;
449 case ARM::t2STRBi8
: return ARM::t2STRBi12
;
450 case ARM::t2STRHi8
: return ARM::t2STRHi12
;
451 case ARM::t2PLDi8
: return ARM::t2PLDi12
;
452 case ARM::t2PLDWi8
: return ARM::t2PLDWi12
;
453 case ARM::t2PLIi8
: return ARM::t2PLIi12
;
458 case ARM::t2LDRSHi12
:
459 case ARM::t2LDRSBi12
:
469 llvm_unreachable("unknown thumb2 opcode.");
474 immediateOffsetOpcode(unsigned opcode
)
477 case ARM::t2LDRs
: return ARM::t2LDRi12
;
478 case ARM::t2LDRHs
: return ARM::t2LDRHi12
;
479 case ARM::t2LDRBs
: return ARM::t2LDRBi12
;
480 case ARM::t2LDRSHs
: return ARM::t2LDRSHi12
;
481 case ARM::t2LDRSBs
: return ARM::t2LDRSBi12
;
482 case ARM::t2STRs
: return ARM::t2STRi12
;
483 case ARM::t2STRBs
: return ARM::t2STRBi12
;
484 case ARM::t2STRHs
: return ARM::t2STRHi12
;
485 case ARM::t2PLDs
: return ARM::t2PLDi12
;
486 case ARM::t2PLDWs
: return ARM::t2PLDWi12
;
487 case ARM::t2PLIs
: return ARM::t2PLIi12
;
492 case ARM::t2LDRSHi12
:
493 case ARM::t2LDRSBi12
:
514 llvm_unreachable("unknown thumb2 opcode.");
518 bool llvm::rewriteT2FrameIndex(MachineInstr
&MI
, unsigned FrameRegIdx
,
519 Register FrameReg
, int &Offset
,
520 const ARMBaseInstrInfo
&TII
,
521 const TargetRegisterInfo
*TRI
) {
522 unsigned Opcode
= MI
.getOpcode();
523 const MCInstrDesc
&Desc
= MI
.getDesc();
524 unsigned AddrMode
= (Desc
.TSFlags
& ARMII::AddrModeMask
);
527 MachineFunction
&MF
= *MI
.getParent()->getParent();
528 const TargetRegisterClass
*RegClass
=
529 TII
.getRegClass(Desc
, FrameRegIdx
, TRI
, MF
);
531 // Memory operands in inline assembly always use AddrModeT2_i12.
532 if (Opcode
== ARM::INLINEASM
|| Opcode
== ARM::INLINEASM_BR
)
533 AddrMode
= ARMII::AddrModeT2_i12
; // FIXME. mode for thumb2?
535 const bool IsSP
= Opcode
== ARM::t2ADDspImm12
|| Opcode
== ARM::t2ADDspImm
;
536 if (IsSP
|| Opcode
== ARM::t2ADDri
|| Opcode
== ARM::t2ADDri12
) {
537 Offset
+= MI
.getOperand(FrameRegIdx
+1).getImm();
540 if (Offset
== 0 && getInstrPredicate(MI
, PredReg
) == ARMCC::AL
&&
541 !MI
.definesRegister(ARM::CPSR
)) {
542 // Turn it into a move.
543 MI
.setDesc(TII
.get(ARM::tMOVr
));
544 MI
.getOperand(FrameRegIdx
).ChangeToRegister(FrameReg
, false);
545 // Remove offset and remaining explicit predicate operands.
546 do MI
.RemoveOperand(FrameRegIdx
+1);
547 while (MI
.getNumOperands() > FrameRegIdx
+1);
548 MachineInstrBuilder
MIB(*MI
.getParent()->getParent(), &MI
);
549 MIB
.add(predOps(ARMCC::AL
));
553 bool HasCCOut
= (Opcode
!= ARM::t2ADDspImm12
&& Opcode
!= ARM::t2ADDri12
);
558 MI
.setDesc(IsSP
? TII
.get(ARM::t2SUBspImm
) : TII
.get(ARM::t2SUBri
));
560 MI
.setDesc(IsSP
? TII
.get(ARM::t2ADDspImm
) : TII
.get(ARM::t2ADDri
));
563 // Common case: small offset, fits into instruction.
564 if (ARM_AM::getT2SOImmVal(Offset
) != -1) {
565 MI
.getOperand(FrameRegIdx
).ChangeToRegister(FrameReg
, false);
566 MI
.getOperand(FrameRegIdx
+1).ChangeToImmediate(Offset
);
567 // Add cc_out operand if the original instruction did not have one.
569 MI
.addOperand(MachineOperand::CreateReg(0, false));
573 // Another common case: imm12.
575 (!HasCCOut
|| MI
.getOperand(MI
.getNumOperands()-1).getReg() == 0)) {
576 unsigned NewOpc
= isSub
? IsSP
? ARM::t2SUBspImm12
: ARM::t2SUBri12
577 : IsSP
? ARM::t2ADDspImm12
: ARM::t2ADDri12
;
578 MI
.setDesc(TII
.get(NewOpc
));
579 MI
.getOperand(FrameRegIdx
).ChangeToRegister(FrameReg
, false);
580 MI
.getOperand(FrameRegIdx
+1).ChangeToImmediate(Offset
);
581 // Remove the cc_out operand.
583 MI
.RemoveOperand(MI
.getNumOperands()-1);
588 // Otherwise, extract 8 adjacent bits from the immediate into this
590 unsigned RotAmt
= countLeadingZeros
<unsigned>(Offset
);
591 unsigned ThisImmVal
= Offset
& ARM_AM::rotr32(0xff000000U
, RotAmt
);
593 // We will handle these bits from offset, clear them.
594 Offset
&= ~ThisImmVal
;
596 assert(ARM_AM::getT2SOImmVal(ThisImmVal
) != -1 &&
597 "Bit extraction didn't work?");
598 MI
.getOperand(FrameRegIdx
+1).ChangeToImmediate(ThisImmVal
);
599 // Add cc_out operand if the original instruction did not have one.
601 MI
.addOperand(MachineOperand::CreateReg(0, false));
603 // AddrMode4 and AddrMode6 cannot handle any offset.
604 if (AddrMode
== ARMII::AddrMode4
|| AddrMode
== ARMII::AddrMode6
)
607 // AddrModeT2_so cannot handle any offset. If there is no offset
608 // register then we change to an immediate version.
609 unsigned NewOpc
= Opcode
;
610 if (AddrMode
== ARMII::AddrModeT2_so
) {
611 Register OffsetReg
= MI
.getOperand(FrameRegIdx
+ 1).getReg();
612 if (OffsetReg
!= 0) {
613 MI
.getOperand(FrameRegIdx
).ChangeToRegister(FrameReg
, false);
617 MI
.RemoveOperand(FrameRegIdx
+1);
618 MI
.getOperand(FrameRegIdx
+1).ChangeToImmediate(0);
619 NewOpc
= immediateOffsetOpcode(Opcode
);
620 AddrMode
= ARMII::AddrModeT2_i12
;
623 unsigned NumBits
= 0;
625 if (AddrMode
== ARMII::AddrModeT2_i8
|| AddrMode
== ARMII::AddrModeT2_i12
) {
626 // i8 supports only negative, and i12 supports only positive, so
627 // based on Offset sign convert Opcode to the appropriate
629 Offset
+= MI
.getOperand(FrameRegIdx
+1).getImm();
631 NewOpc
= negativeOffsetOpcode(Opcode
);
636 NewOpc
= positiveOffsetOpcode(Opcode
);
639 } else if (AddrMode
== ARMII::AddrMode5
) {
641 const MachineOperand
&OffOp
= MI
.getOperand(FrameRegIdx
+1);
642 int InstrOffs
= ARM_AM::getAM5Offset(OffOp
.getImm());
643 if (ARM_AM::getAM5Op(OffOp
.getImm()) == ARM_AM::sub
)
647 Offset
+= InstrOffs
* 4;
648 assert((Offset
& (Scale
-1)) == 0 && "Can't encode this offset!");
653 } else if (AddrMode
== ARMII::AddrMode5FP16
) {
655 const MachineOperand
&OffOp
= MI
.getOperand(FrameRegIdx
+1);
656 int InstrOffs
= ARM_AM::getAM5FP16Offset(OffOp
.getImm());
657 if (ARM_AM::getAM5FP16Op(OffOp
.getImm()) == ARM_AM::sub
)
661 Offset
+= InstrOffs
* 2;
662 assert((Offset
& (Scale
-1)) == 0 && "Can't encode this offset!");
667 } else if (AddrMode
== ARMII::AddrModeT2_i7s4
||
668 AddrMode
== ARMII::AddrModeT2_i7s2
||
669 AddrMode
== ARMII::AddrModeT2_i7
) {
670 Offset
+= MI
.getOperand(FrameRegIdx
+ 1).getImm();
673 case ARMII::AddrModeT2_i7s4
: NumBits
= 9; OffsetMask
= 0x3; break;
674 case ARMII::AddrModeT2_i7s2
: NumBits
= 8; OffsetMask
= 0x1; break;
675 default: NumBits
= 7; OffsetMask
= 0x0; break;
677 // MCInst operand expects already scaled value.
679 assert((Offset
& OffsetMask
) == 0 && "Can't encode this offset!");
680 (void)OffsetMask
; // squash unused-variable warning at -NDEBUG
681 } else if (AddrMode
== ARMII::AddrModeT2_i8s4
) {
682 Offset
+= MI
.getOperand(FrameRegIdx
+ 1).getImm();
684 // MCInst operand expects already scaled value.
686 assert((Offset
& 3) == 0 && "Can't encode this offset!");
687 } else if (AddrMode
== ARMII::AddrModeT2_ldrex
) {
688 Offset
+= MI
.getOperand(FrameRegIdx
+ 1).getImm() * 4;
689 NumBits
= 8; // 8 bits scaled by 4
691 assert((Offset
& 3) == 0 && "Can't encode this offset!");
693 llvm_unreachable("Unsupported addressing mode!");
696 if (NewOpc
!= Opcode
)
697 MI
.setDesc(TII
.get(NewOpc
));
699 MachineOperand
&ImmOp
= MI
.getOperand(FrameRegIdx
+1);
701 // Attempt to fold address computation
702 // Common case: small offset, fits into instruction. We need to make sure
703 // the register class is correct too, for instructions like the MVE
704 // VLDRH.32, which only accepts low tGPR registers.
705 int ImmedOffset
= Offset
/ Scale
;
706 unsigned Mask
= (1 << NumBits
) - 1;
707 if ((unsigned)Offset
<= Mask
* Scale
&&
708 (Register::isVirtualRegister(FrameReg
) ||
709 RegClass
->contains(FrameReg
))) {
710 if (Register::isVirtualRegister(FrameReg
)) {
711 // Make sure the register class for the virtual register is correct
712 MachineRegisterInfo
*MRI
= &MF
.getRegInfo();
713 if (!MRI
->constrainRegClass(FrameReg
, RegClass
))
714 llvm_unreachable("Unable to constrain virtual register class.");
717 // Replace the FrameIndex with fp/sp
718 MI
.getOperand(FrameRegIdx
).ChangeToRegister(FrameReg
, false);
720 if (AddrMode
== ARMII::AddrMode5
|| AddrMode
== ARMII::AddrMode5FP16
)
721 // FIXME: Not consistent.
722 ImmedOffset
|= 1 << NumBits
;
724 ImmedOffset
= -ImmedOffset
;
726 ImmOp
.ChangeToImmediate(ImmedOffset
);
731 // Otherwise, offset doesn't fit. Pull in what we can to simplify
732 ImmedOffset
= ImmedOffset
& Mask
;
734 if (AddrMode
== ARMII::AddrMode5
|| AddrMode
== ARMII::AddrMode5FP16
)
735 // FIXME: Not consistent.
736 ImmedOffset
|= 1 << NumBits
;
738 ImmedOffset
= -ImmedOffset
;
739 if (ImmedOffset
== 0)
740 // Change the opcode back if the encoded offset is zero.
741 MI
.setDesc(TII
.get(positiveOffsetOpcode(NewOpc
)));
744 ImmOp
.ChangeToImmediate(ImmedOffset
);
745 Offset
&= ~(Mask
*Scale
);
748 Offset
= (isSub
) ? -Offset
: Offset
;
749 return Offset
== 0 && (Register::isVirtualRegister(FrameReg
) ||
750 RegClass
->contains(FrameReg
));
753 ARMCC::CondCodes
llvm::getITInstrPredicate(const MachineInstr
&MI
,
755 unsigned Opc
= MI
.getOpcode();
756 if (Opc
== ARM::tBcc
|| Opc
== ARM::t2Bcc
)
758 return getInstrPredicate(MI
, PredReg
);
761 int llvm::findFirstVPTPredOperandIdx(const MachineInstr
&MI
) {
762 const MCInstrDesc
&MCID
= MI
.getDesc();
767 for (unsigned i
= 0, e
= MCID
.getNumOperands(); i
!= e
; ++i
)
768 if (ARM::isVpred(MCID
.OpInfo
[i
].OperandType
))
774 ARMVCC::VPTCodes
llvm::getVPTInstrPredicate(const MachineInstr
&MI
,
776 int PIdx
= findFirstVPTPredOperandIdx(MI
);
782 PredReg
= MI
.getOperand(PIdx
+1).getReg();
783 return (ARMVCC::VPTCodes
)MI
.getOperand(PIdx
).getImm();
786 void llvm::recomputeVPTBlockMask(MachineInstr
&Instr
) {
787 assert(isVPTOpcode(Instr
.getOpcode()) && "Not a VPST or VPT Instruction!");
789 MachineOperand
&MaskOp
= Instr
.getOperand(0);
790 assert(MaskOp
.isImm() && "Operand 0 is not the block mask of the VPT/VPST?!");
792 MachineBasicBlock::iterator Iter
= ++Instr
.getIterator(),
793 End
= Instr
.getParent()->end();
795 // Verify that the instruction after the VPT/VPST is predicated (it should
798 getVPTInstrPredicate(*Iter
) == ARMVCC::Then
&&
799 "VPT/VPST should be followed by an instruction with a 'then' predicate!");
802 // Iterate over the predicated instructions, updating the BlockMask as we go.
803 ARM::PredBlockMask BlockMask
= ARM::PredBlockMask::T
;
804 while (Iter
!= End
) {
805 ARMVCC::VPTCodes Pred
= getVPTInstrPredicate(*Iter
);
806 if (Pred
== ARMVCC::None
)
808 BlockMask
= expandPredBlockMask(BlockMask
, Pred
);
812 // Rewrite the BlockMask.
813 MaskOp
.setImm((int64_t)(BlockMask
));