Change MCSectionELF to represent a section semantically instead of
[oota-llvm.git] / lib / Target / XCore / XCoreISelDAGToDAG.cpp
1 //===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines an instruction selector for the XCore target.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "XCore.h"
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"
34 #include <queue>
35 #include <set>
36 using namespace llvm;
37
38 /// XCoreDAGToDAGISel - XCore specific code to select XCore machine
39 /// instructions for SelectionDAG operations.
40 ///
41 namespace {
42   class XCoreDAGToDAGISel : public SelectionDAGISel {
43     XCoreTargetLowering &Lowering;
44     const XCoreSubtarget &Subtarget;
45
46   public:
47     XCoreDAGToDAGISel(XCoreTargetMachine &TM)
48       : SelectionDAGISel(TM),
49         Lowering(*TM.getTargetLowering()), 
50         Subtarget(*TM.getSubtargetImpl()) { }
51
52     SDNode *Select(SDValue Op);
53     
54     /// getI32Imm - Return a target constant with the specified value, of type
55     /// i32.
56     inline SDValue getI32Imm(unsigned Imm) {
57       return CurDAG->getTargetConstant(Imm, MVT::i32);
58     }
59
60     // Complex Pattern Selectors.
61     bool SelectADDRspii(SDValue Op, SDValue Addr, SDValue &Base,
62                         SDValue &Offset);
63     bool SelectADDRdpii(SDValue Op, SDValue Addr, SDValue &Base,
64                         SDValue &Offset);
65     bool SelectADDRcpii(SDValue Op, SDValue Addr, SDValue &Base,
66                         SDValue &Offset);
67     
68     virtual void InstructionSelect();
69
70     virtual const char *getPassName() const {
71       return "XCore DAG->DAG Pattern Instruction Selection";
72     } 
73     
74     // Include the pieces autogenerated from the target description.
75   #include "XCoreGenDAGISel.inc"
76   };
77 }  // end anonymous namespace
78
79 /// createXCoreISelDag - This pass converts a legalized DAG into a 
80 /// XCore-specific DAG, ready for instruction scheduling.
81 ///
82 FunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM) {
83   return new XCoreDAGToDAGISel(TM);
84 }
85
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);
92     return true;
93   }
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);
102       return true;
103     }
104   }
105   return false;
106 }
107
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);
113     return true;
114   }
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);
123       return true;
124     }
125   }
126   return false;
127 }
128
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);
134     return true;
135   }
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);
144       return true;
145     }
146   }
147   return false;
148 }
149
150 /// InstructionSelect - This callback is invoked by
151 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
152 void XCoreDAGToDAGISel::
153 InstructionSelect() {
154   DEBUG(BB->dump());
155
156   // Select target instructions for the DAG.
157   SelectRoot(*CurDAG);
158   
159   CurDAG->RemoveDeadNodes();
160 }
161
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()) {
168       default: break;
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);
173         }
174         else if (! Predicate_immU16(N)) {
175           unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
176           SDValue CPIdx =
177             CurDAG->getTargetConstantPool(ConstantInt::get(Type::Int32Ty, Val),
178                                           TLI.getPointerTy());
179           return CurDAG->getTargetNode(XCore::LDWCP_lru6, dl, MVT::i32, 
180                                        MVT::Other, CPIdx, 
181                                        CurDAG->getEntryNode());
182         }
183         break;
184       }
185       case ISD::SMUL_LOHI: {
186         // FIXME fold addition into the macc instruction
187         if (!Subtarget.isXS1A()) {
188           SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, dl, MVT::i32,
189                                   CurDAG->getTargetConstant(0, MVT::i32)), 0);
190           SDValue Ops[] = { Zero, Zero, Op.getOperand(0), Op.getOperand(1) };
191           SDNode *ResNode = CurDAG->getTargetNode(XCore::MACCS_l4r, dl,
192                                                   MVT::i32, MVT::i32, Ops, 4);
193           ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1));
194           ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0));
195           return NULL;
196         }
197         break;
198       }
199       case ISD::UMUL_LOHI: {
200         // FIXME fold addition into the macc / lmul instruction
201         SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, dl, MVT::i32,
202                                   CurDAG->getTargetConstant(0, MVT::i32)), 0);
203         SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
204                             Zero, Zero };
205         SDNode *ResNode = CurDAG->getTargetNode(XCore::LMUL_l6r, dl, MVT::i32,
206                                                 MVT::i32, Ops, 4);
207         ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1));
208         ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0));
209         return NULL;
210       }
211       case XCoreISD::LADD: {
212         if (!Subtarget.isXS1A()) {
213           SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
214                               Op.getOperand(2) };
215           return CurDAG->getTargetNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32,
216                                        Ops, 3);
217         }
218         break;
219       }
220       case XCoreISD::LSUB: {
221         if (!Subtarget.isXS1A()) {
222           SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
223                               Op.getOperand(2) };
224           return CurDAG->getTargetNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32,
225                                        Ops, 3);
226         }
227         break;
228       }
229       // Other cases are autogenerated.
230     }
231   }
232   return SelectCode(Op);
233 }