1 //===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===//
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 XCore target.
12 //===----------------------------------------------------------------------===//
15 #include "XCoreISelLowering.h"
16 #include "XCoreTargetMachine.h"
17 #include "llvm/DerivedTypes.h"
18 #include "llvm/Function.h"
19 #include "llvm/Intrinsics.h"
20 #include "llvm/CallingConv.h"
21 #include "llvm/Constants.h"
22 #include "llvm/LLVMContext.h"
23 #include "llvm/CodeGen/MachineFrameInfo.h"
24 #include "llvm/CodeGen/MachineFunction.h"
25 #include "llvm/CodeGen/MachineInstrBuilder.h"
26 #include "llvm/CodeGen/MachineRegisterInfo.h"
27 #include "llvm/CodeGen/SelectionDAG.h"
28 #include "llvm/CodeGen/SelectionDAGISel.h"
29 #include "llvm/Target/TargetLowering.h"
30 #include "llvm/Support/Compiler.h"
31 #include "llvm/Support/Debug.h"
32 #include "llvm/Support/ErrorHandling.h"
33 #include "llvm/Support/raw_ostream.h"
38 /// XCoreDAGToDAGISel - XCore specific code to select XCore machine
39 /// instructions for SelectionDAG operations.
42 class XCoreDAGToDAGISel
: public SelectionDAGISel
{
43 XCoreTargetLowering
&Lowering
;
44 const XCoreSubtarget
&Subtarget
;
47 XCoreDAGToDAGISel(XCoreTargetMachine
&TM
)
48 : SelectionDAGISel(TM
),
49 Lowering(*TM
.getTargetLowering()),
50 Subtarget(*TM
.getSubtargetImpl()) { }
52 SDNode
*Select(SDValue Op
);
54 /// getI32Imm - Return a target constant with the specified value, of type
56 inline SDValue
getI32Imm(unsigned Imm
) {
57 return CurDAG
->getTargetConstant(Imm
, MVT::i32
);
60 // Complex Pattern Selectors.
61 bool SelectADDRspii(SDValue Op
, SDValue Addr
, SDValue
&Base
,
63 bool SelectADDRdpii(SDValue Op
, SDValue Addr
, SDValue
&Base
,
65 bool SelectADDRcpii(SDValue Op
, SDValue Addr
, SDValue
&Base
,
68 virtual void InstructionSelect();
70 virtual const char *getPassName() const {
71 return "XCore DAG->DAG Pattern Instruction Selection";
74 // Include the pieces autogenerated from the target description.
75 #include "XCoreGenDAGISel.inc"
77 } // end anonymous namespace
79 /// createXCoreISelDag - This pass converts a legalized DAG into a
80 /// XCore-specific DAG, ready for instruction scheduling.
82 FunctionPass
*llvm::createXCoreISelDag(XCoreTargetMachine
&TM
) {
83 return new XCoreDAGToDAGISel(TM
);
86 bool XCoreDAGToDAGISel::SelectADDRspii(SDValue Op
, SDValue Addr
,
87 SDValue
&Base
, SDValue
&Offset
) {
88 FrameIndexSDNode
*FIN
= 0;
89 if ((FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
))) {
90 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), MVT::i32
);
91 Offset
= CurDAG
->getTargetConstant(0, MVT::i32
);
94 if (Addr
.getOpcode() == ISD::ADD
) {
95 ConstantSDNode
*CN
= 0;
96 if ((FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
.getOperand(0)))
97 && (CN
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1)))
98 && (CN
->getSExtValue() % 4 == 0 && CN
->getSExtValue() >= 0)) {
99 // Constant positive word offset from frame index
100 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), MVT::i32
);
101 Offset
= CurDAG
->getTargetConstant(CN
->getSExtValue(), MVT::i32
);
108 bool XCoreDAGToDAGISel::SelectADDRdpii(SDValue Op
, SDValue Addr
,
109 SDValue
&Base
, SDValue
&Offset
) {
110 if (Addr
.getOpcode() == XCoreISD::DPRelativeWrapper
) {
111 Base
= Addr
.getOperand(0);
112 Offset
= CurDAG
->getTargetConstant(0, MVT::i32
);
115 if (Addr
.getOpcode() == ISD::ADD
) {
116 ConstantSDNode
*CN
= 0;
117 if ((Addr
.getOperand(0).getOpcode() == XCoreISD::DPRelativeWrapper
)
118 && (CN
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1)))
119 && (CN
->getSExtValue() % 4 == 0)) {
120 // Constant word offset from a object in the data region
121 Base
= Addr
.getOperand(0).getOperand(0);
122 Offset
= CurDAG
->getTargetConstant(CN
->getSExtValue(), MVT::i32
);
129 bool XCoreDAGToDAGISel::SelectADDRcpii(SDValue Op
, SDValue Addr
,
130 SDValue
&Base
, SDValue
&Offset
) {
131 if (Addr
.getOpcode() == XCoreISD::CPRelativeWrapper
) {
132 Base
= Addr
.getOperand(0);
133 Offset
= CurDAG
->getTargetConstant(0, MVT::i32
);
136 if (Addr
.getOpcode() == ISD::ADD
) {
137 ConstantSDNode
*CN
= 0;
138 if ((Addr
.getOperand(0).getOpcode() == XCoreISD::CPRelativeWrapper
)
139 && (CN
= dyn_cast
<ConstantSDNode
>(Addr
.getOperand(1)))
140 && (CN
->getSExtValue() % 4 == 0)) {
141 // Constant word offset from a object in the data region
142 Base
= Addr
.getOperand(0).getOperand(0);
143 Offset
= CurDAG
->getTargetConstant(CN
->getSExtValue(), MVT::i32
);
150 /// InstructionSelect - This callback is invoked by
151 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
152 void XCoreDAGToDAGISel::
153 InstructionSelect() {
156 // Select target instructions for the DAG.
159 CurDAG
->RemoveDeadNodes();
162 SDNode
*XCoreDAGToDAGISel::Select(SDValue Op
) {
163 SDNode
*N
= Op
.getNode();
164 DebugLoc dl
= N
->getDebugLoc();
165 EVT NVT
= N
->getValueType(0);
166 if (NVT
== MVT::i32
) {
167 switch (N
->getOpcode()) {
169 case ISD::Constant
: {
170 if (Predicate_immMskBitp(N
)) {
171 SDValue MskSize
= Transform_msksize_xform(N
);
172 return CurDAG
->getTargetNode(XCore::MKMSK_rus
, dl
, MVT::i32
, MskSize
);
174 else if (! Predicate_immU16(N
)) {
175 unsigned Val
= cast
<ConstantSDNode
>(N
)->getZExtValue();
177 CurDAG
->getTargetConstantPool(ConstantInt::get(
178 Type::getInt32Ty(*CurDAG
->getContext()), Val
),
180 return CurDAG
->getTargetNode(XCore::LDWCP_lru6
, dl
, MVT::i32
,
182 CurDAG
->getEntryNode());
186 case ISD::SMUL_LOHI
: {
187 // FIXME fold addition into the macc instruction
188 if (!Subtarget
.isXS1A()) {
189 SDValue
Zero(CurDAG
->getTargetNode(XCore::LDC_ru6
, dl
, MVT::i32
,
190 CurDAG
->getTargetConstant(0, MVT::i32
)), 0);
191 SDValue Ops
[] = { Zero
, Zero
, Op
.getOperand(0), Op
.getOperand(1) };
192 SDNode
*ResNode
= CurDAG
->getTargetNode(XCore::MACCS_l4r
, dl
,
193 MVT::i32
, MVT::i32
, Ops
, 4);
194 ReplaceUses(SDValue(N
, 0), SDValue(ResNode
, 1));
195 ReplaceUses(SDValue(N
, 1), SDValue(ResNode
, 0));
200 case ISD::UMUL_LOHI
: {
201 // FIXME fold addition into the macc / lmul instruction
202 SDValue
Zero(CurDAG
->getTargetNode(XCore::LDC_ru6
, dl
, MVT::i32
,
203 CurDAG
->getTargetConstant(0, MVT::i32
)), 0);
204 SDValue Ops
[] = { Op
.getOperand(0), Op
.getOperand(1),
206 SDNode
*ResNode
= CurDAG
->getTargetNode(XCore::LMUL_l6r
, dl
, MVT::i32
,
208 ReplaceUses(SDValue(N
, 0), SDValue(ResNode
, 1));
209 ReplaceUses(SDValue(N
, 1), SDValue(ResNode
, 0));
212 case XCoreISD::LADD
: {
213 if (!Subtarget
.isXS1A()) {
214 SDValue Ops
[] = { Op
.getOperand(0), Op
.getOperand(1),
216 return CurDAG
->getTargetNode(XCore::LADD_l5r
, dl
, MVT::i32
, MVT::i32
,
221 case XCoreISD::LSUB
: {
222 if (!Subtarget
.isXS1A()) {
223 SDValue Ops
[] = { Op
.getOperand(0), Op
.getOperand(1),
225 return CurDAG
->getTargetNode(XCore::LSUB_l5r
, dl
, MVT::i32
, MVT::i32
,
230 // Other cases are autogenerated.
233 return SelectCode(Op
);