LLVM API Documentation
00001 //===-- XCoreISelLowering.cpp - XCore DAG Lowering Implementation ---------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the XCoreTargetLowering class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #define DEBUG_TYPE "xcore-lower" 00015 00016 #include "XCoreISelLowering.h" 00017 #include "XCore.h" 00018 #include "XCoreMachineFunctionInfo.h" 00019 #include "XCoreSubtarget.h" 00020 #include "XCoreTargetMachine.h" 00021 #include "XCoreTargetObjectFile.h" 00022 #include "llvm/CodeGen/CallingConvLower.h" 00023 #include "llvm/CodeGen/MachineFrameInfo.h" 00024 #include "llvm/CodeGen/MachineFunction.h" 00025 #include "llvm/CodeGen/MachineInstrBuilder.h" 00026 #include "llvm/CodeGen/MachineJumpTableInfo.h" 00027 #include "llvm/CodeGen/MachineRegisterInfo.h" 00028 #include "llvm/CodeGen/SelectionDAGISel.h" 00029 #include "llvm/CodeGen/ValueTypes.h" 00030 #include "llvm/IR/CallingConv.h" 00031 #include "llvm/IR/DerivedTypes.h" 00032 #include "llvm/IR/Function.h" 00033 #include "llvm/IR/GlobalAlias.h" 00034 #include "llvm/IR/GlobalVariable.h" 00035 #include "llvm/IR/Intrinsics.h" 00036 #include "llvm/Support/Debug.h" 00037 #include "llvm/Support/ErrorHandling.h" 00038 #include "llvm/Support/raw_ostream.h" 00039 #include <algorithm> 00040 00041 using namespace llvm; 00042 00043 const char *XCoreTargetLowering:: 00044 getTargetNodeName(unsigned Opcode) const 00045 { 00046 switch (Opcode) 00047 { 00048 case XCoreISD::BL : return "XCoreISD::BL"; 00049 case XCoreISD::PCRelativeWrapper : return "XCoreISD::PCRelativeWrapper"; 00050 case XCoreISD::DPRelativeWrapper : return "XCoreISD::DPRelativeWrapper"; 00051 case XCoreISD::CPRelativeWrapper : return "XCoreISD::CPRelativeWrapper"; 00052 case XCoreISD::STWSP : return "XCoreISD::STWSP"; 00053 case XCoreISD::RETSP : return "XCoreISD::RETSP"; 00054 case XCoreISD::LADD : return "XCoreISD::LADD"; 00055 case XCoreISD::LSUB : return "XCoreISD::LSUB"; 00056 case XCoreISD::LMUL : return "XCoreISD::LMUL"; 00057 case XCoreISD::MACCU : return "XCoreISD::MACCU"; 00058 case XCoreISD::MACCS : return "XCoreISD::MACCS"; 00059 case XCoreISD::CRC8 : return "XCoreISD::CRC8"; 00060 case XCoreISD::BR_JT : return "XCoreISD::BR_JT"; 00061 case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32"; 00062 default : return NULL; 00063 } 00064 } 00065 00066 XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) 00067 : TargetLowering(XTM, new XCoreTargetObjectFile()), 00068 TM(XTM), 00069 Subtarget(*XTM.getSubtargetImpl()) { 00070 00071 // Set up the register classes. 00072 addRegisterClass(MVT::i32, &XCore::GRRegsRegClass); 00073 00074 // Compute derived properties from the register classes 00075 computeRegisterProperties(); 00076 00077 // Division is expensive 00078 setIntDivIsCheap(false); 00079 00080 setStackPointerRegisterToSaveRestore(XCore::SP); 00081 00082 setSchedulingPreference(Sched::RegPressure); 00083 00084 // Use i32 for setcc operations results (slt, sgt, ...). 00085 setBooleanContents(ZeroOrOneBooleanContent); 00086 setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct? 00087 00088 // XCore does not have the NodeTypes below. 00089 setOperationAction(ISD::BR_CC, MVT::i32, Expand); 00090 setOperationAction(ISD::SELECT_CC, MVT::i32, Custom); 00091 setOperationAction(ISD::ADDC, MVT::i32, Expand); 00092 setOperationAction(ISD::ADDE, MVT::i32, Expand); 00093 setOperationAction(ISD::SUBC, MVT::i32, Expand); 00094 setOperationAction(ISD::SUBE, MVT::i32, Expand); 00095 00096 // Stop the combiner recombining select and set_cc 00097 setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); 00098 00099 // 64bit 00100 setOperationAction(ISD::ADD, MVT::i64, Custom); 00101 setOperationAction(ISD::SUB, MVT::i64, Custom); 00102 setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom); 00103 setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom); 00104 setOperationAction(ISD::MULHS, MVT::i32, Expand); 00105 setOperationAction(ISD::MULHU, MVT::i32, Expand); 00106 setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); 00107 setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); 00108 setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); 00109 00110 // Bit Manipulation 00111 setOperationAction(ISD::CTPOP, MVT::i32, Expand); 00112 setOperationAction(ISD::ROTL , MVT::i32, Expand); 00113 setOperationAction(ISD::ROTR , MVT::i32, Expand); 00114 setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); 00115 setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand); 00116 00117 setOperationAction(ISD::TRAP, MVT::Other, Legal); 00118 00119 // Jump tables. 00120 setOperationAction(ISD::BR_JT, MVT::Other, Custom); 00121 00122 setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); 00123 setOperationAction(ISD::BlockAddress, MVT::i32 , Custom); 00124 00125 // Conversion of i64 -> double produces constantpool nodes 00126 setOperationAction(ISD::ConstantPool, MVT::i32, Custom); 00127 00128 // Loads 00129 setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); 00130 setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); 00131 setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); 00132 00133 setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand); 00134 setLoadExtAction(ISD::ZEXTLOAD, MVT::i16, Expand); 00135 00136 // Custom expand misaligned loads / stores. 00137 setOperationAction(ISD::LOAD, MVT::i32, Custom); 00138 setOperationAction(ISD::STORE, MVT::i32, Custom); 00139 00140 // Varargs 00141 setOperationAction(ISD::VAEND, MVT::Other, Expand); 00142 setOperationAction(ISD::VACOPY, MVT::Other, Expand); 00143 setOperationAction(ISD::VAARG, MVT::Other, Custom); 00144 setOperationAction(ISD::VASTART, MVT::Other, Custom); 00145 00146 // Dynamic stack 00147 setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); 00148 setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); 00149 setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); 00150 00151 // TRAMPOLINE is custom lowered. 00152 setOperationAction(ISD::INIT_TRAMPOLINE, MVT::Other, Custom); 00153 setOperationAction(ISD::ADJUST_TRAMPOLINE, MVT::Other, Custom); 00154 00155 // We want to custom lower some of our intrinsics. 00156 setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); 00157 00158 MaxStoresPerMemset = MaxStoresPerMemsetOptSize = 4; 00159 MaxStoresPerMemmove = MaxStoresPerMemmoveOptSize 00160 = MaxStoresPerMemcpy = MaxStoresPerMemcpyOptSize = 2; 00161 00162 // We have target-specific dag combine patterns for the following nodes: 00163 setTargetDAGCombine(ISD::STORE); 00164 setTargetDAGCombine(ISD::ADD); 00165 00166 setMinFunctionAlignment(1); 00167 } 00168 00169 SDValue XCoreTargetLowering:: 00170 LowerOperation(SDValue Op, SelectionDAG &DAG) const { 00171 switch (Op.getOpcode()) 00172 { 00173 case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); 00174 case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); 00175 case ISD::ConstantPool: return LowerConstantPool(Op, DAG); 00176 case ISD::BR_JT: return LowerBR_JT(Op, DAG); 00177 case ISD::LOAD: return LowerLOAD(Op, DAG); 00178 case ISD::STORE: return LowerSTORE(Op, DAG); 00179 case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); 00180 case ISD::VAARG: return LowerVAARG(Op, DAG); 00181 case ISD::VASTART: return LowerVASTART(Op, DAG); 00182 case ISD::SMUL_LOHI: return LowerSMUL_LOHI(Op, DAG); 00183 case ISD::UMUL_LOHI: return LowerUMUL_LOHI(Op, DAG); 00184 // FIXME: Remove these when LegalizeDAGTypes lands. 00185 case ISD::ADD: 00186 case ISD::SUB: return ExpandADDSUB(Op.getNode(), DAG); 00187 case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); 00188 case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG); 00189 case ISD::ADJUST_TRAMPOLINE: return LowerADJUST_TRAMPOLINE(Op, DAG); 00190 case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); 00191 default: 00192 llvm_unreachable("unimplemented operand"); 00193 } 00194 } 00195 00196 /// ReplaceNodeResults - Replace the results of node with an illegal result 00197 /// type with new values built out of custom code. 00198 void XCoreTargetLowering::ReplaceNodeResults(SDNode *N, 00199 SmallVectorImpl<SDValue>&Results, 00200 SelectionDAG &DAG) const { 00201 switch (N->getOpcode()) { 00202 default: 00203 llvm_unreachable("Don't know how to custom expand this!"); 00204 case ISD::ADD: 00205 case ISD::SUB: 00206 Results.push_back(ExpandADDSUB(N, DAG)); 00207 return; 00208 } 00209 } 00210 00211 //===----------------------------------------------------------------------===// 00212 // Misc Lower Operation implementation 00213 //===----------------------------------------------------------------------===// 00214 00215 SDValue XCoreTargetLowering:: 00216 LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const 00217 { 00218 DebugLoc dl = Op.getDebugLoc(); 00219 SDValue Cond = DAG.getNode(ISD::SETCC, dl, MVT::i32, Op.getOperand(2), 00220 Op.getOperand(3), Op.getOperand(4)); 00221 return DAG.getNode(ISD::SELECT, dl, MVT::i32, Cond, Op.getOperand(0), 00222 Op.getOperand(1)); 00223 } 00224 00225 SDValue XCoreTargetLowering:: 00226 getGlobalAddressWrapper(SDValue GA, const GlobalValue *GV, 00227 SelectionDAG &DAG) const 00228 { 00229 // FIXME there is no actual debug info here 00230 DebugLoc dl = GA.getDebugLoc(); 00231 const GlobalValue *UnderlyingGV = GV; 00232 // If GV is an alias then use the aliasee to determine the wrapper type 00233 if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) 00234 UnderlyingGV = GA->resolveAliasedGlobal(); 00235 if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(UnderlyingGV)) { 00236 if (GVar->isConstant()) 00237 return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, GA); 00238 return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, GA); 00239 } 00240 return DAG.getNode(XCoreISD::PCRelativeWrapper, dl, MVT::i32, GA); 00241 } 00242 00243 SDValue XCoreTargetLowering:: 00244 LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const 00245 { 00246 DebugLoc DL = Op.getDebugLoc(); 00247 const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op); 00248 const GlobalValue *GV = GN->getGlobal(); 00249 int64_t Offset = GN->getOffset(); 00250 // We can only fold positive offsets that are a multiple of the word size. 00251 int64_t FoldedOffset = std::max(Offset & ~3, (int64_t)0); 00252 SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, FoldedOffset); 00253 GA = getGlobalAddressWrapper(GA, GV, DAG); 00254 // Handle the rest of the offset. 00255 if (Offset != FoldedOffset) { 00256 SDValue Remaining = DAG.getConstant(Offset - FoldedOffset, MVT::i32); 00257 GA = DAG.getNode(ISD::ADD, DL, MVT::i32, GA, Remaining); 00258 } 00259 return GA; 00260 } 00261 00262 static inline SDValue BuildGetId(SelectionDAG &DAG, DebugLoc dl) { 00263 return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::i32, 00264 DAG.getConstant(Intrinsic::xcore_getid, MVT::i32)); 00265 } 00266 00267 SDValue XCoreTargetLowering:: 00268 LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const 00269 { 00270 DebugLoc DL = Op.getDebugLoc(); 00271 00272 const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); 00273 SDValue Result = DAG.getTargetBlockAddress(BA, getPointerTy()); 00274 00275 return DAG.getNode(XCoreISD::PCRelativeWrapper, DL, getPointerTy(), Result); 00276 } 00277 00278 SDValue XCoreTargetLowering:: 00279 LowerConstantPool(SDValue Op, SelectionDAG &DAG) const 00280 { 00281 ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); 00282 // FIXME there isn't really debug info here 00283 DebugLoc dl = CP->getDebugLoc(); 00284 EVT PtrVT = Op.getValueType(); 00285 SDValue Res; 00286 if (CP->isMachineConstantPoolEntry()) { 00287 Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), PtrVT, 00288 CP->getAlignment()); 00289 } else { 00290 Res = DAG.getTargetConstantPool(CP->getConstVal(), PtrVT, 00291 CP->getAlignment()); 00292 } 00293 return DAG.getNode(XCoreISD::CPRelativeWrapper, dl, MVT::i32, Res); 00294 } 00295 00296 unsigned XCoreTargetLowering::getJumpTableEncoding() const { 00297 return MachineJumpTableInfo::EK_Inline; 00298 } 00299 00300 SDValue XCoreTargetLowering:: 00301 LowerBR_JT(SDValue Op, SelectionDAG &DAG) const 00302 { 00303 SDValue Chain = Op.getOperand(0); 00304 SDValue Table = Op.getOperand(1); 00305 SDValue Index = Op.getOperand(2); 00306 DebugLoc dl = Op.getDebugLoc(); 00307 JumpTableSDNode *JT = cast<JumpTableSDNode>(Table); 00308 unsigned JTI = JT->getIndex(); 00309 MachineFunction &MF = DAG.getMachineFunction(); 00310 const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo(); 00311 SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32); 00312 00313 unsigned NumEntries = MJTI->getJumpTables()[JTI].MBBs.size(); 00314 if (NumEntries <= 32) { 00315 return DAG.getNode(XCoreISD::BR_JT, dl, MVT::Other, Chain, TargetJT, Index); 00316 } 00317 assert((NumEntries >> 31) == 0); 00318 SDValue ScaledIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index, 00319 DAG.getConstant(1, MVT::i32)); 00320 return DAG.getNode(XCoreISD::BR_JT32, dl, MVT::Other, Chain, TargetJT, 00321 ScaledIndex); 00322 } 00323 00324 SDValue XCoreTargetLowering:: 00325 lowerLoadWordFromAlignedBasePlusOffset(DebugLoc DL, SDValue Chain, SDValue Base, 00326 int64_t Offset, SelectionDAG &DAG) const 00327 { 00328 if ((Offset & 0x3) == 0) { 00329 return DAG.getLoad(getPointerTy(), DL, Chain, Base, MachinePointerInfo(), 00330 false, false, false, 0); 00331 } 00332 // Lower to pair of consecutive word aligned loads plus some bit shifting. 00333 int32_t HighOffset = RoundUpToAlignment(Offset, 4); 00334 int32_t LowOffset = HighOffset - 4; 00335 SDValue LowAddr, HighAddr; 00336 if (GlobalAddressSDNode *GASD = 00337 dyn_cast<GlobalAddressSDNode>(Base.getNode())) { 00338 LowAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(), 00339 LowOffset); 00340 HighAddr = DAG.getGlobalAddress(GASD->getGlobal(), DL, Base.getValueType(), 00341 HighOffset); 00342 } else { 00343 LowAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, 00344 DAG.getConstant(LowOffset, MVT::i32)); 00345 HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, Base, 00346 DAG.getConstant(HighOffset, MVT::i32)); 00347 } 00348 SDValue LowShift = DAG.getConstant((Offset - LowOffset) * 8, MVT::i32); 00349 SDValue HighShift = DAG.getConstant((HighOffset - Offset) * 8, MVT::i32); 00350 00351 SDValue Low = DAG.getLoad(getPointerTy(), DL, Chain, 00352 LowAddr, MachinePointerInfo(), 00353 false, false, false, 0); 00354 SDValue High = DAG.getLoad(getPointerTy(), DL, Chain, 00355 HighAddr, MachinePointerInfo(), 00356 false, false, false, 0); 00357 SDValue LowShifted = DAG.getNode(ISD::SRL, DL, MVT::i32, Low, LowShift); 00358 SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, HighShift); 00359 SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, LowShifted, HighShifted); 00360 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1), 00361 High.getValue(1)); 00362 SDValue Ops[] = { Result, Chain }; 00363 return DAG.getMergeValues(Ops, 2, DL); 00364 } 00365 00366 static bool isWordAligned(SDValue Value, SelectionDAG &DAG) 00367 { 00368 APInt KnownZero, KnownOne; 00369 DAG.ComputeMaskedBits(Value, KnownZero, KnownOne); 00370 return KnownZero.countTrailingOnes() >= 2; 00371 } 00372 00373 SDValue XCoreTargetLowering:: 00374 LowerLOAD(SDValue Op, SelectionDAG &DAG) const { 00375 const TargetLowering &TLI = DAG.getTargetLoweringInfo(); 00376 LoadSDNode *LD = cast<LoadSDNode>(Op); 00377 assert(LD->getExtensionType() == ISD::NON_EXTLOAD && 00378 "Unexpected extension type"); 00379 assert(LD->getMemoryVT() == MVT::i32 && "Unexpected load EVT"); 00380 if (allowsUnalignedMemoryAccesses(LD->getMemoryVT())) 00381 return SDValue(); 00382 00383 unsigned ABIAlignment = getDataLayout()-> 00384 getABITypeAlignment(LD->getMemoryVT().getTypeForEVT(*DAG.getContext())); 00385 // Leave aligned load alone. 00386 if (LD->getAlignment() >= ABIAlignment) 00387 return SDValue(); 00388 00389 SDValue Chain = LD->getChain(); 00390 SDValue BasePtr = LD->getBasePtr(); 00391 DebugLoc DL = Op.getDebugLoc(); 00392 00393 if (!LD->isVolatile()) { 00394 const GlobalValue *GV; 00395 int64_t Offset = 0; 00396 if (DAG.isBaseWithConstantOffset(BasePtr) && 00397 isWordAligned(BasePtr->getOperand(0), DAG)) { 00398 SDValue NewBasePtr = BasePtr->getOperand(0); 00399 Offset = cast<ConstantSDNode>(BasePtr->getOperand(1))->getSExtValue(); 00400 return lowerLoadWordFromAlignedBasePlusOffset(DL, Chain, NewBasePtr, 00401 Offset, DAG); 00402 } 00403 if (TLI.isGAPlusOffset(BasePtr.getNode(), GV, Offset) && 00404 MinAlign(GV->getAlignment(), 4) == 4) { 00405 SDValue NewBasePtr = DAG.getGlobalAddress(GV, DL, 00406 BasePtr->getValueType(0)); 00407 return lowerLoadWordFromAlignedBasePlusOffset(DL, Chain, NewBasePtr, 00408 Offset, DAG); 00409 } 00410 } 00411 00412 if (LD->getAlignment() == 2) { 00413 SDValue Low = DAG.getExtLoad(ISD::ZEXTLOAD, DL, MVT::i32, Chain, 00414 BasePtr, LD->getPointerInfo(), MVT::i16, 00415 LD->isVolatile(), LD->isNonTemporal(), 2); 00416 SDValue HighAddr = DAG.getNode(ISD::ADD, DL, MVT::i32, BasePtr, 00417 DAG.getConstant(2, MVT::i32)); 00418 SDValue High = DAG.getExtLoad(ISD::EXTLOAD, DL, MVT::i32, Chain, 00419 HighAddr, 00420 LD->getPointerInfo().getWithOffset(2), 00421 MVT::i16, LD->isVolatile(), 00422 LD->isNonTemporal(), 2); 00423 SDValue HighShifted = DAG.getNode(ISD::SHL, DL, MVT::i32, High, 00424 DAG.getConstant(16, MVT::i32)); 00425 SDValue Result = DAG.getNode(ISD::OR, DL, MVT::i32, Low, HighShifted); 00426 Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Low.getValue(1), 00427 High.getValue(1)); 00428 SDValue Ops[] = { Result, Chain }; 00429 return DAG.getMergeValues(Ops, 2, DL); 00430 } 00431 00432 // Lower to a call to __misaligned_load(BasePtr). 00433 Type *IntPtrTy = getDataLayout()->getIntPtrType(*DAG.getContext()); 00434 TargetLowering::ArgListTy Args; 00435 TargetLowering::ArgListEntry Entry; 00436 00437 Entry.Ty = IntPtrTy; 00438 Entry.Node = BasePtr; 00439 Args.push_back(Entry); 00440 00441 TargetLowering::CallLoweringInfo CLI(Chain, IntPtrTy, false, false, 00442 false, false, 0, CallingConv::C, /*isTailCall=*/false, 00443 /*doesNotRet=*/false, /*isReturnValueUsed=*/true, 00444 DAG.getExternalSymbol("__misaligned_load", getPointerTy()), 00445 Args, DAG, DL); 00446 std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); 00447 00448 SDValue Ops[] = 00449 { CallResult.first, CallResult.second }; 00450 00451 return DAG.getMergeValues(Ops, 2, DL); 00452 } 00453 00454 SDValue XCoreTargetLowering:: 00455 LowerSTORE(SDValue Op, SelectionDAG &DAG) const 00456 { 00457 StoreSDNode *ST = cast<StoreSDNode>(Op); 00458 assert(!ST->isTruncatingStore() && "Unexpected store type"); 00459 assert(ST->getMemoryVT() == MVT::i32 && "Unexpected store EVT"); 00460 if (allowsUnalignedMemoryAccesses(ST->getMemoryVT())) { 00461 return SDValue(); 00462 } 00463 unsigned ABIAlignment = getDataLayout()-> 00464 getABITypeAlignment(ST->getMemoryVT().getTypeForEVT(*DAG.getContext())); 00465 // Leave aligned store alone. 00466 if (ST->getAlignment() >= ABIAlignment) { 00467 return SDValue(); 00468 } 00469 SDValue Chain = ST->getChain(); 00470 SDValue BasePtr = ST->getBasePtr(); 00471 SDValue Value = ST->getValue(); 00472 DebugLoc dl = Op.getDebugLoc(); 00473 00474 if (ST->getAlignment() == 2) { 00475 SDValue Low = Value; 00476 SDValue High = DAG.getNode(ISD::SRL, dl, MVT::i32, Value, 00477 DAG.getConstant(16, MVT::i32)); 00478 SDValue StoreLow = DAG.getTruncStore(Chain, dl, Low, BasePtr, 00479 ST->getPointerInfo(), MVT::i16, 00480 ST->isVolatile(), ST->isNonTemporal(), 00481 2); 00482 SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr, 00483 DAG.getConstant(2, MVT::i32)); 00484 SDValue StoreHigh = DAG.getTruncStore(Chain, dl, High, HighAddr, 00485 ST->getPointerInfo().getWithOffset(2), 00486 MVT::i16, ST->isVolatile(), 00487 ST->isNonTemporal(), 2); 00488 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, StoreLow, StoreHigh); 00489 } 00490 00491 // Lower to a call to __misaligned_store(BasePtr, Value). 00492 Type *IntPtrTy = getDataLayout()->getIntPtrType(*DAG.getContext()); 00493 TargetLowering::ArgListTy Args; 00494 TargetLowering::ArgListEntry Entry; 00495 00496 Entry.Ty = IntPtrTy; 00497 Entry.Node = BasePtr; 00498 Args.push_back(Entry); 00499 00500 Entry.Node = Value; 00501 Args.push_back(Entry); 00502 00503 TargetLowering::CallLoweringInfo CLI(Chain, 00504 Type::getVoidTy(*DAG.getContext()), false, false, 00505 false, false, 0, CallingConv::C, /*isTailCall=*/false, 00506 /*doesNotRet=*/false, /*isReturnValueUsed=*/true, 00507 DAG.getExternalSymbol("__misaligned_store", getPointerTy()), 00508 Args, DAG, dl); 00509 std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); 00510 00511 return CallResult.second; 00512 } 00513 00514 SDValue XCoreTargetLowering:: 00515 LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const 00516 { 00517 assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::SMUL_LOHI && 00518 "Unexpected operand to lower!"); 00519 DebugLoc dl = Op.getDebugLoc(); 00520 SDValue LHS = Op.getOperand(0); 00521 SDValue RHS = Op.getOperand(1); 00522 SDValue Zero = DAG.getConstant(0, MVT::i32); 00523 SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl, 00524 DAG.getVTList(MVT::i32, MVT::i32), Zero, Zero, 00525 LHS, RHS); 00526 SDValue Lo(Hi.getNode(), 1); 00527 SDValue Ops[] = { Lo, Hi }; 00528 return DAG.getMergeValues(Ops, 2, dl); 00529 } 00530 00531 SDValue XCoreTargetLowering:: 00532 LowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) const 00533 { 00534 assert(Op.getValueType() == MVT::i32 && Op.getOpcode() == ISD::UMUL_LOHI && 00535 "Unexpected operand to lower!"); 00536 DebugLoc dl = Op.getDebugLoc(); 00537 SDValue LHS = Op.getOperand(0); 00538 SDValue RHS = Op.getOperand(1); 00539 SDValue Zero = DAG.getConstant(0, MVT::i32); 00540 SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl, 00541 DAG.getVTList(MVT::i32, MVT::i32), LHS, RHS, 00542 Zero, Zero); 00543 SDValue Lo(Hi.getNode(), 1); 00544 SDValue Ops[] = { Lo, Hi }; 00545 return DAG.getMergeValues(Ops, 2, dl); 00546 } 00547 00548 /// isADDADDMUL - Return whether Op is in a form that is equivalent to 00549 /// add(add(mul(x,y),a),b). If requireIntermediatesHaveOneUse is true then 00550 /// each intermediate result in the calculation must also have a single use. 00551 /// If the Op is in the correct form the constituent parts are written to Mul0, 00552 /// Mul1, Addend0 and Addend1. 00553 static bool 00554 isADDADDMUL(SDValue Op, SDValue &Mul0, SDValue &Mul1, SDValue &Addend0, 00555 SDValue &Addend1, bool requireIntermediatesHaveOneUse) 00556 { 00557 if (Op.getOpcode() != ISD::ADD) 00558 return false; 00559 SDValue N0 = Op.getOperand(0); 00560 SDValue N1 = Op.getOperand(1); 00561 SDValue AddOp; 00562 SDValue OtherOp; 00563 if (N0.getOpcode() == ISD::ADD) { 00564 AddOp = N0; 00565 OtherOp = N1; 00566 } else if (N1.getOpcode() == ISD::ADD) { 00567 AddOp = N1; 00568 OtherOp = N0; 00569 } else { 00570 return false; 00571 } 00572 if (requireIntermediatesHaveOneUse && !AddOp.hasOneUse()) 00573 return false; 00574 if (OtherOp.getOpcode() == ISD::MUL) { 00575 // add(add(a,b),mul(x,y)) 00576 if (requireIntermediatesHaveOneUse && !OtherOp.hasOneUse()) 00577 return false; 00578 Mul0 = OtherOp.getOperand(0); 00579 Mul1 = OtherOp.getOperand(1); 00580 Addend0 = AddOp.getOperand(0); 00581 Addend1 = AddOp.getOperand(1); 00582 return true; 00583 } 00584 if (AddOp.getOperand(0).getOpcode() == ISD::MUL) { 00585 // add(add(mul(x,y),a),b) 00586 if (requireIntermediatesHaveOneUse && !AddOp.getOperand(0).hasOneUse()) 00587 return false; 00588 Mul0 = AddOp.getOperand(0).getOperand(0); 00589 Mul1 = AddOp.getOperand(0).getOperand(1); 00590 Addend0 = AddOp.getOperand(1); 00591 Addend1 = OtherOp; 00592 return true; 00593 } 00594 if (AddOp.getOperand(1).getOpcode() == ISD::MUL) { 00595 // add(add(a,mul(x,y)),b) 00596 if (requireIntermediatesHaveOneUse && !AddOp.getOperand(1).hasOneUse()) 00597 return false; 00598 Mul0 = AddOp.getOperand(1).getOperand(0); 00599 Mul1 = AddOp.getOperand(1).getOperand(1); 00600 Addend0 = AddOp.getOperand(0); 00601 Addend1 = OtherOp; 00602 return true; 00603 } 00604 return false; 00605 } 00606 00607 SDValue XCoreTargetLowering:: 00608 TryExpandADDWithMul(SDNode *N, SelectionDAG &DAG) const 00609 { 00610 SDValue Mul; 00611 SDValue Other; 00612 if (N->getOperand(0).getOpcode() == ISD::MUL) { 00613 Mul = N->getOperand(0); 00614 Other = N->getOperand(1); 00615 } else if (N->getOperand(1).getOpcode() == ISD::MUL) { 00616 Mul = N->getOperand(1); 00617 Other = N->getOperand(0); 00618 } else { 00619 return SDValue(); 00620 } 00621 DebugLoc dl = N->getDebugLoc(); 00622 SDValue LL, RL, AddendL, AddendH; 00623 LL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 00624 Mul.getOperand(0), DAG.getConstant(0, MVT::i32)); 00625 RL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 00626 Mul.getOperand(1), DAG.getConstant(0, MVT::i32)); 00627 AddendL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 00628 Other, DAG.getConstant(0, MVT::i32)); 00629 AddendH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 00630 Other, DAG.getConstant(1, MVT::i32)); 00631 APInt HighMask = APInt::getHighBitsSet(64, 32); 00632 unsigned LHSSB = DAG.ComputeNumSignBits(Mul.getOperand(0)); 00633 unsigned RHSSB = DAG.ComputeNumSignBits(Mul.getOperand(1)); 00634 if (DAG.MaskedValueIsZero(Mul.getOperand(0), HighMask) && 00635 DAG.MaskedValueIsZero(Mul.getOperand(1), HighMask)) { 00636 // The inputs are both zero-extended. 00637 SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl, 00638 DAG.getVTList(MVT::i32, MVT::i32), AddendH, 00639 AddendL, LL, RL); 00640 SDValue Lo(Hi.getNode(), 1); 00641 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 00642 } 00643 if (LHSSB > 32 && RHSSB > 32) { 00644 // The inputs are both sign-extended. 00645 SDValue Hi = DAG.getNode(XCoreISD::MACCS, dl, 00646 DAG.getVTList(MVT::i32, MVT::i32), AddendH, 00647 AddendL, LL, RL); 00648 SDValue Lo(Hi.getNode(), 1); 00649 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 00650 } 00651 SDValue LH, RH; 00652 LH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 00653 Mul.getOperand(0), DAG.getConstant(1, MVT::i32)); 00654 RH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 00655 Mul.getOperand(1), DAG.getConstant(1, MVT::i32)); 00656 SDValue Hi = DAG.getNode(XCoreISD::MACCU, dl, 00657 DAG.getVTList(MVT::i32, MVT::i32), AddendH, 00658 AddendL, LL, RL); 00659 SDValue Lo(Hi.getNode(), 1); 00660 RH = DAG.getNode(ISD::MUL, dl, MVT::i32, LL, RH); 00661 LH = DAG.getNode(ISD::MUL, dl, MVT::i32, LH, RL); 00662 Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, RH); 00663 Hi = DAG.getNode(ISD::ADD, dl, MVT::i32, Hi, LH); 00664 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 00665 } 00666 00667 SDValue XCoreTargetLowering:: 00668 ExpandADDSUB(SDNode *N, SelectionDAG &DAG) const 00669 { 00670 assert(N->getValueType(0) == MVT::i64 && 00671 (N->getOpcode() == ISD::ADD || N->getOpcode() == ISD::SUB) && 00672 "Unknown operand to lower!"); 00673 00674 if (N->getOpcode() == ISD::ADD) { 00675 SDValue Result = TryExpandADDWithMul(N, DAG); 00676 if (Result.getNode() != 0) 00677 return Result; 00678 } 00679 00680 DebugLoc dl = N->getDebugLoc(); 00681 00682 // Extract components 00683 SDValue LHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 00684 N->getOperand(0), DAG.getConstant(0, MVT::i32)); 00685 SDValue LHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 00686 N->getOperand(0), DAG.getConstant(1, MVT::i32)); 00687 SDValue RHSL = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 00688 N->getOperand(1), DAG.getConstant(0, MVT::i32)); 00689 SDValue RHSH = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 00690 N->getOperand(1), DAG.getConstant(1, MVT::i32)); 00691 00692 // Expand 00693 unsigned Opcode = (N->getOpcode() == ISD::ADD) ? XCoreISD::LADD : 00694 XCoreISD::LSUB; 00695 SDValue Zero = DAG.getConstant(0, MVT::i32); 00696 SDValue Lo = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32), 00697 LHSL, RHSL, Zero); 00698 SDValue Carry(Lo.getNode(), 1); 00699 00700 SDValue Hi = DAG.getNode(Opcode, dl, DAG.getVTList(MVT::i32, MVT::i32), 00701 LHSH, RHSH, Carry); 00702 SDValue Ignored(Hi.getNode(), 1); 00703 // Merge the pieces 00704 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 00705 } 00706 00707 SDValue XCoreTargetLowering:: 00708 LowerVAARG(SDValue Op, SelectionDAG &DAG) const 00709 { 00710 llvm_unreachable("unimplemented"); 00711 // FIXME Arguments passed by reference need a extra dereference. 00712 SDNode *Node = Op.getNode(); 00713 DebugLoc dl = Node->getDebugLoc(); 00714 const Value *V = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); 00715 EVT VT = Node->getValueType(0); 00716 SDValue VAList = DAG.getLoad(getPointerTy(), dl, Node->getOperand(0), 00717 Node->getOperand(1), MachinePointerInfo(V), 00718 false, false, false, 0); 00719 // Increment the pointer, VAList, to the next vararg 00720 SDValue Tmp3 = DAG.getNode(ISD::ADD, dl, getPointerTy(), VAList, 00721 DAG.getConstant(VT.getSizeInBits(), 00722 getPointerTy())); 00723 // Store the incremented VAList to the legalized pointer 00724 Tmp3 = DAG.getStore(VAList.getValue(1), dl, Tmp3, Node->getOperand(1), 00725 MachinePointerInfo(V), false, false, 0); 00726 // Load the actual argument out of the pointer VAList 00727 return DAG.getLoad(VT, dl, Tmp3, VAList, MachinePointerInfo(), 00728 false, false, false, 0); 00729 } 00730 00731 SDValue XCoreTargetLowering:: 00732 LowerVASTART(SDValue Op, SelectionDAG &DAG) const 00733 { 00734 DebugLoc dl = Op.getDebugLoc(); 00735 // vastart stores the address of the VarArgsFrameIndex slot into the 00736 // memory location argument 00737 MachineFunction &MF = DAG.getMachineFunction(); 00738 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 00739 SDValue Addr = DAG.getFrameIndex(XFI->getVarArgsFrameIndex(), MVT::i32); 00740 return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1), 00741 MachinePointerInfo(), false, false, 0); 00742 } 00743 00744 SDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op, 00745 SelectionDAG &DAG) const { 00746 DebugLoc dl = Op.getDebugLoc(); 00747 // Depths > 0 not supported yet! 00748 if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0) 00749 return SDValue(); 00750 00751 MachineFunction &MF = DAG.getMachineFunction(); 00752 const TargetRegisterInfo *RegInfo = getTargetMachine().getRegisterInfo(); 00753 return DAG.getCopyFromReg(DAG.getEntryNode(), dl, 00754 RegInfo->getFrameRegister(MF), MVT::i32); 00755 } 00756 00757 SDValue XCoreTargetLowering:: 00758 LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const { 00759 return Op.getOperand(0); 00760 } 00761 00762 SDValue XCoreTargetLowering:: 00763 LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const { 00764 SDValue Chain = Op.getOperand(0); 00765 SDValue Trmp = Op.getOperand(1); // trampoline 00766 SDValue FPtr = Op.getOperand(2); // nested function 00767 SDValue Nest = Op.getOperand(3); // 'nest' parameter value 00768 00769 const Value *TrmpAddr = cast<SrcValueSDNode>(Op.getOperand(4))->getValue(); 00770 00771 // .align 4 00772 // LDAPF_u10 r11, nest 00773 // LDW_2rus r11, r11[0] 00774 // STWSP_ru6 r11, sp[0] 00775 // LDAPF_u10 r11, fptr 00776 // LDW_2rus r11, r11[0] 00777 // BAU_1r r11 00778 // nest: 00779 // .word nest 00780 // fptr: 00781 // .word fptr 00782 SDValue OutChains[5]; 00783 00784 SDValue Addr = Trmp; 00785 00786 DebugLoc dl = Op.getDebugLoc(); 00787 OutChains[0] = DAG.getStore(Chain, dl, DAG.getConstant(0x0a3cd805, MVT::i32), 00788 Addr, MachinePointerInfo(TrmpAddr), false, false, 00789 0); 00790 00791 Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 00792 DAG.getConstant(4, MVT::i32)); 00793 OutChains[1] = DAG.getStore(Chain, dl, DAG.getConstant(0xd80456c0, MVT::i32), 00794 Addr, MachinePointerInfo(TrmpAddr, 4), false, 00795 false, 0); 00796 00797 Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 00798 DAG.getConstant(8, MVT::i32)); 00799 OutChains[2] = DAG.getStore(Chain, dl, DAG.getConstant(0x27fb0a3c, MVT::i32), 00800 Addr, MachinePointerInfo(TrmpAddr, 8), false, 00801 false, 0); 00802 00803 Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 00804 DAG.getConstant(12, MVT::i32)); 00805 OutChains[3] = DAG.getStore(Chain, dl, Nest, Addr, 00806 MachinePointerInfo(TrmpAddr, 12), false, false, 00807 0); 00808 00809 Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, 00810 DAG.getConstant(16, MVT::i32)); 00811 OutChains[4] = DAG.getStore(Chain, dl, FPtr, Addr, 00812 MachinePointerInfo(TrmpAddr, 16), false, false, 00813 0); 00814 00815 return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 5); 00816 } 00817 00818 SDValue XCoreTargetLowering:: 00819 LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const { 00820 DebugLoc DL = Op.getDebugLoc(); 00821 unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); 00822 switch (IntNo) { 00823 case Intrinsic::xcore_crc8: 00824 EVT VT = Op.getValueType(); 00825 SDValue Data = 00826 DAG.getNode(XCoreISD::CRC8, DL, DAG.getVTList(VT, VT), 00827 Op.getOperand(1), Op.getOperand(2) , Op.getOperand(3)); 00828 SDValue Crc(Data.getNode(), 1); 00829 SDValue Results[] = { Crc, Data }; 00830 return DAG.getMergeValues(Results, 2, DL); 00831 } 00832 return SDValue(); 00833 } 00834 00835 //===----------------------------------------------------------------------===// 00836 // Calling Convention Implementation 00837 //===----------------------------------------------------------------------===// 00838 00839 #include "XCoreGenCallingConv.inc" 00840 00841 //===----------------------------------------------------------------------===// 00842 // Call Calling Convention Implementation 00843 //===----------------------------------------------------------------------===// 00844 00845 /// XCore call implementation 00846 SDValue 00847 XCoreTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, 00848 SmallVectorImpl<SDValue> &InVals) const { 00849 SelectionDAG &DAG = CLI.DAG; 00850 DebugLoc &dl = CLI.DL; 00851 SmallVector<ISD::OutputArg, 32> &Outs = CLI.Outs; 00852 SmallVector<SDValue, 32> &OutVals = CLI.OutVals; 00853 SmallVector<ISD::InputArg, 32> &Ins = CLI.Ins; 00854 SDValue Chain = CLI.Chain; 00855 SDValue Callee = CLI.Callee; 00856 bool &isTailCall = CLI.IsTailCall; 00857 CallingConv::ID CallConv = CLI.CallConv; 00858 bool isVarArg = CLI.IsVarArg; 00859 00860 // XCore target does not yet support tail call optimization. 00861 isTailCall = false; 00862 00863 // For now, only CallingConv::C implemented 00864 switch (CallConv) 00865 { 00866 default: 00867 llvm_unreachable("Unsupported calling convention"); 00868 case CallingConv::Fast: 00869 case CallingConv::C: 00870 return LowerCCCCallTo(Chain, Callee, CallConv, isVarArg, isTailCall, 00871 Outs, OutVals, Ins, dl, DAG, InVals); 00872 } 00873 } 00874 00875 /// LowerCCCCallTo - functions arguments are copied from virtual 00876 /// regs to (physical regs)/(stack frame), CALLSEQ_START and 00877 /// CALLSEQ_END are emitted. 00878 /// TODO: isTailCall, sret. 00879 SDValue 00880 XCoreTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, 00881 CallingConv::ID CallConv, bool isVarArg, 00882 bool isTailCall, 00883 const SmallVectorImpl<ISD::OutputArg> &Outs, 00884 const SmallVectorImpl<SDValue> &OutVals, 00885 const SmallVectorImpl<ISD::InputArg> &Ins, 00886 DebugLoc dl, SelectionDAG &DAG, 00887 SmallVectorImpl<SDValue> &InVals) const { 00888 00889 // Analyze operands of the call, assigning locations to each operand. 00890 SmallVector<CCValAssign, 16> ArgLocs; 00891 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 00892 getTargetMachine(), ArgLocs, *DAG.getContext()); 00893 00894 // The ABI dictates there should be one stack slot available to the callee 00895 // on function entry (for saving lr). 00896 CCInfo.AllocateStack(4, 4); 00897 00898 CCInfo.AnalyzeCallOperands(Outs, CC_XCore); 00899 00900 // Get a count of how many bytes are to be pushed on the stack. 00901 unsigned NumBytes = CCInfo.getNextStackOffset(); 00902 00903 Chain = DAG.getCALLSEQ_START(Chain,DAG.getConstant(NumBytes, 00904 getPointerTy(), true)); 00905 00906 SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass; 00907 SmallVector<SDValue, 12> MemOpChains; 00908 00909 // Walk the register/memloc assignments, inserting copies/loads. 00910 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 00911 CCValAssign &VA = ArgLocs[i]; 00912 SDValue Arg = OutVals[i]; 00913 00914 // Promote the value if needed. 00915 switch (VA.getLocInfo()) { 00916 default: llvm_unreachable("Unknown loc info!"); 00917 case CCValAssign::Full: break; 00918 case CCValAssign::SExt: 00919 Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); 00920 break; 00921 case CCValAssign::ZExt: 00922 Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); 00923 break; 00924 case CCValAssign::AExt: 00925 Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); 00926 break; 00927 } 00928 00929 // Arguments that can be passed on register must be kept at 00930 // RegsToPass vector 00931 if (VA.isRegLoc()) { 00932 RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); 00933 } else { 00934 assert(VA.isMemLoc()); 00935 00936 int Offset = VA.getLocMemOffset(); 00937 00938 MemOpChains.push_back(DAG.getNode(XCoreISD::STWSP, dl, MVT::Other, 00939 Chain, Arg, 00940 DAG.getConstant(Offset/4, MVT::i32))); 00941 } 00942 } 00943 00944 // Transform all store nodes into one single node because 00945 // all store nodes are independent of each other. 00946 if (!MemOpChains.empty()) 00947 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 00948 &MemOpChains[0], MemOpChains.size()); 00949 00950 // Build a sequence of copy-to-reg nodes chained together with token 00951 // chain and flag operands which copy the outgoing args into registers. 00952 // The InFlag in necessary since all emitted instructions must be 00953 // stuck together. 00954 SDValue InFlag; 00955 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { 00956 Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, 00957 RegsToPass[i].second, InFlag); 00958 InFlag = Chain.getValue(1); 00959 } 00960 00961 // If the callee is a GlobalAddress node (quite common, every direct call is) 00962 // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. 00963 // Likewise ExternalSymbol -> TargetExternalSymbol. 00964 if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) 00965 Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32); 00966 else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) 00967 Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32); 00968 00969 // XCoreBranchLink = #chain, #target_address, #opt_in_flags... 00970 // = Chain, Callee, Reg#1, Reg#2, ... 00971 // 00972 // Returns a chain & a flag for retval copy to use. 00973 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); 00974 SmallVector<SDValue, 8> Ops; 00975 Ops.push_back(Chain); 00976 Ops.push_back(Callee); 00977 00978 // Add argument registers to the end of the list so that they are 00979 // known live into the call. 00980 for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) 00981 Ops.push_back(DAG.getRegister(RegsToPass[i].first, 00982 RegsToPass[i].second.getValueType())); 00983 00984 if (InFlag.getNode()) 00985 Ops.push_back(InFlag); 00986 00987 Chain = DAG.getNode(XCoreISD::BL, dl, NodeTys, &Ops[0], Ops.size()); 00988 InFlag = Chain.getValue(1); 00989 00990 // Create the CALLSEQ_END node. 00991 Chain = DAG.getCALLSEQ_END(Chain, 00992 DAG.getConstant(NumBytes, getPointerTy(), true), 00993 DAG.getConstant(0, getPointerTy(), true), 00994 InFlag); 00995 InFlag = Chain.getValue(1); 00996 00997 // Handle result values, copying them out of physregs into vregs that we 00998 // return. 00999 return LowerCallResult(Chain, InFlag, CallConv, isVarArg, 01000 Ins, dl, DAG, InVals); 01001 } 01002 01003 /// LowerCallResult - Lower the result values of a call into the 01004 /// appropriate copies out of appropriate physical registers. 01005 SDValue 01006 XCoreTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, 01007 CallingConv::ID CallConv, bool isVarArg, 01008 const SmallVectorImpl<ISD::InputArg> &Ins, 01009 DebugLoc dl, SelectionDAG &DAG, 01010 SmallVectorImpl<SDValue> &InVals) const { 01011 01012 // Assign locations to each value returned by this call. 01013 SmallVector<CCValAssign, 16> RVLocs; 01014 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 01015 getTargetMachine(), RVLocs, *DAG.getContext()); 01016 01017 CCInfo.AnalyzeCallResult(Ins, RetCC_XCore); 01018 01019 // Copy all of the result registers out of their specified physreg. 01020 for (unsigned i = 0; i != RVLocs.size(); ++i) { 01021 Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(), 01022 RVLocs[i].getValVT(), InFlag).getValue(1); 01023 InFlag = Chain.getValue(2); 01024 InVals.push_back(Chain.getValue(0)); 01025 } 01026 01027 return Chain; 01028 } 01029 01030 //===----------------------------------------------------------------------===// 01031 // Formal Arguments Calling Convention Implementation 01032 //===----------------------------------------------------------------------===// 01033 01034 /// XCore formal arguments implementation 01035 SDValue 01036 XCoreTargetLowering::LowerFormalArguments(SDValue Chain, 01037 CallingConv::ID CallConv, 01038 bool isVarArg, 01039 const SmallVectorImpl<ISD::InputArg> &Ins, 01040 DebugLoc dl, 01041 SelectionDAG &DAG, 01042 SmallVectorImpl<SDValue> &InVals) 01043 const { 01044 switch (CallConv) 01045 { 01046 default: 01047 llvm_unreachable("Unsupported calling convention"); 01048 case CallingConv::C: 01049 case CallingConv::Fast: 01050 return LowerCCCArguments(Chain, CallConv, isVarArg, 01051 Ins, dl, DAG, InVals); 01052 } 01053 } 01054 01055 /// LowerCCCArguments - transform physical registers into 01056 /// virtual registers and generate load operations for 01057 /// arguments places on the stack. 01058 /// TODO: sret 01059 SDValue 01060 XCoreTargetLowering::LowerCCCArguments(SDValue Chain, 01061 CallingConv::ID CallConv, 01062 bool isVarArg, 01063 const SmallVectorImpl<ISD::InputArg> 01064 &Ins, 01065 DebugLoc dl, 01066 SelectionDAG &DAG, 01067 SmallVectorImpl<SDValue> &InVals) const { 01068 MachineFunction &MF = DAG.getMachineFunction(); 01069 MachineFrameInfo *MFI = MF.getFrameInfo(); 01070 MachineRegisterInfo &RegInfo = MF.getRegInfo(); 01071 01072 // Assign locations to all of the incoming arguments. 01073 SmallVector<CCValAssign, 16> ArgLocs; 01074 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 01075 getTargetMachine(), ArgLocs, *DAG.getContext()); 01076 01077 CCInfo.AnalyzeFormalArguments(Ins, CC_XCore); 01078 01079 unsigned StackSlotSize = XCoreFrameLowering::stackSlotSize(); 01080 01081 unsigned LRSaveSize = StackSlotSize; 01082 01083 for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { 01084 01085 CCValAssign &VA = ArgLocs[i]; 01086 01087 if (VA.isRegLoc()) { 01088 // Arguments passed in registers 01089 EVT RegVT = VA.getLocVT(); 01090 switch (RegVT.getSimpleVT().SimpleTy) { 01091 default: 01092 { 01093 #ifndef NDEBUG 01094 errs() << "LowerFormalArguments Unhandled argument type: " 01095 << RegVT.getSimpleVT().SimpleTy << "\n"; 01096 #endif 01097 llvm_unreachable(0); 01098 } 01099 case MVT::i32: 01100 unsigned VReg = RegInfo.createVirtualRegister(&XCore::GRRegsRegClass); 01101 RegInfo.addLiveIn(VA.getLocReg(), VReg); 01102 InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT)); 01103 } 01104 } else { 01105 // sanity check 01106 assert(VA.isMemLoc()); 01107 // Load the argument to a virtual register 01108 unsigned ObjSize = VA.getLocVT().getSizeInBits()/8; 01109 if (ObjSize > StackSlotSize) { 01110 errs() << "LowerFormalArguments Unhandled argument type: " 01111 << EVT(VA.getLocVT()).getEVTString() 01112 << "\n"; 01113 } 01114 // Create the frame index object for this incoming parameter... 01115 int FI = MFI->CreateFixedObject(ObjSize, 01116 LRSaveSize + VA.getLocMemOffset(), 01117 true); 01118 01119 // Create the SelectionDAG nodes corresponding to a load 01120 //from this parameter 01121 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 01122 InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, 01123 MachinePointerInfo::getFixedStack(FI), 01124 false, false, false, 0)); 01125 } 01126 } 01127 01128 if (isVarArg) { 01129 /* Argument registers */ 01130 static const uint16_t ArgRegs[] = { 01131 XCore::R0, XCore::R1, XCore::R2, XCore::R3 01132 }; 01133 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>(); 01134 unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs, 01135 array_lengthof(ArgRegs)); 01136 if (FirstVAReg < array_lengthof(ArgRegs)) { 01137 SmallVector<SDValue, 4> MemOps; 01138 int offset = 0; 01139 // Save remaining registers, storing higher register numbers at a higher 01140 // address 01141 for (int i = array_lengthof(ArgRegs) - 1; i >= (int)FirstVAReg; --i) { 01142 // Create a stack slot 01143 int FI = MFI->CreateFixedObject(4, offset, true); 01144 if (i == (int)FirstVAReg) { 01145 XFI->setVarArgsFrameIndex(FI); 01146 } 01147 offset -= StackSlotSize; 01148 SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); 01149 // Move argument from phys reg -> virt reg 01150 unsigned VReg = RegInfo.createVirtualRegister(&XCore::GRRegsRegClass); 01151 RegInfo.addLiveIn(ArgRegs[i], VReg); 01152 SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); 01153 // Move argument from virt reg -> stack 01154 SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, 01155 MachinePointerInfo(), false, false, 0); 01156 MemOps.push_back(Store); 01157 } 01158 if (!MemOps.empty()) 01159 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, 01160 &MemOps[0], MemOps.size()); 01161 } else { 01162 // This will point to the next argument passed via stack. 01163 XFI->setVarArgsFrameIndex( 01164 MFI->CreateFixedObject(4, LRSaveSize + CCInfo.getNextStackOffset(), 01165 true)); 01166 } 01167 } 01168 01169 return Chain; 01170 } 01171 01172 //===----------------------------------------------------------------------===// 01173 // Return Value Calling Convention Implementation 01174 //===----------------------------------------------------------------------===// 01175 01176 bool XCoreTargetLowering:: 01177 CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, 01178 bool isVarArg, 01179 const SmallVectorImpl<ISD::OutputArg> &Outs, 01180 LLVMContext &Context) const { 01181 SmallVector<CCValAssign, 16> RVLocs; 01182 CCState CCInfo(CallConv, isVarArg, MF, getTargetMachine(), RVLocs, Context); 01183 return CCInfo.CheckReturn(Outs, RetCC_XCore); 01184 } 01185 01186 SDValue 01187 XCoreTargetLowering::LowerReturn(SDValue Chain, 01188 CallingConv::ID CallConv, bool isVarArg, 01189 const SmallVectorImpl<ISD::OutputArg> &Outs, 01190 const SmallVectorImpl<SDValue> &OutVals, 01191 DebugLoc dl, SelectionDAG &DAG) const { 01192 01193 // CCValAssign - represent the assignment of 01194 // the return value to a location 01195 SmallVector<CCValAssign, 16> RVLocs; 01196 01197 // CCState - Info about the registers and stack slot. 01198 CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), 01199 getTargetMachine(), RVLocs, *DAG.getContext()); 01200 01201 // Analyze return values. 01202 CCInfo.AnalyzeReturn(Outs, RetCC_XCore); 01203 01204 SDValue Flag; 01205 SmallVector<SDValue, 4> RetOps(1, Chain); 01206 01207 // Return on XCore is always a "retsp 0" 01208 RetOps.push_back(DAG.getConstant(0, MVT::i32)); 01209 01210 // Copy the result values into the output registers. 01211 for (unsigned i = 0; i != RVLocs.size(); ++i) { 01212 CCValAssign &VA = RVLocs[i]; 01213 assert(VA.isRegLoc() && "Can only return in registers!"); 01214 01215 Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), 01216 OutVals[i], Flag); 01217 01218 // guarantee that all emitted copies are 01219 // stuck together, avoiding something bad 01220 Flag = Chain.getValue(1); 01221 RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); 01222 } 01223 01224 RetOps[0] = Chain; // Update chain. 01225 01226 // Add the flag if we have it. 01227 if (Flag.getNode()) 01228 RetOps.push_back(Flag); 01229 01230 return DAG.getNode(XCoreISD::RETSP, dl, MVT::Other, 01231 &RetOps[0], RetOps.size()); 01232 } 01233 01234 //===----------------------------------------------------------------------===// 01235 // Other Lowering Code 01236 //===----------------------------------------------------------------------===// 01237 01238 MachineBasicBlock * 01239 XCoreTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, 01240 MachineBasicBlock *BB) const { 01241 const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); 01242 DebugLoc dl = MI->getDebugLoc(); 01243 assert((MI->getOpcode() == XCore::SELECT_CC) && 01244 "Unexpected instr type to insert"); 01245 01246 // To "insert" a SELECT_CC instruction, we actually have to insert the diamond 01247 // control-flow pattern. The incoming instruction knows the destination vreg 01248 // to set, the condition code register to branch on, the true/false values to 01249 // select between, and a branch opcode to use. 01250 const BasicBlock *LLVM_BB = BB->getBasicBlock(); 01251 MachineFunction::iterator It = BB; 01252 ++It; 01253 01254 // thisMBB: 01255 // ... 01256 // TrueVal = ... 01257 // cmpTY ccX, r1, r2 01258 // bCC copy1MBB 01259 // fallthrough --> copy0MBB 01260 MachineBasicBlock *thisMBB = BB; 01261 MachineFunction *F = BB->getParent(); 01262 MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); 01263 MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); 01264 F->insert(It, copy0MBB); 01265 F->insert(It, sinkMBB); 01266 01267 // Transfer the remainder of BB and its successor edges to sinkMBB. 01268 sinkMBB->splice(sinkMBB->begin(), BB, 01269 llvm::next(MachineBasicBlock::iterator(MI)), 01270 BB->end()); 01271 sinkMBB->transferSuccessorsAndUpdatePHIs(BB); 01272 01273 // Next, add the true and fallthrough blocks as its successors. 01274 BB->addSuccessor(copy0MBB); 01275 BB->addSuccessor(sinkMBB); 01276 01277 BuildMI(BB, dl, TII.get(XCore::BRFT_lru6)) 01278 .addReg(MI->getOperand(1).getReg()).addMBB(sinkMBB); 01279 01280 // copy0MBB: 01281 // %FalseValue = ... 01282 // # fallthrough to sinkMBB 01283 BB = copy0MBB; 01284 01285 // Update machine-CFG edges 01286 BB->addSuccessor(sinkMBB); 01287 01288 // sinkMBB: 01289 // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] 01290 // ... 01291 BB = sinkMBB; 01292 BuildMI(*BB, BB->begin(), dl, 01293 TII.get(XCore::PHI), MI->getOperand(0).getReg()) 01294 .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB) 01295 .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB); 01296 01297 MI->eraseFromParent(); // The pseudo instruction is gone now. 01298 return BB; 01299 } 01300 01301 //===----------------------------------------------------------------------===// 01302 // Target Optimization Hooks 01303 //===----------------------------------------------------------------------===// 01304 01305 SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N, 01306 DAGCombinerInfo &DCI) const { 01307 SelectionDAG &DAG = DCI.DAG; 01308 DebugLoc dl = N->getDebugLoc(); 01309 switch (N->getOpcode()) { 01310 default: break; 01311 case XCoreISD::LADD: { 01312 SDValue N0 = N->getOperand(0); 01313 SDValue N1 = N->getOperand(1); 01314 SDValue N2 = N->getOperand(2); 01315 ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); 01316 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 01317 EVT VT = N0.getValueType(); 01318 01319 // canonicalize constant to RHS 01320 if (N0C && !N1C) 01321 return DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N1, N0, N2); 01322 01323 // fold (ladd 0, 0, x) -> 0, x & 1 01324 if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) { 01325 SDValue Carry = DAG.getConstant(0, VT); 01326 SDValue Result = DAG.getNode(ISD::AND, dl, VT, N2, 01327 DAG.getConstant(1, VT)); 01328 SDValue Ops[] = { Result, Carry }; 01329 return DAG.getMergeValues(Ops, 2, dl); 01330 } 01331 01332 // fold (ladd x, 0, y) -> 0, add x, y iff carry is unused and y has only the 01333 // low bit set 01334 if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 1)) { 01335 APInt KnownZero, KnownOne; 01336 APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 01337 VT.getSizeInBits() - 1); 01338 DAG.ComputeMaskedBits(N2, KnownZero, KnownOne); 01339 if ((KnownZero & Mask) == Mask) { 01340 SDValue Carry = DAG.getConstant(0, VT); 01341 SDValue Result = DAG.getNode(ISD::ADD, dl, VT, N0, N2); 01342 SDValue Ops[] = { Result, Carry }; 01343 return DAG.getMergeValues(Ops, 2, dl); 01344 } 01345 } 01346 } 01347 break; 01348 case XCoreISD::LSUB: { 01349 SDValue N0 = N->getOperand(0); 01350 SDValue N1 = N->getOperand(1); 01351 SDValue N2 = N->getOperand(2); 01352 ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); 01353 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 01354 EVT VT = N0.getValueType(); 01355 01356 // fold (lsub 0, 0, x) -> x, -x iff x has only the low bit set 01357 if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) { 01358 APInt KnownZero, KnownOne; 01359 APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 01360 VT.getSizeInBits() - 1); 01361 DAG.ComputeMaskedBits(N2, KnownZero, KnownOne); 01362 if ((KnownZero & Mask) == Mask) { 01363 SDValue Borrow = N2; 01364 SDValue Result = DAG.getNode(ISD::SUB, dl, VT, 01365 DAG.getConstant(0, VT), N2); 01366 SDValue Ops[] = { Result, Borrow }; 01367 return DAG.getMergeValues(Ops, 2, dl); 01368 } 01369 } 01370 01371 // fold (lsub x, 0, y) -> 0, sub x, y iff borrow is unused and y has only the 01372 // low bit set 01373 if (N1C && N1C->isNullValue() && N->hasNUsesOfValue(0, 1)) { 01374 APInt KnownZero, KnownOne; 01375 APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(), 01376 VT.getSizeInBits() - 1); 01377 DAG.ComputeMaskedBits(N2, KnownZero, KnownOne); 01378 if ((KnownZero & Mask) == Mask) { 01379 SDValue Borrow = DAG.getConstant(0, VT); 01380 SDValue Result = DAG.getNode(ISD::SUB, dl, VT, N0, N2); 01381 SDValue Ops[] = { Result, Borrow }; 01382 return DAG.getMergeValues(Ops, 2, dl); 01383 } 01384 } 01385 } 01386 break; 01387 case XCoreISD::LMUL: { 01388 SDValue N0 = N->getOperand(0); 01389 SDValue N1 = N->getOperand(1); 01390 SDValue N2 = N->getOperand(2); 01391 SDValue N3 = N->getOperand(3); 01392 ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0); 01393 ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1); 01394 EVT VT = N0.getValueType(); 01395 // Canonicalize multiplicative constant to RHS. If both multiplicative 01396 // operands are constant canonicalize smallest to RHS. 01397 if ((N0C && !N1C) || 01398 (N0C && N1C && N0C->getZExtValue() < N1C->getZExtValue())) 01399 return DAG.getNode(XCoreISD::LMUL, dl, DAG.getVTList(VT, VT), 01400 N1, N0, N2, N3); 01401 01402 // lmul(x, 0, a, b) 01403 if (N1C && N1C->isNullValue()) { 01404 // If the high result is unused fold to add(a, b) 01405 if (N->hasNUsesOfValue(0, 0)) { 01406 SDValue Lo = DAG.getNode(ISD::ADD, dl, VT, N2, N3); 01407 SDValue Ops[] = { Lo, Lo }; 01408 return DAG.getMergeValues(Ops, 2, dl); 01409 } 01410 // Otherwise fold to ladd(a, b, 0) 01411 SDValue Result = 01412 DAG.getNode(XCoreISD::LADD, dl, DAG.getVTList(VT, VT), N2, N3, N1); 01413 SDValue Carry(Result.getNode(), 1); 01414 SDValue Ops[] = { Carry, Result }; 01415 return DAG.getMergeValues(Ops, 2, dl); 01416 } 01417 } 01418 break; 01419 case ISD::ADD: { 01420 // Fold 32 bit expressions such as add(add(mul(x,y),a),b) -> 01421 // lmul(x, y, a, b). The high result of lmul will be ignored. 01422 // This is only profitable if the intermediate results are unused 01423 // elsewhere. 01424 SDValue Mul0, Mul1, Addend0, Addend1; 01425 if (N->getValueType(0) == MVT::i32 && 01426 isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, true)) { 01427 SDValue Ignored = DAG.getNode(XCoreISD::LMUL, dl, 01428 DAG.getVTList(MVT::i32, MVT::i32), Mul0, 01429 Mul1, Addend0, Addend1); 01430 SDValue Result(Ignored.getNode(), 1); 01431 return Result; 01432 } 01433 APInt HighMask = APInt::getHighBitsSet(64, 32); 01434 // Fold 64 bit expression such as add(add(mul(x,y),a),b) -> 01435 // lmul(x, y, a, b) if all operands are zero-extended. We do this 01436 // before type legalization as it is messy to match the operands after 01437 // that. 01438 if (N->getValueType(0) == MVT::i64 && 01439 isADDADDMUL(SDValue(N, 0), Mul0, Mul1, Addend0, Addend1, false) && 01440 DAG.MaskedValueIsZero(Mul0, HighMask) && 01441 DAG.MaskedValueIsZero(Mul1, HighMask) && 01442 DAG.MaskedValueIsZero(Addend0, HighMask) && 01443 DAG.MaskedValueIsZero(Addend1, HighMask)) { 01444 SDValue Mul0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 01445 Mul0, DAG.getConstant(0, MVT::i32)); 01446 SDValue Mul1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 01447 Mul1, DAG.getConstant(0, MVT::i32)); 01448 SDValue Addend0L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 01449 Addend0, DAG.getConstant(0, MVT::i32)); 01450 SDValue Addend1L = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, 01451 Addend1, DAG.getConstant(0, MVT::i32)); 01452 SDValue Hi = DAG.getNode(XCoreISD::LMUL, dl, 01453 DAG.getVTList(MVT::i32, MVT::i32), Mul0L, Mul1L, 01454 Addend0L, Addend1L); 01455 SDValue Lo(Hi.getNode(), 1); 01456 return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i64, Lo, Hi); 01457 } 01458 } 01459 break; 01460 case ISD::STORE: { 01461 // Replace unaligned store of unaligned load with memmove. 01462 StoreSDNode *ST = cast<StoreSDNode>(N); 01463 if (!DCI.isBeforeLegalize() || 01464 allowsUnalignedMemoryAccesses(ST->getMemoryVT()) || 01465 ST->isVolatile() || ST->isIndexed()) { 01466 break; 01467 } 01468 SDValue Chain = ST->getChain(); 01469 01470 unsigned StoreBits = ST->getMemoryVT().getStoreSizeInBits(); 01471 if (StoreBits % 8) { 01472 break; 01473 } 01474 unsigned ABIAlignment = getDataLayout()->getABITypeAlignment( 01475 ST->getMemoryVT().getTypeForEVT(*DCI.DAG.getContext())); 01476 unsigned Alignment = ST->getAlignment(); 01477 if (Alignment >= ABIAlignment) { 01478 break; 01479 } 01480 01481 if (LoadSDNode *LD = dyn_cast<LoadSDNode>(ST->getValue())) { 01482 if (LD->hasNUsesOfValue(1, 0) && ST->getMemoryVT() == LD->getMemoryVT() && 01483 LD->getAlignment() == Alignment && 01484 !LD->isVolatile() && !LD->isIndexed() && 01485 Chain.reachesChainWithoutSideEffects(SDValue(LD, 1))) { 01486 return DAG.getMemmove(Chain, dl, ST->getBasePtr(), 01487 LD->getBasePtr(), 01488 DAG.getConstant(StoreBits/8, MVT::i32), 01489 Alignment, false, ST->getPointerInfo(), 01490 LD->getPointerInfo()); 01491 } 01492 } 01493 break; 01494 } 01495 } 01496 return SDValue(); 01497 } 01498 01499 void XCoreTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, 01500 APInt &KnownZero, 01501 APInt &KnownOne, 01502 const SelectionDAG &DAG, 01503 unsigned Depth) const { 01504 KnownZero = KnownOne = APInt(KnownZero.getBitWidth(), 0); 01505 switch (Op.getOpcode()) { 01506 default: break; 01507 case XCoreISD::LADD: 01508 case XCoreISD::LSUB: 01509 if (Op.getResNo() == 1) { 01510 // Top bits of carry / borrow are clear. 01511 KnownZero = APInt::getHighBitsSet(KnownZero.getBitWidth(), 01512 KnownZero.getBitWidth() - 1); 01513 } 01514 break; 01515 } 01516 } 01517 01518 //===----------------------------------------------------------------------===// 01519 // Addressing mode description hooks 01520 //===----------------------------------------------------------------------===// 01521 01522 static inline bool isImmUs(int64_t val) 01523 { 01524 return (val >= 0 && val <= 11); 01525 } 01526 01527 static inline bool isImmUs2(int64_t val) 01528 { 01529 return (val%2 == 0 && isImmUs(val/2)); 01530 } 01531 01532 static inline bool isImmUs4(int64_t val) 01533 { 01534 return (val%4 == 0 && isImmUs(val/4)); 01535 } 01536 01537 /// isLegalAddressingMode - Return true if the addressing mode represented 01538 /// by AM is legal for this target, for a load/store of the specified type. 01539 bool 01540 XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM, 01541 Type *Ty) const { 01542 if (Ty->getTypeID() == Type::VoidTyID) 01543 return AM.Scale == 0 && isImmUs(AM.BaseOffs) && isImmUs4(AM.BaseOffs); 01544 01545 const DataLayout *TD = TM.getDataLayout(); 01546 unsigned Size = TD->getTypeAllocSize(Ty); 01547 if (AM.BaseGV) { 01548 return Size >= 4 && !AM.HasBaseReg && AM.Scale == 0 && 01549 AM.BaseOffs%4 == 0; 01550 } 01551 01552 switch (Size) { 01553 case 1: 01554 // reg + imm 01555 if (AM.Scale == 0) { 01556 return isImmUs(AM.BaseOffs); 01557 } 01558 // reg + reg 01559 return AM.Scale == 1 && AM.BaseOffs == 0; 01560 case 2: 01561 case 3: 01562 // reg + imm 01563 if (AM.Scale == 0) { 01564 return isImmUs2(AM.BaseOffs); 01565 } 01566 // reg + reg<<1 01567 return AM.Scale == 2 && AM.BaseOffs == 0; 01568 default: 01569 // reg + imm 01570 if (AM.Scale == 0) { 01571 return isImmUs4(AM.BaseOffs); 01572 } 01573 // reg + reg<<2 01574 return AM.Scale == 4 && AM.BaseOffs == 0; 01575 } 01576 } 01577 01578 //===----------------------------------------------------------------------===// 01579 // XCore Inline Assembly Support 01580 //===----------------------------------------------------------------------===// 01581 01582 std::pair<unsigned, const TargetRegisterClass*> 01583 XCoreTargetLowering:: 01584 getRegForInlineAsmConstraint(const std::string &Constraint, 01585 EVT VT) const { 01586 if (Constraint.size() == 1) { 01587 switch (Constraint[0]) { 01588 default : break; 01589 case 'r': 01590 return std::make_pair(0U, &XCore::GRRegsRegClass); 01591 } 01592 } 01593 // Use the default implementation in TargetLowering to convert the register 01594 // constraint into a member of a register class. 01595 return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); 01596 }