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