blob: 285c5a6355eac13e8ac3be49c26195ce17b03254 [file] [log] [blame]
Sanjiv Gupta0e687712008-05-13 09:02:57 +00001//===-- 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"
Sanjiv Gupta0e687712008-05-13 09:02:57 +000030#include "llvm/Support/CFG.h"
31#include "llvm/Support/Compiler.h"
32#include "llvm/Support/Debug.h"
33#include "llvm/Target/TargetMachine.h"
34#include <queue>
35#include <set>
36
37using namespace llvm;
38
39//===----------------------------------------------------------------------===//
40// Instruction Selector Implementation
41//===----------------------------------------------------------------------===//
42
43//===----------------------------------------------------------------------===//
44// PIC16DAGToDAGISel - PIC16 specific code to select PIC16 machine
45// instructions for SelectionDAG operations.
46//===----------------------------------------------------------------------===//
47namespace {
48
49class VISIBILITY_HIDDEN PIC16DAGToDAGISel : public SelectionDAGISel {
50
51 /// TM - Keep a reference to PIC16TargetMachine.
52 PIC16TargetMachine &TM;
53
Sanjiv Gupta0e687712008-05-13 09:02:57 +000054public:
Dan Gohman1002c022008-07-07 18:00:37 +000055 explicit PIC16DAGToDAGISel(PIC16TargetMachine &tm) :
Dan Gohmanda8ac5f2008-10-03 16:55:19 +000056 SelectionDAGISel(*tm.getTargetLowering()),
57 TM(tm) {}
Sanjiv Gupta0e687712008-05-13 09:02:57 +000058
Dan Gohmanf350b272008-08-23 02:25:05 +000059 virtual void InstructionSelect();
Sanjiv Gupta0e687712008-05-13 09:02:57 +000060
61 // Pass Name
62 virtual const char *getPassName() const {
63 return "PIC16 DAG->DAG Pattern Instruction Selection";
64 }
65
66private:
67 // Include the pieces autogenerated from the target description.
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +000068#include "PIC16GenDAGISel.inc"
Sanjiv Gupta0e687712008-05-13 09:02:57 +000069
Dan Gohman475871a2008-07-27 21:46:04 +000070 SDNode *Select(SDValue N);
Sanjiv Gupta0e687712008-05-13 09:02:57 +000071
72 // Select addressing mode. currently assume base + offset addr mode.
Dan Gohman475871a2008-07-27 21:46:04 +000073 bool SelectAM(SDValue Op, SDValue N, SDValue &Base, SDValue &Offset);
74 bool SelectDirectAM(SDValue Op, SDValue N, SDValue &Base,
75 SDValue &Offset);
76 bool StoreInDirectAM(SDValue Op, SDValue N, SDValue &fsr);
77 bool LoadFSR(SDValue Op, SDValue N, SDValue &Base, SDValue &Offset);
78 bool LoadNothing(SDValue Op, SDValue N, SDValue &Base,
79 SDValue &Offset);
Sanjiv Gupta0e687712008-05-13 09:02:57 +000080
81 // getI8Imm - Return a target constant with the specified
82 // value, of type i8.
Dan Gohman475871a2008-07-27 21:46:04 +000083 inline SDValue getI8Imm(unsigned Imm) {
Sanjiv Gupta0e687712008-05-13 09:02:57 +000084 return CurDAG->getTargetConstant(Imm, MVT::i8);
85 }
86
87
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +000088#ifndef NDEBUG
Sanjiv Gupta0e687712008-05-13 09:02:57 +000089 unsigned Indent;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +000090#endif
Sanjiv Gupta0e687712008-05-13 09:02:57 +000091};
92
93}
94
Evan Chengdb8d56b2008-06-30 20:45:06 +000095/// InstructionSelect - This callback is invoked by
Sanjiv Gupta0e687712008-05-13 09:02:57 +000096/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
Dan Gohmanf350b272008-08-23 02:25:05 +000097void PIC16DAGToDAGISel::InstructionSelect()
Sanjiv Gupta0e687712008-05-13 09:02:57 +000098{
99 DEBUG(BB->dump());
100 // Codegen the basic block.
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000101
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000102 DOUT << "===== Instruction selection begins:\n";
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000103#ifndef NDEBUG
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000104 Indent = 0;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000105#endif
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000106
107 // Select target instructions for the DAG.
Dan Gohmanad3460c2008-08-21 16:36:34 +0000108 SelectRoot();
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000109
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000110 DOUT << "===== Instruction selection ends:\n";
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000111
Dan Gohmanf350b272008-08-23 02:25:05 +0000112 CurDAG->RemoveDeadNodes();
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000113}
114
115
116bool PIC16DAGToDAGISel::
Dan Gohman475871a2008-07-27 21:46:04 +0000117SelectDirectAM (SDValue Op, SDValue N, SDValue &Base, SDValue &Offset)
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000118{
119 GlobalAddressSDNode *GA;
120 ConstantSDNode *GC;
121
122 // if Address is FI, get the TargetFrameIndex.
123 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N)) {
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000124 DOUT << "--------- its frame Index\n";
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000125 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
126 Offset = CurDAG->getTargetConstant(0, MVT::i32);
127 return true;
128 }
129
130 if (N.getOpcode() == ISD::GlobalAddress) {
131 GA = dyn_cast<GlobalAddressSDNode>(N);
132 Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8);
133 Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
134 GA->getOffset());
135 return true;
136 }
137
138 if (N.getOpcode() == ISD::ADD) {
139 GC = dyn_cast<ConstantSDNode>(N.getOperand(1));
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000140 Offset = CurDAG->getTargetConstant((unsigned char)GC->getZExtValue(),
141 MVT::i8);
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000142 if ((GA = dyn_cast<GlobalAddressSDNode>(N.getOperand(0)))) {
143 Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000144 GC->getZExtValue());
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000145 return true;
146 }
147 else if (FrameIndexSDNode *FIN
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000148 = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) {
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000149 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
150 return true;
151 }
152 }
153
154 return false;
155}
156
157
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000158// FIXME: must also account for preinc/predec/postinc/postdec.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000159bool PIC16DAGToDAGISel::
Dan Gohman475871a2008-07-27 21:46:04 +0000160StoreInDirectAM (SDValue Op, SDValue N, SDValue &fsr)
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000161{
162 RegisterSDNode *Reg;
163 if (N.getOpcode() == ISD::LOAD) {
164 LoadSDNode *LD = dyn_cast<LoadSDNode>(N);
165 if (LD) {
166 fsr = LD->getBasePtr();
167 }
Gabor Greifba36cb52008-08-28 21:40:38 +0000168 else if (isa<RegisterSDNode>(N.getNode())) {
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000169 //FIXME an attempt to retrieve the register number
170 //but does not work
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000171 DOUT << "this is a register\n";
Gabor Greifba36cb52008-08-28 21:40:38 +0000172 Reg = dyn_cast<RegisterSDNode>(N.getNode());
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000173 fsr = CurDAG->getRegister(Reg->getReg(),MVT::i16);
174 }
175 else {
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000176 DOUT << "this is not a register\n";
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000177 // FIXME must use whatever load is using
178 fsr = CurDAG->getRegister(1,MVT::i16);
179 }
180 return true;
181 }
182 return false;
183}
184
185bool PIC16DAGToDAGISel::
Dan Gohman475871a2008-07-27 21:46:04 +0000186LoadFSR (SDValue Op, SDValue N, SDValue &Base, SDValue &Offset)
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000187{
188 GlobalAddressSDNode *GA;
189
190 if (N.getOpcode() == ISD::GlobalAddress) {
191 GA = dyn_cast<GlobalAddressSDNode>(N);
192 Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8);
193 Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000194 GA->getOffset());
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000195 return true;
196 }
197 else if (N.getOpcode() == PIC16ISD::Package) {
Gabor Greifba36cb52008-08-28 21:40:38 +0000198 CurDAG->setGraphColor(Op.getNode(), "blue");
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000199 CurDAG->viewGraph();
200 }
201
202 return false;
203}
204
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000205// LoadNothing - Don't thake this seriously, it will change.
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000206bool PIC16DAGToDAGISel::
Dan Gohman475871a2008-07-27 21:46:04 +0000207LoadNothing (SDValue Op, SDValue N, SDValue &Base, SDValue &Offset)
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000208{
209 GlobalAddressSDNode *GA;
210 if (N.getOpcode() == ISD::GlobalAddress) {
211 GA = dyn_cast<GlobalAddressSDNode>(N);
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000212 DOUT << "==========" << GA->getOffset() << "\n";
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000213 Offset = CurDAG->getTargetConstant((unsigned char)GA->getOffset(), MVT::i8);
214 Base = CurDAG->getTargetGlobalAddress(GA->getGlobal(), MVT::i16,
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000215 GA->getOffset());
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000216 return true;
217 }
218
219 return false;
220}
221
222
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000223/// Select - Select instructions not customized! Used for
224/// expanded, promoted and normal instructions.
Dan Gohman475871a2008-07-27 21:46:04 +0000225SDNode* PIC16DAGToDAGISel::Select(SDValue N)
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000226{
Gabor Greifba36cb52008-08-28 21:40:38 +0000227 SDNode *Node = N.getNode();
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000228 unsigned Opcode = Node->getOpcode();
229
230 // Dump information about the Node being selected
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000231#ifndef NDEBUG
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000232 DOUT << std::string(Indent, ' ') << "Selecting: ";
233 DEBUG(Node->dump(CurDAG));
234 DOUT << "\n";
235 Indent += 2;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000236#endif
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000237
238 // If we have a custom node, we already have selected!
Dan Gohmane8be6c62008-07-17 19:10:17 +0000239 if (Node->isMachineOpcode()) {
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000240#ifndef NDEBUG
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000241 DOUT << std::string(Indent-2, ' ') << "== ";
242 DEBUG(Node->dump(CurDAG));
243 DOUT << "\n";
244 Indent -= 2;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000245#endif
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000246 return NULL;
247 }
248
249 ///
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000250 // FIXME: Instruction Selection not handled by custom or by the
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000251 // auto-generated tablegen selection should be handled here.
252 ///
253 switch(Opcode) {
254 default: break;
255 }
256
257 // Select the default instruction.
258 SDNode *ResNode = SelectCode(N);
259
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000260#ifndef NDEBUG
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000261 DOUT << std::string(Indent-2, ' ') << "=> ";
Gabor Greifba36cb52008-08-28 21:40:38 +0000262 if (ResNode == NULL || ResNode == N.getNode())
263 DEBUG(N.getNode()->dump(CurDAG));
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000264 else
265 DEBUG(ResNode->dump(CurDAG));
266 DOUT << "\n";
267 Indent -= 2;
Sanjiv Gupta2010b3e2008-05-14 11:31:39 +0000268#endif
Sanjiv Gupta0e687712008-05-13 09:02:57 +0000269
270 return ResNode;
271}
272
273/// createPIC16ISelDag - This pass converts a legalized DAG into a
274/// PIC16-specific DAG, ready for instruction scheduling.
275FunctionPass *llvm::createPIC16ISelDag(PIC16TargetMachine &TM) {
276 return new PIC16DAGToDAGISel(TM);
277}
278