Have TableGen emit setSubgraphColor calls under control of a -gen-debug
[oota-llvm.git] / lib / Target / PIC16 / PIC16ISelDAGToDAG.cpp
1 //===-- PIC16ISelDAGToDAG.cpp - A dag to dag inst selector for PIC16 ------===//
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 PIC16 target.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "pic16-isel"
15
16 #include "PIC16.h"
17 #include "PIC16ISelLowering.h"
18 #include "PIC16RegisterInfo.h"
19 #include "PIC16Subtarget.h"
20 #include "PIC16TargetMachine.h"
21 #include "llvm/GlobalValue.h"
22 #include "llvm/Instructions.h"
23 #include "llvm/Intrinsics.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/SelectionDAGISel.h"
30 #include "llvm/Support/CFG.h"
31 #include "llvm/Support/Compiler.h"
32 #include "llvm/Support/Debug.h"
33 #include "llvm/Target/TargetMachine.h"
34 using namespace llvm;
35
36 //===----------------------------------------------------------------------===//
37 // Instruction Selector Implementation
38 //===----------------------------------------------------------------------===//
39
40 //===----------------------------------------------------------------------===//
41 // PIC16DAGToDAGISel - PIC16 specific code to select PIC16 machine
42 // instructions for SelectionDAG operations.
43 //===----------------------------------------------------------------------===//
44 namespace {
45
46 class VISIBILITY_HIDDEN PIC16DAGToDAGISel : public SelectionDAGISel {
47
48   /// TM - Keep a reference to PIC16TargetMachine.
49   PIC16TargetMachine &TM;
50
51 public:
52   explicit PIC16DAGToDAGISel(PIC16TargetMachine &tm) : 
53         SelectionDAGISel(*tm.getTargetLowering()),
54         TM(tm) {}
55   
56   virtual void InstructionSelect();
57
58   // Pass Name
59   virtual const char *getPassName() const {
60     return "PIC16 DAG->DAG Pattern Instruction Selection";
61   } 
62   
63 private:
64   // Include the pieces autogenerated from the target description.
65 #include "PIC16GenDAGISel.inc"
66
67   SDNode *Select(SDValue N);
68
69   // Select addressing mode. currently assume base + offset addr mode.
70   bool SelectAM(SDValue Op, SDValue N, SDValue &Base, SDValue &Offset);
71   bool SelectDirectAM(SDValue Op, SDValue N, SDValue &Base, 
72                       SDValue &Offset);
73   bool StoreInDirectAM(SDValue Op, SDValue N, SDValue &fsr);
74   bool LoadFSR(SDValue Op, SDValue N, SDValue &Base, SDValue &Offset);
75   bool LoadNothing(SDValue Op, SDValue N, SDValue &Base, 
76                    SDValue &Offset);
77
78   // getI8Imm - Return a target constant with the specified
79   // value, of type i8.
80   inline SDValue getI8Imm(unsigned Imm) {
81     return CurDAG->getTargetConstant(Imm, MVT::i8);
82   }
83
84
85 #ifndef NDEBUG
86   unsigned Indent;
87 #endif
88 };
89
90 }
91
92 /// InstructionSelect - This callback is invoked by
93 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
94 void PIC16DAGToDAGISel::InstructionSelect() 
95 {
96   DEBUG(BB->dump());
97   // Codegen the basic block.
98
99   DOUT << "===== Instruction selection begins:\n";
100 #ifndef NDEBUG
101   Indent = 0;
102 #endif
103
104   // Select target instructions for the DAG.
105   SelectRoot(*CurDAG);
106
107   DOUT << "===== Instruction selection ends:\n";
108
109   CurDAG->RemoveDeadNodes();
110 }
111
112
113 bool PIC16DAGToDAGISel::
114 SelectDirectAM (SDValue Op, SDValue N, SDValue &Base, SDValue &Offset)
115 {
116   GlobalAddressSDNode *GA;
117   ConstantSDNode      *GC;
118
119   // if Address is FI, get the TargetFrameIndex.
120   if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
121     DOUT << "--------- its frame Index\n";
122     Base   = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
123     Offset = CurDAG->getTargetConstant(0, MVT::i32);
124     return true;
125   }
126
127   if (N.getOpcode() == ISD::GlobalAddress) {
128     GA = dyn_cast<GlobalAddressSDNode>(N);
129     Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8);
130     Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
131                                           GA->getOffset());
132     return true;
133   } 
134
135   if (N.getOpcode() == ISD::ADD) {
136     GC = dyn_cast<ConstantSDNode>(N.getOperand(1));
137     Offset = CurDAG->getTargetConstant((unsigned char)GC->getZExtValue(),
138                                        MVT::i8);
139     if ((GA = dyn_cast<GlobalAddressSDNode>(N.getOperand(0)))) {
140       Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16, 
141                                             GC->getZExtValue());
142       return true;
143     }
144     else if (FrameIndexSDNode *FIN 
145                 = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) {
146       Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
147       return true;
148     }
149   }
150
151   return false;  
152 }
153
154
155 // FIXME: must also account for preinc/predec/postinc/postdec.
156 bool PIC16DAGToDAGISel::
157 StoreInDirectAM (SDValue Op, SDValue N, SDValue &fsr)
158 {
159   RegisterSDNode *Reg;
160   if (N.getOpcode() == ISD::LOAD) {
161     LoadSDNode *LD = dyn_cast<LoadSDNode>(N);
162     if (LD) {
163       fsr = LD->getBasePtr();
164     }
165     else if (isa<RegisterSDNode>(N.getNode())) { 
166       //FIXME an attempt to retrieve the register number
167       //but does not work
168       DOUT << "this is a register\n";
169       Reg = dyn_cast<RegisterSDNode>(N.getNode());
170       fsr = CurDAG->getRegister(Reg->getReg(),MVT::i16);  
171     }
172     else {
173       DOUT << "this is not a register\n";
174       // FIXME must use whatever load is using
175       fsr = CurDAG->getRegister(1,MVT::i16);
176     }
177     return true;
178   }
179   return false;  
180 }
181
182 bool PIC16DAGToDAGISel::
183 LoadFSR (SDValue Op, SDValue N, SDValue &Base, SDValue &Offset)
184 {
185   GlobalAddressSDNode *GA;
186
187   if (N.getOpcode() == ISD::GlobalAddress) {
188     GA = dyn_cast<GlobalAddressSDNode>(N);
189     Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8);
190     Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
191                                           GA->getOffset());
192     return true;
193   }
194   else if (N.getOpcode() == PIC16ISD::Package) {
195     CurDAG->setGraphColor(Op.getNode(), "blue");
196     CurDAG->viewGraph();
197   }
198
199   return false;
200 }
201
202 // LoadNothing - Don't thake this seriously, it will change.
203 bool PIC16DAGToDAGISel::
204 LoadNothing (SDValue Op, SDValue N, SDValue &Base, SDValue &Offset)
205 {
206   GlobalAddressSDNode *GA;
207   if (N.getOpcode() == ISD::GlobalAddress) {
208     GA = dyn_cast<GlobalAddressSDNode>(N);
209     DOUT << "==========" << GA->getOffset() << "\n";
210     Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8);
211     Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
212                                           GA->getOffset());
213     return true;
214   }  
215
216   return false;
217 }
218
219
220 /// Select - Select instructions not customized! Used for
221 /// expanded, promoted and normal instructions.
222 SDNode* PIC16DAGToDAGISel::Select(SDValue N) 
223 {
224   SDNode *Node = N.getNode();
225   unsigned Opcode = Node->getOpcode();
226
227   // Dump information about the Node being selected
228 #ifndef NDEBUG
229   DOUT << std::string(Indent, ' ') << "Selecting: ";
230   DEBUG(Node->dump(CurDAG));
231   DOUT << "\n";
232   Indent += 2;
233 #endif
234
235   // If we have a custom node, we already have selected!
236   if (Node->isMachineOpcode()) {
237 #ifndef NDEBUG
238     DOUT << std::string(Indent-2, ' ') << "== ";
239     DEBUG(Node->dump(CurDAG));
240     DOUT << "\n";
241     Indent -= 2;
242 #endif
243     return NULL;
244   }
245
246   ///
247   // FIXME: Instruction Selection not handled by custom or by the 
248   // auto-generated tablegen selection should be handled here.
249   /// 
250   switch(Opcode) {
251     default: break;
252   }
253
254   // Select the default instruction.
255   SDNode *ResNode = SelectCode(N);
256
257 #ifndef NDEBUG
258   DOUT << std::string(Indent-2, ' ') << "=> ";
259   if (ResNode == NULL || ResNode == N.getNode())
260     DEBUG(N.getNode()->dump(CurDAG));
261   else
262     DEBUG(ResNode->dump(CurDAG));
263   DOUT << "\n";
264   Indent -= 2;
265 #endif
266
267   return ResNode;
268 }
269
270 /// createPIC16ISelDag - This pass converts a legalized DAG into a 
271 /// PIC16-specific DAG, ready for instruction scheduling.
272 FunctionPass *llvm::createPIC16ISelDag(PIC16TargetMachine &TM) {
273   return new PIC16DAGToDAGISel(TM);
274 }
275