blob: 5d60a1bf5e2d70c947b37ebbb5ee41133ecdeff2 [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);
Chris Lattner217aabf2005-12-17 20:59:06 +0000105 break;
106 }
107 case MVT::i64: {
108 unsigned VRegLo = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
109 MF.addLiveIn(GPR[ArgNo++], VRegLo);
110 unsigned VRegHi = RegMap->createVirtualRegister(&V8::IntRegsRegClass);
111 MF.addLiveIn(GPR[ArgNo++], VRegHi);
112 SDOperand ArgLo = DAG.getCopyFromReg(DAG.getRoot(), VRegLo, MVT::i32);
113 SDOperand ArgHi = DAG.getCopyFromReg(ArgLo.getValue(1), VRegHi, MVT::i32);
114 DAG.setRoot(ArgHi.getValue(1));
115 ArgValues.push_back(DAG.getNode(ISD::BUILD_PAIR, MVT::i64, ArgLo, ArgHi));
116 break;
Chris Lattnera01b7572005-12-17 08:03:24 +0000117 }
118 }
119 }
120
121 assert(!F.isVarArg() && "Unimp");
122
123 // Finally, inform the code generator which regs we return values in.
124 switch (getValueType(F.getReturnType())) {
125 default: assert(0 && "Unknown type!");
126 case MVT::isVoid: break;
127 case MVT::i1:
128 case MVT::i8:
129 case MVT::i16:
130 case MVT::i32:
131 MF.addLiveOut(V8::I0);
132 break;
133 case MVT::i64:
134 MF.addLiveOut(V8::I0);
135 MF.addLiveOut(V8::I1);
136 break;
137 case MVT::f32:
138 MF.addLiveOut(V8::F0);
139 break;
140 case MVT::f64:
141 MF.addLiveOut(V8::D0);
142 break;
143 }
144
145 return ArgValues;
Chris Lattner6c18b102005-12-17 07:47:01 +0000146}
147
148std::pair<SDOperand, SDOperand>
149SparcV8TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
150 bool isVarArg, unsigned CC,
151 bool isTailCall, SDOperand Callee,
152 ArgListTy &Args, SelectionDAG &DAG) {
153 assert(0 && "Unimp");
154 abort();
155}
156
157SDOperand SparcV8TargetLowering::LowerReturnTo(SDOperand Chain, SDOperand Op,
158 SelectionDAG &DAG) {
Chris Lattner4b486312005-12-17 08:15:09 +0000159 if (Op.getValueType() == MVT::i64) {
160 SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
161 DAG.getConstant(1, MVT::i32));
162 SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
163 DAG.getConstant(0, MVT::i32));
164 return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Hi);
165 } else {
166 return DAG.getNode(ISD::RET, MVT::Other, Chain, Op);
167 }
Chris Lattner6c18b102005-12-17 07:47:01 +0000168}
169
170SDOperand SparcV8TargetLowering::LowerVAStart(SDOperand Chain, SDOperand VAListP,
171 Value *VAListV, SelectionDAG &DAG) {
172 assert(0 && "Unimp");
173 abort();
174}
175
176std::pair<SDOperand,SDOperand>
177SparcV8TargetLowering::LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
178 const Type *ArgTy, SelectionDAG &DAG) {
179 assert(0 && "Unimp");
180 abort();
181}
182
183std::pair<SDOperand, SDOperand>
184SparcV8TargetLowering::LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
185 SelectionDAG &DAG) {
186 assert(0 && "Unimp");
187 abort();
188}
189
190//===----------------------------------------------------------------------===//
191// Instruction Selector Implementation
192//===----------------------------------------------------------------------===//
193
194//===--------------------------------------------------------------------===//
195/// SparcV8DAGToDAGISel - PPC specific code to select Sparc V8 machine
196/// instructions for SelectionDAG operations.
197///
198namespace {
199class SparcV8DAGToDAGISel : public SelectionDAGISel {
200 SparcV8TargetLowering V8Lowering;
201public:
202 SparcV8DAGToDAGISel(TargetMachine &TM)
203 : SelectionDAGISel(V8Lowering), V8Lowering(TM) {}
204
205 SDOperand Select(SDOperand Op);
206
Chris Lattnerbc83fd92005-12-17 20:04:49 +0000207 // Complex Pattern Selectors.
208 bool SelectADDRrr(SDOperand N, SDOperand &R1, SDOperand &R2);
209 bool SelectADDRri(SDOperand N, SDOperand &Base, SDOperand &Offset);
210
Chris Lattner6c18b102005-12-17 07:47:01 +0000211 /// InstructionSelectBasicBlock - This callback is invoked by
212 /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
213 virtual void InstructionSelectBasicBlock(SelectionDAG &DAG);
214
215 virtual const char *getPassName() const {
216 return "PowerPC DAG->DAG Pattern Instruction Selection";
217 }
218
219 // Include the pieces autogenerated from the target description.
220#include "SparcV8GenDAGISel.inc"
221};
222} // end anonymous namespace
223
224/// InstructionSelectBasicBlock - This callback is invoked by
225/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
226void SparcV8DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
227 DEBUG(BB->dump());
228
229 // Select target instructions for the DAG.
230 DAG.setRoot(Select(DAG.getRoot()));
231 CodeGenMap.clear();
232 DAG.RemoveDeadNodes();
233
234 // Emit machine code to BB.
235 ScheduleAndEmitDAG(DAG);
236}
237
Chris Lattner9034b882005-12-17 21:25:27 +0000238bool SparcV8DAGToDAGISel::SelectADDRrr(SDOperand Addr, SDOperand &R1,
Chris Lattnerbc83fd92005-12-17 20:04:49 +0000239 SDOperand &R2) {
Chris Lattner9034b882005-12-17 21:25:27 +0000240 if (Addr.getOpcode() == ISD::ADD) {
241 if (isa<ConstantSDNode>(Addr.getOperand(1)) &&
242 Predicate_simm13(Addr.getOperand(1).Val))
243 return false; // Let the reg+imm pattern catch this!
244 R1 = Addr.getOperand(0);
245 R2 = Addr.getOperand(1);
246 return true;
247 }
248
249 R1 = Select(Addr);
Chris Lattnerbc83fd92005-12-17 20:04:49 +0000250 R2 = CurDAG->getRegister(V8::G0, MVT::i32);
251 return true;
252}
253
Chris Lattner9034b882005-12-17 21:25:27 +0000254bool SparcV8DAGToDAGISel::SelectADDRri(SDOperand Addr, SDOperand &Base,
Chris Lattnerbc83fd92005-12-17 20:04:49 +0000255 SDOperand &Offset) {
Chris Lattner9034b882005-12-17 21:25:27 +0000256 if (Addr.getOpcode() == ISD::ADD) {
257 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
258 if (Predicate_simm13(CN)) {
259 Base = Addr.getOperand(0);
260 Offset = CurDAG->getTargetConstant(CN->getValue(), MVT::i32);
261 return true;
262 }
263 }
264 Base = Select(Addr);
Chris Lattnerbc83fd92005-12-17 20:04:49 +0000265 Offset = CurDAG->getTargetConstant(0, MVT::i32);
266 return true;
267}
268
Chris Lattner6c18b102005-12-17 07:47:01 +0000269
270SDOperand SparcV8DAGToDAGISel::Select(SDOperand Op) {
271 SDNode *N = Op.Val;
272 if (N->getOpcode() >= ISD::BUILTIN_OP_END/* &&
273 N->getOpcode() < V8ISD::FIRST_NUMBER*/)
274 return Op; // Already selected.
275 // If this has already been converted, use it.
276 std::map<SDOperand, SDOperand>::iterator CGMI = CodeGenMap.find(Op);
277 if (CGMI != CodeGenMap.end()) return CGMI->second;
278
279 switch (N->getOpcode()) {
280 default: break;
Chris Lattneree3d5fb2005-12-17 22:30:00 +0000281 case ISD::MULHU:
282 case ISD::MULHS: {
283 SDOperand MulLHS = Select(N->getOperand(0));
284 SDOperand MulRHS = Select(N->getOperand(1));
285 unsigned Opcode = N->getOpcode() == ISD::MULHU ? V8::UMULrr : V8::SMULrr;
286 SDOperand Mul = CurDAG->getTargetNode(Opcode, MVT::i32, MVT::Flag,
287 MulLHS, MulRHS);
288 // The high part is in the Y register.
289 return CurDAG->SelectNodeTo(N, V8::RDY, MVT::i32, Mul.getValue(1));
290 }
291
Chris Lattner4b486312005-12-17 08:15:09 +0000292 case ISD::RET: {
293 if (N->getNumOperands() == 2) {
294 SDOperand Chain = Select(N->getOperand(0)); // Token chain.
295 SDOperand Val = Select(N->getOperand(1));
296 if (N->getOperand(1).getValueType() == MVT::i32) {
297 Chain = CurDAG->getCopyToReg(Chain, V8::I0, Val);
298 } else if (N->getOperand(1).getValueType() == MVT::f32) {
299 Chain = CurDAG->getCopyToReg(Chain, V8::F0, Val);
300 } else {
301 assert(N->getOperand(1).getValueType() == MVT::f64);
302 Chain = CurDAG->getCopyToReg(Chain, V8::D0, Val);
303 }
304 return CurDAG->SelectNodeTo(N, V8::RETL, MVT::Other, Chain);
305 } else if (N->getNumOperands() > 1) {
306 SDOperand Chain = Select(N->getOperand(0)); // Token chain.
307 assert(N->getOperand(1).getValueType() == MVT::i32 &&
308 N->getOperand(2).getValueType() == MVT::i32 &&
309 N->getNumOperands() == 3 && "Unknown two-register ret value!");
310 Chain = CurDAG->getCopyToReg(Chain, V8::I0, Select(N->getOperand(1)));
311 Chain = CurDAG->getCopyToReg(Chain, V8::I1, Select(N->getOperand(2)));
312 return CurDAG->SelectNodeTo(N, V8::RETL, MVT::Other, Chain);
313 }
314 break; // Generated code handles the void case.
315 }
Chris Lattner6c18b102005-12-17 07:47:01 +0000316 }
317
318 return SelectCode(Op);
319}
320
321
322/// createPPCISelDag - This pass converts a legalized DAG into a
323/// PowerPC-specific DAG, ready for instruction scheduling.
324///
325FunctionPass *llvm::createSparcV8ISelDag(TargetMachine &TM) {
326 return new SparcV8DAGToDAGISel(TM);
327}