1 //===-- XCoreISelLowering.cpp - XCore 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 XCoreTargetLowering class.
11 //
12 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "xcore-lower"
16 #include "XCoreISelLowering.h"
17 #include "XCoreMachineFunctionInfo.h"
18 #include "XCore.h"
19 #include "XCoreTargetMachine.h"
20 #include "XCoreSubtarget.h"
21 #include "llvm/DerivedTypes.h"
22 #include "llvm/Function.h"
23 #include "llvm/Intrinsics.h"
24 #include "llvm/CallingConv.h"
25 #include "llvm/GlobalVariable.h"
26 #include "llvm/GlobalAlias.h"
27 #include "llvm/CodeGen/CallingConvLower.h"
28 #include "llvm/CodeGen/MachineFrameInfo.h"
29 #include "llvm/CodeGen/MachineFunction.h"
30 #include "llvm/CodeGen/MachineInstrBuilder.h"
31 #include "llvm/CodeGen/MachineRegisterInfo.h"
32 #include "llvm/CodeGen/SelectionDAGISel.h"
33 #include "llvm/CodeGen/ValueTypes.h"
34 #include "llvm/Support/Debug.h"
35 #include "llvm/Support/ErrorHandling.h"
36 #include "llvm/ADT/VectorExtras.h"
37 #include <queue>
38 #include <set>
39 using namespace llvm;
41 const char *XCoreTargetLowering::
42 getTargetNodeName(unsigned Opcode) const
43 {
44 switch (Opcode)
45 {
46 case XCoreISD::BL : return "XCoreISD::BL";
47 case XCoreISD::PCRelativeWrapper : return "XCoreISD::PCRelativeWrapper";
48 case XCoreISD::DPRelativeWrapper : return "XCoreISD::DPRelativeWrapper";
49 case XCoreISD::CPRelativeWrapper : return "XCoreISD::CPRelativeWrapper";
50 case XCoreISD::STWSP : return "XCoreISD::STWSP";
51 case XCoreISD::RETSP : return "XCoreISD::RETSP";
52 default : return NULL;
53 }
54 }
56 XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM)
57 : TargetLowering(XTM),
58 TM(XTM),
59 Subtarget(*XTM.getSubtargetImpl()) {
61 // Set up the register classes.
62 addRegisterClass(MVT::i32, XCore::GRRegsRegisterClass);
64 // Compute derived properties from the register classes
65 computeRegisterProperties();
67 // Division is expensive
68 setIntDivIsCheap(false);
70 setShiftAmountType(MVT::i32);
71 setStackPointerRegisterToSaveRestore(XCore::SP);
73 setSchedulingPreference(SchedulingForRegPressure);
75 // Use i32 for setcc operations results (slt, sgt, ...).
76 setBooleanContents(ZeroOrOneBooleanContent);
78 // XCore does not have the NodeTypes below.
79 setOperationAction(ISD::BR_CC, MVT::Other, Expand);
80 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
81 setOperationAction(ISD::ADDC, MVT::i32, Expand);
82 setOperationAction(ISD::ADDE, MVT::i32, Expand);
83 setOperationAction(ISD::SUBC, MVT::i32, Expand);
84 setOperationAction(ISD::SUBE, MVT::i32, Expand);
86 // Stop the combiner recombining select and set_cc
87 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
89 // 64bit
90 if (!Subtarget.isXS1A()) {
91 setOperationAction(ISD::ADD, MVT::i64, Custom);
92 setOperationAction(ISD::SUB, MVT::i64, Custom);
93 }
94 if (Subtarget.isXS1A()) {
95 setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
96 }
97 setOperationAction(ISD::MULHS, MVT::i32, Expand);
98 setOperationAction(ISD::MULHU, MVT::i32, Expand);
99 setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
100 setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
101 setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
103 // Bit Manipulation
104 setOperationAction(ISD::CTPOP, MVT::i32, Expand);
105 setOperationAction(ISD::ROTL , MVT::i32, Expand);
106 setOperationAction(ISD::ROTR , MVT::i32, Expand);
108 setOperationAction(ISD::TRAP, MVT::Other, Legal);
110 // Expand jump tables for now
111 setOperationAction(ISD::BR_JT, MVT::Other, Expand);
112 setOperationAction(ISD::JumpTable, MVT::i32, Custom);
114 // RET must be custom lowered, to meet ABI requirements
115 setOperationAction(ISD::RET, MVT::Other, Custom);
117 setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
119 // Thread Local Storage
120 setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
122 // Conversion of i64 -> double produces constantpool nodes
123 setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
125 // Loads
126 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
127 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
128 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
130 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand);
131 setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Expand);
133 // Custom expand misaligned loads / stores.
134 setOperationAction(ISD::LOAD, MVT::i32, Custom);
135 setOperationAction(ISD::STORE, MVT::i32, Custom);
137 // Varargs
138 setOperationAction(ISD::VAEND, MVT::Other, Expand);
139 setOperationAction(ISD::VACOPY, MVT::Other, Expand);
140 setOperationAction(ISD::VAARG, MVT::Other, Custom);
141 setOperationAction(ISD::VASTART, MVT::Other, Custom);
143 // Dynamic stack
144 setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
145 setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
146 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
148 // Debug
149 setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
150 setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
152 maxStoresPerMemset = 4;
153 maxStoresPerMemmove = maxStoresPerMemcpy = 2;
155 // We have target-specific dag combine patterns for the following nodes:
156 setTargetDAGCombine(ISD::STORE);
157 }
159 SDValue XCoreTargetLowering::
160 LowerOperation(SDValue Op, SelectionDAG &DAG) {
161 switch (Op.getOpcode())
162 {
163 case ISD::CALL: return LowerCALL(Op, DAG);
164 case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
165 case ISD::RET: return LowerRET(Op, DAG);
166 case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
167 case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
168 case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
169 case ISD::JumpTable: return LowerJumpTable(Op, DAG);
170 case ISD::LOAD: return LowerLOAD(Op, DAG);
171 case ISD::STORE: return LowerSTORE(Op, DAG);
172 case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
173 case ISD::VAARG: return LowerVAARG(Op, DAG);
174 case ISD::VASTART: return LowerVASTART(Op, DAG);
175 // FIXME: Remove these when LegalizeDAGTypes lands.
176 case ISD::ADD:
177 case ISD::SUB: return ExpandADDSUB(Op.getNode(), DAG);
178 case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
179 default:
180 llvm_unreachable("unimplemented operand");
181 return SDValue();
182 }
183 }
185 /// ReplaceNodeResults - Replace the results of node with an illegal result
186 /// type with new values built out of custom code.
187 void XCoreTargetLowering::ReplaceNodeResults(SDNode *N,
188 SmallVectorImpl<SDValue>&Results,
189 SelectionDAG &DAG) {
190 switch (N->getOpcode()) {
191 default:
192 llvm_unreachable("Don't know how to custom expand this!");
193 return;
194 case ISD::ADD:
195 case ISD::SUB:
196 Results.push_back(ExpandADDSUB(N, DAG));
197 return;
198 }
199 }
201 /// getFunctionAlignment - Return the Log2 alignment of this function.
202 unsigned XCoreTargetLowering::
203 getFunctionAlignment(const Function *) const {
204 return 1;
205 }
207 //===----------------------------------------------------------------------===//
208 // Misc Lower Operation implementation
209 //===----------------------------------------------------------------------===//
211 SDValue XCoreTargetLowering::
212 LowerSELECT_CC(SDValue Op, SelectionDAG &DAG)
213 {
214 DebugLoc dl = Op.getDebugLoc();
215 SDValue Cond = DAG.getNode(ISD::SETCC, dl, MVT::i32, Op.getOperand(2),
216 Op.getOperand(3), Op.getOperand(4));
217 return DAG.getNode(ISD::SELECT, dl, MVT::i32, Cond, Op.getOperand(0),
218 Op.getOperand(1));
219 }
221 SDValue XCoreTargetLowering::
222 getGlobalAddressWrapper(SDValue GA, GlobalValue *GV, SelectionDAG &DAG)
223 {
224 // FIXME there is no actual debug info here
225 DebugLoc dl = GA.getDebugLoc();
226 if (isa<Function>(GV)) {
227 return DAG.getNode(XCoreISD::PCRelativeWrapper, dl, MVT::i32, GA);
228 } else if (!Subtarget.isXS1A()) {
229 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
230 if (!GVar) {
231 // If GV is an alias then use the aliasee to determine constness
232 if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
233 GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal());
234 }
235 bool isConst = GVar && GVar->isConstant();
236 if (isConst) {
237 return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA);
238 }
239 }
240 return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, GA);
241 }
243 SDValue XCoreTargetLowering::
244 LowerGlobalAddress(SDValue Op, SelectionDAG &DAG)
245 {
246 GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
247 SDValue GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
248 // If it's a debug information descriptor, don't mess with it.
249 if (DAG.isVerifiedDebugInfoDesc(Op))
250 return GA;
251 return getGlobalAddressWrapper(GA, GV, DAG);
252 }
254 static inline SDValue BuildGetId(SelectionDAG &DAG, DebugLoc dl) {
255 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32,
256 DAG.getConstant(Intrinsic::xcore_getid, MVT::i32));
257 }
259 static inline bool isZeroLengthArray(const Type *Ty) {
260 const ArrayType *AT = dyn_cast_or_null<ArrayType>(Ty);
261 return AT && (AT->getNumElements() == 0);
262 }
264 SDValue XCoreTargetLowering::
265 LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG)
266 {
267 // FIXME there isn't really debug info here
268 DebugLoc dl = Op.getDebugLoc();
269 // transform to label + getid() * size
270 GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
271 SDValue GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
272 const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
273 if (!GVar) {
274 // If GV is an alias then use the aliasee to determine size
275 if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
276 GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal());
277 }
278 if (! GVar) {
279 llvm_unreachable("Thread local object not a GlobalVariable?");
280 return SDValue();
281 }
282 const Type *Ty = cast<PointerType>(GV->getType())->getElementType();
283 if (!Ty->isSized() || isZeroLengthArray(Ty)) {
284 #ifndef NDEBUG
285 cerr << "Size of thread local object " << GVar->getName()
286 << " is unknown\n";
287 #endif
288 llvm_unreachable(0);
289 }
290 SDValue base = getGlobalAddressWrapper(GA, GV, DAG);
291 const TargetData *TD = TM.getTargetData();
292 unsigned Size = TD->getTypeAllocSize(Ty);
293 SDValue offset = DAG.getNode(ISD::MUL, dl, MVT::i32, BuildGetId(DAG, dl),
294 DAG.getConstant(Size, MVT::i32));
295 return DAG.getNode(ISD::ADD, dl, MVT::i32, base, offset);
296 }
298 SDValue XCoreTargetLowering::
299 LowerConstantPool(SDValue Op, SelectionDAG &DAG)
300 {
301 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
302 // FIXME there isn't really debug info here
303 DebugLoc dl = CP->getDebugLoc();
304 if (Subtarget.isXS1A()) {
305 llvm_unreachable("Lowering of constant pool unimplemented");
306 return SDValue();
307 } else {
308 MVT PtrVT = Op.getValueType();
309 SDValue Res;
310 if (CP->isMachineConstantPoolEntry()) {
311 Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT,
312 CP->getAlignment());
313 } else {
314 Res = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT,
315 CP->getAlignment());
316 }
317 return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, Res);
318 }
319 }
321 SDValue XCoreTargetLowering::
322 LowerJumpTable(SDValue Op, SelectionDAG &DAG)
323 {
324 // FIXME there isn't really debug info here
325 DebugLoc dl = Op.getDebugLoc();
326 MVT PtrVT = Op.getValueType();
327 JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
328 SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT);
329 return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, JTI);
330 }
332 static bool
333 IsWordAlignedBasePlusConstantOffset(SDValue Addr, SDValue &AlignedBase,
334 int64_t &Offset)
335 {
336 if (Addr.getOpcode() != ISD::ADD) {
337 return false;
338 }
339 ConstantSDNode *CN = 0;
340 if (!(CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))) {
341 return false;
342 }
343 int64_t off = CN->getSExtValue();
344 const SDValue &Base = Addr.getOperand(0);
345 const SDValue *Root = &Base;
346 if (Base.getOpcode() == ISD::ADD &&
347 Base.getOperand(1).getOpcode() == ISD::SHL) {
348 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Base.getOperand(1)
349 .getOperand(1));
350 if (CN && (CN->getSExtValue() >= 2)) {
351 Root = &Base.getOperand(0);
352 }
353 }
354 if (isa<FrameIndexSDNode>(*Root)) {
355 // All frame indicies are word aligned
356 AlignedBase = Base;
357 Offset = off;
358 return true;
359 }
360 if (Root->getOpcode() == XCoreISD::DPRelativeWrapper ||
361 Root->getOpcode() == XCoreISD::CPRelativeWrapper) {
362 // All dp / cp relative addresses are word aligned
363 AlignedBase = Base;
364 Offset = off;
365 return true;
366 }
367 return false;
368 }
370 SDValue XCoreTargetLowering::
371 LowerLOAD(SDValue Op, SelectionDAG &DAG)
372 {
373 LoadSDNode *LD = cast<LoadSDNode>(Op);
374 assert(LD->getExtensionType() == ISD::NON_EXTLOAD && "Unexpected extension type");
375 assert(LD->getMemoryVT() == MVT::i32 && "Unexpected load MVT");
376 if (allowsUnalignedMemoryAccesses()) {
377 return SDValue();
378 }
379 unsigned ABIAlignment = getTargetData()->
380 getABITypeAlignment(LD->getMemoryVT().getTypeForMVT(*DAG.getContext()));
381 // Leave aligned load alone.
382 if (LD->getAlignment() >= ABIAlignment) {
383 return SDValue();
384 }
385 SDValue Chain = LD->getChain();
386 SDValue BasePtr = LD->getBasePtr();
387 DebugLoc dl = Op.getDebugLoc();
389 SDValue Base;
390 int64_t Offset;
391 if (!LD->isVolatile() &&
392 IsWordAlignedBasePlusConstantOffset(BasePtr, Base, Offset)) {
393 if (Offset % 4 == 0) {
394 // We've managed to infer better alignment information than the load
395 // already has. Use an aligned load.
396 return DAG.getLoad(getPointerTy(), dl, Chain, BasePtr, NULL, 4);
397 }
398 // Lower to
399 // ldw low, base[offset >> 2]
400 // ldw high, base[(offset >> 2) + 1]
401 // shr low_shifted, low, (offset & 0x3) * 8
402 // shl high_shifted, high, 32 - (offset & 0x3) * 8
403 // or result, low_shifted, high_shifted
404 SDValue LowOffset = DAG.getConstant(Offset & ~0x3, MVT::i32);
405 SDValue HighOffset = DAG.getConstant((Offset & ~0x3) + 4, MVT::i32);
406 SDValue LowShift = DAG.getConstant((Offset & 0x3) * 8, MVT::i32);
407 SDValue HighShift = DAG.getConstant(32 - (Offset & 0x3) * 8, MVT::i32);
409 SDValue LowAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, Base, LowOffset);
410 SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, Base, HighOffset);
412 SDValue Low = DAG.getLoad(getPointerTy(), dl, Chain,
413 LowAddr, NULL, 4);
414 SDValue High = DAG.getLoad(getPointerTy(), dl, Chain,
415 HighAddr, NULL, 4);
416 SDValue LowShifted = DAG.getNode(ISD::SRL, dl, MVT::i32, Low, LowShift);
417 SDValue HighShifted = DAG.getNode(ISD::SHL, dl, MVT::i32, High, HighShift);
418 SDValue Result = DAG.getNode(ISD::OR, dl, MVT::i32, LowShifted, HighShifted);
419 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Low.getValue(1),
420 High.getValue(1));
421 SDValue Ops[] = { Result, Chain };
422 return DAG.getMergeValues(Ops, 2, dl);
423 }
425 if (LD->getAlignment() == 2) {
426 int SVOffset = LD->getSrcValueOffset();
427 SDValue Low = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i32, Chain,
428 BasePtr, LD->getSrcValue(), SVOffset, MVT::i16,
429 LD->isVolatile(), 2);
430 SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr,
431 DAG.getConstant(2, MVT::i32));
432 SDValue High = DAG.getExtLoad(ISD::EXTLOAD, dl, MVT::i32, Chain,
433 HighAddr, LD->getSrcValue(), SVOffset + 2,
434 MVT::i16, LD->isVolatile(), 2);
435 SDValue HighShifted = DAG.getNode(ISD::SHL, dl, MVT::i32, High,
436 DAG.getConstant(16, MVT::i32));
437 SDValue Result = DAG.getNode(ISD::OR, dl, MVT::i32, Low, HighShifted);
438 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Low.getValue(1),
439 High.getValue(1));
440 SDValue Ops[] = { Result, Chain };
441 return DAG.getMergeValues(Ops, 2, dl);
442 }
444 // Lower to a call to __misaligned_load(BasePtr).
445 const Type *IntPtrTy = getTargetData()->getIntPtrType();
446 TargetLowering::ArgListTy Args;
447 TargetLowering::ArgListEntry Entry;
449 Entry.Ty = IntPtrTy;
450 Entry.Node = BasePtr;
451 Args.push_back(Entry);
453 std::pair<SDValue, SDValue> CallResult =
454 LowerCallTo(Chain, IntPtrTy, false, false,
455 false, false, 0, CallingConv::C, false,
456 DAG.getExternalSymbol("__misaligned_load", getPointerTy()),
457 Args, DAG, dl);
459 SDValue Ops[] =
460 { CallResult.first, CallResult.second };
462 return DAG.getMergeValues(Ops, 2, dl);
463 }
465 SDValue XCoreTargetLowering::
466 LowerSTORE(SDValue Op, SelectionDAG &DAG)
467 {
468 StoreSDNode *ST = cast<StoreSDNode>(Op);
469 assert(!ST->isTruncatingStore() && "Unexpected store type");
470 assert(ST->getMemoryVT() == MVT::i32 && "Unexpected store MVT");
471 if (allowsUnalignedMemoryAccesses()) {
472 return SDValue();
473 }
474 unsigned ABIAlignment = getTargetData()->
475 getABITypeAlignment(ST->getMemoryVT().getTypeForMVT(*DAG.getContext()));
476 // Leave aligned store alone.
477 if (ST->getAlignment() >= ABIAlignment) {
478 return SDValue();
479 }
480 SDValue Chain = ST->getChain();
481 SDValue BasePtr = ST->getBasePtr();
482 SDValue Value = ST->getValue();
483 DebugLoc dl = Op.getDebugLoc();
485 if (ST->getAlignment() == 2) {
486 int SVOffset = ST->getSrcValueOffset();
487 SDValue Low = Value;
488 SDValue High = DAG.getNode(ISD::SRL, dl, MVT::i32, Value,
489 DAG.getConstant(16, MVT::i32));
490 SDValue StoreLow = DAG.getTruncStore(Chain, dl, Low, BasePtr,
491 ST->getSrcValue(), SVOffset, MVT::i16,
492 ST->isVolatile(), 2);
493 SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr,
494 DAG.getConstant(2, MVT::i32));
495 SDValue StoreHigh = DAG.getTruncStore(Chain, dl, High, HighAddr,
496 ST->getSrcValue(), SVOffset + 2,
497 MVT::i16, ST->isVolatile(), 2);
498 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, StoreLow, StoreHigh);
499 }
501 // Lower to a call to __misaligned_store(BasePtr, Value).
502 const Type *IntPtrTy = getTargetData()->getIntPtrType();
503 TargetLowering::ArgListTy Args;
504 TargetLowering::ArgListEntry Entry;
506 Entry.Ty = IntPtrTy;
507 Entry.Node = BasePtr;
508 Args.push_back(Entry);
510 Entry.Node = Value;
511 Args.push_back(Entry);
513 std::pair<SDValue, SDValue> CallResult =
514 LowerCallTo(Chain, Type::VoidTy, false, false,
515 false, false, 0, CallingConv::C, false,
516 DAG.getExternalSymbol("__misaligned_store", getPointerTy()),
517 Args, DAG, dl);
519 return CallResult.second;
520 }
522 SDValue XCoreTargetLowering::
523 ExpandADDSUB(SDNode *N, SelectionDAG &DAG)
524 {
525 assert(N->getValueType(0) == MVT::i64 &&
526 (N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) &&
527 "Unknown operand to lower!");
528 assert(!Subtarget.isXS1A() && "Cannot custom lower ADD/SUB on xs1a");
529 DebugLoc dl = N->getDebugLoc();
531 // Extract components
532 SDValue LHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
533 N->getOperand(0), DAG.getConstant(0, MVT::i32));
534 SDValue LHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
535 N->getOperand(0), DAG.getConstant(1, MVT::i32));
536 SDValue RHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
537 N->getOperand(1), DAG.getConstant(0, MVT::i32));
538 SDValue RHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32,
539 N->getOperand(1), DAG.getConstant(1, MVT::i32));
541 // Expand
542 unsigned Opcode = (N->getOpcode() == ISD::ADD) ? XCoreISD::LADD :
543 XCoreISD::LSUB;
544 SDValue Zero = DAG.getConstant(0, MVT::i32);
545 SDValue Carry = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32),
546 LHSL, RHSL, Zero);
547 SDValue Lo(Carry.getNode(), 1);
549 SDValue Ignored = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32),
550 LHSH, RHSH, Carry);
551 SDValue Hi(Ignored.getNode(), 1);
552 // Merge the pieces
553 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi);
554 }
556 SDValue XCoreTargetLowering::
557 LowerVAARG(SDValue Op, SelectionDAG &DAG)
558 {
559 llvm_unreachable("unimplemented");
560 // FIX Arguments passed by reference need a extra dereference.
561 SDNode *Node = Op.getNode();
562 DebugLoc dl = Node->getDebugLoc();
563 const Value *V = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
564 MVT VT = Node->getValueType(0);
565 SDValue VAList = DAG.getLoad(getPointerTy(), dl, Node->getOperand(0),
566 Node->getOperand(1), V, 0);
567 // Increment the pointer, VAList, to the next vararg
568 SDValue Tmp3 = DAG.getNode(ISD::ADD, dl, getPointerTy(), VAList,
569 DAG.getConstant(VT.getSizeInBits(),
570 getPointerTy()));
571 // Store the incremented VAList to the legalized pointer
572 Tmp3 = DAG.getStore(VAList.getValue(1), dl, Tmp3, Node->getOperand(1), V, 0);
573 // Load the actual argument out of the pointer VAList
574 return DAG.getLoad(VT, dl, Tmp3, VAList, NULL, 0);
575 }
577 SDValue XCoreTargetLowering::
578 LowerVASTART(SDValue Op, SelectionDAG &DAG)
579 {
580 DebugLoc dl = Op.getDebugLoc();
581 // vastart stores the address of the VarArgsFrameIndex slot into the
582 // memory location argument
583 MachineFunction &MF = DAG.getMachineFunction();
584 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
585 SDValue Addr = DAG.getFrameIndex(XFI->getVarArgsFrameIndex(), MVT::i32);
586 const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
587 return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1), SV, 0);
588 }
590 SDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) {
591 DebugLoc dl = Op.getDebugLoc();
592 // Depths > 0 not supported yet!
593 if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0)
594 return SDValue();
596 MachineFunction &MF = DAG.getMachineFunction();
597 const TargetRegisterInfo *RegInfo = getTargetMachine().getRegisterInfo();
598 return DAG.getCopyFromReg(DAG.getEntryNode(), dl,
599 RegInfo->getFrameRegister(MF), MVT::i32);
600 }
602 //===----------------------------------------------------------------------===//
603 // Calling Convention Implementation
604 //
605 // The lower operations present on calling convention works on this order:
606 // LowerCALL (virt regs --> phys regs, virt regs --> stack)
607 // LowerFORMAL_ARGUMENTS (phys --> virt regs, stack --> virt regs)
608 // LowerRET (virt regs --> phys regs)
609 // LowerCALL (phys regs --> virt regs)
610 //
611 //===----------------------------------------------------------------------===//
613 #include "XCoreGenCallingConv.inc"
615 //===----------------------------------------------------------------------===//
616 // CALL Calling Convention Implementation
617 //===----------------------------------------------------------------------===//
619 /// XCore custom CALL implementation
620 SDValue XCoreTargetLowering::
621 LowerCALL(SDValue Op, SelectionDAG &DAG)
622 {
623 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
624 unsigned CallingConv = TheCall->getCallingConv();
625 // For now, only CallingConv::C implemented
626 switch (CallingConv)
627 {
628 default:
629 llvm_unreachable("Unsupported calling convention");
630 case CallingConv::Fast:
631 case CallingConv::C:
632 return LowerCCCCallTo(Op, DAG, CallingConv);
633 }
634 }
636 /// LowerCCCCallTo - functions arguments are copied from virtual
637 /// regs to (physical regs)/(stack frame), CALLSEQ_START and
638 /// CALLSEQ_END are emitted.
639 /// TODO: isTailCall, sret.
640 SDValue XCoreTargetLowering::
641 LowerCCCCallTo(SDValue Op, SelectionDAG &DAG, unsigned CC)
642 {
643 CallSDNode *TheCall = cast<CallSDNode>(Op.getNode());
644 SDValue Chain = TheCall->getChain();
645 SDValue Callee = TheCall->getCallee();
646 bool isVarArg = TheCall->isVarArg();
647 DebugLoc dl = Op.getDebugLoc();
649 // Analyze operands of the call, assigning locations to each operand.
650 SmallVector<CCValAssign, 16> ArgLocs;
651 CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, DAG.getContext());
653 // The ABI dictates there should be one stack slot available to the callee
654 // on function entry (for saving lr).
655 CCInfo.AllocateStack(4, 4);
657 CCInfo.AnalyzeCallOperands(TheCall, CC_XCore);
659 // Get a count of how many bytes are to be pushed on the stack.
660 unsigned NumBytes = CCInfo.getNextStackOffset();
662 Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes,
663 getPointerTy(), true));
665 SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
666 SmallVector<SDValue, 12> MemOpChains;
668 // Walk the register/memloc assignments, inserting copies/loads.
669 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
670 CCValAssign &VA = ArgLocs[i];
672 // Arguments start after the 5 first operands of ISD::CALL
673 SDValue Arg = TheCall->getArg(i);
675 // Promote the value if needed.
676 switch (VA.getLocInfo()) {
677 default: llvm_unreachable("Unknown loc info!");
678 case CCValAssign::Full: break;
679 case CCValAssign::SExt:
680 Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
681 break;
682 case CCValAssign::ZExt:
683 Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
684 break;
685 case CCValAssign::AExt:
686 Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
687 break;
688 }
690 // Arguments that can be passed on register must be kept at
691 // RegsToPass vector
692 if (VA.isRegLoc()) {
693 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
694 } else {
695 assert(VA.isMemLoc());
697 int Offset = VA.getLocMemOffset();
699 MemOpChains.push_back(DAG.getNode(XCoreISD::STWSP, dl, MVT::Other,
700 Chain, Arg,
701 DAG.getConstant(Offset/4, MVT::i32)));
702 }
703 }
705 // Transform all store nodes into one single node because
706 // all store nodes are independent of each other.
707 if (!MemOpChains.empty())
708 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
709 &MemOpChains[0], MemOpChains.size());
711 // Build a sequence of copy-to-reg nodes chained together with token
712 // chain and flag operands which copy the outgoing args into registers.
713 // The InFlag in necessary since all emited instructions must be
714 // stuck together.
715 SDValue InFlag;
716 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
717 Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
718 RegsToPass[i].second, InFlag);
719 InFlag = Chain.getValue(1);
720 }
722 // If the callee is a GlobalAddress node (quite common, every direct call is)
723 // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
724 // Likewise ExternalSymbol -> TargetExternalSymbol.
725 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
726 Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i32);
727 else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee))
728 Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
730 // XCoreBranchLink = #chain, #target_address, #opt_in_flags...
731 // = Chain, Callee, Reg#1, Reg#2, ...
732 //
733 // Returns a chain & a flag for retval copy to use.
734 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
735 SmallVector<SDValue, 8> Ops;
736 Ops.push_back(Chain);
737 Ops.push_back(Callee);
739 // Add argument registers to the end of the list so that they are
740 // known live into the call.
741 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
742 Ops.push_back(DAG.getRegister(RegsToPass[i].first,
743 RegsToPass[i].second.getValueType()));
745 if (InFlag.getNode())
746 Ops.push_back(InFlag);
748 Chain = DAG.getNode(XCoreISD::BL, dl, NodeTys, &Ops[0], Ops.size());
749 InFlag = Chain.getValue(1);
751 // Create the CALLSEQ_END node.
752 Chain = DAG.getCALLSEQ_END(Chain,
753 DAG.getConstant(NumBytes, getPointerTy(), true),
754 DAG.getConstant(0, getPointerTy(), true),
755 InFlag);
756 InFlag = Chain.getValue(1);
758 // Handle result values, copying them out of physregs into vregs that we
759 // return.
760 return SDValue(LowerCallResult(Chain, InFlag, TheCall, CC, DAG),
761 Op.getResNo());
762 }
764 /// LowerCallResult - Lower the result values of an ISD::CALL into the
765 /// appropriate copies out of appropriate physical registers. This assumes that
766 /// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
767 /// being lowered. Returns a SDNode with the same number of values as the
768 /// ISD::CALL.
769 SDNode *XCoreTargetLowering::
770 LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall,
771 unsigned CallingConv, SelectionDAG &DAG) {
772 bool isVarArg = TheCall->isVarArg();
773 DebugLoc dl = TheCall->getDebugLoc();
775 // Assign locations to each value returned by this call.
776 SmallVector<CCValAssign, 16> RVLocs;
777 CCState CCInfo(CallingConv, isVarArg, getTargetMachine(),
778 RVLocs, DAG.getContext());
780 CCInfo.AnalyzeCallResult(TheCall, RetCC_XCore);
781 SmallVector<SDValue, 8> ResultVals;
783 // Copy all of the result registers out of their specified physreg.
784 for (unsigned i = 0; i != RVLocs.size(); ++i) {
785 Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
786 RVLocs[i].getValVT(), InFlag).getValue(1);
787 InFlag = Chain.getValue(2);
788 ResultVals.push_back(Chain.getValue(0));
789 }
791 ResultVals.push_back(Chain);
793 // Merge everything together with a MERGE_VALUES node.
794 return DAG.getNode(ISD::MERGE_VALUES, dl, TheCall->getVTList(),
795 &ResultVals[0], ResultVals.size()).getNode();
796 }
798 //===----------------------------------------------------------------------===//
799 // FORMAL_ARGUMENTS Calling Convention Implementation
800 //===----------------------------------------------------------------------===//
802 /// XCore custom FORMAL_ARGUMENTS implementation
803 SDValue XCoreTargetLowering::
804 LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG)
805 {
806 unsigned CC = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue();
807 switch(CC)
808 {
809 default:
810 llvm_unreachable("Unsupported calling convention");
811 case CallingConv::C:
812 case CallingConv::Fast:
813 return LowerCCCArguments(Op, DAG);
814 }
815 }
817 /// LowerCCCArguments - transform physical registers into
818 /// virtual registers and generate load operations for
819 /// arguments places on the stack.
820 /// TODO: sret
821 SDValue XCoreTargetLowering::
822 LowerCCCArguments(SDValue Op, SelectionDAG &DAG)
823 {
824 MachineFunction &MF = DAG.getMachineFunction();
825 MachineFrameInfo *MFI = MF.getFrameInfo();
826 MachineRegisterInfo &RegInfo = MF.getRegInfo();
827 SDValue Root = Op.getOperand(0);
828 bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0;
829 unsigned CC = MF.getFunction()->getCallingConv();
830 DebugLoc dl = Op.getDebugLoc();
832 // Assign locations to all of the incoming arguments.
833 SmallVector<CCValAssign, 16> ArgLocs;
834 CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, DAG.getContext());
836 CCInfo.AnalyzeFormalArguments(Op.getNode(), CC_XCore);
838 unsigned StackSlotSize = XCoreFrameInfo::stackSlotSize();
840 SmallVector<SDValue, 16> ArgValues;
842 unsigned LRSaveSize = StackSlotSize;
844 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
846 CCValAssign &VA = ArgLocs[i];
848 if (VA.isRegLoc()) {
849 // Arguments passed in registers
850 MVT RegVT = VA.getLocVT();
851 switch (RegVT.getSimpleVT()) {
852 default:
853 {
854 #ifndef NDEBUG
855 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
856 << RegVT.getSimpleVT() << "\n";
857 #endif
858 llvm_unreachable(0);
859 }
860 case MVT::i32:
861 unsigned VReg = RegInfo.createVirtualRegister(
862 XCore::GRRegsRegisterClass);
863 RegInfo.addLiveIn(VA.getLocReg(), VReg);
864 ArgValues.push_back(DAG.getCopyFromReg(Root, dl, VReg, RegVT));
865 }
866 } else {
867 // sanity check
868 assert(VA.isMemLoc());
869 // Load the argument to a virtual register
870 unsigned ObjSize = VA.getLocVT().getSizeInBits()/8;
871 if (ObjSize > StackSlotSize) {
872 cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: "
873 << VA.getLocVT().getSimpleVT()
874 << "\n";
875 }
876 // Create the frame index object for this incoming parameter...
877 int FI = MFI->CreateFixedObject(ObjSize,
878 LRSaveSize + VA.getLocMemOffset());
880 // Create the SelectionDAG nodes corresponding to a load
881 //from this parameter
882 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
883 ArgValues.push_back(DAG.getLoad(VA.getLocVT(), dl, Root, FIN, NULL, 0));
884 }
885 }
887 if (isVarArg) {
888 /* Argument registers */
889 static const unsigned ArgRegs[] = {
890 XCore::R0, XCore::R1, XCore::R2, XCore::R3
891 };
892 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
893 unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs,
894 array_lengthof(ArgRegs));
895 if (FirstVAReg < array_lengthof(ArgRegs)) {
896 SmallVector<SDValue, 4> MemOps;
897 int offset = 0;
898 // Save remaining registers, storing higher register numbers at a higher
899 // address
900 for (unsigned i = array_lengthof(ArgRegs) - 1; i >= FirstVAReg; --i) {
901 // Create a stack slot
902 int FI = MFI->CreateFixedObject(4, offset);
903 if (i == FirstVAReg) {
904 XFI->setVarArgsFrameIndex(FI);
905 }
906 offset -= StackSlotSize;
907 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
908 // Move argument from phys reg -> virt reg
909 unsigned VReg = RegInfo.createVirtualRegister(
910 XCore::GRRegsRegisterClass);
911 RegInfo.addLiveIn(ArgRegs[i], VReg);
912 SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, MVT::i32);
913 // Move argument from virt reg -> stack
914 SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0);
915 MemOps.push_back(Store);
916 }
917 if (!MemOps.empty())
918 Root = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
919 &MemOps[0], MemOps.size());
920 } else {
921 // This will point to the next argument passed via stack.
922 XFI->setVarArgsFrameIndex(
923 MFI->CreateFixedObject(4, LRSaveSize + CCInfo.getNextStackOffset()));
924 }
925 }
927 ArgValues.push_back(Root);
929 // Return the new list of results.
930 std::vector<MVT> RetVT(Op.getNode()->value_begin(),
931 Op.getNode()->value_end());
932 return DAG.getNode(ISD::MERGE_VALUES, dl, RetVT,
933 &ArgValues[0], ArgValues.size());
934 }
936 //===----------------------------------------------------------------------===//
937 // Return Value Calling Convention Implementation
938 //===----------------------------------------------------------------------===//
940 SDValue XCoreTargetLowering::
941 LowerRET(SDValue Op, SelectionDAG &DAG)
942 {
943 // CCValAssign - represent the assignment of
944 // the return value to a location
945 SmallVector<CCValAssign, 16> RVLocs;
946 unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv();
947 bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg();
948 DebugLoc dl = Op.getDebugLoc();
950 // CCState - Info about the registers and stack slot.
951 CCState CCInfo(CC, isVarArg, getTargetMachine(), RVLocs, DAG.getContext());
953 // Analize return values of ISD::RET
954 CCInfo.AnalyzeReturn(Op.getNode(), RetCC_XCore);
956 // If this is the first return lowered for this function, add
957 // the regs to the liveout set for the function.
958 if (DAG.getMachineFunction().getRegInfo().liveout_empty()) {
959 for (unsigned i = 0; i != RVLocs.size(); ++i)
960 if (RVLocs[i].isRegLoc())
961 DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg());
962 }
964 // The chain is always operand #0
965 SDValue Chain = Op.getOperand(0);
966 SDValue Flag;
968 // Copy the result values into the output registers.
969 for (unsigned i = 0; i != RVLocs.size(); ++i) {
970 CCValAssign &VA = RVLocs[i];
971 assert(VA.isRegLoc() && "Can only return in registers!");
973 // ISD::RET => ret chain, (regnum1,val1), ...
974 // So i*2+1 index only the regnums
975 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(),
976 Op.getOperand(i*2+1), Flag);
978 // guarantee that all emitted copies are
979 // stuck together, avoiding something bad
980 Flag = Chain.getValue(1);
981 }
983 // Return on XCore is always a "retsp 0"
984 if (Flag.getNode())
985 return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other,
986 Chain, DAG.getConstant(0, MVT::i32), Flag);
987 else // Return Void
988 return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other,
989 Chain, DAG.getConstant(0, MVT::i32));
990 }
992 //===----------------------------------------------------------------------===//
993 // Other Lowering Code
994 //===----------------------------------------------------------------------===//
996 MachineBasicBlock *
997 XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
998 MachineBasicBlock *BB) const {
999 const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
1000 DebugLoc dl = MI->getDebugLoc();
1001 assert((MI->getOpcode() == XCore::SELECT_CC) &&
1002 "Unexpected instr type to insert");
1004 // To "insert" a SELECT_CC instruction, we actually have to insert the diamond
1005 // control-flow pattern. The incoming instruction knows the destination vreg
1006 // to set, the condition code register to branch on, the true/false values to
1007 // select between, and a branch opcode to use.
1008 const BasicBlock *LLVM_BB = BB->getBasicBlock();
1009 MachineFunction::iterator It = BB;
1010 ++It;
1012 // thisMBB:
1013 // ...
1014 // TrueVal = ...
1015 // cmpTY ccX, r1, r2
1016 // bCC copy1MBB
1017 // fallthrough --> copy0MBB
1018 MachineBasicBlock *thisMBB = BB;
1019 MachineFunction *F = BB->getParent();
1020 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
1021 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
1022 BuildMI(BB, dl, TII.get(XCore::BRFT_lru6))
1023 .addReg(MI->getOperand(1).getReg()).addMBB(sinkMBB);
1024 F->insert(It, copy0MBB);
1025 F->insert(It, sinkMBB);
1026 // Update machine-CFG edges by transferring all successors of the current
1027 // block to the new block which will contain the Phi node for the select.
1028 sinkMBB->transferSuccessors(BB);
1029 // Next, add the true and fallthrough blocks as its successors.
1030 BB->addSuccessor(copy0MBB);
1031 BB->addSuccessor(sinkMBB);
1033 // copy0MBB:
1034 // %FalseValue = ...
1035 // # fallthrough to sinkMBB
1036 BB = copy0MBB;
1038 // Update machine-CFG edges
1039 BB->addSuccessor(sinkMBB);
1041 // sinkMBB:
1042 // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
1043 // ...
1044 BB = sinkMBB;
1045 BuildMI(BB, dl, TII.get(XCore::PHI), MI->getOperand(0).getReg())
1046 .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB)
1047 .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB);
1049 F->DeleteMachineInstr(MI); // The pseudo instruction is gone now.
1050 return BB;
1051 }
1053 //===----------------------------------------------------------------------===//
1054 // Target Optimization Hooks
1055 //===----------------------------------------------------------------------===//
1057 SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
1058 DAGCombinerInfo &DCI) const {
1059 SelectionDAG &DAG = DCI.DAG;
1060 DebugLoc dl = N->getDebugLoc();
1061 switch (N->getOpcode()) {
1062 default: break;
1063 case ISD::STORE: {
1064 // Replace unaligned store of unaligned load with memmove.
1065 StoreSDNode *ST = cast<StoreSDNode>(N);
1066 if (!DCI.isBeforeLegalize() || allowsUnalignedMemoryAccesses() ||
1067 ST->isVolatile() || ST->isIndexed()) {
1068 break;
1069 }
1070 SDValue Chain = ST->getChain();
1072 unsigned StoreBits = ST->getMemoryVT().getStoreSizeInBits();
1073 if (StoreBits % 8) {
1074 break;
1075 }
1076 unsigned ABIAlignment = getTargetData()->
1077 getABITypeAlignment(ST->getMemoryVT().getTypeForMVT(*DAG.getContext()));
1078 unsigned Alignment = ST->getAlignment();
1079 if (Alignment >= ABIAlignment) {
1080 break;
1081 }
1083 if (LoadSDNode *LD = dyn_cast<LoadSDNode>(ST->getValue())) {
1084 if (LD->hasNUsesOfValue(1, 0) && ST->getMemoryVT() == LD->getMemoryVT() &&
1085 LD->getAlignment() == Alignment &&
1086 !LD->isVolatile() && !LD->isIndexed() &&
1087 Chain.reachesChainWithoutSideEffects(SDValue(LD, 1))) {
1088 return DAG.getMemmove(Chain, dl, ST->getBasePtr(),
1089 LD->getBasePtr(),
1090 DAG.getConstant(StoreBits/8, MVT::i32),
1091 Alignment, ST->getSrcValue(),
1092 ST->getSrcValueOffset(), LD->getSrcValue(),
1093 LD->getSrcValueOffset());
1094 }
1095 }
1096 break;
1097 }
1098 }
1099 return SDValue();
1100 }
1102 //===----------------------------------------------------------------------===//
1103 // Addressing mode description hooks
1104 //===----------------------------------------------------------------------===//
1106 static inline bool isImmUs(int64_t val)
1107 {
1108 return (val >= 0 && val <= 11);
1109 }
1111 static inline bool isImmUs2(int64_t val)
1112 {
1113 return (val%2 == 0 && isImmUs(val/2));
1114 }
1116 static inline bool isImmUs4(int64_t val)
1117 {
1118 return (val%4 == 0 && isImmUs(val/4));
1119 }
1121 /// isLegalAddressingMode - Return true if the addressing mode represented
1122 /// by AM is legal for this target, for a load/store of the specified type.
1123 bool
1124 XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM,
1125 const Type *Ty) const {
1126 // Be conservative with void
1127 // FIXME: Can we be more aggressive?
1128 if (Ty->getTypeID() == Type::VoidTyID)
1129 return false;
1131 const TargetData *TD = TM.getTargetData();
1132 unsigned Size = TD->getTypeAllocSize(Ty);
1133 if (AM.BaseGV) {
1134 return Size >= 4 && !AM.HasBaseReg && AM.Scale == 0 &&
1135 AM.BaseOffs%4 == 0;
1136 }
1138 switch (Size) {
1139 case 1:
1140 // reg + imm
1141 if (AM.Scale == 0) {
1142 return isImmUs(AM.BaseOffs);
1143 }
1144 // reg + reg
1145 return AM.Scale == 1 && AM.BaseOffs == 0;
1146 case 2:
1147 case 3:
1148 // reg + imm
1149 if (AM.Scale == 0) {
1150 return isImmUs2(AM.BaseOffs);
1151 }
1152 // reg + reg<<1
1153 return AM.Scale == 2 && AM.BaseOffs == 0;
1154 default:
1155 // reg + imm
1156 if (AM.Scale == 0) {
1157 return isImmUs4(AM.BaseOffs);
1158 }
1159 // reg + reg<<2
1160 return AM.Scale == 4 && AM.BaseOffs == 0;
1161 }
1163 return false;
1164 }
1166 //===----------------------------------------------------------------------===//
1167 // XCore Inline Assembly Support
1168 //===----------------------------------------------------------------------===//
1170 std::vector<unsigned> XCoreTargetLowering::
1171 getRegClassForInlineAsmConstraint(const std::string &Constraint,
1172 MVT VT) const
1173 {
1174 if (Constraint.size() != 1)
1175 return std::vector<unsigned>();
1177 switch (Constraint[0]) {
1178 default : break;
1179 case 'r':
1180 return make_vector<unsigned>(XCore::R0, XCore::R1, XCore::R2,
1181 XCore::R3, XCore::R4, XCore::R5,
1182 XCore::R6, XCore::R7, XCore::R8,
1183 XCore::R9, XCore::R10, XCore::R11, 0);
1184 break;
1185 }
1186 return std::vector<unsigned>();
1187 }