blob: 29d485a53bc0ae561b11467ccf6af3289f2dd286 [file] [log] [blame]
Chris Lattnerd23405e2008-03-17 03:21:36 +00001//===-- SparcISelLowering.cpp - Sparc DAG Lowering Implementation ---------===//
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 implements the interfaces that Sparc uses to lower LLVM code into a
11// selection DAG.
12//
13//===----------------------------------------------------------------------===//
14
15#include "SparcISelLowering.h"
16#include "SparcTargetMachine.h"
Chris Lattnerd23405e2008-03-17 03:21:36 +000017#include "llvm/Function.h"
Chris Lattner5a65b922008-03-17 05:41:48 +000018#include "llvm/CodeGen/CallingConvLower.h"
Chris Lattnerd23405e2008-03-17 03:21:36 +000019#include "llvm/CodeGen/MachineFrameInfo.h"
20#include "llvm/CodeGen/MachineFunction.h"
21#include "llvm/CodeGen/MachineInstrBuilder.h"
22#include "llvm/CodeGen/MachineRegisterInfo.h"
23#include "llvm/CodeGen/SelectionDAG.h"
Anton Korobeynikov0eefda12008-10-10 20:28:10 +000024#include "llvm/ADT/VectorExtras.h"
Chris Lattnerd23405e2008-03-17 03:21:36 +000025using namespace llvm;
26
Chris Lattner5a65b922008-03-17 05:41:48 +000027
28//===----------------------------------------------------------------------===//
29// Calling Convention Implementation
30//===----------------------------------------------------------------------===//
31
32#include "SparcGenCallingConv.inc"
33
Dan Gohman475871a2008-07-27 21:46:04 +000034static SDValue LowerRET(SDValue Op, SelectionDAG &DAG) {
Chris Lattner5a65b922008-03-17 05:41:48 +000035 // CCValAssign - represent the assignment of the return value to locations.
36 SmallVector<CCValAssign, 16> RVLocs;
Chris Lattner98949a62008-03-17 06:01:07 +000037 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
Chris Lattner5a65b922008-03-17 05:41:48 +000038 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
Dale Johannesena05dca42009-02-04 23:02:30 +000039 DebugLoc dl = Op.getDebugLoc();
Anton Korobeynikov53835702008-10-10 20:27:31 +000040
Chris Lattner5a65b922008-03-17 05:41:48 +000041 // CCState - Info about the registers and stack slot.
42 CCState CCInfo(CC, isVarArg, DAG.getTarget(), RVLocs);
Anton Korobeynikov53835702008-10-10 20:27:31 +000043
Chris Lattner5a65b922008-03-17 05:41:48 +000044 // Analize return values of ISD::RET
Gabor Greifba36cb52008-08-28 21:40:38 +000045 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_Sparc32);
Anton Korobeynikov53835702008-10-10 20:27:31 +000046
Chris Lattner5a65b922008-03-17 05:41:48 +000047 // If this is the first return lowered for this function, add the regs to the
48 // liveout set for the function.
49 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
50 for (unsigned i = 0; i != RVLocs.size(); ++i)
51 if (RVLocs[i].isRegLoc())
52 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
53 }
Anton Korobeynikov53835702008-10-10 20:27:31 +000054
Dan Gohman475871a2008-07-27 21:46:04 +000055 SDValue Chain = Op.getOperand(0);
56 SDValue Flag;
Chris Lattner5a65b922008-03-17 05:41:48 +000057
58 // Copy the result values into the output registers.
59 for (unsigned i = 0; i != RVLocs.size(); ++i) {
60 CCValAssign &VA = RVLocs[i];
61 assert(VA.isRegLoc() && "Can only return in registers!");
Anton Korobeynikov53835702008-10-10 20:27:31 +000062
Chris Lattner5a65b922008-03-17 05:41:48 +000063 // ISD::RET => ret chain, (regnum1,val1), ...
64 // So i*2+1 index only the regnums.
Dale Johannesena05dca42009-02-04 23:02:30 +000065 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
66 Op.getOperand(i*2+1), Flag);
Anton Korobeynikov53835702008-10-10 20:27:31 +000067
Chris Lattner5a65b922008-03-17 05:41:48 +000068 // Guarantee that all emitted copies are stuck together with flags.
69 Flag = Chain.getValue(1);
70 }
Anton Korobeynikov53835702008-10-10 20:27:31 +000071
Gabor Greifba36cb52008-08-28 21:40:38 +000072 if (Flag.getNode())
Dale Johannesena05dca42009-02-04 23:02:30 +000073 return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain, Flag);
74 return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain);
Chris Lattner5a65b922008-03-17 05:41:48 +000075}
76
77/// LowerArguments - V8 uses a very simple ABI, where all values are passed in
78/// either one or two GPRs, including FP values. TODO: we should pass FP values
79/// in FP registers for fastcc functions.
Dan Gohmana44b6742008-06-30 20:31:15 +000080void
81SparcTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG,
Dale Johannesen7d2ad622009-01-30 23:10:59 +000082 SmallVectorImpl<SDValue> &ArgValues,
83 DebugLoc dl) {
Chris Lattner5a65b922008-03-17 05:41:48 +000084 MachineFunction &MF = DAG.getMachineFunction();
85 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Anton Korobeynikov53835702008-10-10 20:27:31 +000086
Chris Lattner5a65b922008-03-17 05:41:48 +000087 static const unsigned ArgRegs[] = {
88 SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
89 };
Anton Korobeynikov53835702008-10-10 20:27:31 +000090
Chris Lattner5a65b922008-03-17 05:41:48 +000091 const unsigned *CurArgReg = ArgRegs, *ArgRegEnd = ArgRegs+6;
92 unsigned ArgOffset = 68;
Anton Korobeynikov53835702008-10-10 20:27:31 +000093
Dan Gohman475871a2008-07-27 21:46:04 +000094 SDValue Root = DAG.getRoot();
95 std::vector<SDValue> OutChains;
Chris Lattner5a65b922008-03-17 05:41:48 +000096
97 for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) {
Duncan Sands83ec4b62008-06-06 12:08:01 +000098 MVT ObjectVT = getValueType(I->getType());
Anton Korobeynikov53835702008-10-10 20:27:31 +000099
Duncan Sands83ec4b62008-06-06 12:08:01 +0000100 switch (ObjectVT.getSimpleVT()) {
Chris Lattner5a65b922008-03-17 05:41:48 +0000101 default: assert(0 && "Unhandled argument type!");
102 case MVT::i1:
103 case MVT::i8:
104 case MVT::i16:
105 case MVT::i32:
106 if (I->use_empty()) { // Argument is dead.
107 if (CurArgReg < ArgRegEnd) ++CurArgReg;
Dale Johannesene8d72302009-02-06 23:05:02 +0000108 ArgValues.push_back(DAG.getUNDEF(ObjectVT));
Chris Lattner5a65b922008-03-17 05:41:48 +0000109 } else if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
110 unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
111 MF.getRegInfo().addLiveIn(*CurArgReg++, VReg);
Dale Johannesen39355f92009-02-04 02:34:38 +0000112 SDValue Arg = DAG.getCopyFromReg(Root, dl, VReg, MVT::i32);
Chris Lattner5a65b922008-03-17 05:41:48 +0000113 if (ObjectVT != MVT::i32) {
114 unsigned AssertOp = ISD::AssertSext;
Dale Johannesen39355f92009-02-04 02:34:38 +0000115 Arg = DAG.getNode(AssertOp, dl, MVT::i32, Arg,
Chris Lattner5a65b922008-03-17 05:41:48 +0000116 DAG.getValueType(ObjectVT));
Dale Johannesen39355f92009-02-04 02:34:38 +0000117 Arg = DAG.getNode(ISD::TRUNCATE, dl, ObjectVT, Arg);
Chris Lattner5a65b922008-03-17 05:41:48 +0000118 }
119 ArgValues.push_back(Arg);
120 } else {
121 int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +0000122 SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
123 SDValue Load;
Chris Lattner5a65b922008-03-17 05:41:48 +0000124 if (ObjectVT == MVT::i32) {
Dale Johannesen39355f92009-02-04 02:34:38 +0000125 Load = DAG.getLoad(MVT::i32, dl, Root, FIPtr, NULL, 0);
Chris Lattner5a65b922008-03-17 05:41:48 +0000126 } else {
127 ISD::LoadExtType LoadOp = ISD::SEXTLOAD;
128
129 // Sparc is big endian, so add an offset based on the ObjectVT.
Duncan Sands83ec4b62008-06-06 12:08:01 +0000130 unsigned Offset = 4-std::max(1U, ObjectVT.getSizeInBits()/8);
Dale Johannesen39355f92009-02-04 02:34:38 +0000131 FIPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, FIPtr,
Chris Lattner5a65b922008-03-17 05:41:48 +0000132 DAG.getConstant(Offset, MVT::i32));
Dale Johannesen39355f92009-02-04 02:34:38 +0000133 Load = DAG.getExtLoad(LoadOp, dl, MVT::i32, Root, FIPtr,
Chris Lattner5a65b922008-03-17 05:41:48 +0000134 NULL, 0, ObjectVT);
Dale Johannesen39355f92009-02-04 02:34:38 +0000135 Load = DAG.getNode(ISD::TRUNCATE, dl, ObjectVT, Load);
Chris Lattner5a65b922008-03-17 05:41:48 +0000136 }
137 ArgValues.push_back(Load);
138 }
Anton Korobeynikov53835702008-10-10 20:27:31 +0000139
Chris Lattner5a65b922008-03-17 05:41:48 +0000140 ArgOffset += 4;
141 break;
142 case MVT::f32:
143 if (I->use_empty()) { // Argument is dead.
144 if (CurArgReg < ArgRegEnd) ++CurArgReg;
Dale Johannesene8d72302009-02-06 23:05:02 +0000145 ArgValues.push_back(DAG.getUNDEF(ObjectVT));
Chris Lattner5a65b922008-03-17 05:41:48 +0000146 } else if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
147 // FP value is passed in an integer register.
148 unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
149 MF.getRegInfo().addLiveIn(*CurArgReg++, VReg);
Dale Johannesen39355f92009-02-04 02:34:38 +0000150 SDValue Arg = DAG.getCopyFromReg(Root, dl, VReg, MVT::i32);
Chris Lattner5a65b922008-03-17 05:41:48 +0000151
Dale Johannesen39355f92009-02-04 02:34:38 +0000152 Arg = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f32, Arg);
Chris Lattner5a65b922008-03-17 05:41:48 +0000153 ArgValues.push_back(Arg);
154 } else {
155 int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +0000156 SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
Dale Johannesen39355f92009-02-04 02:34:38 +0000157 SDValue Load = DAG.getLoad(MVT::f32, dl, Root, FIPtr, NULL, 0);
Chris Lattner5a65b922008-03-17 05:41:48 +0000158 ArgValues.push_back(Load);
159 }
160 ArgOffset += 4;
161 break;
162
163 case MVT::i64:
164 case MVT::f64:
165 if (I->use_empty()) { // Argument is dead.
166 if (CurArgReg < ArgRegEnd) ++CurArgReg;
167 if (CurArgReg < ArgRegEnd) ++CurArgReg;
Dale Johannesene8d72302009-02-06 23:05:02 +0000168 ArgValues.push_back(DAG.getUNDEF(ObjectVT));
Chris Lattner5a65b922008-03-17 05:41:48 +0000169 } else {
Dan Gohman475871a2008-07-27 21:46:04 +0000170 SDValue HiVal;
Chris Lattner5a65b922008-03-17 05:41:48 +0000171 if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
172 unsigned VRegHi = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
173 MF.getRegInfo().addLiveIn(*CurArgReg++, VRegHi);
Dale Johannesen39355f92009-02-04 02:34:38 +0000174 HiVal = DAG.getCopyFromReg(Root, dl, VRegHi, MVT::i32);
Chris Lattner5a65b922008-03-17 05:41:48 +0000175 } else {
176 int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +0000177 SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
Dale Johannesen39355f92009-02-04 02:34:38 +0000178 HiVal = DAG.getLoad(MVT::i32, dl, Root, FIPtr, NULL, 0);
Chris Lattner5a65b922008-03-17 05:41:48 +0000179 }
Anton Korobeynikov53835702008-10-10 20:27:31 +0000180
Dan Gohman475871a2008-07-27 21:46:04 +0000181 SDValue LoVal;
Chris Lattner5a65b922008-03-17 05:41:48 +0000182 if (CurArgReg < ArgRegEnd) { // Lives in an incoming GPR
183 unsigned VRegLo = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
184 MF.getRegInfo().addLiveIn(*CurArgReg++, VRegLo);
Dale Johannesen39355f92009-02-04 02:34:38 +0000185 LoVal = DAG.getCopyFromReg(Root, dl, VRegLo, MVT::i32);
Chris Lattner5a65b922008-03-17 05:41:48 +0000186 } else {
187 int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset+4);
Dan Gohman475871a2008-07-27 21:46:04 +0000188 SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
Dale Johannesen39355f92009-02-04 02:34:38 +0000189 LoVal = DAG.getLoad(MVT::i32, dl, Root, FIPtr, NULL, 0);
Chris Lattner5a65b922008-03-17 05:41:48 +0000190 }
Anton Korobeynikov53835702008-10-10 20:27:31 +0000191
Chris Lattner5a65b922008-03-17 05:41:48 +0000192 // Compose the two halves together into an i64 unit.
Anton Korobeynikov53835702008-10-10 20:27:31 +0000193 SDValue WholeValue =
Dale Johannesen39355f92009-02-04 02:34:38 +0000194 DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, LoVal, HiVal);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000195
Chris Lattner5a65b922008-03-17 05:41:48 +0000196 // If we want a double, do a bit convert.
197 if (ObjectVT == MVT::f64)
Dale Johannesen39355f92009-02-04 02:34:38 +0000198 WholeValue = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, WholeValue);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000199
Chris Lattner5a65b922008-03-17 05:41:48 +0000200 ArgValues.push_back(WholeValue);
201 }
202 ArgOffset += 8;
203 break;
204 }
205 }
Anton Korobeynikov53835702008-10-10 20:27:31 +0000206
Chris Lattner5a65b922008-03-17 05:41:48 +0000207 // Store remaining ArgRegs to the stack if this is a varargs function.
208 if (F.isVarArg()) {
209 // Remember the vararg offset for the va_start implementation.
210 VarArgsFrameOffset = ArgOffset;
Anton Korobeynikov53835702008-10-10 20:27:31 +0000211
Chris Lattner5a65b922008-03-17 05:41:48 +0000212 for (; CurArgReg != ArgRegEnd; ++CurArgReg) {
213 unsigned VReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass);
214 MF.getRegInfo().addLiveIn(*CurArgReg, VReg);
Dale Johannesen39355f92009-02-04 02:34:38 +0000215 SDValue Arg = DAG.getCopyFromReg(DAG.getRoot(), dl, VReg, MVT::i32);
Chris Lattner5a65b922008-03-17 05:41:48 +0000216
217 int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset);
Dan Gohman475871a2008-07-27 21:46:04 +0000218 SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32);
Chris Lattner5a65b922008-03-17 05:41:48 +0000219
Dale Johannesen39355f92009-02-04 02:34:38 +0000220 OutChains.push_back(DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, NULL, 0));
Chris Lattner5a65b922008-03-17 05:41:48 +0000221 ArgOffset += 4;
222 }
223 }
Anton Korobeynikov53835702008-10-10 20:27:31 +0000224
Chris Lattner5a65b922008-03-17 05:41:48 +0000225 if (!OutChains.empty())
Dale Johannesen39355f92009-02-04 02:34:38 +0000226 DAG.setRoot(DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Chris Lattner5a65b922008-03-17 05:41:48 +0000227 &OutChains[0], OutChains.size()));
Chris Lattner5a65b922008-03-17 05:41:48 +0000228}
229
Dan Gohman475871a2008-07-27 21:46:04 +0000230static SDValue LowerCALL(SDValue Op, SelectionDAG &DAG) {
Dan Gohman095cc292008-09-13 01:54:27 +0000231 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
232 unsigned CallingConv = TheCall->getCallingConv();
233 SDValue Chain = TheCall->getChain();
234 SDValue Callee = TheCall->getCallee();
235 bool isVarArg = TheCall->isVarArg();
Dale Johannesen33c960f2009-02-04 20:06:27 +0000236 DebugLoc dl = TheCall->getDebugLoc();
Chris Lattner98949a62008-03-17 06:01:07 +0000237
Chris Lattner315123f2008-03-17 06:58:37 +0000238#if 0
239 // Analyze operands of the call, assigning locations to each operand.
240 SmallVector<CCValAssign, 16> ArgLocs;
241 CCState CCInfo(CallingConv, isVarArg, DAG.getTarget(), ArgLocs);
Gabor Greifba36cb52008-08-28 21:40:38 +0000242 CCInfo.AnalyzeCallOperands(Op.getNode(), CC_Sparc32);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000243
Chris Lattner315123f2008-03-17 06:58:37 +0000244 // Get the size of the outgoing arguments stack space requirement.
245 unsigned ArgsSize = CCInfo.getNextStackOffset();
246 // FIXME: We can't use this until f64 is known to take two GPRs.
247#else
248 (void)CC_Sparc32;
Anton Korobeynikov53835702008-10-10 20:27:31 +0000249
Chris Lattner5a65b922008-03-17 05:41:48 +0000250 // Count the size of the outgoing arguments.
251 unsigned ArgsSize = 0;
Dan Gohman095cc292008-09-13 01:54:27 +0000252 for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; ++i) {
253 switch (TheCall->getArg(i).getValueType().getSimpleVT()) {
Chris Lattner315123f2008-03-17 06:58:37 +0000254 default: assert(0 && "Unknown value type!");
255 case MVT::i1:
256 case MVT::i8:
257 case MVT::i16:
258 case MVT::i32:
259 case MVT::f32:
260 ArgsSize += 4;
261 break;
262 case MVT::i64:
263 case MVT::f64:
264 ArgsSize += 8;
265 break;
Chris Lattner5a65b922008-03-17 05:41:48 +0000266 }
267 }
268 if (ArgsSize > 4*6)
269 ArgsSize -= 4*6; // Space for first 6 arguments is prereserved.
270 else
271 ArgsSize = 0;
Anton Korobeynikov53835702008-10-10 20:27:31 +0000272#endif
273
Chris Lattner5a65b922008-03-17 05:41:48 +0000274 // Keep stack frames 8-byte aligned.
275 ArgsSize = (ArgsSize+7) & ~7;
276
Chris Lattnere563bbc2008-10-11 22:08:30 +0000277 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(ArgsSize, true));
Anton Korobeynikov53835702008-10-10 20:27:31 +0000278
Dan Gohman475871a2008-07-27 21:46:04 +0000279 SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
280 SmallVector<SDValue, 8> MemOpChains;
Anton Korobeynikov53835702008-10-10 20:27:31 +0000281
Chris Lattner315123f2008-03-17 06:58:37 +0000282#if 0
283 // Walk the register/memloc assignments, inserting copies/loads.
284 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
285 CCValAssign &VA = ArgLocs[i];
Anton Korobeynikov53835702008-10-10 20:27:31 +0000286
Chris Lattner315123f2008-03-17 06:58:37 +0000287 // Arguments start after the 5 first operands of ISD::CALL
Dan Gohman095cc292008-09-13 01:54:27 +0000288 SDValue Arg = TheCall->getArg(i);
Chris Lattner315123f2008-03-17 06:58:37 +0000289
290 // Promote the value if needed.
291 switch (VA.getLocInfo()) {
292 default: assert(0 && "Unknown loc info!");
293 case CCValAssign::Full: break;
294 case CCValAssign::SExt:
295 Arg = DAG.getNode(ISD::SIGN_EXTEND, VA.getLocVT(), Arg);
296 break;
297 case CCValAssign::ZExt:
298 Arg = DAG.getNode(ISD::ZERO_EXTEND, VA.getLocVT(), Arg);
299 break;
300 case CCValAssign::AExt:
301 Arg = DAG.getNode(ISD::ANY_EXTEND, VA.getLocVT(), Arg);
302 break;
303 }
Anton Korobeynikov53835702008-10-10 20:27:31 +0000304
305 // Arguments that can be passed on register must be kept at
Chris Lattner315123f2008-03-17 06:58:37 +0000306 // RegsToPass vector
307 if (VA.isRegLoc()) {
308 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
309 continue;
310 }
Anton Korobeynikov53835702008-10-10 20:27:31 +0000311
Chris Lattner315123f2008-03-17 06:58:37 +0000312 assert(VA.isMemLoc());
Anton Korobeynikov53835702008-10-10 20:27:31 +0000313
Chris Lattner315123f2008-03-17 06:58:37 +0000314 // Create a store off the stack pointer for this argument.
Dan Gohman475871a2008-07-27 21:46:04 +0000315 SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
Chris Lattner315123f2008-03-17 06:58:37 +0000316 // FIXME: VERIFY THAT 68 IS RIGHT.
Dan Gohman475871a2008-07-27 21:46:04 +0000317 SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset()+68);
Chris Lattner315123f2008-03-17 06:58:37 +0000318 PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff);
319 MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0));
320 }
Anton Korobeynikov53835702008-10-10 20:27:31 +0000321
322#else
Chris Lattner315123f2008-03-17 06:58:37 +0000323 static const unsigned ArgRegs[] = {
324 SP::I0, SP::I1, SP::I2, SP::I3, SP::I4, SP::I5
325 };
Chris Lattner5a65b922008-03-17 05:41:48 +0000326 unsigned ArgOffset = 68;
Chris Lattner315123f2008-03-17 06:58:37 +0000327
Dan Gohman095cc292008-09-13 01:54:27 +0000328 for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; ++i) {
329 SDValue Val = TheCall->getArg(i);
Duncan Sands83ec4b62008-06-06 12:08:01 +0000330 MVT ObjectVT = Val.getValueType();
Dan Gohman475871a2008-07-27 21:46:04 +0000331 SDValue ValToStore(0, 0);
Chris Lattner5a65b922008-03-17 05:41:48 +0000332 unsigned ObjSize;
Duncan Sands83ec4b62008-06-06 12:08:01 +0000333 switch (ObjectVT.getSimpleVT()) {
Chris Lattner5a65b922008-03-17 05:41:48 +0000334 default: assert(0 && "Unhandled argument type!");
Chris Lattner5a65b922008-03-17 05:41:48 +0000335 case MVT::i32:
336 ObjSize = 4;
337
Chris Lattner315123f2008-03-17 06:58:37 +0000338 if (RegsToPass.size() >= 6) {
Chris Lattner5a65b922008-03-17 05:41:48 +0000339 ValToStore = Val;
340 } else {
Chris Lattner315123f2008-03-17 06:58:37 +0000341 RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Val));
Chris Lattner5a65b922008-03-17 05:41:48 +0000342 }
343 break;
344 case MVT::f32:
345 ObjSize = 4;
Chris Lattner315123f2008-03-17 06:58:37 +0000346 if (RegsToPass.size() >= 6) {
Chris Lattner5a65b922008-03-17 05:41:48 +0000347 ValToStore = Val;
348 } else {
349 // Convert this to a FP value in an int reg.
Dale Johannesen33c960f2009-02-04 20:06:27 +0000350 Val = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Val);
Chris Lattner315123f2008-03-17 06:58:37 +0000351 RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Val));
Chris Lattner5a65b922008-03-17 05:41:48 +0000352 }
353 break;
Duncan Sands8c0f2442008-12-12 08:05:40 +0000354 case MVT::f64: {
Chris Lattner5a65b922008-03-17 05:41:48 +0000355 ObjSize = 8;
Duncan Sands8c0f2442008-12-12 08:05:40 +0000356 if (RegsToPass.size() >= 6) {
357 ValToStore = Val; // Whole thing is passed in memory.
358 break;
359 }
360
361 // Break into top and bottom parts by storing to the stack and loading
362 // out the parts as integers. Top part goes in a reg.
363 SDValue StackPtr = DAG.CreateStackTemporary(MVT::f64, MVT::i32);
Dale Johannesen33c960f2009-02-04 20:06:27 +0000364 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl,
365 Val, StackPtr, NULL, 0);
Duncan Sands8c0f2442008-12-12 08:05:40 +0000366 // Sparc is big-endian, so the high part comes first.
Dale Johannesen33c960f2009-02-04 20:06:27 +0000367 SDValue Hi = DAG.getLoad(MVT::i32, dl, Store, StackPtr, NULL, 0, 0);
Duncan Sands8c0f2442008-12-12 08:05:40 +0000368 // Increment the pointer to the other half.
Dale Johannesen33c960f2009-02-04 20:06:27 +0000369 StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr,
Duncan Sands8c0f2442008-12-12 08:05:40 +0000370 DAG.getIntPtrConstant(4));
371 // Load the low part.
Dale Johannesen33c960f2009-02-04 20:06:27 +0000372 SDValue Lo = DAG.getLoad(MVT::i32, dl, Store, StackPtr, NULL, 0, 0);
Duncan Sands8c0f2442008-12-12 08:05:40 +0000373
374 RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Hi));
375
376 if (RegsToPass.size() >= 6) {
377 ValToStore = Lo;
378 ArgOffset += 4;
379 ObjSize = 4;
380 } else {
381 RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Lo));
382 }
383 break;
384 }
385 case MVT::i64: {
Chris Lattner5a65b922008-03-17 05:41:48 +0000386 ObjSize = 8;
Chris Lattner315123f2008-03-17 06:58:37 +0000387 if (RegsToPass.size() >= 6) {
Chris Lattner5a65b922008-03-17 05:41:48 +0000388 ValToStore = Val; // Whole thing is passed in memory.
389 break;
390 }
Anton Korobeynikov53835702008-10-10 20:27:31 +0000391
Chris Lattner5a65b922008-03-17 05:41:48 +0000392 // Split the value into top and bottom part. Top part goes in a reg.
Dale Johannesen33c960f2009-02-04 20:06:27 +0000393 SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Val,
Chris Lattner5a65b922008-03-17 05:41:48 +0000394 DAG.getConstant(1, MVT::i32));
Dale Johannesen33c960f2009-02-04 20:06:27 +0000395 SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Val,
Chris Lattner5a65b922008-03-17 05:41:48 +0000396 DAG.getConstant(0, MVT::i32));
Chris Lattner315123f2008-03-17 06:58:37 +0000397 RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Hi));
Anton Korobeynikov53835702008-10-10 20:27:31 +0000398
Chris Lattner315123f2008-03-17 06:58:37 +0000399 if (RegsToPass.size() >= 6) {
Chris Lattner5a65b922008-03-17 05:41:48 +0000400 ValToStore = Lo;
401 ArgOffset += 4;
402 ObjSize = 4;
403 } else {
Chris Lattner315123f2008-03-17 06:58:37 +0000404 RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Lo));
Chris Lattner5a65b922008-03-17 05:41:48 +0000405 }
406 break;
407 }
Duncan Sands8c0f2442008-12-12 08:05:40 +0000408 }
Anton Korobeynikov53835702008-10-10 20:27:31 +0000409
Gabor Greifba36cb52008-08-28 21:40:38 +0000410 if (ValToStore.getNode()) {
Dan Gohman475871a2008-07-27 21:46:04 +0000411 SDValue StackPtr = DAG.getRegister(SP::O6, MVT::i32);
412 SDValue PtrOff = DAG.getConstant(ArgOffset, MVT::i32);
Dale Johannesen33c960f2009-02-04 20:06:27 +0000413 PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
414 MemOpChains.push_back(DAG.getStore(Chain, dl, ValToStore,
415 PtrOff, NULL, 0));
Chris Lattner5a65b922008-03-17 05:41:48 +0000416 }
417 ArgOffset += ObjSize;
418 }
Chris Lattner315123f2008-03-17 06:58:37 +0000419#endif
Anton Korobeynikov53835702008-10-10 20:27:31 +0000420
Chris Lattner5a65b922008-03-17 05:41:48 +0000421 // Emit all stores, make sure the occur before any copies into physregs.
Chris Lattner315123f2008-03-17 06:58:37 +0000422 if (!MemOpChains.empty())
Dale Johannesen33c960f2009-02-04 20:06:27 +0000423 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Chris Lattner315123f2008-03-17 06:58:37 +0000424 &MemOpChains[0], MemOpChains.size());
Anton Korobeynikov53835702008-10-10 20:27:31 +0000425
426 // Build a sequence of copy-to-reg nodes chained together with token
Chris Lattner315123f2008-03-17 06:58:37 +0000427 // chain and flag operands which copy the outgoing args into registers.
428 // The InFlag in necessary since all emited instructions must be
429 // stuck together.
Dan Gohman475871a2008-07-27 21:46:04 +0000430 SDValue InFlag;
Chris Lattner315123f2008-03-17 06:58:37 +0000431 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
432 unsigned Reg = RegsToPass[i].first;
433 // Remap I0->I7 -> O0->O7.
434 if (Reg >= SP::I0 && Reg <= SP::I7)
435 Reg = Reg-SP::I0+SP::O0;
436
Dale Johannesen33c960f2009-02-04 20:06:27 +0000437 Chain = DAG.getCopyToReg(Chain, dl, Reg, RegsToPass[i].second, InFlag);
Chris Lattner5a65b922008-03-17 05:41:48 +0000438 InFlag = Chain.getValue(1);
439 }
440
441 // If the callee is a GlobalAddress node (quite common, every direct call is)
442 // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
Bill Wendling056292f2008-09-16 21:48:12 +0000443 // Likewise ExternalSymbol -> TargetExternalSymbol.
Chris Lattner5a65b922008-03-17 05:41:48 +0000444 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
445 Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i32);
Bill Wendling056292f2008-09-16 21:48:12 +0000446 else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
447 Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
Chris Lattner5a65b922008-03-17 05:41:48 +0000448
Duncan Sands83ec4b62008-06-06 12:08:01 +0000449 std::vector<MVT> NodeTys;
Chris Lattner5a65b922008-03-17 05:41:48 +0000450 NodeTys.push_back(MVT::Other); // Returns a chain
451 NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
Dan Gohman475871a2008-07-27 21:46:04 +0000452 SDValue Ops[] = { Chain, Callee, InFlag };
Dale Johannesen33c960f2009-02-04 20:06:27 +0000453 Chain = DAG.getNode(SPISD::CALL, dl, NodeTys, Ops, InFlag.getNode() ? 3 : 2);
Chris Lattner5a65b922008-03-17 05:41:48 +0000454 InFlag = Chain.getValue(1);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000455
Chris Lattnere563bbc2008-10-11 22:08:30 +0000456 Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(ArgsSize, true),
457 DAG.getIntPtrConstant(0, true), InFlag);
Chris Lattner98949a62008-03-17 06:01:07 +0000458 InFlag = Chain.getValue(1);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000459
Chris Lattner98949a62008-03-17 06:01:07 +0000460 // Assign locations to each value returned by this call.
461 SmallVector<CCValAssign, 16> RVLocs;
Chris Lattner315123f2008-03-17 06:58:37 +0000462 CCState RVInfo(CallingConv, isVarArg, DAG.getTarget(), RVLocs);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000463
Dan Gohman095cc292008-09-13 01:54:27 +0000464 RVInfo.AnalyzeCallResult(TheCall, RetCC_Sparc32);
Dan Gohman475871a2008-07-27 21:46:04 +0000465 SmallVector<SDValue, 8> ResultVals;
Anton Korobeynikov53835702008-10-10 20:27:31 +0000466
Chris Lattner98949a62008-03-17 06:01:07 +0000467 // Copy all of the result registers out of their specified physreg.
468 for (unsigned i = 0; i != RVLocs.size(); ++i) {
469 unsigned Reg = RVLocs[i].getLocReg();
Anton Korobeynikov53835702008-10-10 20:27:31 +0000470
Chris Lattner98949a62008-03-17 06:01:07 +0000471 // Remap I0->I7 -> O0->O7.
472 if (Reg >= SP::I0 && Reg <= SP::I7)
473 Reg = Reg-SP::I0+SP::O0;
Anton Korobeynikov53835702008-10-10 20:27:31 +0000474
Dale Johannesen33c960f2009-02-04 20:06:27 +0000475 Chain = DAG.getCopyFromReg(Chain, dl, Reg,
Chris Lattner98949a62008-03-17 06:01:07 +0000476 RVLocs[i].getValVT(), InFlag).getValue(1);
477 InFlag = Chain.getValue(2);
478 ResultVals.push_back(Chain.getValue(0));
Chris Lattner5a65b922008-03-17 05:41:48 +0000479 }
Anton Korobeynikov53835702008-10-10 20:27:31 +0000480
Chris Lattner98949a62008-03-17 06:01:07 +0000481 ResultVals.push_back(Chain);
Duncan Sands4bdcb612008-07-02 17:40:58 +0000482
Chris Lattner98949a62008-03-17 06:01:07 +0000483 // Merge everything together with a MERGE_VALUES node.
Dale Johannesen33c960f2009-02-04 20:06:27 +0000484 return DAG.getNode(ISD::MERGE_VALUES, dl,
485 TheCall->getVTList(), &ResultVals[0],
Duncan Sandsaaffa052008-12-01 11:41:29 +0000486 ResultVals.size());
Chris Lattner5a65b922008-03-17 05:41:48 +0000487}
488
489
490
Chris Lattnerd23405e2008-03-17 03:21:36 +0000491//===----------------------------------------------------------------------===//
492// TargetLowering Implementation
493//===----------------------------------------------------------------------===//
494
495/// IntCondCCodeToICC - Convert a DAG integer condition code to a SPARC ICC
496/// condition.
497static SPCC::CondCodes IntCondCCodeToICC(ISD::CondCode CC) {
498 switch (CC) {
499 default: assert(0 && "Unknown integer condition code!");
500 case ISD::SETEQ: return SPCC::ICC_E;
501 case ISD::SETNE: return SPCC::ICC_NE;
502 case ISD::SETLT: return SPCC::ICC_L;
503 case ISD::SETGT: return SPCC::ICC_G;
504 case ISD::SETLE: return SPCC::ICC_LE;
505 case ISD::SETGE: return SPCC::ICC_GE;
506 case ISD::SETULT: return SPCC::ICC_CS;
507 case ISD::SETULE: return SPCC::ICC_LEU;
508 case ISD::SETUGT: return SPCC::ICC_GU;
509 case ISD::SETUGE: return SPCC::ICC_CC;
510 }
511}
512
513/// FPCondCCodeToFCC - Convert a DAG floatingp oint condition code to a SPARC
514/// FCC condition.
515static SPCC::CondCodes FPCondCCodeToFCC(ISD::CondCode CC) {
516 switch (CC) {
517 default: assert(0 && "Unknown fp condition code!");
518 case ISD::SETEQ:
519 case ISD::SETOEQ: return SPCC::FCC_E;
520 case ISD::SETNE:
521 case ISD::SETUNE: return SPCC::FCC_NE;
522 case ISD::SETLT:
523 case ISD::SETOLT: return SPCC::FCC_L;
524 case ISD::SETGT:
525 case ISD::SETOGT: return SPCC::FCC_G;
526 case ISD::SETLE:
527 case ISD::SETOLE: return SPCC::FCC_LE;
528 case ISD::SETGE:
529 case ISD::SETOGE: return SPCC::FCC_GE;
530 case ISD::SETULT: return SPCC::FCC_UL;
531 case ISD::SETULE: return SPCC::FCC_ULE;
532 case ISD::SETUGT: return SPCC::FCC_UG;
533 case ISD::SETUGE: return SPCC::FCC_UGE;
534 case ISD::SETUO: return SPCC::FCC_U;
535 case ISD::SETO: return SPCC::FCC_O;
536 case ISD::SETONE: return SPCC::FCC_LG;
537 case ISD::SETUEQ: return SPCC::FCC_UE;
538 }
539}
540
541
542SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
543 : TargetLowering(TM) {
Anton Korobeynikov53835702008-10-10 20:27:31 +0000544
Chris Lattnerd23405e2008-03-17 03:21:36 +0000545 // Set up the register classes.
546 addRegisterClass(MVT::i32, SP::IntRegsRegisterClass);
547 addRegisterClass(MVT::f32, SP::FPRegsRegisterClass);
548 addRegisterClass(MVT::f64, SP::DFPRegsRegisterClass);
549
550 // Turn FP extload into load/fextend
Evan Cheng03294662008-10-14 21:26:46 +0000551 setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000552 // Sparc doesn't have i1 sign extending load
Evan Cheng03294662008-10-14 21:26:46 +0000553 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000554 // Turn FP truncstore into trunc + store.
555 setTruncStoreAction(MVT::f64, MVT::f32, Expand);
556
557 // Custom legalize GlobalAddress nodes into LO/HI parts.
558 setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
559 setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
560 setOperationAction(ISD::ConstantPool , MVT::i32, Custom);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000561
Chris Lattnerd23405e2008-03-17 03:21:36 +0000562 // Sparc doesn't have sext_inreg, replace them with shl/sra
563 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
564 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8 , Expand);
565 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand);
566
567 // Sparc has no REM or DIVREM operations.
568 setOperationAction(ISD::UREM, MVT::i32, Expand);
569 setOperationAction(ISD::SREM, MVT::i32, Expand);
570 setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
571 setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
572
573 // Custom expand fp<->sint
574 setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
575 setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
576
577 // Expand fp<->uint
578 setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
579 setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000580
Chris Lattnerd23405e2008-03-17 03:21:36 +0000581 setOperationAction(ISD::BIT_CONVERT, MVT::f32, Expand);
582 setOperationAction(ISD::BIT_CONVERT, MVT::i32, Expand);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000583
Chris Lattnerd23405e2008-03-17 03:21:36 +0000584 // Sparc has no select or setcc: expand to SELECT_CC.
585 setOperationAction(ISD::SELECT, MVT::i32, Expand);
586 setOperationAction(ISD::SELECT, MVT::f32, Expand);
587 setOperationAction(ISD::SELECT, MVT::f64, Expand);
588 setOperationAction(ISD::SETCC, MVT::i32, Expand);
589 setOperationAction(ISD::SETCC, MVT::f32, Expand);
590 setOperationAction(ISD::SETCC, MVT::f64, Expand);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000591
Chris Lattnerd23405e2008-03-17 03:21:36 +0000592 // Sparc doesn't have BRCOND either, it has BR_CC.
593 setOperationAction(ISD::BRCOND, MVT::Other, Expand);
594 setOperationAction(ISD::BRIND, MVT::Other, Expand);
595 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
596 setOperationAction(ISD::BR_CC, MVT::i32, Custom);
597 setOperationAction(ISD::BR_CC, MVT::f32, Custom);
598 setOperationAction(ISD::BR_CC, MVT::f64, Custom);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000599
Chris Lattnerd23405e2008-03-17 03:21:36 +0000600 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
601 setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
602 setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000603
Chris Lattnerd23405e2008-03-17 03:21:36 +0000604 // SPARC has no intrinsics for these particular operations.
Chris Lattnerd23405e2008-03-17 03:21:36 +0000605 setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
606
607 setOperationAction(ISD::FSIN , MVT::f64, Expand);
608 setOperationAction(ISD::FCOS , MVT::f64, Expand);
609 setOperationAction(ISD::FREM , MVT::f64, Expand);
610 setOperationAction(ISD::FSIN , MVT::f32, Expand);
611 setOperationAction(ISD::FCOS , MVT::f32, Expand);
612 setOperationAction(ISD::FREM , MVT::f32, Expand);
613 setOperationAction(ISD::CTPOP, MVT::i32, Expand);
614 setOperationAction(ISD::CTTZ , MVT::i32, Expand);
615 setOperationAction(ISD::CTLZ , MVT::i32, Expand);
616 setOperationAction(ISD::ROTL , MVT::i32, Expand);
617 setOperationAction(ISD::ROTR , MVT::i32, Expand);
618 setOperationAction(ISD::BSWAP, MVT::i32, Expand);
619 setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
620 setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
621 setOperationAction(ISD::FPOW , MVT::f64, Expand);
622 setOperationAction(ISD::FPOW , MVT::f32, Expand);
623
624 setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
625 setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
626 setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
627
628 // FIXME: Sparc provides these multiplies, but we don't have them yet.
629 setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
Anton Korobeynikov4b58b6a2008-10-10 20:29:31 +0000630 setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000631
Chris Lattnerd23405e2008-03-17 03:21:36 +0000632 // We don't have line number support yet.
Dan Gohman7f460202008-06-30 20:59:49 +0000633 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000634 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
Dan Gohman44066042008-07-01 00:05:16 +0000635 setOperationAction(ISD::DBG_LABEL, MVT::Other, Expand);
636 setOperationAction(ISD::EH_LABEL, MVT::Other, Expand);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000637
638 // RET must be custom lowered, to meet ABI requirements
639 setOperationAction(ISD::RET , MVT::Other, Custom);
640
641 // VASTART needs to be custom lowered to use the VarArgsFrameIndex.
642 setOperationAction(ISD::VASTART , MVT::Other, Custom);
643 // VAARG needs to be lowered to not do unaligned accesses for doubles.
644 setOperationAction(ISD::VAARG , MVT::Other, Custom);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000645
Chris Lattnerd23405e2008-03-17 03:21:36 +0000646 // Use the default implementation.
647 setOperationAction(ISD::VACOPY , MVT::Other, Expand);
648 setOperationAction(ISD::VAEND , MVT::Other, Expand);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000649 setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000650 setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
651 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Custom);
652
653 // No debug info support yet.
Dan Gohman7f460202008-06-30 20:59:49 +0000654 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
Dan Gohman44066042008-07-01 00:05:16 +0000655 setOperationAction(ISD::DBG_LABEL, MVT::Other, Expand);
656 setOperationAction(ISD::EH_LABEL, MVT::Other, Expand);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000657 setOperationAction(ISD::DECLARE, MVT::Other, Expand);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000658
Chris Lattnerd23405e2008-03-17 03:21:36 +0000659 setStackPointerRegisterToSaveRestore(SP::O6);
660
661 if (TM.getSubtarget<SparcSubtarget>().isV9())
662 setOperationAction(ISD::CTPOP, MVT::i32, Legal);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000663
Chris Lattnerd23405e2008-03-17 03:21:36 +0000664 computeRegisterProperties();
665}
666
667const char *SparcTargetLowering::getTargetNodeName(unsigned Opcode) const {
668 switch (Opcode) {
669 default: return 0;
670 case SPISD::CMPICC: return "SPISD::CMPICC";
671 case SPISD::CMPFCC: return "SPISD::CMPFCC";
672 case SPISD::BRICC: return "SPISD::BRICC";
673 case SPISD::BRFCC: return "SPISD::BRFCC";
674 case SPISD::SELECT_ICC: return "SPISD::SELECT_ICC";
675 case SPISD::SELECT_FCC: return "SPISD::SELECT_FCC";
676 case SPISD::Hi: return "SPISD::Hi";
677 case SPISD::Lo: return "SPISD::Lo";
678 case SPISD::FTOI: return "SPISD::FTOI";
679 case SPISD::ITOF: return "SPISD::ITOF";
680 case SPISD::CALL: return "SPISD::CALL";
681 case SPISD::RET_FLAG: return "SPISD::RET_FLAG";
682 }
683}
684
685/// isMaskedValueZeroForTargetNode - Return true if 'Op & Mask' is known to
686/// be zero. Op is expected to be a target specific node. Used by DAG
687/// combiner.
Dan Gohman475871a2008-07-27 21:46:04 +0000688void SparcTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
Chris Lattnerd23405e2008-03-17 03:21:36 +0000689 const APInt &Mask,
Anton Korobeynikov53835702008-10-10 20:27:31 +0000690 APInt &KnownZero,
Chris Lattnerd23405e2008-03-17 03:21:36 +0000691 APInt &KnownOne,
692 const SelectionDAG &DAG,
693 unsigned Depth) const {
694 APInt KnownZero2, KnownOne2;
695 KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); // Don't know anything.
Anton Korobeynikov53835702008-10-10 20:27:31 +0000696
Chris Lattnerd23405e2008-03-17 03:21:36 +0000697 switch (Op.getOpcode()) {
698 default: break;
699 case SPISD::SELECT_ICC:
700 case SPISD::SELECT_FCC:
701 DAG.ComputeMaskedBits(Op.getOperand(1), Mask, KnownZero, KnownOne,
702 Depth+1);
703 DAG.ComputeMaskedBits(Op.getOperand(0), Mask, KnownZero2, KnownOne2,
704 Depth+1);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000705 assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
706 assert((KnownZero2 & KnownOne2) == 0 && "Bits known to be one AND zero?");
707
Chris Lattnerd23405e2008-03-17 03:21:36 +0000708 // Only known if known in both the LHS and RHS.
709 KnownOne &= KnownOne2;
710 KnownZero &= KnownZero2;
711 break;
712 }
713}
714
Chris Lattnerd23405e2008-03-17 03:21:36 +0000715// Look at LHS/RHS/CC and see if they are a lowered setcc instruction. If so
716// set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition.
Dan Gohman475871a2008-07-27 21:46:04 +0000717static void LookThroughSetCC(SDValue &LHS, SDValue &RHS,
Chris Lattnerd23405e2008-03-17 03:21:36 +0000718 ISD::CondCode CC, unsigned &SPCC) {
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000719 if (isa<ConstantSDNode>(RHS) &&
720 cast<ConstantSDNode>(RHS)->getZExtValue() == 0 &&
Anton Korobeynikov53835702008-10-10 20:27:31 +0000721 CC == ISD::SETNE &&
Chris Lattnerd23405e2008-03-17 03:21:36 +0000722 ((LHS.getOpcode() == SPISD::SELECT_ICC &&
723 LHS.getOperand(3).getOpcode() == SPISD::CMPICC) ||
724 (LHS.getOpcode() == SPISD::SELECT_FCC &&
725 LHS.getOperand(3).getOpcode() == SPISD::CMPFCC)) &&
726 isa<ConstantSDNode>(LHS.getOperand(0)) &&
727 isa<ConstantSDNode>(LHS.getOperand(1)) &&
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000728 cast<ConstantSDNode>(LHS.getOperand(0))->getZExtValue() == 1 &&
729 cast<ConstantSDNode>(LHS.getOperand(1))->getZExtValue() == 0) {
Dan Gohman475871a2008-07-27 21:46:04 +0000730 SDValue CMPCC = LHS.getOperand(3);
Dan Gohmanf5aeb1a2008-09-12 16:56:44 +0000731 SPCC = cast<ConstantSDNode>(LHS.getOperand(2))->getZExtValue();
Chris Lattnerd23405e2008-03-17 03:21:36 +0000732 LHS = CMPCC.getOperand(0);
733 RHS = CMPCC.getOperand(1);
734 }
735}
736
Dan Gohman475871a2008-07-27 21:46:04 +0000737static SDValue LowerGLOBALADDRESS(SDValue Op, SelectionDAG &DAG) {
Chris Lattnerd23405e2008-03-17 03:21:36 +0000738 GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
Dale Johannesende064702009-02-06 21:50:26 +0000739 // FIXME there isn't really any debug info here
740 DebugLoc dl = Op.getDebugLoc();
Dan Gohman475871a2008-07-27 21:46:04 +0000741 SDValue GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
Dale Johannesende064702009-02-06 21:50:26 +0000742 SDValue Hi = DAG.getNode(SPISD::Hi, dl, MVT::i32, GA);
743 SDValue Lo = DAG.getNode(SPISD::Lo, dl, MVT::i32, GA);
744 return DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000745}
746
Dan Gohman475871a2008-07-27 21:46:04 +0000747static SDValue LowerCONSTANTPOOL(SDValue Op, SelectionDAG &DAG) {
Chris Lattnerd23405e2008-03-17 03:21:36 +0000748 ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
Dale Johannesende064702009-02-06 21:50:26 +0000749 // FIXME there isn't really any debug info here
750 DebugLoc dl = Op.getDebugLoc();
Chris Lattnerd23405e2008-03-17 03:21:36 +0000751 Constant *C = N->getConstVal();
Dan Gohman475871a2008-07-27 21:46:04 +0000752 SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment());
Dale Johannesende064702009-02-06 21:50:26 +0000753 SDValue Hi = DAG.getNode(SPISD::Hi, dl, MVT::i32, CP);
754 SDValue Lo = DAG.getNode(SPISD::Lo, dl, MVT::i32, CP);
755 return DAG.getNode(ISD::ADD, dl, MVT::i32, Lo, Hi);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000756}
757
Dan Gohman475871a2008-07-27 21:46:04 +0000758static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) {
Chris Lattnerd23405e2008-03-17 03:21:36 +0000759 // Convert the fp value to integer in an FP register.
760 assert(Op.getValueType() == MVT::i32);
761 Op = DAG.getNode(SPISD::FTOI, MVT::f32, Op.getOperand(0));
762 return DAG.getNode(ISD::BIT_CONVERT, MVT::i32, Op);
763}
764
Dan Gohman475871a2008-07-27 21:46:04 +0000765static SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) {
Chris Lattnerd23405e2008-03-17 03:21:36 +0000766 assert(Op.getOperand(0).getValueType() == MVT::i32);
Dan Gohman475871a2008-07-27 21:46:04 +0000767 SDValue Tmp = DAG.getNode(ISD::BIT_CONVERT, MVT::f32, Op.getOperand(0));
Chris Lattnerd23405e2008-03-17 03:21:36 +0000768 // Convert the int value to FP in an FP register.
769 return DAG.getNode(SPISD::ITOF, Op.getValueType(), Tmp);
770}
771
Dan Gohman475871a2008-07-27 21:46:04 +0000772static SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) {
773 SDValue Chain = Op.getOperand(0);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000774 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
Dan Gohman475871a2008-07-27 21:46:04 +0000775 SDValue LHS = Op.getOperand(2);
776 SDValue RHS = Op.getOperand(3);
777 SDValue Dest = Op.getOperand(4);
Dale Johannesen3484c092009-02-05 22:07:54 +0000778 DebugLoc dl = Op.getDebugLoc();
Chris Lattnerd23405e2008-03-17 03:21:36 +0000779 unsigned Opc, SPCC = ~0U;
Anton Korobeynikov53835702008-10-10 20:27:31 +0000780
Chris Lattnerd23405e2008-03-17 03:21:36 +0000781 // If this is a br_cc of a "setcc", and if the setcc got lowered into
782 // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values.
783 LookThroughSetCC(LHS, RHS, CC, SPCC);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000784
Chris Lattnerd23405e2008-03-17 03:21:36 +0000785 // Get the condition flag.
Dan Gohman475871a2008-07-27 21:46:04 +0000786 SDValue CompareFlag;
Chris Lattnerd23405e2008-03-17 03:21:36 +0000787 if (LHS.getValueType() == MVT::i32) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000788 std::vector<MVT> VTs;
Chris Lattnerd23405e2008-03-17 03:21:36 +0000789 VTs.push_back(MVT::i32);
790 VTs.push_back(MVT::Flag);
Dan Gohman475871a2008-07-27 21:46:04 +0000791 SDValue Ops[2] = { LHS, RHS };
Dale Johannesen3484c092009-02-05 22:07:54 +0000792 CompareFlag = DAG.getNode(SPISD::CMPICC, dl, VTs, Ops, 2).getValue(1);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000793 if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC);
794 Opc = SPISD::BRICC;
795 } else {
Dale Johannesen3484c092009-02-05 22:07:54 +0000796 CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Flag, LHS, RHS);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000797 if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
798 Opc = SPISD::BRFCC;
799 }
Dale Johannesen3484c092009-02-05 22:07:54 +0000800 return DAG.getNode(Opc, dl, MVT::Other, Chain, Dest,
Chris Lattnerd23405e2008-03-17 03:21:36 +0000801 DAG.getConstant(SPCC, MVT::i32), CompareFlag);
802}
803
Dan Gohman475871a2008-07-27 21:46:04 +0000804static SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
805 SDValue LHS = Op.getOperand(0);
806 SDValue RHS = Op.getOperand(1);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000807 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
Dan Gohman475871a2008-07-27 21:46:04 +0000808 SDValue TrueVal = Op.getOperand(2);
809 SDValue FalseVal = Op.getOperand(3);
Dale Johannesen3484c092009-02-05 22:07:54 +0000810 DebugLoc dl = Op.getDebugLoc();
Chris Lattnerd23405e2008-03-17 03:21:36 +0000811 unsigned Opc, SPCC = ~0U;
Anton Korobeynikov53835702008-10-10 20:27:31 +0000812
Chris Lattnerd23405e2008-03-17 03:21:36 +0000813 // If this is a select_cc of a "setcc", and if the setcc got lowered into
814 // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values.
815 LookThroughSetCC(LHS, RHS, CC, SPCC);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000816
Dan Gohman475871a2008-07-27 21:46:04 +0000817 SDValue CompareFlag;
Chris Lattnerd23405e2008-03-17 03:21:36 +0000818 if (LHS.getValueType() == MVT::i32) {
Duncan Sands83ec4b62008-06-06 12:08:01 +0000819 std::vector<MVT> VTs;
Chris Lattnerd23405e2008-03-17 03:21:36 +0000820 VTs.push_back(LHS.getValueType()); // subcc returns a value
821 VTs.push_back(MVT::Flag);
Dan Gohman475871a2008-07-27 21:46:04 +0000822 SDValue Ops[2] = { LHS, RHS };
Dale Johannesen3484c092009-02-05 22:07:54 +0000823 CompareFlag = DAG.getNode(SPISD::CMPICC, dl, VTs, Ops, 2).getValue(1);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000824 Opc = SPISD::SELECT_ICC;
825 if (SPCC == ~0U) SPCC = IntCondCCodeToICC(CC);
826 } else {
Dale Johannesen3484c092009-02-05 22:07:54 +0000827 CompareFlag = DAG.getNode(SPISD::CMPFCC, dl, MVT::Flag, LHS, RHS);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000828 Opc = SPISD::SELECT_FCC;
829 if (SPCC == ~0U) SPCC = FPCondCCodeToFCC(CC);
830 }
Dale Johannesen3484c092009-02-05 22:07:54 +0000831 return DAG.getNode(Opc, dl, TrueVal.getValueType(), TrueVal, FalseVal,
Chris Lattnerd23405e2008-03-17 03:21:36 +0000832 DAG.getConstant(SPCC, MVT::i32), CompareFlag);
833}
834
Dan Gohman475871a2008-07-27 21:46:04 +0000835static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG,
Chris Lattnerd23405e2008-03-17 03:21:36 +0000836 SparcTargetLowering &TLI) {
837 // vastart just stores the address of the VarArgsFrameIndex slot into the
838 // memory location argument.
Dale Johannesen33c960f2009-02-04 20:06:27 +0000839 DebugLoc dl = Op.getNode()->getDebugLoc();
840 SDValue Offset = DAG.getNode(ISD::ADD, dl, MVT::i32,
Chris Lattnerd23405e2008-03-17 03:21:36 +0000841 DAG.getRegister(SP::I6, MVT::i32),
842 DAG.getConstant(TLI.getVarArgsFrameOffset(),
843 MVT::i32));
844 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
Dale Johannesen33c960f2009-02-04 20:06:27 +0000845 return DAG.getStore(Op.getOperand(0), dl, Offset, Op.getOperand(1), SV, 0);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000846}
847
Dan Gohman475871a2008-07-27 21:46:04 +0000848static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) {
Gabor Greifba36cb52008-08-28 21:40:38 +0000849 SDNode *Node = Op.getNode();
Duncan Sands83ec4b62008-06-06 12:08:01 +0000850 MVT VT = Node->getValueType(0);
Dan Gohman475871a2008-07-27 21:46:04 +0000851 SDValue InChain = Node->getOperand(0);
852 SDValue VAListPtr = Node->getOperand(1);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000853 const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
Dale Johannesen33c960f2009-02-04 20:06:27 +0000854 DebugLoc dl = Node->getDebugLoc();
855 SDValue VAList = DAG.getLoad(MVT::i32, dl, InChain, VAListPtr, SV, 0);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000856 // Increment the pointer, VAList, to the next vaarg
Dale Johannesen33c960f2009-02-04 20:06:27 +0000857 SDValue NextPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, VAList,
Duncan Sands83ec4b62008-06-06 12:08:01 +0000858 DAG.getConstant(VT.getSizeInBits()/8,
Chris Lattnerd23405e2008-03-17 03:21:36 +0000859 MVT::i32));
860 // Store the incremented VAList to the legalized pointer
Dale Johannesen33c960f2009-02-04 20:06:27 +0000861 InChain = DAG.getStore(VAList.getValue(1), dl, NextPtr,
Chris Lattnerd23405e2008-03-17 03:21:36 +0000862 VAListPtr, SV, 0);
863 // Load the actual argument out of the pointer VAList, unless this is an
864 // f64 load.
865 if (VT != MVT::f64)
Dale Johannesen33c960f2009-02-04 20:06:27 +0000866 return DAG.getLoad(VT, dl, InChain, VAList, NULL, 0);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000867
Chris Lattnerd23405e2008-03-17 03:21:36 +0000868 // Otherwise, load it as i64, then do a bitconvert.
Dale Johannesen33c960f2009-02-04 20:06:27 +0000869 SDValue V = DAG.getLoad(MVT::i64, dl, InChain, VAList, NULL, 0);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000870
Chris Lattnerd23405e2008-03-17 03:21:36 +0000871 // Bit-Convert the value to f64.
Dan Gohman475871a2008-07-27 21:46:04 +0000872 SDValue Ops[2] = {
Dale Johannesen33c960f2009-02-04 20:06:27 +0000873 DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, V),
Chris Lattnerd23405e2008-03-17 03:21:36 +0000874 V.getValue(1)
875 };
Dale Johannesen33c960f2009-02-04 20:06:27 +0000876 return DAG.getMergeValues(Ops, 2, dl);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000877}
878
Dan Gohman475871a2008-07-27 21:46:04 +0000879static SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) {
880 SDValue Chain = Op.getOperand(0); // Legalize the chain.
881 SDValue Size = Op.getOperand(1); // Legalize the size.
Dale Johannesena05dca42009-02-04 23:02:30 +0000882 DebugLoc dl = Op.getDebugLoc();
Anton Korobeynikov53835702008-10-10 20:27:31 +0000883
Chris Lattnerd23405e2008-03-17 03:21:36 +0000884 unsigned SPReg = SP::O6;
Dale Johannesena05dca42009-02-04 23:02:30 +0000885 SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, MVT::i32);
886 SDValue NewSP = DAG.getNode(ISD::SUB, dl, MVT::i32, SP, Size); // Value
887 Chain = DAG.getCopyToReg(SP.getValue(1), dl, SPReg, NewSP); // Output chain
Anton Korobeynikov53835702008-10-10 20:27:31 +0000888
Chris Lattnerd23405e2008-03-17 03:21:36 +0000889 // The resultant pointer is actually 16 words from the bottom of the stack,
890 // to provide a register spill area.
Dale Johannesena05dca42009-02-04 23:02:30 +0000891 SDValue NewVal = DAG.getNode(ISD::ADD, dl, MVT::i32, NewSP,
Chris Lattnerd23405e2008-03-17 03:21:36 +0000892 DAG.getConstant(96, MVT::i32));
Dan Gohman475871a2008-07-27 21:46:04 +0000893 SDValue Ops[2] = { NewVal, Chain };
Dale Johannesena05dca42009-02-04 23:02:30 +0000894 return DAG.getMergeValues(Ops, 2, dl);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000895}
896
Chris Lattnerd23405e2008-03-17 03:21:36 +0000897
Dan Gohman475871a2008-07-27 21:46:04 +0000898SDValue SparcTargetLowering::
899LowerOperation(SDValue Op, SelectionDAG &DAG) {
Chris Lattnerd23405e2008-03-17 03:21:36 +0000900 switch (Op.getOpcode()) {
901 default: assert(0 && "Should not custom lower this!");
902 // Frame & Return address. Currently unimplemented
Dan Gohman475871a2008-07-27 21:46:04 +0000903 case ISD::RETURNADDR: return SDValue();
904 case ISD::FRAMEADDR: return SDValue();
Chris Lattnerd23405e2008-03-17 03:21:36 +0000905 case ISD::GlobalTLSAddress:
906 assert(0 && "TLS not implemented for Sparc.");
907 case ISD::GlobalAddress: return LowerGLOBALADDRESS(Op, DAG);
908 case ISD::ConstantPool: return LowerCONSTANTPOOL(Op, DAG);
909 case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG);
910 case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG);
911 case ISD::BR_CC: return LowerBR_CC(Op, DAG);
912 case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
913 case ISD::VASTART: return LowerVASTART(Op, DAG, *this);
914 case ISD::VAARG: return LowerVAARG(Op, DAG);
915 case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
Chris Lattner98949a62008-03-17 06:01:07 +0000916 case ISD::CALL: return LowerCALL(Op, DAG);
Chris Lattnerd23405e2008-03-17 03:21:36 +0000917 case ISD::RET: return LowerRET(Op, DAG);
918 }
919}
920
921MachineBasicBlock *
922SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
923 MachineBasicBlock *BB) {
924 const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
925 unsigned BROpcode;
926 unsigned CC;
927 // Figure out the conditional branch opcode to use for this select_cc.
928 switch (MI->getOpcode()) {
929 default: assert(0 && "Unknown SELECT_CC!");
930 case SP::SELECT_CC_Int_ICC:
931 case SP::SELECT_CC_FP_ICC:
932 case SP::SELECT_CC_DFP_ICC:
933 BROpcode = SP::BCOND;
934 break;
935 case SP::SELECT_CC_Int_FCC:
936 case SP::SELECT_CC_FP_FCC:
937 case SP::SELECT_CC_DFP_FCC:
938 BROpcode = SP::FBCOND;
939 break;
940 }
941
942 CC = (SPCC::CondCodes)MI->getOperand(3).getImm();
Anton Korobeynikov53835702008-10-10 20:27:31 +0000943
Chris Lattnerd23405e2008-03-17 03:21:36 +0000944 // To "insert" a SELECT_CC instruction, we actually have to insert the diamond
945 // control-flow pattern. The incoming instruction knows the destination vreg
946 // to set, the condition code register to branch on, the true/false values to
947 // select between, and a branch opcode to use.
948 const BasicBlock *LLVM_BB = BB->getBasicBlock();
Dan Gohman8e5f2c62008-07-07 23:14:23 +0000949 MachineFunction::iterator It = BB;
Chris Lattnerd23405e2008-03-17 03:21:36 +0000950 ++It;
Anton Korobeynikov53835702008-10-10 20:27:31 +0000951
Chris Lattnerd23405e2008-03-17 03:21:36 +0000952 // thisMBB:
953 // ...
954 // TrueVal = ...
955 // [f]bCC copy1MBB
956 // fallthrough --> copy0MBB
957 MachineBasicBlock *thisMBB = BB;
Chris Lattnerd23405e2008-03-17 03:21:36 +0000958 MachineFunction *F = BB->getParent();
Dan Gohman8e5f2c62008-07-07 23:14:23 +0000959 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
960 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
961 BuildMI(BB, TII.get(BROpcode)).addMBB(sinkMBB).addImm(CC);
962 F->insert(It, copy0MBB);
963 F->insert(It, sinkMBB);
Dan Gohman0011dc42008-06-21 20:21:19 +0000964 // Update machine-CFG edges by transferring all successors of the current
Chris Lattnerd23405e2008-03-17 03:21:36 +0000965 // block to the new block which will contain the Phi node for the select.
Dan Gohman0011dc42008-06-21 20:21:19 +0000966 sinkMBB->transferSuccessors(BB);
967 // Next, add the true and fallthrough blocks as its successors.
Chris Lattnerd23405e2008-03-17 03:21:36 +0000968 BB->addSuccessor(copy0MBB);
969 BB->addSuccessor(sinkMBB);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000970
Chris Lattnerd23405e2008-03-17 03:21:36 +0000971 // copy0MBB:
972 // %FalseValue = ...
973 // # fallthrough to sinkMBB
974 BB = copy0MBB;
Anton Korobeynikov53835702008-10-10 20:27:31 +0000975
Chris Lattnerd23405e2008-03-17 03:21:36 +0000976 // Update machine-CFG edges
977 BB->addSuccessor(sinkMBB);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000978
Chris Lattnerd23405e2008-03-17 03:21:36 +0000979 // sinkMBB:
980 // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
981 // ...
982 BB = sinkMBB;
983 BuildMI(BB, TII.get(SP::PHI), MI->getOperand(0).getReg())
984 .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB)
985 .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB);
Anton Korobeynikov53835702008-10-10 20:27:31 +0000986
Dan Gohman8e5f2c62008-07-07 23:14:23 +0000987 F->DeleteMachineInstr(MI); // The pseudo instruction is gone now.
Chris Lattnerd23405e2008-03-17 03:21:36 +0000988 return BB;
989}
Anton Korobeynikov0eefda12008-10-10 20:28:10 +0000990
991//===----------------------------------------------------------------------===//
992// Sparc Inline Assembly Support
993//===----------------------------------------------------------------------===//
994
995/// getConstraintType - Given a constraint letter, return the type of
996/// constraint it is for this target.
997SparcTargetLowering::ConstraintType
998SparcTargetLowering::getConstraintType(const std::string &Constraint) const {
999 if (Constraint.size() == 1) {
1000 switch (Constraint[0]) {
1001 default: break;
1002 case 'r': return C_RegisterClass;
1003 }
1004 }
1005
1006 return TargetLowering::getConstraintType(Constraint);
1007}
1008
1009std::pair<unsigned, const TargetRegisterClass*>
1010SparcTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint,
1011 MVT VT) const {
1012 if (Constraint.size() == 1) {
1013 switch (Constraint[0]) {
1014 case 'r':
1015 return std::make_pair(0U, SP::IntRegsRegisterClass);
1016 }
1017 }
1018
1019 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
1020}
1021
1022std::vector<unsigned> SparcTargetLowering::
1023getRegClassForInlineAsmConstraint(const std::string &Constraint,
1024 MVT VT) const {
1025 if (Constraint.size() != 1)
1026 return std::vector<unsigned>();
1027
1028 switch (Constraint[0]) {
1029 default: break;
1030 case 'r':
1031 return make_vector<unsigned>(SP::L0, SP::L1, SP::L2, SP::L3,
1032 SP::L4, SP::L5, SP::L6, SP::L7,
1033 SP::I0, SP::I1, SP::I2, SP::I3,
1034 SP::I4, SP::I5,
1035 SP::O0, SP::O1, SP::O2, SP::O3,
1036 SP::O4, SP::O5, SP::O7, 0);
1037 }
1038
1039 return std::vector<unsigned>();
1040}
Dan Gohman6520e202008-10-18 02:06:02 +00001041
1042bool
1043SparcTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
1044 // The Sparc target isn't yet aware of offsets.
1045 return false;
1046}