1 //===-- MipsISelDAGToDAG.cpp - A dag to dag inst selector for Mips --------===//
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 defines an instruction selector for the MIPS target.
12 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "mips-isel"
16 #include "MipsMachineFunction.h"
17 #include "MipsRegisterInfo.h"
18 #include "MipsSubtarget.h"
19 #include "MipsTargetMachine.h"
20 #include "llvm/GlobalValue.h"
21 #include "llvm/Instructions.h"
22 #include "llvm/Intrinsics.h"
23 #include "llvm/Support/CFG.h"
24 #include "llvm/Type.h"
25 #include "llvm/CodeGen/MachineConstantPool.h"
26 #include "llvm/CodeGen/MachineFunction.h"
27 #include "llvm/CodeGen/MachineFrameInfo.h"
28 #include "llvm/CodeGen/MachineInstrBuilder.h"
29 #include "llvm/CodeGen/MachineRegisterInfo.h"
30 #include "llvm/CodeGen/SelectionDAGISel.h"
31 #include "llvm/Target/TargetMachine.h"
32 #include "llvm/Support/Debug.h"
33 #include "llvm/Support/ErrorHandling.h"
34 #include "llvm/Support/raw_ostream.h"
37 //===----------------------------------------------------------------------===//
38 // Instruction Selector Implementation
39 //===----------------------------------------------------------------------===//
41 //===----------------------------------------------------------------------===//
42 // MipsDAGToDAGISel - MIPS specific code to select MIPS machine
43 // instructions for SelectionDAG operations.
44 //===----------------------------------------------------------------------===//
47 class MipsDAGToDAGISel
: public SelectionDAGISel
{
49 /// TM - Keep a reference to MipsTargetMachine.
50 MipsTargetMachine
&TM
;
52 /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can
53 /// make the right decision when generating code for different targets.
54 const MipsSubtarget
&Subtarget
;
57 explicit MipsDAGToDAGISel(MipsTargetMachine
&tm
) :
59 TM(tm
), Subtarget(tm
.getSubtarget
<MipsSubtarget
>()) {}
62 virtual const char *getPassName() const {
63 return "MIPS DAG->DAG Pattern Instruction Selection";
68 // Include the pieces autogenerated from the target description.
69 #include "MipsGenDAGISel.inc"
71 /// getTargetMachine - Return a reference to the TargetMachine, casted
72 /// to the target-specific type.
73 const MipsTargetMachine
&getTargetMachine() {
74 return static_cast<const MipsTargetMachine
&>(TM
);
77 /// getInstrInfo - Return a reference to the TargetInstrInfo, casted
78 /// to the target-specific type.
79 const MipsInstrInfo
*getInstrInfo() {
80 return getTargetMachine().getInstrInfo();
83 SDNode
*getGlobalBaseReg();
84 SDNode
*Select(SDNode
*N
);
87 bool SelectAddr(SDValue N
, SDValue
&Base
, SDValue
&Offset
);
89 SDNode
*SelectLoadFp64(SDNode
*N
);
90 SDNode
*SelectStoreFp64(SDNode
*N
);
92 // getI32Imm - Return a target constant with the specified
93 // value, of type i32.
94 inline SDValue
getI32Imm(unsigned Imm
) {
95 return CurDAG
->getTargetConstant(Imm
, MVT::i32
);
98 virtual bool SelectInlineAsmMemoryOperand(const SDValue
&Op
,
100 std::vector
<SDValue
> &OutOps
);
106 /// getGlobalBaseReg - Output the instructions required to put the
107 /// GOT address into a register.
108 SDNode
*MipsDAGToDAGISel::getGlobalBaseReg() {
109 unsigned GlobalBaseReg
= getInstrInfo()->getGlobalBaseReg(MF
);
110 return CurDAG
->getRegister(GlobalBaseReg
, TLI
.getPointerTy()).getNode();
113 /// ComplexPattern used on MipsInstrInfo
114 /// Used on Mips Load/Store instructions
115 bool MipsDAGToDAGISel::
116 SelectAddr(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
) {
117 // if Address is FI, get the TargetFrameIndex.
118 if (FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
)) {
119 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), MVT::i32
);
120 Offset
= CurDAG
->getTargetConstant(0, MVT::i32
);
124 // on PIC code Load GA
125 if (TM
.getRelocationModel() == Reloc::PIC_
) {
126 if (Addr
.getOpcode() == MipsISD::WrapperPIC
) {
127 Base
= CurDAG
->getRegister(Mips::GP
, MVT::i32
);
128 Offset
= Addr
.getOperand(0);
132 if ((Addr
.getOpcode() == ISD::TargetExternalSymbol
||
133 Addr
.getOpcode() == ISD::TargetGlobalAddress
))
135 else if (Addr
.getOpcode() == ISD::TargetGlobalTLSAddress
) {
136 Base
= CurDAG
->getRegister(Mips::GP
, MVT::i32
);
142 // Addresses of the form FI+const or FI|const
143 if (CurDAG
->isBaseWithConstantOffset(Addr
)) {
144 ConstantSDNode
*CN
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1));
145 if (isInt
<16>(CN
->getSExtValue())) {
147 // If the first operand is a FI, get the TargetFI Node
148 if (FrameIndexSDNode
*FIN
= dyn_cast
<FrameIndexSDNode
>
149 (Addr
.getOperand(0)))
150 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), MVT::i32
);
152 Base
= Addr
.getOperand(0);
154 Offset
= CurDAG
->getTargetConstant(CN
->getZExtValue(), MVT::i32
);
159 // Operand is a result from an ADD.
160 if (Addr
.getOpcode() == ISD::ADD
) {
161 // When loading from constant pools, load the lower address part in
162 // the instruction itself. Example, instead of:
163 // lui $2, %hi($CPI1_0)
164 // addiu $2, $2, %lo($CPI1_0)
167 // lui $2, %hi($CPI1_0)
168 // lwc1 $f0, %lo($CPI1_0)($2)
169 if ((Addr
.getOperand(0).getOpcode() == MipsISD::Hi
||
170 Addr
.getOperand(0).getOpcode() == ISD::LOAD
) &&
171 Addr
.getOperand(1).getOpcode() == MipsISD::Lo
) {
172 SDValue LoVal
= Addr
.getOperand(1);
173 if (isa
<ConstantPoolSDNode
>(LoVal
.getOperand(0)) ||
174 isa
<GlobalAddressSDNode
>(LoVal
.getOperand(0))) {
175 Base
= Addr
.getOperand(0);
176 Offset
= LoVal
.getOperand(0);
183 Offset
= CurDAG
->getTargetConstant(0, MVT::i32
);
187 SDNode
*MipsDAGToDAGISel::SelectLoadFp64(SDNode
*N
) {
188 MVT::SimpleValueType NVT
=
189 N
->getValueType(0).getSimpleVT().SimpleTy
;
191 if (!Subtarget
.isMips1() || NVT
!= MVT::f64
)
194 LoadSDNode
*LN
= cast
<LoadSDNode
>(N
);
195 if (LN
->getExtensionType() != ISD::NON_EXTLOAD
||
196 LN
->getAddressingMode() != ISD::UNINDEXED
)
199 SDValue Chain
= N
->getOperand(0);
200 SDValue N1
= N
->getOperand(1);
201 SDValue Offset0
, Offset1
, Base
;
203 if (!SelectAddr(N1
, Base
, Offset0
) ||
204 N1
.getValueType() != MVT::i32
)
207 MachineSDNode::mmo_iterator MemRefs0
= MF
->allocateMemRefsArray(1);
208 MemRefs0
[0] = cast
<MemSDNode
>(N
)->getMemOperand();
209 DebugLoc dl
= N
->getDebugLoc();
211 // The second load should start after for 4 bytes.
212 if (ConstantSDNode
*C
= dyn_cast
<ConstantSDNode
>(Offset0
))
213 Offset1
= CurDAG
->getTargetConstant(C
->getSExtValue()+4, MVT::i32
);
214 else if (ConstantPoolSDNode
*CP
= dyn_cast
<ConstantPoolSDNode
>(Offset0
))
215 Offset1
= CurDAG
->getTargetConstantPool(CP
->getConstVal(),
219 CP
->getTargetFlags());
223 // Choose the offsets depending on the endianess
224 if (TM
.getTargetData()->isBigEndian())
225 std::swap(Offset0
, Offset1
);
232 SDNode
*LD0
= CurDAG
->getMachineNode(Mips::LWC1
, dl
, MVT::f32
,
233 MVT::Other
, Base
, Offset0
, Chain
);
234 SDValue Undef
= SDValue(CurDAG
->getMachineNode(TargetOpcode::IMPLICIT_DEF
,
236 SDValue I0
= CurDAG
->getTargetInsertSubreg(Mips::sub_fpeven
, dl
,
237 MVT::f64
, Undef
, SDValue(LD0
, 0));
239 SDNode
*LD1
= CurDAG
->getMachineNode(Mips::LWC1
, dl
, MVT::f32
,
240 MVT::Other
, Base
, Offset1
, SDValue(LD0
, 1));
241 SDValue I1
= CurDAG
->getTargetInsertSubreg(Mips::sub_fpodd
, dl
,
242 MVT::f64
, I0
, SDValue(LD1
, 0));
244 ReplaceUses(SDValue(N
, 0), I1
);
245 ReplaceUses(SDValue(N
, 1), Chain
);
246 cast
<MachineSDNode
>(LD0
)->setMemRefs(MemRefs0
, MemRefs0
+ 1);
247 cast
<MachineSDNode
>(LD1
)->setMemRefs(MemRefs0
, MemRefs0
+ 1);
251 SDNode
*MipsDAGToDAGISel::SelectStoreFp64(SDNode
*N
) {
253 if (!Subtarget
.isMips1() ||
254 N
->getOperand(1).getValueType() != MVT::f64
)
257 SDValue Chain
= N
->getOperand(0);
259 StoreSDNode
*SN
= cast
<StoreSDNode
>(N
);
260 if (SN
->isTruncatingStore() || SN
->getAddressingMode() != ISD::UNINDEXED
)
263 SDValue N1
= N
->getOperand(1);
264 SDValue N2
= N
->getOperand(2);
265 SDValue Offset0
, Offset1
, Base
;
267 if (!SelectAddr(N2
, Base
, Offset0
) ||
268 N1
.getValueType() != MVT::f64
||
269 N2
.getValueType() != MVT::i32
)
272 MachineSDNode::mmo_iterator MemRefs0
= MF
->allocateMemRefsArray(1);
273 MemRefs0
[0] = cast
<MemSDNode
>(N
)->getMemOperand();
274 DebugLoc dl
= N
->getDebugLoc();
276 // Get the even and odd part from the f64 register
277 SDValue FPOdd
= CurDAG
->getTargetExtractSubreg(Mips::sub_fpodd
,
279 SDValue FPEven
= CurDAG
->getTargetExtractSubreg(Mips::sub_fpeven
,
282 // The second store should start after for 4 bytes.
283 if (ConstantSDNode
*C
= dyn_cast
<ConstantSDNode
>(Offset0
))
284 Offset1
= CurDAG
->getTargetConstant(C
->getSExtValue()+4, MVT::i32
);
288 // Choose the offsets depending on the endianess
289 if (TM
.getTargetData()->isBigEndian())
290 std::swap(Offset0
, Offset1
);
297 SDValue Ops0
[] = { FPEven
, Base
, Offset0
, Chain
};
298 Chain
= SDValue(CurDAG
->getMachineNode(Mips::SWC1
, dl
,
299 MVT::Other
, Ops0
, 4), 0);
300 cast
<MachineSDNode
>(Chain
.getNode())->setMemRefs(MemRefs0
, MemRefs0
+ 1);
302 SDValue Ops1
[] = { FPOdd
, Base
, Offset1
, Chain
};
303 Chain
= SDValue(CurDAG
->getMachineNode(Mips::SWC1
, dl
,
304 MVT::Other
, Ops1
, 4), 0);
305 cast
<MachineSDNode
>(Chain
.getNode())->setMemRefs(MemRefs0
, MemRefs0
+ 1);
307 ReplaceUses(SDValue(N
, 0), Chain
);
308 return Chain
.getNode();
311 /// Select instructions not customized! Used for
312 /// expanded, promoted and normal instructions
313 SDNode
* MipsDAGToDAGISel::Select(SDNode
*Node
) {
314 unsigned Opcode
= Node
->getOpcode();
315 DebugLoc dl
= Node
->getDebugLoc();
317 // Dump information about the Node being selected
318 DEBUG(errs() << "Selecting: "; Node
->dump(CurDAG
); errs() << "\n");
320 // If we have a custom node, we already have selected!
321 if (Node
->isMachineOpcode()) {
322 DEBUG(errs() << "== "; Node
->dump(CurDAG
); errs() << "\n");
327 // Instruction Selection not handled by the auto-generated
328 // tablegen selection should be handled here.
335 SDValue InFlag
= Node
->getOperand(2), CmpLHS
;
336 unsigned Opc
= InFlag
.getOpcode(); (void)Opc
;
337 assert(((Opc
== ISD::ADDC
|| Opc
== ISD::ADDE
) ||
338 (Opc
== ISD::SUBC
|| Opc
== ISD::SUBE
)) &&
339 "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn");
342 if (Opcode
== ISD::ADDE
) {
343 CmpLHS
= InFlag
.getValue(0);
346 CmpLHS
= InFlag
.getOperand(0);
350 SDValue Ops
[] = { CmpLHS
, InFlag
.getOperand(1) };
352 SDValue LHS
= Node
->getOperand(0);
353 SDValue RHS
= Node
->getOperand(1);
355 EVT VT
= LHS
.getValueType();
356 SDNode
*Carry
= CurDAG
->getMachineNode(Mips::SLTu
, dl
, VT
, Ops
, 2);
357 SDNode
*AddCarry
= CurDAG
->getMachineNode(Mips::ADDu
, dl
, VT
,
358 SDValue(Carry
,0), RHS
);
360 return CurDAG
->SelectNodeTo(Node
, MOp
, VT
, MVT::Glue
,
361 LHS
, SDValue(AddCarry
,0));
364 /// Mul with two results
366 case ISD::UMUL_LOHI
: {
367 SDValue Op1
= Node
->getOperand(0);
368 SDValue Op2
= Node
->getOperand(1);
371 Op
= (Opcode
== ISD::UMUL_LOHI
? Mips::MULTu
: Mips::MULT
);
373 SDNode
*Mul
= CurDAG
->getMachineNode(Op
, dl
, MVT::Glue
, Op1
, Op2
);
375 SDValue InFlag
= SDValue(Mul
, 0);
376 SDNode
*Lo
= CurDAG
->getMachineNode(Mips::MFLO
, dl
, MVT::i32
,
378 InFlag
= SDValue(Lo
,1);
379 SDNode
*Hi
= CurDAG
->getMachineNode(Mips::MFHI
, dl
, MVT::i32
, InFlag
);
381 if (!SDValue(Node
, 0).use_empty())
382 ReplaceUses(SDValue(Node
, 0), SDValue(Lo
,0));
384 if (!SDValue(Node
, 1).use_empty())
385 ReplaceUses(SDValue(Node
, 1), SDValue(Hi
,0));
392 if (Subtarget
.isMips32())
396 SDValue MulOp1
= Node
->getOperand(0);
397 SDValue MulOp2
= Node
->getOperand(1);
399 unsigned MulOp
= (Opcode
== ISD::MULHU
? Mips::MULTu
: Mips::MULT
);
400 SDNode
*MulNode
= CurDAG
->getMachineNode(MulOp
, dl
,
401 MVT::Glue
, MulOp1
, MulOp2
);
403 SDValue InFlag
= SDValue(MulNode
, 0);
405 if (Opcode
== ISD::MUL
)
406 return CurDAG
->getMachineNode(Mips::MFLO
, dl
, MVT::i32
, InFlag
);
408 return CurDAG
->getMachineNode(Mips::MFHI
, dl
, MVT::i32
, InFlag
);
411 // Get target GOT address.
412 case ISD::GLOBAL_OFFSET_TABLE
:
413 return getGlobalBaseReg();
415 case ISD::ConstantFP
: {
416 ConstantFPSDNode
*CN
= dyn_cast
<ConstantFPSDNode
>(Node
);
417 if (Node
->getValueType(0) == MVT::f64
&& CN
->isExactlyValue(+0.0)) {
418 SDValue Zero
= CurDAG
->getCopyFromReg(CurDAG
->getEntryNode(), dl
,
419 Mips::ZERO
, MVT::i32
);
420 SDValue Undef
= SDValue(
421 CurDAG
->getMachineNode(TargetOpcode::IMPLICIT_DEF
, dl
, MVT::f64
), 0);
422 SDNode
*MTC
= CurDAG
->getMachineNode(Mips::MTC1
, dl
, MVT::f32
, Zero
);
423 SDValue I0
= CurDAG
->getTargetInsertSubreg(Mips::sub_fpeven
, dl
,
424 MVT::f64
, Undef
, SDValue(MTC
, 0));
425 SDValue I1
= CurDAG
->getTargetInsertSubreg(Mips::sub_fpodd
, dl
,
426 MVT::f64
, I0
, SDValue(MTC
, 0));
427 ReplaceUses(SDValue(Node
, 0), I1
);
434 if (SDNode
*ResNode
= SelectLoadFp64(Node
))
436 // Other cases are autogenerated.
440 if (SDNode
*ResNode
= SelectStoreFp64(Node
))
442 // Other cases are autogenerated.
445 case MipsISD::ThreadPointer
: {
446 unsigned SrcReg
= Mips::HWR29
;
447 unsigned DestReg
= Mips::V1
;
448 SDNode
*Rdhwr
= CurDAG
->getMachineNode(Mips::RDHWR
, Node
->getDebugLoc(),
449 Node
->getValueType(0), CurDAG
->getRegister(SrcReg
, MVT::i32
));
450 SDValue Chain
= CurDAG
->getCopyToReg(CurDAG
->getEntryNode(), dl
, DestReg
,
452 SDValue ResNode
= CurDAG
->getCopyFromReg(Chain
, dl
, DestReg
, MVT::i32
);
453 ReplaceUses(SDValue(Node
, 0), ResNode
);
454 return ResNode
.getNode();
458 // Select the default instruction
459 SDNode
*ResNode
= SelectCode(Node
);
461 DEBUG(errs() << "=> ");
462 if (ResNode
== NULL
|| ResNode
== Node
)
463 DEBUG(Node
->dump(CurDAG
));
465 DEBUG(ResNode
->dump(CurDAG
));
466 DEBUG(errs() << "\n");
470 bool MipsDAGToDAGISel::
471 SelectInlineAsmMemoryOperand(const SDValue
&Op
, char ConstraintCode
,
472 std::vector
<SDValue
> &OutOps
) {
473 assert(ConstraintCode
== 'm' && "unexpected asm memory constraint");
474 OutOps
.push_back(Op
);
478 /// createMipsISelDag - This pass converts a legalized DAG into a
479 /// MIPS-specific DAG, ready for instruction scheduling.
480 FunctionPass
*llvm::createMipsISelDag(MipsTargetMachine
&TM
) {
481 return new MipsDAGToDAGISel(TM
);