1 //===- Thumb2InstrInfo.cpp - Thumb-2 Instruction Information --------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains the Thumb-2 implementation of the TargetInstrInfo class.
12 //===----------------------------------------------------------------------===//
14 #include "ARMInstrInfo.h"
16 #include "ARMAddressingModes.h"
17 #include "ARMGenInstrInfo.inc"
18 #include "ARMMachineFunctionInfo.h"
19 #include "llvm/CodeGen/MachineFrameInfo.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "Thumb2InstrInfo.h"
26 Thumb2InstrInfo::Thumb2InstrInfo(const ARMSubtarget
&STI
) : RI(*this, STI
) {
29 unsigned Thumb2InstrInfo::getUnindexedOpcode(unsigned Opc
) const {
35 Thumb2InstrInfo::BlockHasNoFallThrough(const MachineBasicBlock
&MBB
) const {
36 if (MBB
.empty()) return false;
38 switch (MBB
.back().getOpcode()) {
40 case ARM::t2B
: // Uncond branch.
41 case ARM::t2BR_JT
: // Jumptable branch.
42 case ARM::t2TBB
: // Table branch byte.
43 case ARM::t2TBH
: // Table branch halfword.
44 case ARM::tBR_JTr
: // Jumptable branch (16-bit version).
46 case ARM::tBX_RET_vararg
:
58 Thumb2InstrInfo::copyRegToReg(MachineBasicBlock
&MBB
,
59 MachineBasicBlock::iterator I
,
60 unsigned DestReg
, unsigned SrcReg
,
61 const TargetRegisterClass
*DestRC
,
62 const TargetRegisterClass
*SrcRC
) const {
63 DebugLoc DL
= DebugLoc::getUnknownLoc();
64 if (I
!= MBB
.end()) DL
= I
->getDebugLoc();
66 if (DestRC
== ARM::GPRRegisterClass
&&
67 SrcRC
== ARM::GPRRegisterClass
) {
68 AddDefaultCC(AddDefaultPred(BuildMI(MBB
, I
, DL
, get(ARM::t2MOVr
),
69 DestReg
).addReg(SrcReg
)));
71 } else if (DestRC
== ARM::GPRRegisterClass
&&
72 SrcRC
== ARM::tGPRRegisterClass
) {
73 BuildMI(MBB
, I
, DL
, get(ARM::tMOVtgpr2gpr
), DestReg
).addReg(SrcReg
);
75 } else if (DestRC
== ARM::tGPRRegisterClass
&&
76 SrcRC
== ARM::GPRRegisterClass
) {
77 BuildMI(MBB
, I
, DL
, get(ARM::tMOVgpr2tgpr
), DestReg
).addReg(SrcReg
);
81 // Handle SPR, DPR, and QPR copies.
82 return ARMBaseInstrInfo::copyRegToReg(MBB
, I
, DestReg
, SrcReg
, DestRC
, SrcRC
);
85 void Thumb2InstrInfo::
86 storeRegToStackSlot(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator I
,
87 unsigned SrcReg
, bool isKill
, int FI
,
88 const TargetRegisterClass
*RC
) const {
89 DebugLoc DL
= DebugLoc::getUnknownLoc();
90 if (I
!= MBB
.end()) DL
= I
->getDebugLoc();
92 if (RC
== ARM::GPRRegisterClass
) {
93 AddDefaultPred(BuildMI(MBB
, I
, DL
, get(ARM::t2STRi12
))
94 .addReg(SrcReg
, getKillRegState(isKill
))
95 .addFrameIndex(FI
).addImm(0));
99 ARMBaseInstrInfo::storeRegToStackSlot(MBB
, I
, SrcReg
, isKill
, FI
, RC
);
102 void Thumb2InstrInfo::
103 loadRegFromStackSlot(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator I
,
104 unsigned DestReg
, int FI
,
105 const TargetRegisterClass
*RC
) const {
106 DebugLoc DL
= DebugLoc::getUnknownLoc();
107 if (I
!= MBB
.end()) DL
= I
->getDebugLoc();
109 if (RC
== ARM::GPRRegisterClass
) {
110 AddDefaultPred(BuildMI(MBB
, I
, DL
, get(ARM::t2LDRi12
), DestReg
)
111 .addFrameIndex(FI
).addImm(0));
115 ARMBaseInstrInfo::loadRegFromStackSlot(MBB
, I
, DestReg
, FI
, RC
);
119 void llvm::emitT2RegPlusImmediate(MachineBasicBlock
&MBB
,
120 MachineBasicBlock::iterator
&MBBI
, DebugLoc dl
,
121 unsigned DestReg
, unsigned BaseReg
, int NumBytes
,
122 ARMCC::CondCodes Pred
, unsigned PredReg
,
123 const ARMBaseInstrInfo
&TII
) {
124 bool isSub
= NumBytes
< 0;
125 if (isSub
) NumBytes
= -NumBytes
;
127 // If profitable, use a movw or movt to materialize the offset.
128 // FIXME: Use the scavenger to grab a scratch register.
129 if (DestReg
!= ARM::SP
&& DestReg
!= BaseReg
&&
131 ARM_AM::getT2SOImmVal(NumBytes
) == -1) {
133 if (NumBytes
< 65536) {
134 // Use a movw to materialize the 16-bit constant.
135 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::t2MOVi16
), DestReg
)
137 .addImm((unsigned)Pred
).addReg(PredReg
).addReg(0);
139 } else if ((NumBytes
& 0xffff) == 0) {
140 // Use a movt to materialize the 32-bit constant.
141 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::t2MOVTi16
), DestReg
)
143 .addImm(NumBytes
>> 16)
144 .addImm((unsigned)Pred
).addReg(PredReg
).addReg(0);
150 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::t2SUBrr
), DestReg
)
151 .addReg(BaseReg
, RegState::Kill
)
152 .addReg(DestReg
, RegState::Kill
)
153 .addImm((unsigned)Pred
).addReg(PredReg
).addReg(0);
155 BuildMI(MBB
, MBBI
, dl
, TII
.get(ARM::t2ADDrr
), DestReg
)
156 .addReg(DestReg
, RegState::Kill
)
157 .addReg(BaseReg
, RegState::Kill
)
158 .addImm((unsigned)Pred
).addReg(PredReg
).addReg(0);
165 unsigned Opc
= isSub
? ARM::t2SUBri
: ARM::t2ADDri
;
166 unsigned ThisVal
= NumBytes
;
167 if (ARM_AM::getT2SOImmVal(NumBytes
) != -1) {
169 } else if (ThisVal
< 4096) {
170 Opc
= isSub
? ARM::t2SUBri12
: ARM::t2ADDri12
;
173 // FIXME: Move this to ARMAddressingModes.h?
174 unsigned RotAmt
= CountLeadingZeros_32(ThisVal
);
175 ThisVal
= ThisVal
& ARM_AM::rotr32(0xff000000U
, RotAmt
);
176 NumBytes
&= ~ThisVal
;
177 assert(ARM_AM::getT2SOImmVal(ThisVal
) != -1 &&
178 "Bit extraction didn't work?");
181 // Build the new ADD / SUB.
182 BuildMI(MBB
, MBBI
, dl
, TII
.get(Opc
), DestReg
)
183 .addReg(BaseReg
, RegState::Kill
).addImm(ThisVal
)
184 .addImm((unsigned)Pred
).addReg(PredReg
).addReg(0);
190 negativeOffsetOpcode(unsigned opcode
)
193 case ARM::t2LDRi12
: return ARM::t2LDRi8
;
194 case ARM::t2LDRHi12
: return ARM::t2LDRHi8
;
195 case ARM::t2LDRBi12
: return ARM::t2LDRBi8
;
196 case ARM::t2LDRSHi12
: return ARM::t2LDRSHi8
;
197 case ARM::t2LDRSBi12
: return ARM::t2LDRSBi8
;
198 case ARM::t2STRi12
: return ARM::t2STRi8
;
199 case ARM::t2STRBi12
: return ARM::t2STRBi8
;
200 case ARM::t2STRHi12
: return ARM::t2STRHi8
;
220 positiveOffsetOpcode(unsigned opcode
)
223 case ARM::t2LDRi8
: return ARM::t2LDRi12
;
224 case ARM::t2LDRHi8
: return ARM::t2LDRHi12
;
225 case ARM::t2LDRBi8
: return ARM::t2LDRBi12
;
226 case ARM::t2LDRSHi8
: return ARM::t2LDRSHi12
;
227 case ARM::t2LDRSBi8
: return ARM::t2LDRSBi12
;
228 case ARM::t2STRi8
: return ARM::t2STRi12
;
229 case ARM::t2STRBi8
: return ARM::t2STRBi12
;
230 case ARM::t2STRHi8
: return ARM::t2STRHi12
;
235 case ARM::t2LDRSHi12
:
236 case ARM::t2LDRSBi12
:
250 immediateOffsetOpcode(unsigned opcode
)
253 case ARM::t2LDRs
: return ARM::t2LDRi12
;
254 case ARM::t2LDRHs
: return ARM::t2LDRHi12
;
255 case ARM::t2LDRBs
: return ARM::t2LDRBi12
;
256 case ARM::t2LDRSHs
: return ARM::t2LDRSHi12
;
257 case ARM::t2LDRSBs
: return ARM::t2LDRSBi12
;
258 case ARM::t2STRs
: return ARM::t2STRi12
;
259 case ARM::t2STRBs
: return ARM::t2STRBi12
;
260 case ARM::t2STRHs
: return ARM::t2STRHi12
;
265 case ARM::t2LDRSHi12
:
266 case ARM::t2LDRSBi12
:
287 int llvm::rewriteT2FrameIndex(MachineInstr
&MI
, unsigned FrameRegIdx
,
288 unsigned FrameReg
, int Offset
,
289 const ARMBaseInstrInfo
&TII
) {
290 unsigned Opcode
= MI
.getOpcode();
291 unsigned NewOpc
= Opcode
;
292 const TargetInstrDesc
&Desc
= MI
.getDesc();
293 unsigned AddrMode
= (Desc
.TSFlags
& ARMII::AddrModeMask
);
296 // Memory operands in inline assembly always use AddrModeT2_i12.
297 if (Opcode
== ARM::INLINEASM
)
298 AddrMode
= ARMII::AddrModeT2_i12
; // FIXME. mode for thumb2?
300 if (Opcode
== ARM::t2ADDri
|| Opcode
== ARM::t2ADDri12
) {
301 Offset
+= MI
.getOperand(FrameRegIdx
+1).getImm();
303 // Turn it into a move.
304 MI
.setDesc(TII
.get(ARM::t2MOVr
));
305 MI
.getOperand(FrameRegIdx
).ChangeToRegister(FrameReg
, false);
306 MI
.RemoveOperand(FrameRegIdx
+1);
313 MI
.setDesc(TII
.get(ARM::t2SUBri
));
316 // Common case: small offset, fits into instruction.
317 if (ARM_AM::getT2SOImmVal(Offset
) != -1) {
318 NewOpc
= isSub
? ARM::t2SUBri
: ARM::t2ADDri
;
319 if (NewOpc
!= Opcode
)
320 MI
.setDesc(TII
.get(NewOpc
));
321 MI
.getOperand(FrameRegIdx
).ChangeToRegister(FrameReg
, false);
322 MI
.getOperand(FrameRegIdx
+1).ChangeToImmediate(Offset
);
325 // Another common case: imm12.
327 NewOpc
= isSub
? ARM::t2SUBri12
: ARM::t2ADDri12
;
328 if (NewOpc
!= Opcode
)
329 MI
.setDesc(TII
.get(NewOpc
));
330 MI
.getOperand(FrameRegIdx
).ChangeToRegister(FrameReg
, false);
331 MI
.getOperand(FrameRegIdx
+1).ChangeToImmediate(Offset
);
335 // Otherwise, extract 8 adjacent bits from the immediate into this
337 unsigned RotAmt
= CountLeadingZeros_32(Offset
);
338 unsigned ThisImmVal
= Offset
& ARM_AM::rotr32(0xff000000U
, RotAmt
);
340 // We will handle these bits from offset, clear them.
341 Offset
&= ~ThisImmVal
;
343 assert(ARM_AM::getT2SOImmVal(ThisImmVal
) != -1 &&
344 "Bit extraction didn't work?");
345 MI
.getOperand(FrameRegIdx
+1).ChangeToImmediate(ThisImmVal
);
347 // AddrModeT2_so cannot handle any offset. If there is no offset
348 // register then we change to an immediate version.
350 if (AddrMode
== ARMII::AddrModeT2_so
) {
351 unsigned OffsetReg
= MI
.getOperand(FrameRegIdx
+1).getReg();
352 if (OffsetReg
!= 0) {
353 MI
.getOperand(FrameRegIdx
).ChangeToRegister(FrameReg
, false);
357 MI
.RemoveOperand(FrameRegIdx
+1);
358 MI
.getOperand(FrameRegIdx
+1).ChangeToImmediate(0);
359 NewOpc
= immediateOffsetOpcode(Opcode
);
360 AddrMode
= ARMII::AddrModeT2_i12
;
363 unsigned NumBits
= 0;
365 if (AddrMode
== ARMII::AddrModeT2_i8
|| AddrMode
== ARMII::AddrModeT2_i12
) {
366 // i8 supports only negative, and i12 supports only positive, so
367 // based on Offset sign convert Opcode to the appropriate
369 Offset
+= MI
.getOperand(FrameRegIdx
+1).getImm();
371 NewOpc
= negativeOffsetOpcode(Opcode
);
376 NewOpc
= positiveOffsetOpcode(Opcode
);
380 // VFP address modes.
381 assert(AddrMode
== ARMII::AddrMode5
);
382 int InstrOffs
=ARM_AM::getAM5Offset(MI
.getOperand(FrameRegIdx
+1).getImm());
383 if (ARM_AM::getAM5Op(MI
.getOperand(FrameRegIdx
+1).getImm()) ==ARM_AM::sub
)
387 Offset
+= InstrOffs
* 4;
388 assert((Offset
& (Scale
-1)) == 0 && "Can't encode this offset!");
395 if (NewOpc
!= Opcode
)
396 MI
.setDesc(TII
.get(NewOpc
));
398 MachineOperand
&ImmOp
= MI
.getOperand(FrameRegIdx
+1);
400 // Attempt to fold address computation
401 // Common case: small offset, fits into instruction.
402 int ImmedOffset
= Offset
/ Scale
;
403 unsigned Mask
= (1 << NumBits
) - 1;
404 if ((unsigned)Offset
<= Mask
* Scale
) {
405 // Replace the FrameIndex with fp/sp
406 MI
.getOperand(FrameRegIdx
).ChangeToRegister(FrameReg
, false);
408 if (AddrMode
== ARMII::AddrMode5
)
409 // FIXME: Not consistent.
410 ImmedOffset
|= 1 << NumBits
;
412 ImmedOffset
= -ImmedOffset
;
414 ImmOp
.ChangeToImmediate(ImmedOffset
);
418 // Otherwise, offset doesn't fit. Pull in what we can to simplify
419 ImmedOffset
= ImmedOffset
& Mask
;
421 if (AddrMode
== ARMII::AddrMode5
)
422 // FIXME: Not consistent.
423 ImmedOffset
|= 1 << NumBits
;
425 ImmedOffset
= -ImmedOffset
;
426 if (ImmedOffset
== 0)
427 // Change the opcode back if the encoded offset is zero.
428 MI
.setDesc(TII
.get(positiveOffsetOpcode(NewOpc
)));
431 ImmOp
.ChangeToImmediate(ImmedOffset
);
432 Offset
&= ~(Mask
*Scale
);
435 return (isSub
) ? -Offset
: Offset
;