1 //===- AlphaInstrInfo.cpp - Alpha 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 Alpha implementation of the TargetInstrInfo class.
12 //===----------------------------------------------------------------------===//
15 #include "AlphaInstrInfo.h"
16 #include "AlphaGenInstrInfo.inc"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 AlphaInstrInfo::AlphaInstrInfo()
23 : TargetInstrInfoImpl(AlphaInsts
, array_lengthof(AlphaInsts
)),
27 bool AlphaInstrInfo::isMoveInstr(const MachineInstr
& MI
,
28 unsigned& sourceReg
, unsigned& destReg
,
29 unsigned& SrcSR
, unsigned& DstSR
) const {
30 unsigned oc
= MI
.getOpcode();
31 if (oc
== Alpha::BISr
||
34 oc
== Alpha::CPYSSt
||
35 oc
== Alpha::CPYSTs
) {
38 assert(MI
.getNumOperands() >= 3 &&
39 MI
.getOperand(0).isReg() &&
40 MI
.getOperand(1).isReg() &&
41 MI
.getOperand(2).isReg() &&
42 "invalid Alpha BIS instruction!");
43 if (MI
.getOperand(1).getReg() == MI
.getOperand(2).getReg()) {
44 sourceReg
= MI
.getOperand(1).getReg();
45 destReg
= MI
.getOperand(0).getReg();
54 AlphaInstrInfo::isLoadFromStackSlot(const MachineInstr
*MI
,
55 int &FrameIndex
) const {
56 switch (MI
->getOpcode()) {
63 if (MI
->getOperand(1).isFI()) {
64 FrameIndex
= MI
->getOperand(1).getIndex();
65 return MI
->getOperand(0).getReg();
73 AlphaInstrInfo::isStoreToStackSlot(const MachineInstr
*MI
,
74 int &FrameIndex
) const {
75 switch (MI
->getOpcode()) {
82 if (MI
->getOperand(1).isFI()) {
83 FrameIndex
= MI
->getOperand(1).getIndex();
84 return MI
->getOperand(0).getReg();
91 static bool isAlphaIntCondCode(unsigned Opcode
) {
107 unsigned AlphaInstrInfo::InsertBranch(MachineBasicBlock
&MBB
,
108 MachineBasicBlock
*TBB
,
109 MachineBasicBlock
*FBB
,
110 const SmallVectorImpl
<MachineOperand
> &Cond
) const {
111 // FIXME this should probably have a DebugLoc argument
112 DebugLoc dl
= DebugLoc::getUnknownLoc();
113 assert(TBB
&& "InsertBranch must not be told to insert a fallthrough");
114 assert((Cond
.size() == 2 || Cond
.size() == 0) &&
115 "Alpha branch conditions have two components!");
119 if (Cond
.empty()) // Unconditional branch
120 BuildMI(&MBB
, dl
, get(Alpha::BR
)).addMBB(TBB
);
121 else // Conditional branch
122 if (isAlphaIntCondCode(Cond
[0].getImm()))
123 BuildMI(&MBB
, dl
, get(Alpha::COND_BRANCH_I
))
124 .addImm(Cond
[0].getImm()).addReg(Cond
[1].getReg()).addMBB(TBB
);
126 BuildMI(&MBB
, dl
, get(Alpha::COND_BRANCH_F
))
127 .addImm(Cond
[0].getImm()).addReg(Cond
[1].getReg()).addMBB(TBB
);
131 // Two-way Conditional Branch.
132 if (isAlphaIntCondCode(Cond
[0].getImm()))
133 BuildMI(&MBB
, dl
, get(Alpha::COND_BRANCH_I
))
134 .addImm(Cond
[0].getImm()).addReg(Cond
[1].getReg()).addMBB(TBB
);
136 BuildMI(&MBB
, dl
, get(Alpha::COND_BRANCH_F
))
137 .addImm(Cond
[0].getImm()).addReg(Cond
[1].getReg()).addMBB(TBB
);
138 BuildMI(&MBB
, dl
, get(Alpha::BR
)).addMBB(FBB
);
142 bool AlphaInstrInfo::copyRegToReg(MachineBasicBlock
&MBB
,
143 MachineBasicBlock::iterator MI
,
144 unsigned DestReg
, unsigned SrcReg
,
145 const TargetRegisterClass
*DestRC
,
146 const TargetRegisterClass
*SrcRC
) const {
147 //cerr << "copyRegToReg " << DestReg << " <- " << SrcReg << "\n";
148 if (DestRC
!= SrcRC
) {
149 // Not yet supported!
153 DebugLoc DL
= DebugLoc::getUnknownLoc();
154 if (MI
!= MBB
.end()) DL
= MI
->getDebugLoc();
156 if (DestRC
== Alpha::GPRCRegisterClass
) {
157 BuildMI(MBB
, MI
, DL
, get(Alpha::BISr
), DestReg
)
160 } else if (DestRC
== Alpha::F4RCRegisterClass
) {
161 BuildMI(MBB
, MI
, DL
, get(Alpha::CPYSS
), DestReg
)
164 } else if (DestRC
== Alpha::F8RCRegisterClass
) {
165 BuildMI(MBB
, MI
, DL
, get(Alpha::CPYST
), DestReg
)
169 // Attempt to copy register that is not GPR or FPR
177 AlphaInstrInfo::storeRegToStackSlot(MachineBasicBlock
&MBB
,
178 MachineBasicBlock::iterator MI
,
179 unsigned SrcReg
, bool isKill
, int FrameIdx
,
180 const TargetRegisterClass
*RC
) const {
181 //cerr << "Trying to store " << getPrettyName(SrcReg) << " to "
182 // << FrameIdx << "\n";
183 //BuildMI(MBB, MI, Alpha::WTF, 0).addReg(SrcReg);
185 DebugLoc DL
= DebugLoc::getUnknownLoc();
186 if (MI
!= MBB
.end()) DL
= MI
->getDebugLoc();
188 if (RC
== Alpha::F4RCRegisterClass
)
189 BuildMI(MBB
, MI
, DL
, get(Alpha::STS
))
190 .addReg(SrcReg
, getKillRegState(isKill
))
191 .addFrameIndex(FrameIdx
).addReg(Alpha::F31
);
192 else if (RC
== Alpha::F8RCRegisterClass
)
193 BuildMI(MBB
, MI
, DL
, get(Alpha::STT
))
194 .addReg(SrcReg
, getKillRegState(isKill
))
195 .addFrameIndex(FrameIdx
).addReg(Alpha::F31
);
196 else if (RC
== Alpha::GPRCRegisterClass
)
197 BuildMI(MBB
, MI
, DL
, get(Alpha::STQ
))
198 .addReg(SrcReg
, getKillRegState(isKill
))
199 .addFrameIndex(FrameIdx
).addReg(Alpha::F31
);
204 void AlphaInstrInfo::storeRegToAddr(MachineFunction
&MF
, unsigned SrcReg
,
206 SmallVectorImpl
<MachineOperand
> &Addr
,
207 const TargetRegisterClass
*RC
,
208 SmallVectorImpl
<MachineInstr
*> &NewMIs
) const {
210 if (RC
== Alpha::F4RCRegisterClass
)
212 else if (RC
== Alpha::F8RCRegisterClass
)
214 else if (RC
== Alpha::GPRCRegisterClass
)
218 DebugLoc DL
= DebugLoc::getUnknownLoc();
219 MachineInstrBuilder MIB
=
220 BuildMI(MF
, DL
, get(Opc
)).addReg(SrcReg
, getKillRegState(isKill
));
221 for (unsigned i
= 0, e
= Addr
.size(); i
!= e
; ++i
)
222 MIB
.addOperand(Addr
[i
]);
223 NewMIs
.push_back(MIB
);
227 AlphaInstrInfo::loadRegFromStackSlot(MachineBasicBlock
&MBB
,
228 MachineBasicBlock::iterator MI
,
229 unsigned DestReg
, int FrameIdx
,
230 const TargetRegisterClass
*RC
) const {
231 //cerr << "Trying to load " << getPrettyName(DestReg) << " to "
232 // << FrameIdx << "\n";
233 DebugLoc DL
= DebugLoc::getUnknownLoc();
234 if (MI
!= MBB
.end()) DL
= MI
->getDebugLoc();
236 if (RC
== Alpha::F4RCRegisterClass
)
237 BuildMI(MBB
, MI
, DL
, get(Alpha::LDS
), DestReg
)
238 .addFrameIndex(FrameIdx
).addReg(Alpha::F31
);
239 else if (RC
== Alpha::F8RCRegisterClass
)
240 BuildMI(MBB
, MI
, DL
, get(Alpha::LDT
), DestReg
)
241 .addFrameIndex(FrameIdx
).addReg(Alpha::F31
);
242 else if (RC
== Alpha::GPRCRegisterClass
)
243 BuildMI(MBB
, MI
, DL
, get(Alpha::LDQ
), DestReg
)
244 .addFrameIndex(FrameIdx
).addReg(Alpha::F31
);
249 void AlphaInstrInfo::loadRegFromAddr(MachineFunction
&MF
, unsigned DestReg
,
250 SmallVectorImpl
<MachineOperand
> &Addr
,
251 const TargetRegisterClass
*RC
,
252 SmallVectorImpl
<MachineInstr
*> &NewMIs
) const {
254 if (RC
== Alpha::F4RCRegisterClass
)
256 else if (RC
== Alpha::F8RCRegisterClass
)
258 else if (RC
== Alpha::GPRCRegisterClass
)
262 DebugLoc DL
= DebugLoc::getUnknownLoc();
263 MachineInstrBuilder MIB
=
264 BuildMI(MF
, DL
, get(Opc
), DestReg
);
265 for (unsigned i
= 0, e
= Addr
.size(); i
!= e
; ++i
)
266 MIB
.addOperand(Addr
[i
]);
267 NewMIs
.push_back(MIB
);
270 MachineInstr
*AlphaInstrInfo::foldMemoryOperandImpl(MachineFunction
&MF
,
272 const SmallVectorImpl
<unsigned> &Ops
,
273 int FrameIndex
) const {
274 if (Ops
.size() != 1) return NULL
;
276 // Make sure this is a reg-reg copy.
277 unsigned Opc
= MI
->getOpcode();
279 MachineInstr
*NewMI
= NULL
;
286 if (MI
->getOperand(1).getReg() == MI
->getOperand(2).getReg()) {
287 if (Ops
[0] == 0) { // move -> store
288 unsigned InReg
= MI
->getOperand(1).getReg();
289 bool isKill
= MI
->getOperand(1).isKill();
290 Opc
= (Opc
== Alpha::BISr
) ? Alpha::STQ
:
291 ((Opc
== Alpha::CPYSS
) ? Alpha::STS
: Alpha::STT
);
292 NewMI
= BuildMI(MF
, MI
->getDebugLoc(), get(Opc
))
293 .addReg(InReg
, getKillRegState(isKill
))
294 .addFrameIndex(FrameIndex
)
296 } else { // load -> move
297 unsigned OutReg
= MI
->getOperand(0).getReg();
298 bool isDead
= MI
->getOperand(0).isDead();
299 Opc
= (Opc
== Alpha::BISr
) ? Alpha::LDQ
:
300 ((Opc
== Alpha::CPYSS
) ? Alpha::LDS
: Alpha::LDT
);
301 NewMI
= BuildMI(MF
, MI
->getDebugLoc(), get(Opc
))
302 .addReg(OutReg
, RegState::Define
| getDeadRegState(isDead
))
303 .addFrameIndex(FrameIndex
)
312 static unsigned AlphaRevCondCode(unsigned Opcode
) {
314 case Alpha::BEQ
: return Alpha::BNE
;
315 case Alpha::BNE
: return Alpha::BEQ
;
316 case Alpha::BGE
: return Alpha::BLT
;
317 case Alpha::BGT
: return Alpha::BLE
;
318 case Alpha::BLE
: return Alpha::BGT
;
319 case Alpha::BLT
: return Alpha::BGE
;
320 case Alpha::BLBC
: return Alpha::BLBS
;
321 case Alpha::BLBS
: return Alpha::BLBC
;
322 case Alpha::FBEQ
: return Alpha::FBNE
;
323 case Alpha::FBNE
: return Alpha::FBEQ
;
324 case Alpha::FBGE
: return Alpha::FBLT
;
325 case Alpha::FBGT
: return Alpha::FBLE
;
326 case Alpha::FBLE
: return Alpha::FBGT
;
327 case Alpha::FBLT
: return Alpha::FBGE
;
329 assert(0 && "Unknown opcode");
331 return 0; // Not reached
335 bool AlphaInstrInfo::AnalyzeBranch(MachineBasicBlock
&MBB
,MachineBasicBlock
*&TBB
,
336 MachineBasicBlock
*&FBB
,
337 SmallVectorImpl
<MachineOperand
> &Cond
,
338 bool AllowModify
) const {
339 // If the block has no terminators, it just falls into the block after it.
340 MachineBasicBlock::iterator I
= MBB
.end();
341 if (I
== MBB
.begin() || !isUnpredicatedTerminator(--I
))
344 // Get the last instruction in the block.
345 MachineInstr
*LastInst
= I
;
347 // If there is only one terminator instruction, process it.
348 if (I
== MBB
.begin() || !isUnpredicatedTerminator(--I
)) {
349 if (LastInst
->getOpcode() == Alpha::BR
) {
350 TBB
= LastInst
->getOperand(0).getMBB();
352 } else if (LastInst
->getOpcode() == Alpha::COND_BRANCH_I
||
353 LastInst
->getOpcode() == Alpha::COND_BRANCH_F
) {
354 // Block ends with fall-through condbranch.
355 TBB
= LastInst
->getOperand(2).getMBB();
356 Cond
.push_back(LastInst
->getOperand(0));
357 Cond
.push_back(LastInst
->getOperand(1));
360 // Otherwise, don't know what this is.
364 // Get the instruction before it if it's a terminator.
365 MachineInstr
*SecondLastInst
= I
;
367 // If there are three terminators, we don't know what sort of block this is.
368 if (SecondLastInst
&& I
!= MBB
.begin() &&
369 isUnpredicatedTerminator(--I
))
372 // If the block ends with Alpha::BR and Alpha::COND_BRANCH_*, handle it.
373 if ((SecondLastInst
->getOpcode() == Alpha::COND_BRANCH_I
||
374 SecondLastInst
->getOpcode() == Alpha::COND_BRANCH_F
) &&
375 LastInst
->getOpcode() == Alpha::BR
) {
376 TBB
= SecondLastInst
->getOperand(2).getMBB();
377 Cond
.push_back(SecondLastInst
->getOperand(0));
378 Cond
.push_back(SecondLastInst
->getOperand(1));
379 FBB
= LastInst
->getOperand(0).getMBB();
383 // If the block ends with two Alpha::BRs, handle it. The second one is not
384 // executed, so remove it.
385 if (SecondLastInst
->getOpcode() == Alpha::BR
&&
386 LastInst
->getOpcode() == Alpha::BR
) {
387 TBB
= SecondLastInst
->getOperand(0).getMBB();
390 I
->eraseFromParent();
394 // Otherwise, can't handle this.
398 unsigned AlphaInstrInfo::RemoveBranch(MachineBasicBlock
&MBB
) const {
399 MachineBasicBlock::iterator I
= MBB
.end();
400 if (I
== MBB
.begin()) return 0;
402 if (I
->getOpcode() != Alpha::BR
&&
403 I
->getOpcode() != Alpha::COND_BRANCH_I
&&
404 I
->getOpcode() != Alpha::COND_BRANCH_F
)
407 // Remove the branch.
408 I
->eraseFromParent();
412 if (I
== MBB
.begin()) return 1;
414 if (I
->getOpcode() != Alpha::COND_BRANCH_I
&&
415 I
->getOpcode() != Alpha::COND_BRANCH_F
)
418 // Remove the branch.
419 I
->eraseFromParent();
423 void AlphaInstrInfo::insertNoop(MachineBasicBlock
&MBB
,
424 MachineBasicBlock::iterator MI
) const {
425 DebugLoc DL
= DebugLoc::getUnknownLoc();
426 if (MI
!= MBB
.end()) DL
= MI
->getDebugLoc();
427 BuildMI(MBB
, MI
, DL
, get(Alpha::BISr
), Alpha::R31
)
432 bool AlphaInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock
&MBB
) const {
433 if (MBB
.empty()) return false;
435 switch (MBB
.back().getOpcode()) {
436 case Alpha::RETDAG
: // Return.
438 case Alpha::BR
: // Uncond branch.
439 case Alpha::JMP
: // Indirect branch.
441 default: return false;
444 bool AlphaInstrInfo::
445 ReverseBranchCondition(SmallVectorImpl
<MachineOperand
> &Cond
) const {
446 assert(Cond
.size() == 2 && "Invalid Alpha branch opcode!");
447 Cond
[0].setImm(AlphaRevCondCode(Cond
[0].getImm()));