blob: ec19c38e0dcfc8257fc98be2a7e896357a6887a7 [file] [log] [blame]
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +00001//===-- MSP430ISelLowering.cpp - MSP430 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 MSP430TargetLowering class.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "msp430-lower"
15
16#include "MSP430ISelLowering.h"
17#include "MSP430.h"
18#include "MSP430TargetMachine.h"
19#include "MSP430Subtarget.h"
20#include "llvm/DerivedTypes.h"
21#include "llvm/Function.h"
22#include "llvm/Intrinsics.h"
23#include "llvm/CallingConv.h"
24#include "llvm/GlobalVariable.h"
25#include "llvm/GlobalAlias.h"
26#include "llvm/CodeGen/CallingConvLower.h"
27#include "llvm/CodeGen/MachineFrameInfo.h"
28#include "llvm/CodeGen/MachineFunction.h"
29#include "llvm/CodeGen/MachineInstrBuilder.h"
30#include "llvm/CodeGen/MachineRegisterInfo.h"
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +000031#include "llvm/CodeGen/PseudoSourceValue.h"
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +000032#include "llvm/CodeGen/SelectionDAGISel.h"
33#include "llvm/CodeGen/ValueTypes.h"
Chris Lattnerf0144122009-07-28 03:13:23 +000034#include "llvm/Target/TargetLoweringObjectFile.h"
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +000035#include "llvm/Support/Debug.h"
Torok Edwin804e0fe2009-07-08 19:04:27 +000036#include "llvm/Support/ErrorHandling.h"
Chris Lattner4437ae22009-08-23 07:05:07 +000037#include "llvm/Support/raw_ostream.h"
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +000038#include "llvm/ADT/VectorExtras.h"
39using namespace llvm;
40
41MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) :
Chris Lattnerf0144122009-07-28 03:13:23 +000042 TargetLowering(tm, new TargetLoweringObjectFileELF()),
43 Subtarget(*tm.getSubtargetImpl()), TM(tm) {
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +000044
45 // Set up the register classes.
Owen Anderson825b72b2009-08-11 20:47:22 +000046 addRegisterClass(MVT::i8, MSP430::GR8RegisterClass);
47 addRegisterClass(MVT::i16, MSP430::GR16RegisterClass);
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +000048
49 // Compute derived properties from the register classes
50 computeRegisterProperties();
Anton Korobeynikovfd1b7c72009-05-03 12:59:50 +000051
Anton Korobeynikov1476d972009-05-03 13:03:14 +000052 // Provide all sorts of operation actions
53
54 // Division is expensive
55 setIntDivIsCheap(false);
56
Anton Korobeynikovd2c94ae2009-05-03 13:03:33 +000057 // Even if we have only 1 bit shift here, we can perform
58 // shifts of the whole bitwidth 1 bit per step.
Owen Anderson825b72b2009-08-11 20:47:22 +000059 setShiftAmountType(MVT::i8);
Anton Korobeynikovd2c94ae2009-05-03 13:03:33 +000060
Anton Korobeynikovc08163e2009-05-03 13:11:35 +000061 setStackPointerRegisterToSaveRestore(MSP430::SPW);
62 setBooleanContents(ZeroOrOneBooleanContent);
63 setSchedulingPreference(SchedulingForLatency);
64
Owen Anderson825b72b2009-08-11 20:47:22 +000065 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
66 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
67 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
68 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand);
69 setLoadExtAction(ISD::SEXTLOAD, MVT::i16, Expand);
Anton Korobeynikov36b6e532009-05-03 13:06:03 +000070
Anton Korobeynikov54f30d32009-05-03 13:06:26 +000071 // We don't have any truncstores
Owen Anderson825b72b2009-08-11 20:47:22 +000072 setTruncStoreAction(MVT::i16, MVT::i8, Expand);
Anton Korobeynikov54f30d32009-05-03 13:06:26 +000073
Owen Anderson825b72b2009-08-11 20:47:22 +000074 setOperationAction(ISD::SRA, MVT::i8, Custom);
75 setOperationAction(ISD::SHL, MVT::i8, Custom);
76 setOperationAction(ISD::SRL, MVT::i8, Custom);
77 setOperationAction(ISD::SRA, MVT::i16, Custom);
78 setOperationAction(ISD::SHL, MVT::i16, Custom);
79 setOperationAction(ISD::SRL, MVT::i16, Custom);
80 setOperationAction(ISD::ROTL, MVT::i8, Expand);
81 setOperationAction(ISD::ROTR, MVT::i8, Expand);
82 setOperationAction(ISD::ROTL, MVT::i16, Expand);
83 setOperationAction(ISD::ROTR, MVT::i16, Expand);
84 setOperationAction(ISD::GlobalAddress, MVT::i16, Custom);
85 setOperationAction(ISD::ExternalSymbol, MVT::i16, Custom);
86 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
87 setOperationAction(ISD::BRIND, MVT::Other, Expand);
88 setOperationAction(ISD::BR_CC, MVT::i8, Custom);
89 setOperationAction(ISD::BR_CC, MVT::i16, Custom);
90 setOperationAction(ISD::BRCOND, MVT::Other, Expand);
91 setOperationAction(ISD::SETCC, MVT::i8, Expand);
92 setOperationAction(ISD::SETCC, MVT::i16, Expand);
93 setOperationAction(ISD::SELECT, MVT::i8, Expand);
94 setOperationAction(ISD::SELECT, MVT::i16, Expand);
95 setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
96 setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
97 setOperationAction(ISD::SIGN_EXTEND, MVT::i16, Custom);
Anton Korobeynikov8725bd22009-05-03 13:14:25 +000098
Owen Anderson825b72b2009-08-11 20:47:22 +000099 setOperationAction(ISD::CTTZ, MVT::i8, Expand);
100 setOperationAction(ISD::CTTZ, MVT::i16, Expand);
101 setOperationAction(ISD::CTLZ, MVT::i8, Expand);
102 setOperationAction(ISD::CTLZ, MVT::i16, Expand);
103 setOperationAction(ISD::CTPOP, MVT::i8, Expand);
104 setOperationAction(ISD::CTPOP, MVT::i16, Expand);
Eli Friedmane4ce8802009-07-17 07:28:06 +0000105
Owen Anderson825b72b2009-08-11 20:47:22 +0000106 setOperationAction(ISD::SHL_PARTS, MVT::i8, Expand);
107 setOperationAction(ISD::SHL_PARTS, MVT::i16, Expand);
108 setOperationAction(ISD::SRL_PARTS, MVT::i8, Expand);
109 setOperationAction(ISD::SRL_PARTS, MVT::i16, Expand);
110 setOperationAction(ISD::SRA_PARTS, MVT::i8, Expand);
111 setOperationAction(ISD::SRA_PARTS, MVT::i16, Expand);
Eli Friedmane4ce8802009-07-17 07:28:06 +0000112
Owen Anderson825b72b2009-08-11 20:47:22 +0000113 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Eli Friedmane4ce8802009-07-17 07:28:06 +0000114
Anton Korobeynikov8725bd22009-05-03 13:14:25 +0000115 // FIXME: Implement efficiently multiplication by a constant
Owen Anderson825b72b2009-08-11 20:47:22 +0000116 setOperationAction(ISD::MUL, MVT::i16, Expand);
117 setOperationAction(ISD::MULHS, MVT::i16, Expand);
118 setOperationAction(ISD::MULHU, MVT::i16, Expand);
119 setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand);
120 setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand);
Anton Korobeynikovf2f54022009-05-03 13:18:33 +0000121
Owen Anderson825b72b2009-08-11 20:47:22 +0000122 setOperationAction(ISD::UDIV, MVT::i16, Expand);
123 setOperationAction(ISD::UDIVREM, MVT::i16, Expand);
124 setOperationAction(ISD::UREM, MVT::i16, Expand);
125 setOperationAction(ISD::SDIV, MVT::i16, Expand);
126 setOperationAction(ISD::SDIVREM, MVT::i16, Expand);
127 setOperationAction(ISD::SREM, MVT::i16, Expand);
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000128}
129
Anton Korobeynikovb8639f52009-05-03 13:03:50 +0000130SDValue MSP430TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000131 switch (Op.getOpcode()) {
Anton Korobeynikovea54c982009-05-03 13:13:17 +0000132 case ISD::SHL: // FALLTHROUGH
Anton Korobeynikove699d0f2009-05-03 13:16:17 +0000133 case ISD::SRL:
Anton Korobeynikov44288852009-05-03 13:07:31 +0000134 case ISD::SRA: return LowerShifts(Op, DAG);
Anton Korobeynikov3513ca82009-05-03 13:08:33 +0000135 case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
Anton Korobeynikov5d59f682009-05-03 13:14:46 +0000136 case ISD::ExternalSymbol: return LowerExternalSymbol(Op, DAG);
Anton Korobeynikov1bb8cd72009-05-03 13:19:09 +0000137 case ISD::BR_CC: return LowerBR_CC(Op, DAG);
138 case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
Anton Korobeynikovb78e2142009-05-03 13:17:49 +0000139 case ISD::SIGN_EXTEND: return LowerSIGN_EXTEND(Op, DAG);
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000140 default:
Torok Edwinc23197a2009-07-14 16:55:14 +0000141 llvm_unreachable("unimplemented operand");
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000142 return SDValue();
143 }
144}
145
Bill Wendlingb4202b82009-07-01 18:50:55 +0000146/// getFunctionAlignment - Return the Log2 alignment of this function.
Bill Wendling20c568f2009-06-30 22:38:32 +0000147unsigned MSP430TargetLowering::getFunctionAlignment(const Function *F) const {
148 return F->hasFnAttr(Attribute::OptimizeForSize) ? 1 : 4;
149}
150
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000151//===----------------------------------------------------------------------===//
152// Calling Convention Implementation
153//===----------------------------------------------------------------------===//
154
Anton Korobeynikovf2c3e172009-05-03 12:57:15 +0000155#include "MSP430GenCallingConv.inc"
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000156
Dan Gohman98ca4f22009-08-05 01:29:28 +0000157SDValue
158MSP430TargetLowering::LowerFormalArguments(SDValue Chain,
159 unsigned CallConv,
160 bool isVarArg,
161 const SmallVectorImpl<ISD::InputArg>
162 &Ins,
163 DebugLoc dl,
164 SelectionDAG &DAG,
165 SmallVectorImpl<SDValue> &InVals) {
166
167 switch (CallConv) {
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000168 default:
Torok Edwinc23197a2009-07-14 16:55:14 +0000169 llvm_unreachable("Unsupported calling convention");
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000170 case CallingConv::C:
171 case CallingConv::Fast:
Dan Gohman98ca4f22009-08-05 01:29:28 +0000172 return LowerCCCArguments(Chain, CallConv, isVarArg, Ins, dl, DAG, InVals);
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000173 }
174}
175
Dan Gohman98ca4f22009-08-05 01:29:28 +0000176SDValue
177MSP430TargetLowering::LowerCall(SDValue Chain, SDValue Callee,
178 unsigned CallConv, bool isVarArg,
179 bool isTailCall,
180 const SmallVectorImpl<ISD::OutputArg> &Outs,
181 const SmallVectorImpl<ISD::InputArg> &Ins,
182 DebugLoc dl, SelectionDAG &DAG,
183 SmallVectorImpl<SDValue> &InVals) {
184
185 switch (CallConv) {
Anton Korobeynikov44288852009-05-03 13:07:31 +0000186 default:
Torok Edwinc23197a2009-07-14 16:55:14 +0000187 llvm_unreachable("Unsupported calling convention");
Anton Korobeynikov44288852009-05-03 13:07:31 +0000188 case CallingConv::Fast:
189 case CallingConv::C:
Dan Gohman98ca4f22009-08-05 01:29:28 +0000190 return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall,
191 Outs, Ins, dl, DAG, InVals);
Anton Korobeynikov44288852009-05-03 13:07:31 +0000192 }
193}
194
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000195/// LowerCCCArguments - transform physical registers into virtual registers and
196/// generate load operations for arguments places on the stack.
197// FIXME: struct return stuff
198// FIXME: varargs
Dan Gohman98ca4f22009-08-05 01:29:28 +0000199SDValue
200MSP430TargetLowering::LowerCCCArguments(SDValue Chain,
201 unsigned CallConv,
202 bool isVarArg,
203 const SmallVectorImpl<ISD::InputArg>
204 &Ins,
205 DebugLoc dl,
206 SelectionDAG &DAG,
207 SmallVectorImpl<SDValue> &InVals) {
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000208 MachineFunction &MF = DAG.getMachineFunction();
209 MachineFrameInfo *MFI = MF.getFrameInfo();
210 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000211
212 // Assign locations to all of the incoming arguments.
213 SmallVector<CCValAssign, 16> ArgLocs;
Dan Gohman98ca4f22009-08-05 01:29:28 +0000214 CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
215 ArgLocs, *DAG.getContext());
216 CCInfo.AnalyzeFormalArguments(Ins, CC_MSP430);
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000217
218 assert(!isVarArg && "Varargs not supported yet");
219
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000220 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
221 CCValAssign &VA = ArgLocs[i];
222 if (VA.isRegLoc()) {
223 // Arguments passed in registers
Owen Andersone50ed302009-08-10 22:56:29 +0000224 EVT RegVT = VA.getLocVT();
Owen Anderson825b72b2009-08-11 20:47:22 +0000225 switch (RegVT.getSimpleVT().SimpleTy) {
Torok Edwin804e0fe2009-07-08 19:04:27 +0000226 default:
227 {
Torok Edwindac237e2009-07-08 20:53:28 +0000228#ifndef NDEBUG
Chris Lattner4437ae22009-08-23 07:05:07 +0000229 errs() << "LowerFormalArguments Unhandled argument type: "
Owen Anderson825b72b2009-08-11 20:47:22 +0000230 << RegVT.getSimpleVT().SimpleTy << "\n";
Torok Edwindac237e2009-07-08 20:53:28 +0000231#endif
Torok Edwinc23197a2009-07-14 16:55:14 +0000232 llvm_unreachable(0);
Torok Edwin804e0fe2009-07-08 19:04:27 +0000233 }
Owen Anderson825b72b2009-08-11 20:47:22 +0000234 case MVT::i16:
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000235 unsigned VReg =
Anton Korobeynikov1df221f2009-05-03 13:02:04 +0000236 RegInfo.createVirtualRegister(MSP430::GR16RegisterClass);
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000237 RegInfo.addLiveIn(VA.getLocReg(), VReg);
Dan Gohman98ca4f22009-08-05 01:29:28 +0000238 SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000239
240 // If this is an 8-bit value, it is really passed promoted to 16
241 // bits. Insert an assert[sz]ext to capture this, then truncate to the
242 // right size.
243 if (VA.getLocInfo() == CCValAssign::SExt)
244 ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue,
245 DAG.getValueType(VA.getValVT()));
246 else if (VA.getLocInfo() == CCValAssign::ZExt)
247 ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue,
248 DAG.getValueType(VA.getValVT()));
249
250 if (VA.getLocInfo() != CCValAssign::Full)
251 ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
252
Dan Gohman98ca4f22009-08-05 01:29:28 +0000253 InVals.push_back(ArgValue);
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000254 }
255 } else {
256 // Sanity check
257 assert(VA.isMemLoc());
258 // Load the argument to a virtual register
259 unsigned ObjSize = VA.getLocVT().getSizeInBits()/8;
260 if (ObjSize > 2) {
Chris Lattner4437ae22009-08-23 07:05:07 +0000261 errs() << "LowerFormalArguments Unhandled argument type: "
Owen Anderson825b72b2009-08-11 20:47:22 +0000262 << VA.getLocVT().getSimpleVT().SimpleTy
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000263 << "\n";
264 }
265 // Create the frame index object for this incoming parameter...
266 int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset());
267
268 // Create the SelectionDAG nodes corresponding to a load
269 //from this parameter
Owen Anderson825b72b2009-08-11 20:47:22 +0000270 SDValue FIN = DAG.getFrameIndex(FI, MVT::i16);
Dan Gohman98ca4f22009-08-05 01:29:28 +0000271 InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
272 PseudoSourceValue::getFixedStack(FI), 0));
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000273 }
274 }
275
Dan Gohman98ca4f22009-08-05 01:29:28 +0000276 return Chain;
Anton Korobeynikovc8fbb6a2009-05-03 12:59:33 +0000277}
Anton Korobeynikovfd1b7c72009-05-03 12:59:50 +0000278
Dan Gohman98ca4f22009-08-05 01:29:28 +0000279SDValue
280MSP430TargetLowering::LowerReturn(SDValue Chain,
281 unsigned CallConv, bool isVarArg,
282 const SmallVectorImpl<ISD::OutputArg> &Outs,
283 DebugLoc dl, SelectionDAG &DAG) {
284
Anton Korobeynikovfd1b7c72009-05-03 12:59:50 +0000285 // CCValAssign - represent the assignment of the return value to a location
286 SmallVector<CCValAssign, 16> RVLocs;
Anton Korobeynikovfd1b7c72009-05-03 12:59:50 +0000287
288 // CCState - Info about the registers and stack slot.
Dan Gohman98ca4f22009-08-05 01:29:28 +0000289 CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
290 RVLocs, *DAG.getContext());
Anton Korobeynikovfd1b7c72009-05-03 12:59:50 +0000291
Dan Gohman98ca4f22009-08-05 01:29:28 +0000292 // Analize return values.
293 CCInfo.AnalyzeReturn(Outs, RetCC_MSP430);
Anton Korobeynikovfd1b7c72009-05-03 12:59:50 +0000294
295 // If this is the first return lowered for this function, add the regs to the
296 // liveout set for the function.
297 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
298 for (unsigned i = 0; i != RVLocs.size(); ++i)
299 if (RVLocs[i].isRegLoc())
300 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
301 }
302
Anton Korobeynikovfd1b7c72009-05-03 12:59:50 +0000303 SDValue Flag;
304
305 // Copy the result values into the output registers.
306 for (unsigned i = 0; i != RVLocs.size(); ++i) {
307 CCValAssign &VA = RVLocs[i];
308 assert(VA.isRegLoc() && "Can only return in registers!");
309
Anton Korobeynikovfd1b7c72009-05-03 12:59:50 +0000310 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
Dan Gohman98ca4f22009-08-05 01:29:28 +0000311 Outs[i].Val, Flag);
Anton Korobeynikovfd1b7c72009-05-03 12:59:50 +0000312
Anton Korobeynikovdcb802c2009-05-03 13:00:11 +0000313 // Guarantee that all emitted copies are stuck together,
314 // avoiding something bad.
Anton Korobeynikovfd1b7c72009-05-03 12:59:50 +0000315 Flag = Chain.getValue(1);
316 }
317
318 if (Flag.getNode())
Owen Anderson825b72b2009-08-11 20:47:22 +0000319 return DAG.getNode(MSP430ISD::RET_FLAG, dl, MVT::Other, Chain, Flag);
Anton Korobeynikovfd1b7c72009-05-03 12:59:50 +0000320
321 // Return Void
Owen Anderson825b72b2009-08-11 20:47:22 +0000322 return DAG.getNode(MSP430ISD::RET_FLAG, dl, MVT::Other, Chain);
Anton Korobeynikovfd1b7c72009-05-03 12:59:50 +0000323}
324
Anton Korobeynikov44288852009-05-03 13:07:31 +0000325/// LowerCCCCallTo - functions arguments are copied from virtual regs to
326/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
327/// TODO: sret.
Dan Gohman98ca4f22009-08-05 01:29:28 +0000328SDValue
329MSP430TargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee,
330 unsigned CallConv, bool isVarArg,
331 bool isTailCall,
332 const SmallVectorImpl<ISD::OutputArg>
333 &Outs,
334 const SmallVectorImpl<ISD::InputArg> &Ins,
335 DebugLoc dl, SelectionDAG &DAG,
336 SmallVectorImpl<SDValue> &InVals) {
Anton Korobeynikov44288852009-05-03 13:07:31 +0000337 // Analyze operands of the call, assigning locations to each operand.
338 SmallVector<CCValAssign, 16> ArgLocs;
Dan Gohman98ca4f22009-08-05 01:29:28 +0000339 CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
340 ArgLocs, *DAG.getContext());
Anton Korobeynikov44288852009-05-03 13:07:31 +0000341
Dan Gohman98ca4f22009-08-05 01:29:28 +0000342 CCInfo.AnalyzeCallOperands(Outs, CC_MSP430);
Anton Korobeynikov44288852009-05-03 13:07:31 +0000343
344 // Get a count of how many bytes are to be pushed on the stack.
345 unsigned NumBytes = CCInfo.getNextStackOffset();
346
347 Chain = DAG.getCALLSEQ_START(Chain ,DAG.getConstant(NumBytes,
348 getPointerTy(), true));
349
350 SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
351 SmallVector<SDValue, 12> MemOpChains;
352 SDValue StackPtr;
353
354 // Walk the register/memloc assignments, inserting copies/loads.
355 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
356 CCValAssign &VA = ArgLocs[i];
357
Dan Gohman98ca4f22009-08-05 01:29:28 +0000358 SDValue Arg = Outs[i].Val;
Anton Korobeynikov44288852009-05-03 13:07:31 +0000359
360 // Promote the value if needed.
361 switch (VA.getLocInfo()) {
Torok Edwinc23197a2009-07-14 16:55:14 +0000362 default: llvm_unreachable("Unknown loc info!");
Anton Korobeynikov44288852009-05-03 13:07:31 +0000363 case CCValAssign::Full: break;
364 case CCValAssign::SExt:
365 Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
366 break;
367 case CCValAssign::ZExt:
368 Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
369 break;
370 case CCValAssign::AExt:
371 Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
372 break;
373 }
374
375 // Arguments that can be passed on register must be kept at RegsToPass
376 // vector
377 if (VA.isRegLoc()) {
378 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
379 } else {
380 assert(VA.isMemLoc());
381
382 if (StackPtr.getNode() == 0)
383 StackPtr = DAG.getCopyFromReg(Chain, dl, MSP430::SPW, getPointerTy());
384
385 SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(),
386 StackPtr,
387 DAG.getIntPtrConstant(VA.getLocMemOffset()));
388
389
390 MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
391 PseudoSourceValue::getStack(),
392 VA.getLocMemOffset()));
393 }
394 }
395
396 // Transform all store nodes into one single node because all store nodes are
397 // independent of each other.
398 if (!MemOpChains.empty())
Owen Anderson825b72b2009-08-11 20:47:22 +0000399 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
Anton Korobeynikov44288852009-05-03 13:07:31 +0000400 &MemOpChains[0], MemOpChains.size());
401
402 // Build a sequence of copy-to-reg nodes chained together with token chain and
403 // flag operands which copy the outgoing args into registers. The InFlag in
404 // necessary since all emited instructions must be stuck together.
405 SDValue InFlag;
406 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
407 Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
408 RegsToPass[i].second, InFlag);
409 InFlag = Chain.getValue(1);
410 }
411
412 // If the callee is a GlobalAddress node (quite common, every direct call is)
413 // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
414 // Likewise ExternalSymbol -> TargetExternalSymbol.
415 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
Owen Anderson825b72b2009-08-11 20:47:22 +0000416 Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i16);
Anton Korobeynikov44288852009-05-03 13:07:31 +0000417 else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
Owen Anderson825b72b2009-08-11 20:47:22 +0000418 Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i16);
Anton Korobeynikov44288852009-05-03 13:07:31 +0000419
420 // Returns a chain & a flag for retval copy to use.
Owen Anderson825b72b2009-08-11 20:47:22 +0000421 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
Anton Korobeynikov44288852009-05-03 13:07:31 +0000422 SmallVector<SDValue, 8> Ops;
423 Ops.push_back(Chain);
424 Ops.push_back(Callee);
425
426 // Add argument registers to the end of the list so that they are
427 // known live into the call.
428 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
429 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
430 RegsToPass[i].second.getValueType()));
431
432 if (InFlag.getNode())
433 Ops.push_back(InFlag);
434
435 Chain = DAG.getNode(MSP430ISD::CALL, dl, NodeTys, &Ops[0], Ops.size());
436 InFlag = Chain.getValue(1);
437
438 // Create the CALLSEQ_END node.
439 Chain = DAG.getCALLSEQ_END(Chain,
440 DAG.getConstant(NumBytes, getPointerTy(), true),
441 DAG.getConstant(0, getPointerTy(), true),
442 InFlag);
443 InFlag = Chain.getValue(1);
444
445 // Handle result values, copying them out of physregs into vregs that we
446 // return.
Dan Gohman98ca4f22009-08-05 01:29:28 +0000447 return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl,
448 DAG, InVals);
Anton Korobeynikov44288852009-05-03 13:07:31 +0000449}
450
Dan Gohman98ca4f22009-08-05 01:29:28 +0000451/// LowerCallResult - Lower the result values of a call into the
452/// appropriate copies out of appropriate physical registers.
453///
454SDValue
Anton Korobeynikov44288852009-05-03 13:07:31 +0000455MSP430TargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag,
Dan Gohman98ca4f22009-08-05 01:29:28 +0000456 unsigned CallConv, bool isVarArg,
457 const SmallVectorImpl<ISD::InputArg> &Ins,
458 DebugLoc dl, SelectionDAG &DAG,
459 SmallVectorImpl<SDValue> &InVals) {
Anton Korobeynikov44288852009-05-03 13:07:31 +0000460
461 // Assign locations to each value returned by this call.
462 SmallVector<CCValAssign, 16> RVLocs;
Dan Gohman98ca4f22009-08-05 01:29:28 +0000463 CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
Owen Andersone922c022009-07-22 00:24:57 +0000464 RVLocs, *DAG.getContext());
Anton Korobeynikov44288852009-05-03 13:07:31 +0000465
Dan Gohman98ca4f22009-08-05 01:29:28 +0000466 CCInfo.AnalyzeCallResult(Ins, RetCC_MSP430);
Anton Korobeynikov44288852009-05-03 13:07:31 +0000467
468 // Copy all of the result registers out of their specified physreg.
469 for (unsigned i = 0; i != RVLocs.size(); ++i) {
470 Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
471 RVLocs[i].getValVT(), InFlag).getValue(1);
472 InFlag = Chain.getValue(2);
Dan Gohman98ca4f22009-08-05 01:29:28 +0000473 InVals.push_back(Chain.getValue(0));
Anton Korobeynikov44288852009-05-03 13:07:31 +0000474 }
475
Dan Gohman98ca4f22009-08-05 01:29:28 +0000476 return Chain;
Anton Korobeynikov44288852009-05-03 13:07:31 +0000477}
478
Anton Korobeynikovd2c94ae2009-05-03 13:03:33 +0000479SDValue MSP430TargetLowering::LowerShifts(SDValue Op,
480 SelectionDAG &DAG) {
Anton Korobeynikovea54c982009-05-03 13:13:17 +0000481 unsigned Opc = Op.getOpcode();
Anton Korobeynikovd2c94ae2009-05-03 13:03:33 +0000482 SDNode* N = Op.getNode();
Owen Andersone50ed302009-08-10 22:56:29 +0000483 EVT VT = Op.getValueType();
Anton Korobeynikovd2c94ae2009-05-03 13:03:33 +0000484 DebugLoc dl = N->getDebugLoc();
485
Anton Korobeynikovea54c982009-05-03 13:13:17 +0000486 // We currently only lower shifts of constant argument.
Anton Korobeynikovd2c94ae2009-05-03 13:03:33 +0000487 if (!isa<ConstantSDNode>(N->getOperand(1)))
488 return SDValue();
489
490 uint64_t ShiftAmount = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
491
492 // Expand the stuff into sequence of shifts.
493 // FIXME: for some shift amounts this might be done better!
494 // E.g.: foo >> (8 + N) => sxt(swpb(foo)) >> N
495 SDValue Victim = N->getOperand(0);
Anton Korobeynikove699d0f2009-05-03 13:16:17 +0000496
497 if (Opc == ISD::SRL && ShiftAmount) {
498 // Emit a special goodness here:
499 // srl A, 1 => clrc; rrc A
Anton Korobeynikovbf8ef3f2009-05-03 13:16:37 +0000500 Victim = DAG.getNode(MSP430ISD::RRC, dl, VT, Victim);
Anton Korobeynikove699d0f2009-05-03 13:16:17 +0000501 ShiftAmount -= 1;
502 }
503
Anton Korobeynikovd2c94ae2009-05-03 13:03:33 +0000504 while (ShiftAmount--)
Anton Korobeynikovaceb6202009-05-17 10:15:22 +0000505 Victim = DAG.getNode((Opc == ISD::SHL ? MSP430ISD::RLA : MSP430ISD::RRA),
Anton Korobeynikovea54c982009-05-03 13:13:17 +0000506 dl, VT, Victim);
Anton Korobeynikovd2c94ae2009-05-03 13:03:33 +0000507
508 return Victim;
509}
510
Anton Korobeynikov3513ca82009-05-03 13:08:33 +0000511SDValue MSP430TargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) {
512 const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
513 int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset();
514
515 // Create the TargetGlobalAddress node, folding in the constant offset.
516 SDValue Result = DAG.getTargetGlobalAddress(GV, getPointerTy(), Offset);
517 return DAG.getNode(MSP430ISD::Wrapper, Op.getDebugLoc(),
518 getPointerTy(), Result);
519}
520
Anton Korobeynikov5d59f682009-05-03 13:14:46 +0000521SDValue MSP430TargetLowering::LowerExternalSymbol(SDValue Op,
522 SelectionDAG &DAG) {
523 DebugLoc dl = Op.getDebugLoc();
524 const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol();
525 SDValue Result = DAG.getTargetExternalSymbol(Sym, getPointerTy());
526
527 return DAG.getNode(MSP430ISD::Wrapper, dl, getPointerTy(), Result);;
528}
529
Anton Korobeynikov1bb8cd72009-05-03 13:19:09 +0000530static SDValue EmitCMP(SDValue &LHS, SDValue &RHS, unsigned &TargetCC,
531 ISD::CondCode CC,
532 DebugLoc dl, SelectionDAG &DAG) {
Anton Korobeynikoved1a51a2009-05-03 13:12:06 +0000533 // FIXME: Handle bittests someday
534 assert(!LHS.getValueType().isFloatingPoint() && "We don't handle FP yet");
535
536 // FIXME: Handle jump negative someday
Anton Korobeynikov1bb8cd72009-05-03 13:19:09 +0000537 TargetCC = MSP430::COND_INVALID;
Anton Korobeynikoved1a51a2009-05-03 13:12:06 +0000538 switch (CC) {
Torok Edwinc23197a2009-07-14 16:55:14 +0000539 default: llvm_unreachable("Invalid integer condition!");
Anton Korobeynikoved1a51a2009-05-03 13:12:06 +0000540 case ISD::SETEQ:
541 TargetCC = MSP430::COND_E; // aka COND_Z
542 break;
543 case ISD::SETNE:
544 TargetCC = MSP430::COND_NE; // aka COND_NZ
545 break;
546 case ISD::SETULE:
547 std::swap(LHS, RHS); // FALLTHROUGH
548 case ISD::SETUGE:
549 TargetCC = MSP430::COND_HS; // aka COND_C
550 break;
551 case ISD::SETUGT:
552 std::swap(LHS, RHS); // FALLTHROUGH
553 case ISD::SETULT:
554 TargetCC = MSP430::COND_LO; // aka COND_NC
555 break;
556 case ISD::SETLE:
557 std::swap(LHS, RHS); // FALLTHROUGH
558 case ISD::SETGE:
559 TargetCC = MSP430::COND_GE;
560 break;
561 case ISD::SETGT:
562 std::swap(LHS, RHS); // FALLTHROUGH
563 case ISD::SETLT:
564 TargetCC = MSP430::COND_L;
565 break;
566 }
567
Owen Anderson825b72b2009-08-11 20:47:22 +0000568 return DAG.getNode(MSP430ISD::CMP, dl, MVT::Flag, LHS, RHS);
Anton Korobeynikoved1a51a2009-05-03 13:12:06 +0000569}
570
Anton Korobeynikov1bb8cd72009-05-03 13:19:09 +0000571
572SDValue MSP430TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) {
Anton Korobeynikoved1a51a2009-05-03 13:12:06 +0000573 SDValue Chain = Op.getOperand(0);
Anton Korobeynikov1bb8cd72009-05-03 13:19:09 +0000574 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
575 SDValue LHS = Op.getOperand(2);
576 SDValue RHS = Op.getOperand(3);
577 SDValue Dest = Op.getOperand(4);
578 DebugLoc dl = Op.getDebugLoc();
Anton Korobeynikoved1a51a2009-05-03 13:12:06 +0000579
Anton Korobeynikov1bb8cd72009-05-03 13:19:09 +0000580 unsigned TargetCC = MSP430::COND_INVALID;
581 SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG);
Anton Korobeynikoved1a51a2009-05-03 13:12:06 +0000582
Anton Korobeynikov1bb8cd72009-05-03 13:19:09 +0000583 return DAG.getNode(MSP430ISD::BR_CC, dl, Op.getValueType(),
584 Chain,
Owen Anderson825b72b2009-08-11 20:47:22 +0000585 Dest, DAG.getConstant(TargetCC, MVT::i8),
Anton Korobeynikov1bb8cd72009-05-03 13:19:09 +0000586 Flag);
Anton Korobeynikoved1a51a2009-05-03 13:12:06 +0000587}
588
Anton Korobeynikov1bb8cd72009-05-03 13:19:09 +0000589SDValue MSP430TargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
590 SDValue LHS = Op.getOperand(0);
591 SDValue RHS = Op.getOperand(1);
592 SDValue TrueV = Op.getOperand(2);
593 SDValue FalseV = Op.getOperand(3);
594 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
Anton Korobeynikov8b528e52009-05-03 13:12:23 +0000595 DebugLoc dl = Op.getDebugLoc();
Anton Korobeynikov8b528e52009-05-03 13:12:23 +0000596
Anton Korobeynikov1bb8cd72009-05-03 13:19:09 +0000597 unsigned TargetCC = MSP430::COND_INVALID;
598 SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG);
Anton Korobeynikov8b528e52009-05-03 13:12:23 +0000599
Owen Anderson825b72b2009-08-11 20:47:22 +0000600 SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Flag);
Anton Korobeynikov8b528e52009-05-03 13:12:23 +0000601 SmallVector<SDValue, 4> Ops;
602 Ops.push_back(TrueV);
603 Ops.push_back(FalseV);
Owen Anderson825b72b2009-08-11 20:47:22 +0000604 Ops.push_back(DAG.getConstant(TargetCC, MVT::i8));
Anton Korobeynikov1bb8cd72009-05-03 13:19:09 +0000605 Ops.push_back(Flag);
Anton Korobeynikov8b528e52009-05-03 13:12:23 +0000606
Anton Korobeynikov1bb8cd72009-05-03 13:19:09 +0000607 return DAG.getNode(MSP430ISD::SELECT_CC, dl, VTs, &Ops[0], Ops.size());
Anton Korobeynikov8b528e52009-05-03 13:12:23 +0000608}
609
Anton Korobeynikovb78e2142009-05-03 13:17:49 +0000610SDValue MSP430TargetLowering::LowerSIGN_EXTEND(SDValue Op,
611 SelectionDAG &DAG) {
612 SDValue Val = Op.getOperand(0);
Owen Andersone50ed302009-08-10 22:56:29 +0000613 EVT VT = Op.getValueType();
Anton Korobeynikovb78e2142009-05-03 13:17:49 +0000614 DebugLoc dl = Op.getDebugLoc();
615
Owen Anderson825b72b2009-08-11 20:47:22 +0000616 assert(VT == MVT::i16 && "Only support i16 for now!");
Anton Korobeynikovb78e2142009-05-03 13:17:49 +0000617
618 return DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, VT,
619 DAG.getNode(ISD::ANY_EXTEND, dl, VT, Val),
620 DAG.getValueType(Val.getValueType()));
621}
622
Anton Korobeynikovfd1b7c72009-05-03 12:59:50 +0000623const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const {
624 switch (Opcode) {
625 default: return NULL;
626 case MSP430ISD::RET_FLAG: return "MSP430ISD::RET_FLAG";
Anton Korobeynikovd2c94ae2009-05-03 13:03:33 +0000627 case MSP430ISD::RRA: return "MSP430ISD::RRA";
Anton Korobeynikove699d0f2009-05-03 13:16:17 +0000628 case MSP430ISD::RLA: return "MSP430ISD::RLA";
629 case MSP430ISD::RRC: return "MSP430ISD::RRC";
Anton Korobeynikovb5612642009-05-03 13:07:54 +0000630 case MSP430ISD::CALL: return "MSP430ISD::CALL";
Anton Korobeynikov3513ca82009-05-03 13:08:33 +0000631 case MSP430ISD::Wrapper: return "MSP430ISD::Wrapper";
Anton Korobeynikov1bb8cd72009-05-03 13:19:09 +0000632 case MSP430ISD::BR_CC: return "MSP430ISD::BR_CC";
Anton Korobeynikoved1a51a2009-05-03 13:12:06 +0000633 case MSP430ISD::CMP: return "MSP430ISD::CMP";
Anton Korobeynikov1bb8cd72009-05-03 13:19:09 +0000634 case MSP430ISD::SELECT_CC: return "MSP430ISD::SELECT_CC";
Anton Korobeynikovfd1b7c72009-05-03 12:59:50 +0000635 }
636}
Anton Korobeynikov8b528e52009-05-03 13:12:23 +0000637
638//===----------------------------------------------------------------------===//
639// Other Lowering Code
640//===----------------------------------------------------------------------===//
641
642MachineBasicBlock*
643MSP430TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
644 MachineBasicBlock *BB) const {
645 const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
646 DebugLoc dl = MI->getDebugLoc();
Anton Korobeynikovda4d2f62009-05-08 18:51:21 +0000647 assert((MI->getOpcode() == MSP430::Select16 ||
648 MI->getOpcode() == MSP430::Select8) &&
Anton Korobeynikov8b528e52009-05-03 13:12:23 +0000649 "Unexpected instr type to insert");
650
651 // To "insert" a SELECT instruction, we actually have to insert the diamond
652 // control-flow pattern. The incoming instruction knows the destination vreg
653 // to set, the condition code register to branch on, the true/false values to
654 // select between, and a branch opcode to use.
655 const BasicBlock *LLVM_BB = BB->getBasicBlock();
656 MachineFunction::iterator I = BB;
657 ++I;
658
659 // thisMBB:
660 // ...
661 // TrueVal = ...
662 // cmpTY ccX, r1, r2
663 // jCC copy1MBB
664 // fallthrough --> copy0MBB
665 MachineBasicBlock *thisMBB = BB;
666 MachineFunction *F = BB->getParent();
667 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
668 MachineBasicBlock *copy1MBB = F->CreateMachineBasicBlock(LLVM_BB);
669 BuildMI(BB, dl, TII.get(MSP430::JCC))
670 .addMBB(copy1MBB)
671 .addImm(MI->getOperand(3).getImm());
672 F->insert(I, copy0MBB);
673 F->insert(I, copy1MBB);
674 // Update machine-CFG edges by transferring all successors of the current
675 // block to the new block which will contain the Phi node for the select.
676 copy1MBB->transferSuccessors(BB);
677 // Next, add the true and fallthrough blocks as its successors.
678 BB->addSuccessor(copy0MBB);
679 BB->addSuccessor(copy1MBB);
680
681 // copy0MBB:
682 // %FalseValue = ...
683 // # fallthrough to copy1MBB
684 BB = copy0MBB;
685
686 // Update machine-CFG edges
687 BB->addSuccessor(copy1MBB);
688
689 // copy1MBB:
690 // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
691 // ...
692 BB = copy1MBB;
693 BuildMI(BB, dl, TII.get(MSP430::PHI),
694 MI->getOperand(0).getReg())
695 .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB)
696 .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB);
697
698 F->DeleteMachineInstr(MI); // The pseudo instruction is gone now.
699 return BB;
700}