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 "MCTargetDesc/ARMAddressingModes.h"
16 #include "llvm/CodeGen/MachineBasicBlock.h"
17 #include "llvm/CodeGen/MachineFrameInfo.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineInstr.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
21 #include "llvm/CodeGen/MachineMemOperand.h"
22 #include "llvm/CodeGen/MachineOperand.h"
23 #include "llvm/CodeGen/MachineRegisterInfo.h"
24 #include "llvm/CodeGen/TargetRegisterInfo.h"
25 #include "llvm/IR/DebugLoc.h"
26 #include "llvm/MC/MCInst.h"
27 #include "llvm/MC/MCInstrDesc.h"
28 #include "llvm/Support/CommandLine.h"
29 #include "llvm/Support/ErrorHandling.h"
30 #include "llvm/Support/MathExtras.h"
31 #include "llvm/Target/TargetMachine.h"
37 OldT2IfCvt("old-thumb2-ifcvt", cl::Hidden
,
38 cl::desc("Use old-style Thumb2 if-conversion heuristics"),
41 Thumb2InstrInfo::Thumb2InstrInfo(const ARMSubtarget
&STI
)
42 : ARMBaseInstrInfo(STI
) {}
44 /// Return the noop instruction to use for a noop.
45 void Thumb2InstrInfo::getNoop(MCInst
&NopInst
) const {
46 NopInst
.setOpcode(ARM::tHINT
);
47 NopInst
.addOperand(MCOperand::createImm(0));
48 NopInst
.addOperand(MCOperand::createImm(ARMCC::AL
));
49 NopInst
.addOperand(MCOperand::createReg(0));
52 unsigned Thumb2InstrInfo::getUnindexedOpcode(unsigned Opc
) const {
58 Thumb2InstrInfo::ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail
,
59 MachineBasicBlock
*NewDest
) const {
60 MachineBasicBlock
*MBB
= Tail
->getParent();
61 ARMFunctionInfo
*AFI
= MBB
->getParent()->getInfo
<ARMFunctionInfo
>();
62 if (!AFI
->hasITBlocks() || Tail
->isBranch()) {
63 TargetInstrInfo::ReplaceTailWithBranchTo(Tail
, NewDest
);
67 // If the first instruction of Tail is predicated, we may have to update
68 // the IT instruction.
70 ARMCC::CondCodes CC
= getInstrPredicate(*Tail
, PredReg
);
71 MachineBasicBlock::iterator MBBI
= Tail
;
73 // Expecting at least the t2IT instruction before it.
76 // Actually replace the tail.
77 TargetInstrInfo::ReplaceTailWithBranchTo(Tail
, NewDest
);
80 if (CC
!= ARMCC::AL
) {
81 MachineBasicBlock::iterator E
= MBB
->begin();
82 unsigned Count
= 4; // At most 4 instructions in an IT block.
83 while (Count
&& MBBI
!= E
) {
84 if (MBBI
->isDebugInstr()) {
88 if (MBBI
->getOpcode() == ARM::t2IT
) {
89 unsigned Mask
= MBBI
->getOperand(1).getImm();
91 MBBI
->eraseFromParent();
93 unsigned MaskOn
= 1 << Count
;
94 unsigned MaskOff
= ~(MaskOn
- 1);
95 MBBI
->getOperand(1).setImm((Mask
& MaskOff
) | MaskOn
);
103 // Ctrl flow can reach here if branch folding is run before IT block
109 Thumb2InstrInfo::isLegalToSplitMBBAt(MachineBasicBlock
&MBB
,
110 MachineBasicBlock::iterator MBBI
) const {
111 while (MBBI
->isDebugInstr()) {
113 if (MBBI
== MBB
.end())
117 unsigned PredReg
= 0;
118 return getITInstrPredicate(*MBBI
, PredReg
) == ARMCC::AL
;
121 void Thumb2InstrInfo::copyPhysReg(MachineBasicBlock
&MBB
,
122 MachineBasicBlock::iterator I
,
123 const DebugLoc
&DL
, unsigned DestReg
,
124 unsigned SrcReg
, bool KillSrc
) const {
125 // Handle SPR, DPR, and QPR copies.
126 if (!ARM::GPRRegClass
.contains(DestReg
, SrcReg
))
127 return ARMBaseInstrInfo::copyPhysReg(MBB
, I
, DL
, DestReg
, SrcReg
, KillSrc
);
129 BuildMI(MBB
, I
, DL
, get(ARM::tMOVr
), DestReg
)
130 .addReg(SrcReg
, getKillRegState(KillSrc
))
131 .add(predOps(ARMCC::AL
));
134 void Thumb2InstrInfo::
135 storeRegToStackSlot(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator I
,
136 unsigned SrcReg
, bool isKill
, int FI
,
137 const TargetRegisterClass
*RC
,
138 const TargetRegisterInfo
*TRI
) const {
140 if (I
!= MBB
.end()) DL
= I
->getDebugLoc();
142 MachineFunction
&MF
= *MBB
.getParent();
143 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
144 MachineMemOperand
*MMO
= MF
.getMachineMemOperand(
145 MachinePointerInfo::getFixedStack(MF
, FI
), MachineMemOperand::MOStore
,
146 MFI
.getObjectSize(FI
), MFI
.getObjectAlignment(FI
));
148 if (ARM::GPRRegClass
.hasSubClassEq(RC
)) {
149 BuildMI(MBB
, I
, DL
, get(ARM::t2STRi12
))
150 .addReg(SrcReg
, getKillRegState(isKill
))
154 .add(predOps(ARMCC::AL
));
158 if (ARM::GPRPairRegClass
.hasSubClassEq(RC
)) {
159 // Thumb2 STRD expects its dest-registers to be in rGPR. Not a problem for
160 // gsub_0, but needs an extra constraint for gsub_1 (which could be sp
162 if (Register::isVirtualRegister(SrcReg
)) {
163 MachineRegisterInfo
*MRI
= &MF
.getRegInfo();
164 MRI
->constrainRegClass(SrcReg
, &ARM::GPRPairnospRegClass
);
167 MachineInstrBuilder MIB
= BuildMI(MBB
, I
, DL
, get(ARM::t2STRDi8
));
168 AddDReg(MIB
, SrcReg
, ARM::gsub_0
, getKillRegState(isKill
), TRI
);
169 AddDReg(MIB
, SrcReg
, ARM::gsub_1
, 0, TRI
);
170 MIB
.addFrameIndex(FI
).addImm(0).addMemOperand(MMO
).add(predOps(ARMCC::AL
));
174 ARMBaseInstrInfo::storeRegToStackSlot(MBB
, I
, SrcReg
, isKill
, FI
, RC
, TRI
);
177 void Thumb2InstrInfo::
178 loadRegFromStackSlot(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator I
,
179 unsigned DestReg
, int FI
,
180 const TargetRegisterClass
*RC
,
181 const TargetRegisterInfo
*TRI
) const {
182 MachineFunction
&MF
= *MBB
.getParent();
183 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
184 MachineMemOperand
*MMO
= MF
.getMachineMemOperand(
185 MachinePointerInfo::getFixedStack(MF
, FI
), MachineMemOperand::MOLoad
,
186 MFI
.getObjectSize(FI
), MFI
.getObjectAlignment(FI
));
188 if (I
!= MBB
.end()) DL
= I
->getDebugLoc();
190 if (ARM::GPRRegClass
.hasSubClassEq(RC
)) {
191 BuildMI(MBB
, I
, DL
, get(ARM::t2LDRi12
), DestReg
)
195 .add(predOps(ARMCC::AL
));
199 if (ARM::GPRPairRegClass
.hasSubClassEq(RC
)) {
200 // Thumb2 LDRD expects its dest-registers to be in rGPR. Not a problem for
201 // gsub_0, but needs an extra constraint for gsub_1 (which could be sp
203 if (Register::isVirtualRegister(DestReg
)) {
204 MachineRegisterInfo
*MRI
= &MF
.getRegInfo();
205 MRI
->constrainRegClass(DestReg
, &ARM::GPRPairnospRegClass
);
208 MachineInstrBuilder MIB
= BuildMI(MBB
, I
, DL
, get(ARM::t2LDRDi8
));
209 AddDReg(MIB
, DestReg
, ARM::gsub_0
, RegState::DefineNoRead
, TRI
);
210 AddDReg(MIB
, DestReg
, ARM::gsub_1
, RegState::DefineNoRead
, TRI
);
211 MIB
.addFrameIndex(FI
).addImm(0).addMemOperand(MMO
).add(predOps(ARMCC::AL
));
213 if (Register::isPhysicalRegister(DestReg
))
214 MIB
.addReg(DestReg
, RegState::ImplicitDefine
);
218 ARMBaseInstrInfo::loadRegFromStackSlot(MBB
, I
, DestReg
, FI
, RC
, TRI
);
221 void Thumb2InstrInfo::expandLoadStackGuard(
222 MachineBasicBlock::iterator MI
) const {
223 MachineFunction
&MF
= *MI
->getParent()->getParent();
224 if (MF
.getTarget().isPositionIndependent())
225 expandLoadStackGuardBase(MI
, ARM::t2MOV_ga_pcrel
, ARM::t2LDRi12
);
227 expandLoadStackGuardBase(MI
, ARM::t2MOVi32imm
, ARM::t2LDRi12
);
230 void llvm::emitT2RegPlusImmediate(MachineBasicBlock
&MBB
,
231 MachineBasicBlock::iterator
&MBBI
,
232 const DebugLoc
&dl
, unsigned DestReg
,
233 unsigned BaseReg
, int NumBytes
,
234 ARMCC::CondCodes Pred
, unsigned PredReg
,
235 const ARMBaseInstrInfo
&TII
,
237 if (NumBytes
== 0 && DestReg
!= BaseReg
) {
238 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::tMOVr
), DestReg
)
239 .addReg(BaseReg
, RegState::Kill
)
240 .addImm((unsigned)Pred
).addReg(PredReg
).setMIFlags(MIFlags
);
244 bool isSub
= NumBytes
< 0;
245 if (isSub
) NumBytes
= -NumBytes
;
247 // If profitable, use a movw or movt to materialize the offset.
248 // FIXME: Use the scavenger to grab a scratch register.
249 if (DestReg
!= ARM::SP
&& DestReg
!= BaseReg
&&
251 ARM_AM::getT2SOImmVal(NumBytes
) == -1) {
253 if (NumBytes
< 65536) {
254 // Use a movw to materialize the 16-bit constant.
255 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::t2MOVi16
), DestReg
)
257 .addImm((unsigned)Pred
).addReg(PredReg
).setMIFlags(MIFlags
);
259 } else if ((NumBytes
& 0xffff) == 0) {
260 // Use a movt to materialize the 32-bit constant.
261 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::t2MOVTi16
), DestReg
)
263 .addImm(NumBytes
>> 16)
264 .addImm((unsigned)Pred
).addReg(PredReg
).setMIFlags(MIFlags
);
270 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::t2SUBrr
), DestReg
)
272 .addReg(DestReg
, RegState::Kill
)
273 .add(predOps(Pred
, PredReg
))
275 .setMIFlags(MIFlags
);
277 // Here we know that DestReg is not SP but we do not
278 // know anything about BaseReg. t2ADDrr is an invalid
279 // instruction is SP is used as the second argument, but
280 // is fine if SP is the first argument. To be sure we
281 // do not generate invalid encoding, put BaseReg first.
282 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::t2ADDrr
), DestReg
)
284 .addReg(DestReg
, RegState::Kill
)
285 .add(predOps(Pred
, PredReg
))
287 .setMIFlags(MIFlags
);
294 unsigned ThisVal
= NumBytes
;
296 if (DestReg
== ARM::SP
&& BaseReg
!= ARM::SP
) {
297 // mov sp, rn. Note t2MOVr cannot be used.
298 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::tMOVr
), DestReg
)
301 .add(predOps(ARMCC::AL
));
306 bool HasCCOut
= true;
307 if (BaseReg
== ARM::SP
) {
309 if (DestReg
== ARM::SP
&& (ThisVal
< ((1 << 7)-1) * 4)) {
310 assert((ThisVal
& 3) == 0 && "Stack update is not multiple of 4?");
311 Opc
= isSub
? ARM::tSUBspi
: ARM::tADDspi
;
312 BuildMI(MBB
, MBBI
, dl
, TII
.get(Opc
), DestReg
)
316 .add(predOps(ARMCC::AL
));
321 // sub rd, sp, so_imm
322 Opc
= isSub
? ARM::t2SUBri
: ARM::t2ADDri
;
323 if (ARM_AM::getT2SOImmVal(NumBytes
) != -1) {
326 // FIXME: Move this to ARMAddressingModes.h?
327 unsigned RotAmt
= countLeadingZeros(ThisVal
);
328 ThisVal
= ThisVal
& ARM_AM::rotr32(0xff000000U
, RotAmt
);
329 NumBytes
&= ~ThisVal
;
330 assert(ARM_AM::getT2SOImmVal(ThisVal
) != -1 &&
331 "Bit extraction didn't work?");
334 assert(DestReg
!= ARM::SP
&& BaseReg
!= ARM::SP
);
335 Opc
= isSub
? ARM::t2SUBri
: ARM::t2ADDri
;
336 if (ARM_AM::getT2SOImmVal(NumBytes
) != -1) {
338 } else if (ThisVal
< 4096) {
339 Opc
= isSub
? ARM::t2SUBri12
: ARM::t2ADDri12
;
343 // FIXME: Move this to ARMAddressingModes.h?
344 unsigned RotAmt
= countLeadingZeros(ThisVal
);
345 ThisVal
= ThisVal
& ARM_AM::rotr32(0xff000000U
, RotAmt
);
346 NumBytes
&= ~ThisVal
;
347 assert(ARM_AM::getT2SOImmVal(ThisVal
) != -1 &&
348 "Bit extraction didn't work?");
352 // Build the new ADD / SUB.
353 MachineInstrBuilder MIB
= BuildMI(MBB
, MBBI
, dl
, TII
.get(Opc
), DestReg
)
354 .addReg(BaseReg
, RegState::Kill
)
356 .add(predOps(ARMCC::AL
))
357 .setMIFlags(MIFlags
);
359 MIB
.add(condCodeOp());
366 negativeOffsetOpcode(unsigned opcode
)
369 case ARM::t2LDRi12
: return ARM::t2LDRi8
;
370 case ARM::t2LDRHi12
: return ARM::t2LDRHi8
;
371 case ARM::t2LDRBi12
: return ARM::t2LDRBi8
;
372 case ARM::t2LDRSHi12
: return ARM::t2LDRSHi8
;
373 case ARM::t2LDRSBi12
: return ARM::t2LDRSBi8
;
374 case ARM::t2STRi12
: return ARM::t2STRi8
;
375 case ARM::t2STRBi12
: return ARM::t2STRBi8
;
376 case ARM::t2STRHi12
: return ARM::t2STRHi8
;
377 case ARM::t2PLDi12
: return ARM::t2PLDi8
;
398 positiveOffsetOpcode(unsigned opcode
)
401 case ARM::t2LDRi8
: return ARM::t2LDRi12
;
402 case ARM::t2LDRHi8
: return ARM::t2LDRHi12
;
403 case ARM::t2LDRBi8
: return ARM::t2LDRBi12
;
404 case ARM::t2LDRSHi8
: return ARM::t2LDRSHi12
;
405 case ARM::t2LDRSBi8
: return ARM::t2LDRSBi12
;
406 case ARM::t2STRi8
: return ARM::t2STRi12
;
407 case ARM::t2STRBi8
: return ARM::t2STRBi12
;
408 case ARM::t2STRHi8
: return ARM::t2STRHi12
;
409 case ARM::t2PLDi8
: return ARM::t2PLDi12
;
414 case ARM::t2LDRSHi12
:
415 case ARM::t2LDRSBi12
:
430 immediateOffsetOpcode(unsigned opcode
)
433 case ARM::t2LDRs
: return ARM::t2LDRi12
;
434 case ARM::t2LDRHs
: return ARM::t2LDRHi12
;
435 case ARM::t2LDRBs
: return ARM::t2LDRBi12
;
436 case ARM::t2LDRSHs
: return ARM::t2LDRSHi12
;
437 case ARM::t2LDRSBs
: return ARM::t2LDRSBi12
;
438 case ARM::t2STRs
: return ARM::t2STRi12
;
439 case ARM::t2STRBs
: return ARM::t2STRBi12
;
440 case ARM::t2STRHs
: return ARM::t2STRHi12
;
441 case ARM::t2PLDs
: return ARM::t2PLDi12
;
446 case ARM::t2LDRSHi12
:
447 case ARM::t2LDRSBi12
:
470 bool llvm::rewriteT2FrameIndex(MachineInstr
&MI
, unsigned FrameRegIdx
,
471 unsigned FrameReg
, int &Offset
,
472 const ARMBaseInstrInfo
&TII
,
473 const TargetRegisterInfo
*TRI
) {
474 unsigned Opcode
= MI
.getOpcode();
475 const MCInstrDesc
&Desc
= MI
.getDesc();
476 unsigned AddrMode
= (Desc
.TSFlags
& ARMII::AddrModeMask
);
479 MachineFunction
&MF
= *MI
.getParent()->getParent();
480 const TargetRegisterClass
*RegClass
=
481 TII
.getRegClass(Desc
, FrameRegIdx
, TRI
, MF
);
483 // Memory operands in inline assembly always use AddrModeT2_i12.
484 if (Opcode
== ARM::INLINEASM
|| Opcode
== ARM::INLINEASM_BR
)
485 AddrMode
= ARMII::AddrModeT2_i12
; // FIXME. mode for thumb2?
487 if (Opcode
== ARM::t2ADDri
|| Opcode
== ARM::t2ADDri12
) {
488 Offset
+= MI
.getOperand(FrameRegIdx
+1).getImm();
491 if (Offset
== 0 && getInstrPredicate(MI
, PredReg
) == ARMCC::AL
&&
492 !MI
.definesRegister(ARM::CPSR
)) {
493 // Turn it into a move.
494 MI
.setDesc(TII
.get(ARM::tMOVr
));
495 MI
.getOperand(FrameRegIdx
).ChangeToRegister(FrameReg
, false);
496 // Remove offset and remaining explicit predicate operands.
497 do MI
.RemoveOperand(FrameRegIdx
+1);
498 while (MI
.getNumOperands() > FrameRegIdx
+1);
499 MachineInstrBuilder
MIB(*MI
.getParent()->getParent(), &MI
);
500 MIB
.add(predOps(ARMCC::AL
));
504 bool HasCCOut
= Opcode
!= ARM::t2ADDri12
;
509 MI
.setDesc(TII
.get(ARM::t2SUBri
));
511 MI
.setDesc(TII
.get(ARM::t2ADDri
));
514 // Common case: small offset, fits into instruction.
515 if (ARM_AM::getT2SOImmVal(Offset
) != -1) {
516 MI
.getOperand(FrameRegIdx
).ChangeToRegister(FrameReg
, false);
517 MI
.getOperand(FrameRegIdx
+1).ChangeToImmediate(Offset
);
518 // Add cc_out operand if the original instruction did not have one.
520 MI
.addOperand(MachineOperand::CreateReg(0, false));
524 // Another common case: imm12.
526 (!HasCCOut
|| MI
.getOperand(MI
.getNumOperands()-1).getReg() == 0)) {
527 unsigned NewOpc
= isSub
? ARM::t2SUBri12
: ARM::t2ADDri12
;
528 MI
.setDesc(TII
.get(NewOpc
));
529 MI
.getOperand(FrameRegIdx
).ChangeToRegister(FrameReg
, false);
530 MI
.getOperand(FrameRegIdx
+1).ChangeToImmediate(Offset
);
531 // Remove the cc_out operand.
533 MI
.RemoveOperand(MI
.getNumOperands()-1);
538 // Otherwise, extract 8 adjacent bits from the immediate into this
540 unsigned RotAmt
= countLeadingZeros
<unsigned>(Offset
);
541 unsigned ThisImmVal
= Offset
& ARM_AM::rotr32(0xff000000U
, RotAmt
);
543 // We will handle these bits from offset, clear them.
544 Offset
&= ~ThisImmVal
;
546 assert(ARM_AM::getT2SOImmVal(ThisImmVal
) != -1 &&
547 "Bit extraction didn't work?");
548 MI
.getOperand(FrameRegIdx
+1).ChangeToImmediate(ThisImmVal
);
549 // Add cc_out operand if the original instruction did not have one.
551 MI
.addOperand(MachineOperand::CreateReg(0, false));
553 // AddrMode4 and AddrMode6 cannot handle any offset.
554 if (AddrMode
== ARMII::AddrMode4
|| AddrMode
== ARMII::AddrMode6
)
557 // AddrModeT2_so cannot handle any offset. If there is no offset
558 // register then we change to an immediate version.
559 unsigned NewOpc
= Opcode
;
560 if (AddrMode
== ARMII::AddrModeT2_so
) {
561 Register OffsetReg
= MI
.getOperand(FrameRegIdx
+ 1).getReg();
562 if (OffsetReg
!= 0) {
563 MI
.getOperand(FrameRegIdx
).ChangeToRegister(FrameReg
, false);
567 MI
.RemoveOperand(FrameRegIdx
+1);
568 MI
.getOperand(FrameRegIdx
+1).ChangeToImmediate(0);
569 NewOpc
= immediateOffsetOpcode(Opcode
);
570 AddrMode
= ARMII::AddrModeT2_i12
;
573 unsigned NumBits
= 0;
575 if (AddrMode
== ARMII::AddrModeT2_i8
|| AddrMode
== ARMII::AddrModeT2_i12
) {
576 // i8 supports only negative, and i12 supports only positive, so
577 // based on Offset sign convert Opcode to the appropriate
579 Offset
+= MI
.getOperand(FrameRegIdx
+1).getImm();
581 NewOpc
= negativeOffsetOpcode(Opcode
);
586 NewOpc
= positiveOffsetOpcode(Opcode
);
589 } else if (AddrMode
== ARMII::AddrMode5
) {
591 const MachineOperand
&OffOp
= MI
.getOperand(FrameRegIdx
+1);
592 int InstrOffs
= ARM_AM::getAM5Offset(OffOp
.getImm());
593 if (ARM_AM::getAM5Op(OffOp
.getImm()) == ARM_AM::sub
)
597 Offset
+= InstrOffs
* 4;
598 assert((Offset
& (Scale
-1)) == 0 && "Can't encode this offset!");
603 } else if (AddrMode
== ARMII::AddrMode5FP16
) {
605 const MachineOperand
&OffOp
= MI
.getOperand(FrameRegIdx
+1);
606 int InstrOffs
= ARM_AM::getAM5FP16Offset(OffOp
.getImm());
607 if (ARM_AM::getAM5FP16Op(OffOp
.getImm()) == ARM_AM::sub
)
611 Offset
+= InstrOffs
* 2;
612 assert((Offset
& (Scale
-1)) == 0 && "Can't encode this offset!");
617 } else if (AddrMode
== ARMII::AddrModeT2_i7s4
||
618 AddrMode
== ARMII::AddrModeT2_i7s2
||
619 AddrMode
== ARMII::AddrModeT2_i7
) {
620 Offset
+= MI
.getOperand(FrameRegIdx
+ 1).getImm();
623 case ARMII::AddrModeT2_i7s4
: NumBits
= 9; OffsetMask
= 0x3; break;
624 case ARMII::AddrModeT2_i7s2
: NumBits
= 8; OffsetMask
= 0x1; break;
625 default: NumBits
= 7; OffsetMask
= 0x0; break;
627 // MCInst operand expects already scaled value.
629 assert((Offset
& OffsetMask
) == 0 && "Can't encode this offset!");
630 (void)OffsetMask
; // squash unused-variable warning at -NDEBUG
631 } else if (AddrMode
== ARMII::AddrModeT2_i8s4
) {
632 Offset
+= MI
.getOperand(FrameRegIdx
+ 1).getImm() * 4;
634 // MCInst operand expects already scaled value.
636 assert((Offset
& 3) == 0 && "Can't encode this offset!");
637 } else if (AddrMode
== ARMII::AddrModeT2_ldrex
) {
638 Offset
+= MI
.getOperand(FrameRegIdx
+ 1).getImm() * 4;
639 NumBits
= 8; // 8 bits scaled by 4
641 assert((Offset
& 3) == 0 && "Can't encode this offset!");
643 llvm_unreachable("Unsupported addressing mode!");
646 if (NewOpc
!= Opcode
)
647 MI
.setDesc(TII
.get(NewOpc
));
649 MachineOperand
&ImmOp
= MI
.getOperand(FrameRegIdx
+1);
651 // Attempt to fold address computation
652 // Common case: small offset, fits into instruction. We need to make sure
653 // the register class is correct too, for instructions like the MVE
654 // VLDRH.32, which only accepts low tGPR registers.
655 int ImmedOffset
= Offset
/ Scale
;
656 unsigned Mask
= (1 << NumBits
) - 1;
657 if ((unsigned)Offset
<= Mask
* Scale
&&
658 (Register::isVirtualRegister(FrameReg
) ||
659 RegClass
->contains(FrameReg
))) {
660 if (Register::isVirtualRegister(FrameReg
)) {
661 // Make sure the register class for the virtual register is correct
662 MachineRegisterInfo
*MRI
= &MF
.getRegInfo();
663 if (!MRI
->constrainRegClass(FrameReg
, RegClass
))
664 llvm_unreachable("Unable to constrain virtual register class.");
667 // Replace the FrameIndex with fp/sp
668 MI
.getOperand(FrameRegIdx
).ChangeToRegister(FrameReg
, false);
670 if (AddrMode
== ARMII::AddrMode5
|| AddrMode
== ARMII::AddrMode5FP16
)
671 // FIXME: Not consistent.
672 ImmedOffset
|= 1 << NumBits
;
674 ImmedOffset
= -ImmedOffset
;
676 ImmOp
.ChangeToImmediate(ImmedOffset
);
681 // Otherwise, offset doesn't fit. Pull in what we can to simplify
682 ImmedOffset
= ImmedOffset
& Mask
;
684 if (AddrMode
== ARMII::AddrMode5
|| AddrMode
== ARMII::AddrMode5FP16
)
685 // FIXME: Not consistent.
686 ImmedOffset
|= 1 << NumBits
;
688 ImmedOffset
= -ImmedOffset
;
689 if (ImmedOffset
== 0)
690 // Change the opcode back if the encoded offset is zero.
691 MI
.setDesc(TII
.get(positiveOffsetOpcode(NewOpc
)));
694 ImmOp
.ChangeToImmediate(ImmedOffset
);
695 Offset
&= ~(Mask
*Scale
);
698 Offset
= (isSub
) ? -Offset
: Offset
;
699 return Offset
== 0 && (Register::isVirtualRegister(FrameReg
) ||
700 RegClass
->contains(FrameReg
));
703 ARMCC::CondCodes
llvm::getITInstrPredicate(const MachineInstr
&MI
,
705 unsigned Opc
= MI
.getOpcode();
706 if (Opc
== ARM::tBcc
|| Opc
== ARM::t2Bcc
)
708 return getInstrPredicate(MI
, PredReg
);
711 int llvm::findFirstVPTPredOperandIdx(const MachineInstr
&MI
) {
712 const MCInstrDesc
&MCID
= MI
.getDesc();
717 for (unsigned i
= 0, e
= MCID
.getNumOperands(); i
!= e
; ++i
)
718 if (ARM::isVpred(MCID
.OpInfo
[i
].OperandType
))
724 ARMVCC::VPTCodes
llvm::getVPTInstrPredicate(const MachineInstr
&MI
,
726 int PIdx
= findFirstVPTPredOperandIdx(MI
);
732 PredReg
= MI
.getOperand(PIdx
+1).getReg();
733 return (ARMVCC::VPTCodes
)MI
.getOperand(PIdx
).getImm();