blob: a2eb9c7acb9d4f995f7edef74b3cb14ed4b6d0e9 [file] [log] [blame]
Chris Lattner6c18b102005-12-17 07:47:01 +00001//===-- SparcV8ISelDAGToDAG.cpp - A dag to dag inst selector for SparcV8 --===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines an instruction selector for the V8 target
11//
12//===----------------------------------------------------------------------===//
13
14#include "SparcV8.h"
15#include "SparcV8TargetMachine.h"
Chris Lattnera01b7572005-12-17 08:03:24 +000016#include "llvm/Function.h"
17#include "llvm/CodeGen/MachineFunction.h"
Chris Lattner6c18b102005-12-17 07:47:01 +000018#include "llvm/CodeGen/SelectionDAG.h"
19#include "llvm/CodeGen/SelectionDAGISel.h"
Chris Lattnera01b7572005-12-17 08:03:24 +000020#include "llvm/CodeGen/SSARegMap.h"
Chris Lattner6c18b102005-12-17 07:47:01 +000021#include "llvm/Target/TargetLowering.h"
22#include "llvm/Support/Debug.h"
23#include <iostream>
24using namespace llvm;
25
26//===----------------------------------------------------------------------===//
27// TargetLowering Implementation
28//===----------------------------------------------------------------------===//
29
30namespace {
31 class SparcV8TargetLowering : public TargetLowering {
32 public:
33 SparcV8TargetLowering(TargetMachine &TM);
34
35 virtual std::vector<SDOperand>
36 LowerArguments(Function &F, SelectionDAG &DAG);
37 virtual std::pair<SDOperand, SDOperand>
38 LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg,
39 unsigned CC,
40 bool isTailCall, SDOperand Callee, ArgListTy &Args,
41 SelectionDAG &DAG);
42
43 virtual SDOperand LowerReturnTo(SDOperand Chain, SDOperand Op,
44 SelectionDAG &DAG);
45 virtual SDOperand LowerVAStart(SDOperand Chain, SDOperand VAListP,
46 Value *VAListV, SelectionDAG &DAG);
47 virtual std::pair<SDOperand,SDOperand>
48 LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
49 const Type *ArgTy, SelectionDAG &DAG);
50 virtual std::pair<SDOperand, SDOperand>
51 LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
52 SelectionDAG &DAG);
53 };
54}
55
56SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM)
57 : TargetLowering(TM) {
58
59 // Set up the register classes.
60 addRegisterClass(MVT::i32, V8::IntRegsRegisterClass);
61 addRegisterClass(MVT::f32, V8::FPRegsRegisterClass);
62 addRegisterClass(MVT::f64, V8::DFPRegsRegisterClass);
Chris Lattner9a60ff62005-12-17 20:50:42 +000063
64 // Sparc doesn't have sext_inreg, replace them with shl/sra
65 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16 , Expand);
66 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand);
67 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand);
Chris Lattner6c18b102005-12-17 07:47:01 +000068
69 computeRegisterProperties();
70}
71
72std::vector<SDOperand>
73SparcV8TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
Chris Lattnera01b7572005-12-17 08:03:24 +000074 MachineFunction &MF = DAG.getMachineFunction();
75 SSARegMap *RegMap = MF.getSSARegMap();
76 std::vector<SDOperand> ArgValues;
77
78 static const unsigned GPR[] = {
79 V8::I0, V8::I1, V8::I2, V8::I3, V8::I4, V8::I5
80 };
81 unsigned ArgNo = 0;
82 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
83 MVT::ValueType ObjectVT = getValueType(I->getType());
84 assert(ArgNo < 6 && "Only args in regs for now");
85
86 switch (ObjectVT) {
87 default: assert(0 && "Unhandled argument type!");
88 // TODO: MVT::i64 & FP
89 case MVT::i1:
90 case MVT::i8:
91 case MVT::i16:
92 case MVT::i32: {
93 unsigned VReg = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
94 MF.addLiveIn(GPR[ArgNo++], VReg);
95 SDOperand Arg = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32);
96 DAG.setRoot(Arg.getValue(1));
97 if (ObjectVT != MVT::i32) {
98 unsigned AssertOp = I->getType()->isSigned() ? ISD::AssertSext
99 : ISD::AssertZext;
100 Arg = DAG.getNode(AssertOp, MVT::i32, Arg,
101 DAG.getValueType(ObjectVT));
102 Arg = DAG.getNode(ISD::TRUNCATE, ObjectVT, Arg);
103 }
104 ArgValues.push_back(Arg);
105 }
106 }
107 }
108
109 assert(!F.isVarArg() && "Unimp");
110
111 // Finally, inform the code generator which regs we return values in.
112 switch (getValueType(F.getReturnType())) {
113 default: assert(0 && "Unknown type!");
114 case MVT::isVoid: break;
115 case MVT::i1:
116 case MVT::i8:
117 case MVT::i16:
118 case MVT::i32:
119 MF.addLiveOut(V8::I0);
120 break;
121 case MVT::i64:
122 MF.addLiveOut(V8::I0);
123 MF.addLiveOut(V8::I1);
124 break;
125 case MVT::f32:
126 MF.addLiveOut(V8::F0);
127 break;
128 case MVT::f64:
129 MF.addLiveOut(V8::D0);
130 break;
131 }
132
133 return ArgValues;
Chris Lattner6c18b102005-12-17 07:47:01 +0000134}
135
136std::pair<SDOperand, SDOperand>
137SparcV8TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
138 bool isVarArg, unsigned CC,
139 bool isTailCall, SDOperand Callee,
140 ArgListTy &Args, SelectionDAG &DAG) {
141 assert(0 && "Unimp");
142 abort();
143}
144
145SDOperand SparcV8TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
146 SelectionDAG &DAG) {
Chris Lattner4b486312005-12-17 08:15:09 +0000147 if (Op.getValueType() == MVT::i64) {
148 SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
149 DAG.getConstant(1, MVT::i32));
150 SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
151 DAG.getConstant(0, MVT::i32));
152 return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Hi);
153 } else {
154 return DAG.getNode(ISD::RET, MVT::Other, Chain, Op);
155 }
Chris Lattner6c18b102005-12-17 07:47:01 +0000156}
157
158SDOperand SparcV8TargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP,
159 Value *VAListV, SelectionDAG &DAG) {
160 assert(0 && "Unimp");
161 abort();
162}
163
164std::pair<SDOperand,SDOperand>
165SparcV8TargetLowering::LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
166 const Type *ArgTy, SelectionDAG &DAG) {
167 assert(0 && "Unimp");
168 abort();
169}
170
171std::pair<SDOperand, SDOperand>
172SparcV8TargetLowering::LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
173 SelectionDAG &DAG) {
174 assert(0 && "Unimp");
175 abort();
176}
177
178//===----------------------------------------------------------------------===//
179// Instruction Selector Implementation
180//===----------------------------------------------------------------------===//
181
182//===--------------------------------------------------------------------===//
183/// SparcV8DAGToDAGISel - PPC specific code to select Sparc V8 machine
184/// instructions for SelectionDAG operations.
185///
186namespace {
187class SparcV8DAGToDAGISel : public SelectionDAGISel {
188 SparcV8TargetLowering V8Lowering;
189public:
190 SparcV8DAGToDAGISel(TargetMachine &TM)
191 : SelectionDAGISel(V8Lowering), V8Lowering(TM) {}
192
193 SDOperand Select(SDOperand Op);
194
Chris Lattnerbc83fd92005-12-17 20:04:49 +0000195 // Complex Pattern Selectors.
196 bool SelectADDRrr(SDOperand N, SDOperand &R1, SDOperand &R2);
197 bool SelectADDRri(SDOperand N, SDOperand &Base, SDOperand &Offset);
198
Chris Lattner6c18b102005-12-17 07:47:01 +0000199 /// InstructionSelectBasicBlock - This callback is invoked by
200 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
201 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
202
203 virtual const char *getPassName() const {
204 return "PowerPC DAG->DAG Pattern Instruction Selection";
205 }
206
207 // Include the pieces autogenerated from the target description.
208#include "SparcV8GenDAGISel.inc"
209};
210} // end anonymous namespace
211
212/// InstructionSelectBasicBlock - This callback is invoked by
213/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
214void SparcV8DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
215 DEBUG(BB->dump());
216
217 // Select target instructions for the DAG.
218 DAG.setRoot(Select(DAG.getRoot()));
219 CodeGenMap.clear();
220 DAG.RemoveDeadNodes();
221
222 // Emit machine code to BB.
223 ScheduleAndEmitDAG(DAG);
224}
225
Chris Lattnerbc83fd92005-12-17 20:04:49 +0000226bool SparcV8DAGToDAGISel::SelectADDRrr(SDOperand N, SDOperand &R1,
227 SDOperand &R2) {
228 // FIXME: This should obviously be smarter.
229 R1 = Select(N);
230 R2 = CurDAG->getRegister(V8::G0, MVT::i32);
231 return true;
232}
233
234bool SparcV8DAGToDAGISel::SelectADDRri(SDOperand N, SDOperand &Base,
235 SDOperand &Offset) {
236 // FIXME: This should obviously be smarter.
237 Base = Select(N);
238 Offset = CurDAG->getTargetConstant(0, MVT::i32);
239 return true;
240}
241
Chris Lattner6c18b102005-12-17 07:47:01 +0000242
243SDOperand SparcV8DAGToDAGISel::Select(SDOperand Op) {
244 SDNode *N = Op.Val;
245 if (N->getOpcode() >= ISD::BUILTIN_OP_END/* &&
246 N->getOpcode() < V8ISD::FIRST_NUMBER*/)
247 return Op; // Already selected.
248 // If this has already been converted, use it.
249 std::map<SDOperand, SDOperand>::iterator CGMI = CodeGenMap.find(Op);
250 if (CGMI != CodeGenMap.end()) return CGMI->second;
251
252 switch (N->getOpcode()) {
253 default: break;
Chris Lattner4b486312005-12-17 08:15:09 +0000254 case ISD::RET: {
255 if (N->getNumOperands() == 2) {
256 SDOperand Chain = Select(N->getOperand(0)); // Token chain.
257 SDOperand Val = Select(N->getOperand(1));
258 if (N->getOperand(1).getValueType() == MVT::i32) {
259 Chain = CurDAG->getCopyToReg(Chain, V8::I0, Val);
260 } else if (N->getOperand(1).getValueType() == MVT::f32) {
261 Chain = CurDAG->getCopyToReg(Chain, V8::F0, Val);
262 } else {
263 assert(N->getOperand(1).getValueType() == MVT::f64);
264 Chain = CurDAG->getCopyToReg(Chain, V8::D0, Val);
265 }
266 return CurDAG->SelectNodeTo(N, V8::RETL, MVT::Other, Chain);
267 } else if (N->getNumOperands() > 1) {
268 SDOperand Chain = Select(N->getOperand(0)); // Token chain.
269 assert(N->getOperand(1).getValueType() == MVT::i32 &&
270 N->getOperand(2).getValueType() == MVT::i32 &&
271 N->getNumOperands() == 3 && "Unknown two-register ret value!");
272 Chain = CurDAG->getCopyToReg(Chain, V8::I0, Select(N->getOperand(1)));
273 Chain = CurDAG->getCopyToReg(Chain, V8::I1, Select(N->getOperand(2)));
274 return CurDAG->SelectNodeTo(N, V8::RETL, MVT::Other, Chain);
275 }
276 break; // Generated code handles the void case.
277 }
Chris Lattner6c18b102005-12-17 07:47:01 +0000278 }
279
280 return SelectCode(Op);
281}
282
283
284/// createPPCISelDag - This pass converts a legalized DAG into a
285/// PowerPC-specific DAG, ready for instruction scheduling.
286///
287FunctionPass *llvm::createSparcV8ISelDag(TargetMachine &TM) {
288 return new SparcV8DAGToDAGISel(TM);
289}