blob: cb2c62029454a1abf64793efdfaad230d4b5871f [file] [log] [blame]
Anton Korobeynikov10138002009-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
Anton Korobeynikov10138002009-05-03 12:57:15 +000014#include "MSP430ISelLowering.h"
15#include "MSP430.h"
Anton Korobeynikovff4ab512009-12-07 02:28:10 +000016#include "MSP430MachineFunctionInfo.h"
Anton Korobeynikov10138002009-05-03 12:57:15 +000017#include "MSP430Subtarget.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000018#include "MSP430TargetMachine.h"
Anton Korobeynikov10138002009-05-03 12:57:15 +000019#include "llvm/CodeGen/CallingConvLower.h"
20#include "llvm/CodeGen/MachineFrameInfo.h"
21#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/MachineInstrBuilder.h"
23#include "llvm/CodeGen/MachineRegisterInfo.h"
24#include "llvm/CodeGen/SelectionDAGISel.h"
Anton Korobeynikovab663a02010-02-15 22:37:53 +000025#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
Anton Korobeynikov10138002009-05-03 12:57:15 +000026#include "llvm/CodeGen/ValueTypes.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000027#include "llvm/IR/CallingConv.h"
28#include "llvm/IR/DerivedTypes.h"
29#include "llvm/IR/Function.h"
30#include "llvm/IR/GlobalAlias.h"
31#include "llvm/IR/GlobalVariable.h"
32#include "llvm/IR/Intrinsics.h"
Anton Korobeynikov28d3c732009-12-07 02:27:08 +000033#include "llvm/Support/CommandLine.h"
Anton Korobeynikov10138002009-05-03 12:57:15 +000034#include "llvm/Support/Debug.h"
Torok Edwinfa040022009-07-08 19:04:27 +000035#include "llvm/Support/ErrorHandling.h"
Chris Lattner317dbbc2009-08-23 07:05:07 +000036#include "llvm/Support/raw_ostream.h"
Anton Korobeynikov10138002009-05-03 12:57:15 +000037using namespace llvm;
38
Chandler Carruth84e68b22014-04-22 02:41:26 +000039#define DEBUG_TYPE "msp430-lower"
40
Anton Korobeynikov28d3c732009-12-07 02:27:08 +000041typedef enum {
42 NoHWMult,
43 HWMultIntr,
44 HWMultNoIntr
45} HWMultUseMode;
46
47static cl::opt<HWMultUseMode>
Nadav Rotem7f27e0b2013-10-18 23:38:13 +000048HWMultMode("msp430-hwmult-mode", cl::Hidden,
Anton Korobeynikov28d3c732009-12-07 02:27:08 +000049 cl::desc("Hardware multiplier use mode"),
50 cl::init(HWMultNoIntr),
51 cl::values(
52 clEnumValN(NoHWMult, "no",
53 "Do not use hardware multiplier"),
54 clEnumValN(HWMultIntr, "interrupts",
55 "Assume hardware multiplier can be used inside interrupts"),
56 clEnumValN(HWMultNoIntr, "use",
57 "Assume hardware multiplier cannot be used inside interrupts"),
58 clEnumValEnd));
59
Eric Christopher23a3a7c2015-02-26 00:00:24 +000060MSP430TargetLowering::MSP430TargetLowering(const TargetMachine &TM,
61 const MSP430Subtarget &STI)
Aditya Nandakumar30531552014-11-13 21:29:21 +000062 : TargetLowering(TM) {
Anton Korobeynikovff4ab512009-12-07 02:28:10 +000063
Anton Korobeynikov10138002009-05-03 12:57:15 +000064 // Set up the register classes.
Craig Topperc7242e02012-04-20 07:30:17 +000065 addRegisterClass(MVT::i8, &MSP430::GR8RegClass);
66 addRegisterClass(MVT::i16, &MSP430::GR16RegClass);
Anton Korobeynikov10138002009-05-03 12:57:15 +000067
68 // Compute derived properties from the register classes
Eric Christopher23a3a7c2015-02-26 00:00:24 +000069 computeRegisterProperties(STI.getRegisterInfo());
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +000070
Anton Korobeynikov55a085b2009-05-03 13:03:14 +000071 // Provide all sorts of operation actions
Job Noormaneb19aea2014-09-10 06:58:14 +000072 setStackPointerRegisterToSaveRestore(MSP430::SP);
Anton Korobeynikov7212c152009-05-03 13:11:35 +000073 setBooleanContents(ZeroOrOneBooleanContent);
Duncan Sandsf2641e12011-09-06 19:07:46 +000074 setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
Anton Korobeynikov7212c152009-05-03 13:11:35 +000075
Anton Korobeynikovcf84ab52009-11-07 17:15:25 +000076 // We have post-incremented loads / stores.
Anton Korobeynikovd3c83192009-11-07 17:15:06 +000077 setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal);
78 setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal);
79
Ahmed Bougacha2b6917b2015-01-08 00:51:32 +000080 for (MVT VT : MVT::integer_valuetypes()) {
81 setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote);
82 setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
83 setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote);
84 setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i8, Expand);
85 setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i16, Expand);
86 }
Anton Korobeynikov31ecd232009-05-03 13:06:03 +000087
Anton Korobeynikoved1c3df2009-05-03 13:06:26 +000088 // We don't have any truncstores
Owen Anderson9f944592009-08-11 20:47:22 +000089 setTruncStoreAction(MVT::i16, MVT::i8, Expand);
Anton Korobeynikoved1c3df2009-05-03 13:06:26 +000090
Owen Anderson9f944592009-08-11 20:47:22 +000091 setOperationAction(ISD::SRA, MVT::i8, Custom);
92 setOperationAction(ISD::SHL, MVT::i8, Custom);
93 setOperationAction(ISD::SRL, MVT::i8, Custom);
94 setOperationAction(ISD::SRA, MVT::i16, Custom);
95 setOperationAction(ISD::SHL, MVT::i16, Custom);
96 setOperationAction(ISD::SRL, MVT::i16, Custom);
97 setOperationAction(ISD::ROTL, MVT::i8, Expand);
98 setOperationAction(ISD::ROTR, MVT::i8, Expand);
99 setOperationAction(ISD::ROTL, MVT::i16, Expand);
100 setOperationAction(ISD::ROTR, MVT::i16, Expand);
101 setOperationAction(ISD::GlobalAddress, MVT::i16, Custom);
102 setOperationAction(ISD::ExternalSymbol, MVT::i16, Custom);
Anton Korobeynikovebbdfef2010-05-01 12:04:32 +0000103 setOperationAction(ISD::BlockAddress, MVT::i16, Custom);
Owen Anderson9f944592009-08-11 20:47:22 +0000104 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
Owen Anderson9f944592009-08-11 20:47:22 +0000105 setOperationAction(ISD::BR_CC, MVT::i8, Custom);
106 setOperationAction(ISD::BR_CC, MVT::i16, Custom);
107 setOperationAction(ISD::BRCOND, MVT::Other, Expand);
Anton Korobeynikove27e0282009-12-11 23:01:29 +0000108 setOperationAction(ISD::SETCC, MVT::i8, Custom);
109 setOperationAction(ISD::SETCC, MVT::i16, Custom);
Owen Anderson9f944592009-08-11 20:47:22 +0000110 setOperationAction(ISD::SELECT, MVT::i8, Expand);
111 setOperationAction(ISD::SELECT, MVT::i16, Expand);
112 setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
113 setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
114 setOperationAction(ISD::SIGN_EXTEND, MVT::i16, Custom);
Anton Korobeynikov271cdda2009-08-25 17:00:23 +0000115 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i8, Expand);
116 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i16, Expand);
Anton Korobeynikovde60d1c2009-05-03 13:14:25 +0000117
Owen Anderson9f944592009-08-11 20:47:22 +0000118 setOperationAction(ISD::CTTZ, MVT::i8, Expand);
119 setOperationAction(ISD::CTTZ, MVT::i16, Expand);
120 setOperationAction(ISD::CTLZ, MVT::i8, Expand);
121 setOperationAction(ISD::CTLZ, MVT::i16, Expand);
122 setOperationAction(ISD::CTPOP, MVT::i8, Expand);
123 setOperationAction(ISD::CTPOP, MVT::i16, Expand);
Eli Friedman6a60a66b2009-07-17 07:28:06 +0000124
Owen Anderson9f944592009-08-11 20:47:22 +0000125 setOperationAction(ISD::SHL_PARTS, MVT::i8, Expand);
126 setOperationAction(ISD::SHL_PARTS, MVT::i16, Expand);
127 setOperationAction(ISD::SRL_PARTS, MVT::i8, Expand);
128 setOperationAction(ISD::SRL_PARTS, MVT::i16, Expand);
129 setOperationAction(ISD::SRA_PARTS, MVT::i8, Expand);
130 setOperationAction(ISD::SRA_PARTS, MVT::i16, Expand);
Eli Friedman6a60a66b2009-07-17 07:28:06 +0000131
Owen Anderson9f944592009-08-11 20:47:22 +0000132 setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
Eli Friedman6a60a66b2009-07-17 07:28:06 +0000133
Anton Korobeynikovde60d1c2009-05-03 13:14:25 +0000134 // FIXME: Implement efficiently multiplication by a constant
Anton Korobeynikovf93bb392009-11-07 17:14:39 +0000135 setOperationAction(ISD::MUL, MVT::i8, Expand);
136 setOperationAction(ISD::MULHS, MVT::i8, Expand);
137 setOperationAction(ISD::MULHU, MVT::i8, Expand);
138 setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand);
139 setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand);
Owen Anderson9f944592009-08-11 20:47:22 +0000140 setOperationAction(ISD::MUL, MVT::i16, Expand);
141 setOperationAction(ISD::MULHS, MVT::i16, Expand);
142 setOperationAction(ISD::MULHU, MVT::i16, Expand);
143 setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand);
144 setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand);
Anton Korobeynikoveb2152f2009-05-03 13:18:33 +0000145
Anton Korobeynikovf93bb392009-11-07 17:14:39 +0000146 setOperationAction(ISD::UDIV, MVT::i8, Expand);
147 setOperationAction(ISD::UDIVREM, MVT::i8, Expand);
148 setOperationAction(ISD::UREM, MVT::i8, Expand);
149 setOperationAction(ISD::SDIV, MVT::i8, Expand);
150 setOperationAction(ISD::SDIVREM, MVT::i8, Expand);
151 setOperationAction(ISD::SREM, MVT::i8, Expand);
Owen Anderson9f944592009-08-11 20:47:22 +0000152 setOperationAction(ISD::UDIV, MVT::i16, Expand);
153 setOperationAction(ISD::UDIVREM, MVT::i16, Expand);
154 setOperationAction(ISD::UREM, MVT::i16, Expand);
155 setOperationAction(ISD::SDIV, MVT::i16, Expand);
156 setOperationAction(ISD::SDIVREM, MVT::i16, Expand);
157 setOperationAction(ISD::SREM, MVT::i16, Expand);
Anton Korobeynikov28d3c732009-12-07 02:27:08 +0000158
Anton Korobeynikov568afeb2012-11-21 17:28:27 +0000159 // varargs support
160 setOperationAction(ISD::VASTART, MVT::Other, Custom);
161 setOperationAction(ISD::VAARG, MVT::Other, Expand);
162 setOperationAction(ISD::VAEND, MVT::Other, Expand);
163 setOperationAction(ISD::VACOPY, MVT::Other, Expand);
Anton Korobeynikov82bedb12013-07-01 19:44:44 +0000164 setOperationAction(ISD::JumpTable, MVT::i16, Custom);
Anton Korobeynikov568afeb2012-11-21 17:28:27 +0000165
Anton Korobeynikov28d3c732009-12-07 02:27:08 +0000166 // Libcalls names.
167 if (HWMultMode == HWMultIntr) {
168 setLibcallName(RTLIB::MUL_I8, "__mulqi3hw");
169 setLibcallName(RTLIB::MUL_I16, "__mulhi3hw");
170 } else if (HWMultMode == HWMultNoIntr) {
171 setLibcallName(RTLIB::MUL_I8, "__mulqi3hw_noint");
172 setLibcallName(RTLIB::MUL_I16, "__mulhi3hw_noint");
173 }
Eli Friedman2518f832011-05-06 20:34:06 +0000174
175 setMinFunctionAlignment(1);
176 setPrefFunctionAlignment(2);
Anton Korobeynikov10138002009-05-03 12:57:15 +0000177}
178
Dan Gohman21cea8a2010-04-17 15:26:15 +0000179SDValue MSP430TargetLowering::LowerOperation(SDValue Op,
180 SelectionDAG &DAG) const {
Anton Korobeynikov10138002009-05-03 12:57:15 +0000181 switch (Op.getOpcode()) {
Anton Korobeynikova3f7a832009-05-03 13:13:17 +0000182 case ISD::SHL: // FALLTHROUGH
Anton Korobeynikov61763b52009-05-03 13:16:17 +0000183 case ISD::SRL:
Anton Korobeynikov56135102009-05-03 13:07:31 +0000184 case ISD::SRA: return LowerShifts(Op, DAG);
Anton Korobeynikovcfc97052009-05-03 13:08:33 +0000185 case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
Anton Korobeynikovebbdfef2010-05-01 12:04:32 +0000186 case ISD::BlockAddress: return LowerBlockAddress(Op, DAG);
Anton Korobeynikovba0e81d2009-05-03 13:14:46 +0000187 case ISD::ExternalSymbol: return LowerExternalSymbol(Op, DAG);
Anton Korobeynikove27e0282009-12-11 23:01:29 +0000188 case ISD::SETCC: return LowerSETCC(Op, DAG);
Anton Korobeynikov47fcd722009-05-03 13:19:09 +0000189 case ISD::BR_CC: return LowerBR_CC(Op, DAG);
190 case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
Anton Korobeynikov29747e92009-05-03 13:17:49 +0000191 case ISD::SIGN_EXTEND: return LowerSIGN_EXTEND(Op, DAG);
Anton Korobeynikovff4ab512009-12-07 02:28:10 +0000192 case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
193 case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
Anton Korobeynikov568afeb2012-11-21 17:28:27 +0000194 case ISD::VASTART: return LowerVASTART(Op, DAG);
Anton Korobeynikov82bedb12013-07-01 19:44:44 +0000195 case ISD::JumpTable: return LowerJumpTable(Op, DAG);
Anton Korobeynikov10138002009-05-03 12:57:15 +0000196 default:
Torok Edwinfbcc6632009-07-14 16:55:14 +0000197 llvm_unreachable("unimplemented operand");
Anton Korobeynikov10138002009-05-03 12:57:15 +0000198 }
199}
200
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000201//===----------------------------------------------------------------------===//
Anton Korobeynikova0e01be2009-08-26 13:44:29 +0000202// MSP430 Inline Assembly Support
203//===----------------------------------------------------------------------===//
204
205/// getConstraintType - Given a constraint letter, return the type of
206/// constraint it is for this target.
207TargetLowering::ConstraintType
Benjamin Kramer9bfb6272015-07-05 19:29:18 +0000208MSP430TargetLowering::getConstraintType(StringRef Constraint) const {
Anton Korobeynikova0e01be2009-08-26 13:44:29 +0000209 if (Constraint.size() == 1) {
210 switch (Constraint[0]) {
211 case 'r':
212 return C_RegisterClass;
213 default:
214 break;
215 }
216 }
217 return TargetLowering::getConstraintType(Constraint);
218}
219
Eric Christopher11e4df72015-02-26 22:38:43 +0000220std::pair<unsigned, const TargetRegisterClass *>
221MSP430TargetLowering::getRegForInlineAsmConstraint(
Benjamin Kramer9bfb6272015-07-05 19:29:18 +0000222 const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
Anton Korobeynikova0e01be2009-08-26 13:44:29 +0000223 if (Constraint.size() == 1) {
224 // GCC Constraint Letters
225 switch (Constraint[0]) {
226 default: break;
227 case 'r': // GENERAL_REGS
228 if (VT == MVT::i8)
Craig Topperc7242e02012-04-20 07:30:17 +0000229 return std::make_pair(0U, &MSP430::GR8RegClass);
Anton Korobeynikova0e01be2009-08-26 13:44:29 +0000230
Craig Topperc7242e02012-04-20 07:30:17 +0000231 return std::make_pair(0U, &MSP430::GR16RegClass);
Anton Korobeynikova0e01be2009-08-26 13:44:29 +0000232 }
233 }
234
Eric Christopher11e4df72015-02-26 22:38:43 +0000235 return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
Anton Korobeynikova0e01be2009-08-26 13:44:29 +0000236}
237
238//===----------------------------------------------------------------------===//
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000239// Calling Convention Implementation
240//===----------------------------------------------------------------------===//
241
Anton Korobeynikov10138002009-05-03 12:57:15 +0000242#include "MSP430GenCallingConv.inc"
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000243
Job Noormane9a1d4c2013-10-15 08:19:39 +0000244/// For each argument in a function store the number of pieces it is composed
245/// of.
246template<typename ArgT>
247static void ParseFunctionArgs(const SmallVectorImpl<ArgT> &Args,
248 SmallVectorImpl<unsigned> &Out) {
249 unsigned CurrentArgIndex = ~0U;
250 for (unsigned i = 0, e = Args.size(); i != e; i++) {
251 if (CurrentArgIndex == Args[i].OrigArgIndex) {
252 Out.back()++;
253 } else {
254 Out.push_back(1);
255 CurrentArgIndex++;
256 }
257 }
258}
259
260static void AnalyzeVarArgs(CCState &State,
261 const SmallVectorImpl<ISD::OutputArg> &Outs) {
262 State.AnalyzeCallOperands(Outs, CC_MSP430_AssignStack);
263}
264
265static void AnalyzeVarArgs(CCState &State,
266 const SmallVectorImpl<ISD::InputArg> &Ins) {
267 State.AnalyzeFormalArguments(Ins, CC_MSP430_AssignStack);
268}
269
270/// Analyze incoming and outgoing function arguments. We need custom C++ code
271/// to handle special constraints in the ABI like reversing the order of the
272/// pieces of splitted arguments. In addition, all pieces of a certain argument
273/// have to be passed either using registers or the stack but never mixing both.
274template<typename ArgT>
275static void AnalyzeArguments(CCState &State,
276 SmallVectorImpl<CCValAssign> &ArgLocs,
277 const SmallVectorImpl<ArgT> &Args) {
Craig Topper840beec2014-04-04 05:16:06 +0000278 static const MCPhysReg RegList[] = {
Job Noormaneb19aea2014-09-10 06:58:14 +0000279 MSP430::R15, MSP430::R14, MSP430::R13, MSP430::R12
Job Noormane9a1d4c2013-10-15 08:19:39 +0000280 };
281 static const unsigned NbRegs = array_lengthof(RegList);
282
283 if (State.isVarArg()) {
284 AnalyzeVarArgs(State, Args);
285 return;
286 }
287
288 SmallVector<unsigned, 4> ArgsParts;
289 ParseFunctionArgs(Args, ArgsParts);
290
291 unsigned RegsLeft = NbRegs;
292 bool UseStack = false;
293 unsigned ValNo = 0;
294
295 for (unsigned i = 0, e = ArgsParts.size(); i != e; i++) {
296 MVT ArgVT = Args[ValNo].VT;
297 ISD::ArgFlagsTy ArgFlags = Args[ValNo].Flags;
298 MVT LocVT = ArgVT;
299 CCValAssign::LocInfo LocInfo = CCValAssign::Full;
300
301 // Promote i8 to i16
302 if (LocVT == MVT::i8) {
303 LocVT = MVT::i16;
304 if (ArgFlags.isSExt())
305 LocInfo = CCValAssign::SExt;
306 else if (ArgFlags.isZExt())
307 LocInfo = CCValAssign::ZExt;
308 else
309 LocInfo = CCValAssign::AExt;
310 }
311
312 // Handle byval arguments
313 if (ArgFlags.isByVal()) {
314 State.HandleByVal(ValNo++, ArgVT, LocVT, LocInfo, 2, 2, ArgFlags);
315 continue;
316 }
317
318 unsigned Parts = ArgsParts[i];
319
320 if (!UseStack && Parts <= RegsLeft) {
321 unsigned FirstVal = ValNo;
322 for (unsigned j = 0; j < Parts; j++) {
Tim Northover3b6b7ca2015-02-21 02:11:17 +0000323 unsigned Reg = State.AllocateReg(RegList);
Job Noormane9a1d4c2013-10-15 08:19:39 +0000324 State.addLoc(CCValAssign::getReg(ValNo++, ArgVT, Reg, LocVT, LocInfo));
325 RegsLeft--;
326 }
327
328 // Reverse the order of the pieces to agree with the "big endian" format
329 // required in the calling convention ABI.
330 SmallVectorImpl<CCValAssign>::iterator B = ArgLocs.begin() + FirstVal;
331 std::reverse(B, B + Parts);
332 } else {
333 UseStack = true;
334 for (unsigned j = 0; j < Parts; j++)
335 CC_MSP430_AssignStack(ValNo++, ArgVT, LocVT, LocInfo, ArgFlags, State);
336 }
337 }
338}
339
340static void AnalyzeRetResult(CCState &State,
341 const SmallVectorImpl<ISD::InputArg> &Ins) {
342 State.AnalyzeCallResult(Ins, RetCC_MSP430);
343}
344
345static void AnalyzeRetResult(CCState &State,
346 const SmallVectorImpl<ISD::OutputArg> &Outs) {
347 State.AnalyzeReturn(Outs, RetCC_MSP430);
348}
349
350template<typename ArgT>
351static void AnalyzeReturnValues(CCState &State,
352 SmallVectorImpl<CCValAssign> &RVLocs,
353 const SmallVectorImpl<ArgT> &Args) {
354 AnalyzeRetResult(State, Args);
355
356 // Reverse splitted return values to get the "big endian" format required
357 // to agree with the calling convention ABI.
358 std::reverse(RVLocs.begin(), RVLocs.end());
359}
360
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000361SDValue MSP430TargetLowering::LowerFormalArguments(
362 SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
363 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
364 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000365
366 switch (CallConv) {
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000367 default:
Torok Edwinfbcc6632009-07-14 16:55:14 +0000368 llvm_unreachable("Unsupported calling convention");
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000369 case CallingConv::C:
370 case CallingConv::Fast:
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000371 return LowerCCCArguments(Chain, CallConv, isVarArg, Ins, dl, DAG, InVals);
Anton Korobeynikovb4be8ce2009-12-07 02:27:53 +0000372 case CallingConv::MSP430_INTR:
David Blaikie46a9f012012-01-20 21:51:11 +0000373 if (Ins.empty())
374 return Chain;
Chris Lattner2104b8d2010-04-07 22:58:41 +0000375 report_fatal_error("ISRs cannot have arguments");
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000376 }
377}
378
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000379SDValue
Justin Holewinskiaa583972012-05-25 16:35:28 +0000380MSP430TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
Dan Gohman21cea8a2010-04-17 15:26:15 +0000381 SmallVectorImpl<SDValue> &InVals) const {
Justin Holewinskiaa583972012-05-25 16:35:28 +0000382 SelectionDAG &DAG = CLI.DAG;
Andrew Trickef9de2a2013-05-25 02:42:55 +0000383 SDLoc &dl = CLI.DL;
Craig Topperb94011f2013-07-14 04:42:23 +0000384 SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
385 SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
386 SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
Justin Holewinskiaa583972012-05-25 16:35:28 +0000387 SDValue Chain = CLI.Chain;
388 SDValue Callee = CLI.Callee;
389 bool &isTailCall = CLI.IsTailCall;
390 CallingConv::ID CallConv = CLI.CallConv;
391 bool isVarArg = CLI.IsVarArg;
392
Evan Cheng67a69dd2010-01-27 00:07:07 +0000393 // MSP430 target does not yet support tail call optimization.
394 isTailCall = false;
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000395
396 switch (CallConv) {
Anton Korobeynikov56135102009-05-03 13:07:31 +0000397 default:
Torok Edwinfbcc6632009-07-14 16:55:14 +0000398 llvm_unreachable("Unsupported calling convention");
Anton Korobeynikov56135102009-05-03 13:07:31 +0000399 case CallingConv::Fast:
400 case CallingConv::C:
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000401 return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall,
Dan Gohmanfe7532a2010-07-07 15:54:55 +0000402 Outs, OutVals, Ins, dl, DAG, InVals);
Anton Korobeynikovb4be8ce2009-12-07 02:27:53 +0000403 case CallingConv::MSP430_INTR:
Chris Lattner2104b8d2010-04-07 22:58:41 +0000404 report_fatal_error("ISRs cannot be called directly");
Anton Korobeynikov56135102009-05-03 13:07:31 +0000405 }
406}
407
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000408/// LowerCCCArguments - transform physical registers into virtual registers and
409/// generate load operations for arguments places on the stack.
410// FIXME: struct return stuff
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000411SDValue MSP430TargetLowering::LowerCCCArguments(
412 SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
413 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
414 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000415 MachineFunction &MF = DAG.getMachineFunction();
416 MachineFrameInfo *MFI = MF.getFrameInfo();
417 MachineRegisterInfo &RegInfo = MF.getRegInfo();
Anton Korobeynikov568afeb2012-11-21 17:28:27 +0000418 MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>();
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000419
420 // Assign locations to all of the incoming arguments.
421 SmallVector<CCValAssign, 16> ArgLocs;
Eric Christopherb5217502014-08-06 18:45:26 +0000422 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
423 *DAG.getContext());
Job Noormane9a1d4c2013-10-15 08:19:39 +0000424 AnalyzeArguments(CCInfo, ArgLocs, Ins);
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000425
Anton Korobeynikov568afeb2012-11-21 17:28:27 +0000426 // Create frame index for the start of the first vararg value
427 if (isVarArg) {
428 unsigned Offset = CCInfo.getNextStackOffset();
429 FuncInfo->setVarArgsFrameIndex(MFI->CreateFixedObject(1, Offset, true));
430 }
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000431
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000432 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
433 CCValAssign &VA = ArgLocs[i];
434 if (VA.isRegLoc()) {
435 // Arguments passed in registers
Owen Anderson53aa7a92009-08-10 22:56:29 +0000436 EVT RegVT = VA.getLocVT();
Owen Anderson9f944592009-08-11 20:47:22 +0000437 switch (RegVT.getSimpleVT().SimpleTy) {
Owen Andersonb2c80da2011-02-25 21:41:48 +0000438 default:
Torok Edwinfa040022009-07-08 19:04:27 +0000439 {
Torok Edwinfb8d6d52009-07-08 20:53:28 +0000440#ifndef NDEBUG
Chris Lattner317dbbc2009-08-23 07:05:07 +0000441 errs() << "LowerFormalArguments Unhandled argument type: "
Craig Topper6ff46262016-04-17 17:37:33 +0000442 << RegVT.getEVTString() << "\n";
Torok Edwinfb8d6d52009-07-08 20:53:28 +0000443#endif
Craig Toppere73658d2014-04-28 04:05:08 +0000444 llvm_unreachable(nullptr);
Torok Edwinfa040022009-07-08 19:04:27 +0000445 }
Owen Anderson9f944592009-08-11 20:47:22 +0000446 case MVT::i16:
Craig Topperc7242e02012-04-20 07:30:17 +0000447 unsigned VReg = RegInfo.createVirtualRegister(&MSP430::GR16RegClass);
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000448 RegInfo.addLiveIn(VA.getLocReg(), VReg);
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000449 SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000450
451 // If this is an 8-bit value, it is really passed promoted to 16
452 // bits. Insert an assert[sz]ext to capture this, then truncate to the
453 // right size.
454 if (VA.getLocInfo() == CCValAssign::SExt)
455 ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue,
456 DAG.getValueType(VA.getValVT()));
457 else if (VA.getLocInfo() == CCValAssign::ZExt)
458 ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue,
459 DAG.getValueType(VA.getValVT()));
460
461 if (VA.getLocInfo() != CCValAssign::Full)
462 ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
463
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000464 InVals.push_back(ArgValue);
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000465 }
466 } else {
467 // Sanity check
468 assert(VA.isMemLoc());
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000469
Anton Korobeynikov34148722012-11-21 17:23:03 +0000470 SDValue InVal;
471 ISD::ArgFlagsTy Flags = Ins[i].Flags;
472
473 if (Flags.isByVal()) {
474 int FI = MFI->CreateFixedObject(Flags.getByValSize(),
475 VA.getLocMemOffset(), true);
Mehdi Amini44ede332015-07-09 02:09:04 +0000476 InVal = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
Anton Korobeynikov34148722012-11-21 17:23:03 +0000477 } else {
478 // Load the argument to a virtual register
479 unsigned ObjSize = VA.getLocVT().getSizeInBits()/8;
480 if (ObjSize > 2) {
481 errs() << "LowerFormalArguments Unhandled argument type: "
482 << EVT(VA.getLocVT()).getEVTString()
483 << "\n";
484 }
485 // Create the frame index object for this incoming parameter...
486 int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset(), true);
487
488 // Create the SelectionDAG nodes corresponding to a load
489 //from this parameter
490 SDValue FIN = DAG.getFrameIndex(FI, MVT::i16);
Alex Lorenze40c8a22015-08-11 23:09:45 +0000491 InVal = DAG.getLoad(
492 VA.getLocVT(), dl, Chain, FIN,
Justin Lebar9c375812016-07-15 18:27:10 +0000493 MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI));
Anton Korobeynikov34148722012-11-21 17:23:03 +0000494 }
495
496 InVals.push_back(InVal);
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000497 }
498 }
499
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000500 return Chain;
Anton Korobeynikov3849be62009-05-03 12:59:33 +0000501}
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +0000502
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000503SDValue
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000504MSP430TargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
505 bool isVarArg,
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000506 const SmallVectorImpl<ISD::OutputArg> &Outs,
Dan Gohmanfe7532a2010-07-07 15:54:55 +0000507 const SmallVectorImpl<SDValue> &OutVals,
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000508 const SDLoc &dl, SelectionDAG &DAG) const {
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000509
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +0000510 // CCValAssign - represent the assignment of the return value to a location
511 SmallVector<CCValAssign, 16> RVLocs;
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +0000512
Anton Korobeynikovb4be8ce2009-12-07 02:27:53 +0000513 // ISRs cannot return any value.
David Blaikie46a9f012012-01-20 21:51:11 +0000514 if (CallConv == CallingConv::MSP430_INTR && !Outs.empty())
Chris Lattner2104b8d2010-04-07 22:58:41 +0000515 report_fatal_error("ISRs cannot return any value");
Anton Korobeynikovb4be8ce2009-12-07 02:27:53 +0000516
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +0000517 // CCState - Info about the registers and stack slot.
Eric Christopherb5217502014-08-06 18:45:26 +0000518 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
519 *DAG.getContext());
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +0000520
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000521 // Analize return values.
Job Noormane9a1d4c2013-10-15 08:19:39 +0000522 AnalyzeReturnValues(CCInfo, RVLocs, Outs);
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +0000523
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +0000524 SDValue Flag;
Jakob Stoklund Olesenb52a3ec2013-02-05 18:12:06 +0000525 SmallVector<SDValue, 4> RetOps(1, Chain);
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +0000526
527 // Copy the result values into the output registers.
528 for (unsigned i = 0; i != RVLocs.size(); ++i) {
529 CCValAssign &VA = RVLocs[i];
530 assert(VA.isRegLoc() && "Can only return in registers!");
531
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +0000532 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
Dan Gohmanfe7532a2010-07-07 15:54:55 +0000533 OutVals[i], Flag);
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +0000534
Anton Korobeynikovc10f98a2009-05-03 13:00:11 +0000535 // Guarantee that all emitted copies are stuck together,
536 // avoiding something bad.
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +0000537 Flag = Chain.getValue(1);
Jakob Stoklund Olesenb52a3ec2013-02-05 18:12:06 +0000538 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +0000539 }
540
Anton Korobeynikovb4be8ce2009-12-07 02:27:53 +0000541 unsigned Opc = (CallConv == CallingConv::MSP430_INTR ?
542 MSP430ISD::RETI_FLAG : MSP430ISD::RET_FLAG);
543
Jakob Stoklund Olesenb52a3ec2013-02-05 18:12:06 +0000544 RetOps[0] = Chain; // Update chain.
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +0000545
Jakob Stoklund Olesenb52a3ec2013-02-05 18:12:06 +0000546 // Add the flag if we have it.
547 if (Flag.getNode())
548 RetOps.push_back(Flag);
549
Craig Topper48d114b2014-04-26 18:35:24 +0000550 return DAG.getNode(Opc, dl, MVT::Other, RetOps);
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +0000551}
552
Anton Korobeynikov56135102009-05-03 13:07:31 +0000553/// LowerCCCCallTo - functions arguments are copied from virtual regs to
554/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
Job Noormana928e1d2013-07-15 14:25:26 +0000555// TODO: sret.
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000556SDValue MSP430TargetLowering::LowerCCCCallTo(
557 SDValue Chain, SDValue Callee, CallingConv::ID CallConv, bool isVarArg,
558 bool isTailCall, const SmallVectorImpl<ISD::OutputArg> &Outs,
559 const SmallVectorImpl<SDValue> &OutVals,
560 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
561 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
Anton Korobeynikov56135102009-05-03 13:07:31 +0000562 // Analyze operands of the call, assigning locations to each operand.
563 SmallVector<CCValAssign, 16> ArgLocs;
Eric Christopherb5217502014-08-06 18:45:26 +0000564 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
565 *DAG.getContext());
Job Noormane9a1d4c2013-10-15 08:19:39 +0000566 AnalyzeArguments(CCInfo, ArgLocs, Outs);
Anton Korobeynikov56135102009-05-03 13:07:31 +0000567
568 // Get a count of how many bytes are to be pushed on the stack.
569 unsigned NumBytes = CCInfo.getNextStackOffset();
Mehdi Amini44ede332015-07-09 02:09:04 +0000570 auto PtrVT = getPointerTy(DAG.getDataLayout());
Anton Korobeynikov56135102009-05-03 13:07:31 +0000571
Mehdi Amini44ede332015-07-09 02:09:04 +0000572 Chain = DAG.getCALLSEQ_START(Chain,
573 DAG.getConstant(NumBytes, dl, PtrVT, true), dl);
Anton Korobeynikov56135102009-05-03 13:07:31 +0000574
575 SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
576 SmallVector<SDValue, 12> MemOpChains;
577 SDValue StackPtr;
578
579 // Walk the register/memloc assignments, inserting copies/loads.
580 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
581 CCValAssign &VA = ArgLocs[i];
582
Dan Gohmanfe7532a2010-07-07 15:54:55 +0000583 SDValue Arg = OutVals[i];
Anton Korobeynikov56135102009-05-03 13:07:31 +0000584
585 // Promote the value if needed.
586 switch (VA.getLocInfo()) {
Torok Edwinfbcc6632009-07-14 16:55:14 +0000587 default: llvm_unreachable("Unknown loc info!");
Anton Korobeynikov56135102009-05-03 13:07:31 +0000588 case CCValAssign::Full: break;
589 case CCValAssign::SExt:
590 Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
591 break;
592 case CCValAssign::ZExt:
593 Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
594 break;
595 case CCValAssign::AExt:
596 Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
597 break;
598 }
599
600 // Arguments that can be passed on register must be kept at RegsToPass
601 // vector
602 if (VA.isRegLoc()) {
603 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
604 } else {
605 assert(VA.isMemLoc());
606
Craig Topper062a2ba2014-04-25 05:30:21 +0000607 if (!StackPtr.getNode())
Mehdi Amini44ede332015-07-09 02:09:04 +0000608 StackPtr = DAG.getCopyFromReg(Chain, dl, MSP430::SP, PtrVT);
Anton Korobeynikov56135102009-05-03 13:07:31 +0000609
Mehdi Amini44ede332015-07-09 02:09:04 +0000610 SDValue PtrOff =
611 DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr,
612 DAG.getIntPtrConstant(VA.getLocMemOffset(), dl));
Anton Korobeynikov56135102009-05-03 13:07:31 +0000613
Anton Korobeynikov34148722012-11-21 17:23:03 +0000614 SDValue MemOp;
615 ISD::ArgFlagsTy Flags = Outs[i].Flags;
Anton Korobeynikov56135102009-05-03 13:07:31 +0000616
Anton Korobeynikov34148722012-11-21 17:23:03 +0000617 if (Flags.isByVal()) {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000618 SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), dl, MVT::i16);
Anton Korobeynikov34148722012-11-21 17:23:03 +0000619 MemOp = DAG.getMemcpy(Chain, dl, PtrOff, Arg, SizeNode,
620 Flags.getByValAlign(),
621 /*isVolatile*/false,
622 /*AlwaysInline=*/true,
Krzysztof Parzyszeka46c36b2015-04-13 17:16:45 +0000623 /*isTailCall=*/false,
Anton Korobeynikov34148722012-11-21 17:23:03 +0000624 MachinePointerInfo(),
625 MachinePointerInfo());
626 } else {
Justin Lebar9c375812016-07-15 18:27:10 +0000627 MemOp = DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());
Anton Korobeynikov34148722012-11-21 17:23:03 +0000628 }
629
630 MemOpChains.push_back(MemOp);
Anton Korobeynikov56135102009-05-03 13:07:31 +0000631 }
632 }
633
634 // Transform all store nodes into one single node because all store nodes are
635 // independent of each other.
636 if (!MemOpChains.empty())
Craig Topper48d114b2014-04-26 18:35:24 +0000637 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
Anton Korobeynikov56135102009-05-03 13:07:31 +0000638
639 // Build a sequence of copy-to-reg nodes chained together with token chain and
640 // flag operands which copy the outgoing args into registers. The InFlag in
Chris Lattner0ab5e2c2011-04-15 05:18:47 +0000641 // necessary since all emitted instructions must be stuck together.
Anton Korobeynikov56135102009-05-03 13:07:31 +0000642 SDValue InFlag;
643 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
644 Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
645 RegsToPass[i].second, InFlag);
646 InFlag = Chain.getValue(1);
647 }
648
649 // If the callee is a GlobalAddress node (quite common, every direct call is)
650 // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
651 // Likewise ExternalSymbol -> TargetExternalSymbol.
652 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
Devang Patela3ca21b2010-07-06 22:08:15 +0000653 Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i16);
Anton Korobeynikov56135102009-05-03 13:07:31 +0000654 else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
Owen Anderson9f944592009-08-11 20:47:22 +0000655 Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i16);
Anton Korobeynikov56135102009-05-03 13:07:31 +0000656
657 // Returns a chain & a flag for retval copy to use.
Chris Lattner3e5fbd72010-12-21 02:38:05 +0000658 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
Anton Korobeynikov56135102009-05-03 13:07:31 +0000659 SmallVector<SDValue, 8> Ops;
660 Ops.push_back(Chain);
661 Ops.push_back(Callee);
662
663 // Add argument registers to the end of the list so that they are
664 // known live into the call.
665 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
666 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
667 RegsToPass[i].second.getValueType()));
668
669 if (InFlag.getNode())
670 Ops.push_back(InFlag);
671
Craig Topper48d114b2014-04-26 18:35:24 +0000672 Chain = DAG.getNode(MSP430ISD::CALL, dl, NodeTys, Ops);
Anton Korobeynikov56135102009-05-03 13:07:31 +0000673 InFlag = Chain.getValue(1);
674
675 // Create the CALLSEQ_END node.
Mehdi Amini44ede332015-07-09 02:09:04 +0000676 Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, dl, PtrVT, true),
677 DAG.getConstant(0, dl, PtrVT, true), InFlag, dl);
Anton Korobeynikov56135102009-05-03 13:07:31 +0000678 InFlag = Chain.getValue(1);
679
680 // Handle result values, copying them out of physregs into vregs that we
681 // return.
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000682 return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl,
683 DAG, InVals);
Anton Korobeynikov56135102009-05-03 13:07:31 +0000684}
685
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000686/// LowerCallResult - Lower the result values of a call into the
687/// appropriate copies out of appropriate physical registers.
688///
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000689SDValue MSP430TargetLowering::LowerCallResult(
690 SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool isVarArg,
691 const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
692 SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
Anton Korobeynikov56135102009-05-03 13:07:31 +0000693
694 // Assign locations to each value returned by this call.
695 SmallVector<CCValAssign, 16> RVLocs;
Eric Christopherb5217502014-08-06 18:45:26 +0000696 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
697 *DAG.getContext());
Anton Korobeynikov56135102009-05-03 13:07:31 +0000698
Job Noormane9a1d4c2013-10-15 08:19:39 +0000699 AnalyzeReturnValues(CCInfo, RVLocs, Ins);
Anton Korobeynikov56135102009-05-03 13:07:31 +0000700
701 // Copy all of the result registers out of their specified physreg.
702 for (unsigned i = 0; i != RVLocs.size(); ++i) {
703 Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
704 RVLocs[i].getValVT(), InFlag).getValue(1);
705 InFlag = Chain.getValue(2);
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000706 InVals.push_back(Chain.getValue(0));
Anton Korobeynikov56135102009-05-03 13:07:31 +0000707 }
708
Dan Gohmanf9bbcd12009-08-05 01:29:28 +0000709 return Chain;
Anton Korobeynikov56135102009-05-03 13:07:31 +0000710}
711
Anton Korobeynikov15a515b2009-05-03 13:03:33 +0000712SDValue MSP430TargetLowering::LowerShifts(SDValue Op,
Dan Gohman21cea8a2010-04-17 15:26:15 +0000713 SelectionDAG &DAG) const {
Anton Korobeynikova3f7a832009-05-03 13:13:17 +0000714 unsigned Opc = Op.getOpcode();
Anton Korobeynikov15a515b2009-05-03 13:03:33 +0000715 SDNode* N = Op.getNode();
Owen Anderson53aa7a92009-08-10 22:56:29 +0000716 EVT VT = Op.getValueType();
Andrew Trickef9de2a2013-05-25 02:42:55 +0000717 SDLoc dl(N);
Anton Korobeynikov15a515b2009-05-03 13:03:33 +0000718
Anton Korobeynikovd8f32092009-12-12 18:55:37 +0000719 // Expand non-constant shifts to loops:
Anton Korobeynikov15a515b2009-05-03 13:03:33 +0000720 if (!isa<ConstantSDNode>(N->getOperand(1)))
Anton Korobeynikovd8f32092009-12-12 18:55:37 +0000721 switch (Opc) {
Craig Toppere55c5562012-02-07 02:50:20 +0000722 default: llvm_unreachable("Invalid shift opcode!");
Anton Korobeynikovd8f32092009-12-12 18:55:37 +0000723 case ISD::SHL:
724 return DAG.getNode(MSP430ISD::SHL, dl,
725 VT, N->getOperand(0), N->getOperand(1));
726 case ISD::SRA:
727 return DAG.getNode(MSP430ISD::SRA, dl,
728 VT, N->getOperand(0), N->getOperand(1));
729 case ISD::SRL:
730 return DAG.getNode(MSP430ISD::SRL, dl,
731 VT, N->getOperand(0), N->getOperand(1));
732 }
Anton Korobeynikov15a515b2009-05-03 13:03:33 +0000733
734 uint64_t ShiftAmount = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
735
736 // Expand the stuff into sequence of shifts.
737 // FIXME: for some shift amounts this might be done better!
738 // E.g.: foo >> (8 + N) => sxt(swpb(foo)) >> N
739 SDValue Victim = N->getOperand(0);
Anton Korobeynikov61763b52009-05-03 13:16:17 +0000740
741 if (Opc == ISD::SRL && ShiftAmount) {
742 // Emit a special goodness here:
743 // srl A, 1 => clrc; rrc A
Anton Korobeynikovf3a6bc82009-05-03 13:16:37 +0000744 Victim = DAG.getNode(MSP430ISD::RRC, dl, VT, Victim);
Anton Korobeynikov61763b52009-05-03 13:16:17 +0000745 ShiftAmount -= 1;
746 }
747
Anton Korobeynikov15a515b2009-05-03 13:03:33 +0000748 while (ShiftAmount--)
Anton Korobeynikov6b5523a2009-05-17 10:15:22 +0000749 Victim = DAG.getNode((Opc == ISD::SHL ? MSP430ISD::RLA : MSP430ISD::RRA),
Anton Korobeynikova3f7a832009-05-03 13:13:17 +0000750 dl, VT, Victim);
Anton Korobeynikov15a515b2009-05-03 13:03:33 +0000751
752 return Victim;
753}
754
Dan Gohman21cea8a2010-04-17 15:26:15 +0000755SDValue MSP430TargetLowering::LowerGlobalAddress(SDValue Op,
756 SelectionDAG &DAG) const {
Anton Korobeynikovcfc97052009-05-03 13:08:33 +0000757 const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
758 int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset();
Mehdi Amini44ede332015-07-09 02:09:04 +0000759 auto PtrVT = getPointerTy(DAG.getDataLayout());
Anton Korobeynikovcfc97052009-05-03 13:08:33 +0000760
761 // Create the TargetGlobalAddress node, folding in the constant offset.
Mehdi Amini44ede332015-07-09 02:09:04 +0000762 SDValue Result = DAG.getTargetGlobalAddress(GV, SDLoc(Op), PtrVT, Offset);
763 return DAG.getNode(MSP430ISD::Wrapper, SDLoc(Op), PtrVT, Result);
Anton Korobeynikovcfc97052009-05-03 13:08:33 +0000764}
765
Anton Korobeynikovba0e81d2009-05-03 13:14:46 +0000766SDValue MSP430TargetLowering::LowerExternalSymbol(SDValue Op,
Dan Gohman21cea8a2010-04-17 15:26:15 +0000767 SelectionDAG &DAG) const {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000768 SDLoc dl(Op);
Anton Korobeynikovba0e81d2009-05-03 13:14:46 +0000769 const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol();
Mehdi Amini44ede332015-07-09 02:09:04 +0000770 auto PtrVT = getPointerTy(DAG.getDataLayout());
771 SDValue Result = DAG.getTargetExternalSymbol(Sym, PtrVT);
Anton Korobeynikovba0e81d2009-05-03 13:14:46 +0000772
Mehdi Amini44ede332015-07-09 02:09:04 +0000773 return DAG.getNode(MSP430ISD::Wrapper, dl, PtrVT, Result);
Anton Korobeynikovba0e81d2009-05-03 13:14:46 +0000774}
775
Anton Korobeynikovebbdfef2010-05-01 12:04:32 +0000776SDValue MSP430TargetLowering::LowerBlockAddress(SDValue Op,
777 SelectionDAG &DAG) const {
Andrew Trickef9de2a2013-05-25 02:42:55 +0000778 SDLoc dl(Op);
Mehdi Amini44ede332015-07-09 02:09:04 +0000779 auto PtrVT = getPointerTy(DAG.getDataLayout());
Anton Korobeynikovebbdfef2010-05-01 12:04:32 +0000780 const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
Mehdi Amini44ede332015-07-09 02:09:04 +0000781 SDValue Result = DAG.getTargetBlockAddress(BA, PtrVT);
Anton Korobeynikovebbdfef2010-05-01 12:04:32 +0000782
Mehdi Amini44ede332015-07-09 02:09:04 +0000783 return DAG.getNode(MSP430ISD::Wrapper, dl, PtrVT, Result);
Anton Korobeynikovebbdfef2010-05-01 12:04:32 +0000784}
785
Anton Korobeynikov2983dcb2009-10-21 19:16:49 +0000786static SDValue EmitCMP(SDValue &LHS, SDValue &RHS, SDValue &TargetCC,
Benjamin Kramerbdc49562016-06-12 15:39:02 +0000787 ISD::CondCode CC, const SDLoc &dl, SelectionDAG &DAG) {
Anton Korobeynikov96272012009-05-03 13:12:06 +0000788 // FIXME: Handle bittests someday
789 assert(!LHS.getValueType().isFloatingPoint() && "We don't handle FP yet");
790
791 // FIXME: Handle jump negative someday
Anton Korobeynikov2983dcb2009-10-21 19:16:49 +0000792 MSP430CC::CondCodes TCC = MSP430CC::COND_INVALID;
Anton Korobeynikov96272012009-05-03 13:12:06 +0000793 switch (CC) {
Torok Edwinfbcc6632009-07-14 16:55:14 +0000794 default: llvm_unreachable("Invalid integer condition!");
Anton Korobeynikov96272012009-05-03 13:12:06 +0000795 case ISD::SETEQ:
Anton Korobeynikov2983dcb2009-10-21 19:16:49 +0000796 TCC = MSP430CC::COND_E; // aka COND_Z
Anton Korobeynikovcefa7ad2010-01-15 01:29:49 +0000797 // Minor optimization: if LHS is a constant, swap operands, then the
Anton Korobeynikovabdf86d2009-11-22 01:14:08 +0000798 // constant can be folded into comparison.
Anton Korobeynikovcefa7ad2010-01-15 01:29:49 +0000799 if (LHS.getOpcode() == ISD::Constant)
Anton Korobeynikovabdf86d2009-11-22 01:14:08 +0000800 std::swap(LHS, RHS);
Anton Korobeynikov96272012009-05-03 13:12:06 +0000801 break;
802 case ISD::SETNE:
Anton Korobeynikov2983dcb2009-10-21 19:16:49 +0000803 TCC = MSP430CC::COND_NE; // aka COND_NZ
Anton Korobeynikovcefa7ad2010-01-15 01:29:49 +0000804 // Minor optimization: if LHS is a constant, swap operands, then the
Anton Korobeynikovabdf86d2009-11-22 01:14:08 +0000805 // constant can be folded into comparison.
Anton Korobeynikovcefa7ad2010-01-15 01:29:49 +0000806 if (LHS.getOpcode() == ISD::Constant)
Anton Korobeynikovabdf86d2009-11-22 01:14:08 +0000807 std::swap(LHS, RHS);
Anton Korobeynikov96272012009-05-03 13:12:06 +0000808 break;
809 case ISD::SETULE:
810 std::swap(LHS, RHS); // FALLTHROUGH
811 case ISD::SETUGE:
Anton Korobeynikov6826ce72010-01-15 21:18:02 +0000812 // Turn lhs u>= rhs with lhs constant into rhs u< lhs+1, this allows us to
813 // fold constant into instruction.
814 if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {
815 LHS = RHS;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000816 RHS = DAG.getConstant(C->getSExtValue() + 1, dl, C->getValueType(0));
Anton Korobeynikov6826ce72010-01-15 21:18:02 +0000817 TCC = MSP430CC::COND_LO;
818 break;
819 }
Anton Korobeynikov2983dcb2009-10-21 19:16:49 +0000820 TCC = MSP430CC::COND_HS; // aka COND_C
Anton Korobeynikov96272012009-05-03 13:12:06 +0000821 break;
822 case ISD::SETUGT:
823 std::swap(LHS, RHS); // FALLTHROUGH
824 case ISD::SETULT:
Anton Korobeynikov6826ce72010-01-15 21:18:02 +0000825 // Turn lhs u< rhs with lhs constant into rhs u>= lhs+1, this allows us to
826 // fold constant into instruction.
827 if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {
828 LHS = RHS;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000829 RHS = DAG.getConstant(C->getSExtValue() + 1, dl, C->getValueType(0));
Anton Korobeynikov6826ce72010-01-15 21:18:02 +0000830 TCC = MSP430CC::COND_HS;
831 break;
832 }
Anton Korobeynikov2983dcb2009-10-21 19:16:49 +0000833 TCC = MSP430CC::COND_LO; // aka COND_NC
Anton Korobeynikov96272012009-05-03 13:12:06 +0000834 break;
835 case ISD::SETLE:
836 std::swap(LHS, RHS); // FALLTHROUGH
837 case ISD::SETGE:
Anton Korobeynikov6826ce72010-01-15 21:18:02 +0000838 // Turn lhs >= rhs with lhs constant into rhs < lhs+1, this allows us to
839 // fold constant into instruction.
840 if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {
841 LHS = RHS;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000842 RHS = DAG.getConstant(C->getSExtValue() + 1, dl, C->getValueType(0));
Anton Korobeynikov6826ce72010-01-15 21:18:02 +0000843 TCC = MSP430CC::COND_L;
844 break;
845 }
Anton Korobeynikov2983dcb2009-10-21 19:16:49 +0000846 TCC = MSP430CC::COND_GE;
Anton Korobeynikov96272012009-05-03 13:12:06 +0000847 break;
848 case ISD::SETGT:
849 std::swap(LHS, RHS); // FALLTHROUGH
850 case ISD::SETLT:
Anton Korobeynikov6826ce72010-01-15 21:18:02 +0000851 // Turn lhs < rhs with lhs constant into rhs >= lhs+1, this allows us to
852 // fold constant into instruction.
853 if (const ConstantSDNode * C = dyn_cast<ConstantSDNode>(LHS)) {
854 LHS = RHS;
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000855 RHS = DAG.getConstant(C->getSExtValue() + 1, dl, C->getValueType(0));
Anton Korobeynikov6826ce72010-01-15 21:18:02 +0000856 TCC = MSP430CC::COND_GE;
857 break;
858 }
Anton Korobeynikov2983dcb2009-10-21 19:16:49 +0000859 TCC = MSP430CC::COND_L;
Anton Korobeynikov96272012009-05-03 13:12:06 +0000860 break;
861 }
862
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000863 TargetCC = DAG.getConstant(TCC, dl, MVT::i8);
Chris Lattner3e5fbd72010-12-21 02:38:05 +0000864 return DAG.getNode(MSP430ISD::CMP, dl, MVT::Glue, LHS, RHS);
Anton Korobeynikov96272012009-05-03 13:12:06 +0000865}
866
Anton Korobeynikov47fcd722009-05-03 13:19:09 +0000867
Dan Gohman21cea8a2010-04-17 15:26:15 +0000868SDValue MSP430TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
Anton Korobeynikov96272012009-05-03 13:12:06 +0000869 SDValue Chain = Op.getOperand(0);
Anton Korobeynikov47fcd722009-05-03 13:19:09 +0000870 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
871 SDValue LHS = Op.getOperand(2);
872 SDValue RHS = Op.getOperand(3);
873 SDValue Dest = Op.getOperand(4);
Andrew Trickef9de2a2013-05-25 02:42:55 +0000874 SDLoc dl (Op);
Anton Korobeynikov96272012009-05-03 13:12:06 +0000875
Anton Korobeynikov2983dcb2009-10-21 19:16:49 +0000876 SDValue TargetCC;
Anton Korobeynikov47fcd722009-05-03 13:19:09 +0000877 SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG);
Anton Korobeynikov96272012009-05-03 13:12:06 +0000878
Anton Korobeynikov47fcd722009-05-03 13:19:09 +0000879 return DAG.getNode(MSP430ISD::BR_CC, dl, Op.getValueType(),
Anton Korobeynikov2983dcb2009-10-21 19:16:49 +0000880 Chain, Dest, TargetCC, Flag);
Anton Korobeynikov96272012009-05-03 13:12:06 +0000881}
882
Dan Gohman21cea8a2010-04-17 15:26:15 +0000883SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
Anton Korobeynikove27e0282009-12-11 23:01:29 +0000884 SDValue LHS = Op.getOperand(0);
885 SDValue RHS = Op.getOperand(1);
Andrew Trickef9de2a2013-05-25 02:42:55 +0000886 SDLoc dl (Op);
Anton Korobeynikove27e0282009-12-11 23:01:29 +0000887
888 // If we are doing an AND and testing against zero, then the CMP
889 // will not be generated. The AND (or BIT) will generate the condition codes,
890 // but they are different from CMP.
Anton Korobeynikov93a7d022010-01-15 21:18:18 +0000891 // FIXME: since we're doing a post-processing, use a pseudoinstr here, so
892 // lowering & isel wouldn't diverge.
Anton Korobeynikove27e0282009-12-11 23:01:29 +0000893 bool andCC = false;
894 if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS)) {
895 if (RHSC->isNullValue() && LHS.hasOneUse() &&
896 (LHS.getOpcode() == ISD::AND ||
897 (LHS.getOpcode() == ISD::TRUNCATE &&
898 LHS.getOperand(0).getOpcode() == ISD::AND))) {
899 andCC = true;
900 }
901 }
902 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
903 SDValue TargetCC;
904 SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG);
905
906 // Get the condition codes directly from the status register, if its easy.
907 // Otherwise a branch will be generated. Note that the AND and BIT
908 // instructions generate different flags than CMP, the carry bit can be used
909 // for NE/EQ.
910 bool Invert = false;
911 bool Shift = false;
912 bool Convert = true;
913 switch (cast<ConstantSDNode>(TargetCC)->getZExtValue()) {
914 default:
915 Convert = false;
916 break;
917 case MSP430CC::COND_HS:
Job Noormaneb19aea2014-09-10 06:58:14 +0000918 // Res = SR & 1, no processing is required
Anton Korobeynikove27e0282009-12-11 23:01:29 +0000919 break;
Anton Korobeynikov93a7d022010-01-15 21:18:18 +0000920 case MSP430CC::COND_LO:
Job Noormaneb19aea2014-09-10 06:58:14 +0000921 // Res = ~(SR & 1)
Anton Korobeynikove27e0282009-12-11 23:01:29 +0000922 Invert = true;
923 break;
Anton Korobeynikov93a7d022010-01-15 21:18:18 +0000924 case MSP430CC::COND_NE:
Anton Korobeynikove27e0282009-12-11 23:01:29 +0000925 if (andCC) {
Job Noormaneb19aea2014-09-10 06:58:14 +0000926 // C = ~Z, thus Res = SR & 1, no processing is required
Anton Korobeynikove27e0282009-12-11 23:01:29 +0000927 } else {
Job Noormaneb19aea2014-09-10 06:58:14 +0000928 // Res = ~((SR >> 1) & 1)
Anton Korobeynikove27e0282009-12-11 23:01:29 +0000929 Shift = true;
Anton Korobeynikove96503f2010-02-21 12:28:58 +0000930 Invert = true;
Anton Korobeynikove27e0282009-12-11 23:01:29 +0000931 }
932 break;
Anton Korobeynikov93a7d022010-01-15 21:18:18 +0000933 case MSP430CC::COND_E:
Anton Korobeynikove96503f2010-02-21 12:28:58 +0000934 Shift = true;
Job Noormaneb19aea2014-09-10 06:58:14 +0000935 // C = ~Z for AND instruction, thus we can put Res = ~(SR & 1), however,
936 // Res = (SR >> 1) & 1 is 1 word shorter.
Anton Korobeynikove27e0282009-12-11 23:01:29 +0000937 break;
938 }
939 EVT VT = Op.getValueType();
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000940 SDValue One = DAG.getConstant(1, dl, VT);
Anton Korobeynikove27e0282009-12-11 23:01:29 +0000941 if (Convert) {
Job Noormaneb19aea2014-09-10 06:58:14 +0000942 SDValue SR = DAG.getCopyFromReg(DAG.getEntryNode(), dl, MSP430::SR,
Anton Korobeynikov93a7d022010-01-15 21:18:18 +0000943 MVT::i16, Flag);
Anton Korobeynikove27e0282009-12-11 23:01:29 +0000944 if (Shift)
945 // FIXME: somewhere this is turned into a SRL, lower it MSP specific?
946 SR = DAG.getNode(ISD::SRA, dl, MVT::i16, SR, One);
947 SR = DAG.getNode(ISD::AND, dl, MVT::i16, SR, One);
948 if (Invert)
949 SR = DAG.getNode(ISD::XOR, dl, MVT::i16, SR, One);
950 return SR;
951 } else {
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +0000952 SDValue Zero = DAG.getConstant(0, dl, VT);
Chris Lattner3e5fbd72010-12-21 02:38:05 +0000953 SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue);
Benjamin Kramerea68a942015-02-19 15:26:17 +0000954 SDValue Ops[] = {One, Zero, TargetCC, Flag};
Craig Topper48d114b2014-04-26 18:35:24 +0000955 return DAG.getNode(MSP430ISD::SELECT_CC, dl, VTs, Ops);
Anton Korobeynikove27e0282009-12-11 23:01:29 +0000956 }
957}
958
Dan Gohman21cea8a2010-04-17 15:26:15 +0000959SDValue MSP430TargetLowering::LowerSELECT_CC(SDValue Op,
960 SelectionDAG &DAG) const {
Anton Korobeynikov47fcd722009-05-03 13:19:09 +0000961 SDValue LHS = Op.getOperand(0);
962 SDValue RHS = Op.getOperand(1);
963 SDValue TrueV = Op.getOperand(2);
964 SDValue FalseV = Op.getOperand(3);
965 ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
Andrew Trickef9de2a2013-05-25 02:42:55 +0000966 SDLoc dl (Op);
Anton Korobeynikovb6321e152009-05-03 13:12:23 +0000967
Anton Korobeynikov2983dcb2009-10-21 19:16:49 +0000968 SDValue TargetCC;
Anton Korobeynikov47fcd722009-05-03 13:19:09 +0000969 SDValue Flag = EmitCMP(LHS, RHS, TargetCC, CC, dl, DAG);
Anton Korobeynikovb6321e152009-05-03 13:12:23 +0000970
Chris Lattner3e5fbd72010-12-21 02:38:05 +0000971 SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue);
Benjamin Kramerea68a942015-02-19 15:26:17 +0000972 SDValue Ops[] = {TrueV, FalseV, TargetCC, Flag};
Anton Korobeynikovb6321e152009-05-03 13:12:23 +0000973
Craig Topper48d114b2014-04-26 18:35:24 +0000974 return DAG.getNode(MSP430ISD::SELECT_CC, dl, VTs, Ops);
Anton Korobeynikovb6321e152009-05-03 13:12:23 +0000975}
976
Anton Korobeynikov29747e92009-05-03 13:17:49 +0000977SDValue MSP430TargetLowering::LowerSIGN_EXTEND(SDValue Op,
Dan Gohman21cea8a2010-04-17 15:26:15 +0000978 SelectionDAG &DAG) const {
Anton Korobeynikov29747e92009-05-03 13:17:49 +0000979 SDValue Val = Op.getOperand(0);
Owen Anderson53aa7a92009-08-10 22:56:29 +0000980 EVT VT = Op.getValueType();
Andrew Trickef9de2a2013-05-25 02:42:55 +0000981 SDLoc dl(Op);
Anton Korobeynikov29747e92009-05-03 13:17:49 +0000982
Owen Anderson9f944592009-08-11 20:47:22 +0000983 assert(VT == MVT::i16 && "Only support i16 for now!");
Anton Korobeynikov29747e92009-05-03 13:17:49 +0000984
985 return DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, VT,
986 DAG.getNode(ISD::ANY_EXTEND, dl, VT, Val),
987 DAG.getValueType(Val.getValueType()));
988}
989
Dan Gohman21cea8a2010-04-17 15:26:15 +0000990SDValue
991MSP430TargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) const {
Anton Korobeynikovff4ab512009-12-07 02:28:10 +0000992 MachineFunction &MF = DAG.getMachineFunction();
993 MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>();
994 int ReturnAddrIndex = FuncInfo->getRAIndex();
Mehdi Amini44ede332015-07-09 02:09:04 +0000995 auto PtrVT = getPointerTy(MF.getDataLayout());
Anton Korobeynikovff4ab512009-12-07 02:28:10 +0000996
997 if (ReturnAddrIndex == 0) {
998 // Set up a frame object for the return address.
Mehdi Amini44ede332015-07-09 02:09:04 +0000999 uint64_t SlotSize = MF.getDataLayout().getPointerSize();
Anton Korobeynikovff4ab512009-12-07 02:28:10 +00001000 ReturnAddrIndex = MF.getFrameInfo()->CreateFixedObject(SlotSize, -SlotSize,
Evan Cheng0664a672010-07-03 00:40:23 +00001001 true);
Anton Korobeynikovff4ab512009-12-07 02:28:10 +00001002 FuncInfo->setRAIndex(ReturnAddrIndex);
1003 }
1004
Mehdi Amini44ede332015-07-09 02:09:04 +00001005 return DAG.getFrameIndex(ReturnAddrIndex, PtrVT);
Anton Korobeynikovff4ab512009-12-07 02:28:10 +00001006}
1007
Dan Gohman21cea8a2010-04-17 15:26:15 +00001008SDValue MSP430TargetLowering::LowerRETURNADDR(SDValue Op,
1009 SelectionDAG &DAG) const {
Evan Cheng168ced92010-05-22 01:47:14 +00001010 MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
1011 MFI->setReturnAddressIsTaken(true);
1012
Bill Wendling908bf812014-01-06 00:43:20 +00001013 if (verifyReturnAddressArgumentIsConstant(Op, DAG))
Bill Wendlingdf7dd282014-01-05 01:47:20 +00001014 return SDValue();
Bill Wendlingdf7dd282014-01-05 01:47:20 +00001015
Anton Korobeynikovff4ab512009-12-07 02:28:10 +00001016 unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
Andrew Trickef9de2a2013-05-25 02:42:55 +00001017 SDLoc dl(Op);
Mehdi Amini44ede332015-07-09 02:09:04 +00001018 auto PtrVT = getPointerTy(DAG.getDataLayout());
Anton Korobeynikovff4ab512009-12-07 02:28:10 +00001019
1020 if (Depth > 0) {
1021 SDValue FrameAddr = LowerFRAMEADDR(Op, DAG);
1022 SDValue Offset =
Mehdi Amini44ede332015-07-09 02:09:04 +00001023 DAG.getConstant(DAG.getDataLayout().getPointerSize(), dl, MVT::i16);
1024 return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(),
1025 DAG.getNode(ISD::ADD, dl, PtrVT, FrameAddr, Offset),
Justin Lebar9c375812016-07-15 18:27:10 +00001026 MachinePointerInfo());
Anton Korobeynikovff4ab512009-12-07 02:28:10 +00001027 }
1028
1029 // Just load the return address.
1030 SDValue RetAddrFI = getReturnAddressFrameIndex(DAG);
Mehdi Amini44ede332015-07-09 02:09:04 +00001031 return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), RetAddrFI,
Justin Lebar9c375812016-07-15 18:27:10 +00001032 MachinePointerInfo());
Anton Korobeynikovff4ab512009-12-07 02:28:10 +00001033}
1034
Dan Gohman21cea8a2010-04-17 15:26:15 +00001035SDValue MSP430TargetLowering::LowerFRAMEADDR(SDValue Op,
1036 SelectionDAG &DAG) const {
Anton Korobeynikovff4ab512009-12-07 02:28:10 +00001037 MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
1038 MFI->setFrameAddressIsTaken(true);
Evan Cheng168ced92010-05-22 01:47:14 +00001039
Anton Korobeynikovff4ab512009-12-07 02:28:10 +00001040 EVT VT = Op.getValueType();
Andrew Trickef9de2a2013-05-25 02:42:55 +00001041 SDLoc dl(Op); // FIXME probably not meaningful
Anton Korobeynikovff4ab512009-12-07 02:28:10 +00001042 unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
1043 SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl,
Job Noormaneb19aea2014-09-10 06:58:14 +00001044 MSP430::FP, VT);
Anton Korobeynikovff4ab512009-12-07 02:28:10 +00001045 while (Depth--)
Chris Lattner7727d052010-09-21 06:44:06 +00001046 FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr,
Justin Lebar9c375812016-07-15 18:27:10 +00001047 MachinePointerInfo());
Anton Korobeynikovff4ab512009-12-07 02:28:10 +00001048 return FrameAddr;
1049}
1050
Anton Korobeynikov568afeb2012-11-21 17:28:27 +00001051SDValue MSP430TargetLowering::LowerVASTART(SDValue Op,
1052 SelectionDAG &DAG) const {
1053 MachineFunction &MF = DAG.getMachineFunction();
1054 MSP430MachineFunctionInfo *FuncInfo = MF.getInfo<MSP430MachineFunctionInfo>();
Mehdi Amini44ede332015-07-09 02:09:04 +00001055 auto PtrVT = getPointerTy(DAG.getDataLayout());
Anton Korobeynikov568afeb2012-11-21 17:28:27 +00001056
1057 // Frame index of first vararg argument
Mehdi Amini44ede332015-07-09 02:09:04 +00001058 SDValue FrameIndex =
1059 DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);
Anton Korobeynikov568afeb2012-11-21 17:28:27 +00001060 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
1061
1062 // Create a store of the frame index to the location operand
Justin Lebar9c375812016-07-15 18:27:10 +00001063 return DAG.getStore(Op.getOperand(0), SDLoc(Op), FrameIndex, Op.getOperand(1),
1064 MachinePointerInfo(SV));
Anton Korobeynikov568afeb2012-11-21 17:28:27 +00001065}
1066
Anton Korobeynikov82bedb12013-07-01 19:44:44 +00001067SDValue MSP430TargetLowering::LowerJumpTable(SDValue Op,
1068 SelectionDAG &DAG) const {
1069 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
Mehdi Amini44ede332015-07-09 02:09:04 +00001070 auto PtrVT = getPointerTy(DAG.getDataLayout());
1071 SDValue Result = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
1072 return DAG.getNode(MSP430ISD::Wrapper, SDLoc(JT), PtrVT, Result);
Anton Korobeynikov82bedb12013-07-01 19:44:44 +00001073}
1074
Anton Korobeynikovd3c83192009-11-07 17:15:06 +00001075/// getPostIndexedAddressParts - returns true by value, base pointer and
1076/// offset pointer and addressing mode by reference if this node can be
1077/// combined with a load / store to form a post-indexed load / store.
1078bool MSP430TargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
1079 SDValue &Base,
1080 SDValue &Offset,
1081 ISD::MemIndexedMode &AM,
1082 SelectionDAG &DAG) const {
1083
1084 LoadSDNode *LD = cast<LoadSDNode>(N);
1085 if (LD->getExtensionType() != ISD::NON_EXTLOAD)
1086 return false;
1087
1088 EVT VT = LD->getMemoryVT();
1089 if (VT != MVT::i8 && VT != MVT::i16)
1090 return false;
1091
1092 if (Op->getOpcode() != ISD::ADD)
1093 return false;
1094
1095 if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Op->getOperand(1))) {
1096 uint64_t RHSC = RHS->getZExtValue();
1097 if ((VT == MVT::i16 && RHSC != 2) ||
1098 (VT == MVT::i8 && RHSC != 1))
1099 return false;
1100
1101 Base = Op->getOperand(0);
Sergey Dmitrouk842a51b2015-04-28 14:05:47 +00001102 Offset = DAG.getConstant(RHSC, SDLoc(N), VT);
Anton Korobeynikovd3c83192009-11-07 17:15:06 +00001103 AM = ISD::POST_INC;
1104 return true;
1105 }
1106
1107 return false;
1108}
1109
1110
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +00001111const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const {
Matthias Braund04893f2015-05-07 21:33:59 +00001112 switch ((MSP430ISD::NodeType)Opcode) {
1113 case MSP430ISD::FIRST_NUMBER: break;
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +00001114 case MSP430ISD::RET_FLAG: return "MSP430ISD::RET_FLAG";
Anton Korobeynikov24a63162009-12-07 02:28:41 +00001115 case MSP430ISD::RETI_FLAG: return "MSP430ISD::RETI_FLAG";
Anton Korobeynikov15a515b2009-05-03 13:03:33 +00001116 case MSP430ISD::RRA: return "MSP430ISD::RRA";
Anton Korobeynikov61763b52009-05-03 13:16:17 +00001117 case MSP430ISD::RLA: return "MSP430ISD::RLA";
1118 case MSP430ISD::RRC: return "MSP430ISD::RRC";
Anton Korobeynikovec3f0b32009-05-03 13:07:54 +00001119 case MSP430ISD::CALL: return "MSP430ISD::CALL";
Anton Korobeynikovcfc97052009-05-03 13:08:33 +00001120 case MSP430ISD::Wrapper: return "MSP430ISD::Wrapper";
Anton Korobeynikov47fcd722009-05-03 13:19:09 +00001121 case MSP430ISD::BR_CC: return "MSP430ISD::BR_CC";
Anton Korobeynikov96272012009-05-03 13:12:06 +00001122 case MSP430ISD::CMP: return "MSP430ISD::CMP";
Matthias Braund04893f2015-05-07 21:33:59 +00001123 case MSP430ISD::SETCC: return "MSP430ISD::SETCC";
Anton Korobeynikov47fcd722009-05-03 13:19:09 +00001124 case MSP430ISD::SELECT_CC: return "MSP430ISD::SELECT_CC";
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001125 case MSP430ISD::SHL: return "MSP430ISD::SHL";
1126 case MSP430ISD::SRA: return "MSP430ISD::SRA";
Matthias Braund04893f2015-05-07 21:33:59 +00001127 case MSP430ISD::SRL: return "MSP430ISD::SRL";
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +00001128 }
Matthias Braund04893f2015-05-07 21:33:59 +00001129 return nullptr;
Anton Korobeynikov7bfc3ea2009-05-03 12:59:50 +00001130}
Anton Korobeynikovb6321e152009-05-03 13:12:23 +00001131
Chris Lattner229907c2011-07-18 04:54:35 +00001132bool MSP430TargetLowering::isTruncateFree(Type *Ty1,
1133 Type *Ty2) const {
Duncan Sands9dff9be2010-02-15 16:12:20 +00001134 if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy())
Anton Korobeynikova6450df2010-01-15 21:19:43 +00001135 return false;
1136
1137 return (Ty1->getPrimitiveSizeInBits() > Ty2->getPrimitiveSizeInBits());
1138}
1139
1140bool MSP430TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const {
1141 if (!VT1.isInteger() || !VT2.isInteger())
1142 return false;
1143
1144 return (VT1.getSizeInBits() > VT2.getSizeInBits());
1145}
1146
Chris Lattner229907c2011-07-18 04:54:35 +00001147bool MSP430TargetLowering::isZExtFree(Type *Ty1, Type *Ty2) const {
Anton Korobeynikova6450df2010-01-15 21:19:43 +00001148 // MSP430 implicitly zero-extends 8-bit results in 16-bit registers.
Duncan Sands9dff9be2010-02-15 16:12:20 +00001149 return 0 && Ty1->isIntegerTy(8) && Ty2->isIntegerTy(16);
Anton Korobeynikova6450df2010-01-15 21:19:43 +00001150}
1151
1152bool MSP430TargetLowering::isZExtFree(EVT VT1, EVT VT2) const {
1153 // MSP430 implicitly zero-extends 8-bit results in 16-bit registers.
1154 return 0 && VT1 == MVT::i8 && VT2 == MVT::i16;
1155}
1156
Eli Bendersky39e7c6e2012-12-18 18:21:29 +00001157bool MSP430TargetLowering::isZExtFree(SDValue Val, EVT VT2) const {
1158 return isZExtFree(Val.getValueType(), VT2);
1159}
1160
Anton Korobeynikovb6321e152009-05-03 13:12:23 +00001161//===----------------------------------------------------------------------===//
1162// Other Lowering Code
1163//===----------------------------------------------------------------------===//
1164
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00001165MachineBasicBlock *
1166MSP430TargetLowering::EmitShiftInstr(MachineInstr &MI,
Dan Gohman25c16532010-05-01 00:01:06 +00001167 MachineBasicBlock *BB) const {
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001168 MachineFunction *F = BB->getParent();
1169 MachineRegisterInfo &RI = F->getRegInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00001170 DebugLoc dl = MI.getDebugLoc();
Eric Christopherfbd9fba2015-01-29 23:46:42 +00001171 const TargetInstrInfo &TII = *F->getSubtarget().getInstrInfo();
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001172
1173 unsigned Opc;
1174 const TargetRegisterClass * RC;
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00001175 switch (MI.getOpcode()) {
Craig Toppere55c5562012-02-07 02:50:20 +00001176 default: llvm_unreachable("Invalid shift opcode!");
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001177 case MSP430::Shl8:
1178 Opc = MSP430::SHL8r1;
Craig Topperc7242e02012-04-20 07:30:17 +00001179 RC = &MSP430::GR8RegClass;
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001180 break;
1181 case MSP430::Shl16:
1182 Opc = MSP430::SHL16r1;
Craig Topperc7242e02012-04-20 07:30:17 +00001183 RC = &MSP430::GR16RegClass;
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001184 break;
1185 case MSP430::Sra8:
1186 Opc = MSP430::SAR8r1;
Craig Topperc7242e02012-04-20 07:30:17 +00001187 RC = &MSP430::GR8RegClass;
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001188 break;
1189 case MSP430::Sra16:
1190 Opc = MSP430::SAR16r1;
Craig Topperc7242e02012-04-20 07:30:17 +00001191 RC = &MSP430::GR16RegClass;
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001192 break;
1193 case MSP430::Srl8:
1194 Opc = MSP430::SAR8r1c;
Craig Topperc7242e02012-04-20 07:30:17 +00001195 RC = &MSP430::GR8RegClass;
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001196 break;
1197 case MSP430::Srl16:
1198 Opc = MSP430::SAR16r1c;
Craig Topperc7242e02012-04-20 07:30:17 +00001199 RC = &MSP430::GR16RegClass;
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001200 break;
1201 }
1202
1203 const BasicBlock *LLVM_BB = BB->getBasicBlock();
Duncan P. N. Exon Smithc4829de2015-10-20 01:18:39 +00001204 MachineFunction::iterator I = ++BB->getIterator();
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001205
1206 // Create loop block
1207 MachineBasicBlock *LoopBB = F->CreateMachineBasicBlock(LLVM_BB);
1208 MachineBasicBlock *RemBB = F->CreateMachineBasicBlock(LLVM_BB);
1209
1210 F->insert(I, LoopBB);
1211 F->insert(I, RemBB);
1212
1213 // Update machine-CFG edges by transferring all successors of the current
1214 // block to the block containing instructions after shift.
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +00001215 RemBB->splice(RemBB->begin(), BB, std::next(MachineBasicBlock::iterator(MI)),
Dan Gohman34396292010-07-06 20:24:04 +00001216 BB->end());
1217 RemBB->transferSuccessorsAndUpdatePHIs(BB);
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001218
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001219 // Add adges BB => LoopBB => RemBB, BB => RemBB, LoopBB => LoopBB
1220 BB->addSuccessor(LoopBB);
1221 BB->addSuccessor(RemBB);
1222 LoopBB->addSuccessor(RemBB);
1223 LoopBB->addSuccessor(LoopBB);
1224
Craig Topperc7242e02012-04-20 07:30:17 +00001225 unsigned ShiftAmtReg = RI.createVirtualRegister(&MSP430::GR8RegClass);
1226 unsigned ShiftAmtReg2 = RI.createVirtualRegister(&MSP430::GR8RegClass);
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001227 unsigned ShiftReg = RI.createVirtualRegister(RC);
1228 unsigned ShiftReg2 = RI.createVirtualRegister(RC);
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00001229 unsigned ShiftAmtSrcReg = MI.getOperand(2).getReg();
1230 unsigned SrcReg = MI.getOperand(1).getReg();
1231 unsigned DstReg = MI.getOperand(0).getReg();
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001232
1233 // BB:
1234 // cmp 0, N
1235 // je RemBB
Anton Korobeynikovcefa7ad2010-01-15 01:29:49 +00001236 BuildMI(BB, dl, TII.get(MSP430::CMP8ri))
1237 .addReg(ShiftAmtSrcReg).addImm(0);
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001238 BuildMI(BB, dl, TII.get(MSP430::JCC))
1239 .addMBB(RemBB)
1240 .addImm(MSP430CC::COND_E);
1241
1242 // LoopBB:
1243 // ShiftReg = phi [%SrcReg, BB], [%ShiftReg2, LoopBB]
1244 // ShiftAmt = phi [%N, BB], [%ShiftAmt2, LoopBB]
1245 // ShiftReg2 = shift ShiftReg
1246 // ShiftAmt2 = ShiftAmt - 1;
1247 BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftReg)
1248 .addReg(SrcReg).addMBB(BB)
1249 .addReg(ShiftReg2).addMBB(LoopBB);
1250 BuildMI(LoopBB, dl, TII.get(MSP430::PHI), ShiftAmtReg)
1251 .addReg(ShiftAmtSrcReg).addMBB(BB)
1252 .addReg(ShiftAmtReg2).addMBB(LoopBB);
1253 BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2)
1254 .addReg(ShiftReg);
1255 BuildMI(LoopBB, dl, TII.get(MSP430::SUB8ri), ShiftAmtReg2)
1256 .addReg(ShiftAmtReg).addImm(1);
1257 BuildMI(LoopBB, dl, TII.get(MSP430::JCC))
1258 .addMBB(LoopBB)
1259 .addImm(MSP430CC::COND_NE);
1260
1261 // RemBB:
1262 // DestReg = phi [%SrcReg, BB], [%ShiftReg, LoopBB]
Dan Gohman34396292010-07-06 20:24:04 +00001263 BuildMI(*RemBB, RemBB->begin(), dl, TII.get(MSP430::PHI), DstReg)
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001264 .addReg(SrcReg).addMBB(BB)
1265 .addReg(ShiftReg2).addMBB(LoopBB);
1266
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00001267 MI.eraseFromParent(); // The pseudo instruction is gone now.
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001268 return RemBB;
1269}
1270
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00001271MachineBasicBlock *
1272MSP430TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
Dan Gohman25c16532010-05-01 00:01:06 +00001273 MachineBasicBlock *BB) const {
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00001274 unsigned Opc = MI.getOpcode();
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001275
1276 if (Opc == MSP430::Shl8 || Opc == MSP430::Shl16 ||
1277 Opc == MSP430::Sra8 || Opc == MSP430::Sra16 ||
1278 Opc == MSP430::Srl8 || Opc == MSP430::Srl16)
Dan Gohman25c16532010-05-01 00:01:06 +00001279 return EmitShiftInstr(MI, BB);
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001280
Eric Christopherfbd9fba2015-01-29 23:46:42 +00001281 const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo();
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00001282 DebugLoc dl = MI.getDebugLoc();
Anton Korobeynikovd8f32092009-12-12 18:55:37 +00001283
1284 assert((Opc == MSP430::Select16 || Opc == MSP430::Select8) &&
Anton Korobeynikovb6321e152009-05-03 13:12:23 +00001285 "Unexpected instr type to insert");
1286
1287 // To "insert" a SELECT instruction, we actually have to insert the diamond
1288 // control-flow pattern. The incoming instruction knows the destination vreg
1289 // to set, the condition code register to branch on, the true/false values to
1290 // select between, and a branch opcode to use.
1291 const BasicBlock *LLVM_BB = BB->getBasicBlock();
Duncan P. N. Exon Smithc4829de2015-10-20 01:18:39 +00001292 MachineFunction::iterator I = ++BB->getIterator();
Anton Korobeynikovb6321e152009-05-03 13:12:23 +00001293
1294 // thisMBB:
1295 // ...
1296 // TrueVal = ...
1297 // cmpTY ccX, r1, r2
1298 // jCC copy1MBB
1299 // fallthrough --> copy0MBB
1300 MachineBasicBlock *thisMBB = BB;
1301 MachineFunction *F = BB->getParent();
1302 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
1303 MachineBasicBlock *copy1MBB = F->CreateMachineBasicBlock(LLVM_BB);
Anton Korobeynikovb6321e152009-05-03 13:12:23 +00001304 F->insert(I, copy0MBB);
1305 F->insert(I, copy1MBB);
1306 // Update machine-CFG edges by transferring all successors of the current
1307 // block to the new block which will contain the Phi node for the select.
Dan Gohman34396292010-07-06 20:24:04 +00001308 copy1MBB->splice(copy1MBB->begin(), BB,
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +00001309 std::next(MachineBasicBlock::iterator(MI)), BB->end());
Dan Gohman34396292010-07-06 20:24:04 +00001310 copy1MBB->transferSuccessorsAndUpdatePHIs(BB);
Anton Korobeynikovb6321e152009-05-03 13:12:23 +00001311 // Next, add the true and fallthrough blocks as its successors.
1312 BB->addSuccessor(copy0MBB);
1313 BB->addSuccessor(copy1MBB);
1314
Dan Gohman34396292010-07-06 20:24:04 +00001315 BuildMI(BB, dl, TII.get(MSP430::JCC))
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00001316 .addMBB(copy1MBB)
1317 .addImm(MI.getOperand(3).getImm());
Dan Gohman34396292010-07-06 20:24:04 +00001318
Anton Korobeynikovb6321e152009-05-03 13:12:23 +00001319 // copy0MBB:
1320 // %FalseValue = ...
1321 // # fallthrough to copy1MBB
1322 BB = copy0MBB;
1323
1324 // Update machine-CFG edges
1325 BB->addSuccessor(copy1MBB);
1326
1327 // copy1MBB:
1328 // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
1329 // ...
1330 BB = copy1MBB;
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00001331 BuildMI(*BB, BB->begin(), dl, TII.get(MSP430::PHI), MI.getOperand(0).getReg())
1332 .addReg(MI.getOperand(2).getReg())
1333 .addMBB(copy0MBB)
1334 .addReg(MI.getOperand(1).getReg())
1335 .addMBB(thisMBB);
Anton Korobeynikovb6321e152009-05-03 13:12:23 +00001336
Duncan P. N. Exon Smithe4f5e4f2016-06-30 22:52:52 +00001337 MI.eraseFromParent(); // The pseudo instruction is gone now.
Anton Korobeynikovb6321e152009-05-03 13:12:23 +00001338 return BB;
1339}