LLVM API Documentation
00001 //===-- HexagonISelDAGToDAG.cpp - A dag to dag inst selector for Hexagon --===// 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 defines an instruction selector for the Hexagon target. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #define DEBUG_TYPE "hexagon-isel" 00015 #include "Hexagon.h" 00016 #include "HexagonISelLowering.h" 00017 #include "HexagonTargetMachine.h" 00018 #include "llvm/ADT/DenseMap.h" 00019 #include "llvm/IR/Intrinsics.h" 00020 #include "llvm/CodeGen/SelectionDAGISel.h" 00021 #include "llvm/Support/CommandLine.h" 00022 #include "llvm/Support/Compiler.h" 00023 #include "llvm/Support/Debug.h" 00024 using namespace llvm; 00025 00026 static 00027 cl::opt<unsigned> 00028 MaxNumOfUsesForConstExtenders("ga-max-num-uses-for-constant-extenders", 00029 cl::Hidden, cl::init(2), 00030 cl::desc("Maximum number of uses of a global address such that we still us a" 00031 "constant extended instruction")); 00032 00033 //===----------------------------------------------------------------------===// 00034 // Instruction Selector Implementation 00035 //===----------------------------------------------------------------------===// 00036 00037 namespace llvm { 00038 void initializeHexagonDAGToDAGISelPass(PassRegistry&); 00039 } 00040 00041 //===--------------------------------------------------------------------===// 00042 /// HexagonDAGToDAGISel - Hexagon specific code to select Hexagon machine 00043 /// instructions for SelectionDAG operations. 00044 /// 00045 namespace { 00046 class HexagonDAGToDAGISel : public SelectionDAGISel { 00047 /// Subtarget - Keep a pointer to the Hexagon Subtarget around so that we can 00048 /// make the right decision when generating code for different targets. 00049 const HexagonSubtarget &Subtarget; 00050 00051 // Keep a reference to HexagonTargetMachine. 00052 const HexagonTargetMachine& TM; 00053 const HexagonInstrInfo *TII; 00054 DenseMap<const GlobalValue *, unsigned> GlobalAddressUseCountMap; 00055 public: 00056 explicit HexagonDAGToDAGISel(const HexagonTargetMachine &targetmachine, 00057 CodeGenOpt::Level OptLevel) 00058 : SelectionDAGISel(targetmachine, OptLevel), 00059 Subtarget(targetmachine.getSubtarget<HexagonSubtarget>()), 00060 TM(targetmachine), 00061 TII(static_cast<const HexagonInstrInfo*>(TM.getInstrInfo())) { 00062 initializeHexagonDAGToDAGISelPass(*PassRegistry::getPassRegistry()); 00063 } 00064 bool hasNumUsesBelowThresGA(SDNode *N) const; 00065 00066 SDNode *Select(SDNode *N); 00067 00068 // Complex Pattern Selectors. 00069 inline bool foldGlobalAddress(SDValue &N, SDValue &R); 00070 inline bool foldGlobalAddressGP(SDValue &N, SDValue &R); 00071 bool foldGlobalAddressImpl(SDValue &N, SDValue &R, bool ShouldLookForGP); 00072 bool SelectADDRri(SDValue& N, SDValue &R1, SDValue &R2); 00073 bool SelectADDRriS11_0(SDValue& N, SDValue &R1, SDValue &R2); 00074 bool SelectADDRriS11_1(SDValue& N, SDValue &R1, SDValue &R2); 00075 bool SelectADDRriS11_2(SDValue& N, SDValue &R1, SDValue &R2); 00076 bool SelectMEMriS11_2(SDValue& Addr, SDValue &Base, SDValue &Offset); 00077 bool SelectADDRriS11_3(SDValue& N, SDValue &R1, SDValue &R2); 00078 bool SelectADDRrr(SDValue &Addr, SDValue &Base, SDValue &Offset); 00079 bool SelectADDRriU6_0(SDValue& N, SDValue &R1, SDValue &R2); 00080 bool SelectADDRriU6_1(SDValue& N, SDValue &R1, SDValue &R2); 00081 bool SelectADDRriU6_2(SDValue& N, SDValue &R1, SDValue &R2); 00082 00083 virtual const char *getPassName() const { 00084 return "Hexagon DAG->DAG Pattern Instruction Selection"; 00085 } 00086 00087 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for 00088 /// inline asm expressions. 00089 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, 00090 char ConstraintCode, 00091 std::vector<SDValue> &OutOps); 00092 bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Offset); 00093 00094 SDNode *SelectLoad(SDNode *N); 00095 SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl); 00096 SDNode *SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl); 00097 SDNode *SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode, 00098 DebugLoc dl); 00099 SDNode *SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode, 00100 DebugLoc dl); 00101 SDNode *SelectBaseOffsetStore(StoreSDNode *ST, DebugLoc dl); 00102 SDNode *SelectIndexedStore(StoreSDNode *ST, DebugLoc dl); 00103 SDNode *SelectStore(SDNode *N); 00104 SDNode *SelectSHL(SDNode *N); 00105 SDNode *SelectSelect(SDNode *N); 00106 SDNode *SelectTruncate(SDNode *N); 00107 SDNode *SelectMul(SDNode *N); 00108 SDNode *SelectZeroExtend(SDNode *N); 00109 SDNode *SelectIntrinsicWOChain(SDNode *N); 00110 SDNode *SelectIntrinsicWChain(SDNode *N); 00111 SDNode *SelectConstant(SDNode *N); 00112 SDNode *SelectConstantFP(SDNode *N); 00113 SDNode *SelectAdd(SDNode *N); 00114 bool isConstExtProfitable(SDNode *N) const; 00115 00116 // XformMskToBitPosU5Imm - Returns the bit position which 00117 // the single bit 32 bit mask represents. 00118 // Used in Clr and Set bit immediate memops. 00119 SDValue XformMskToBitPosU5Imm(uint32_t Imm) { 00120 int32_t bitPos; 00121 bitPos = Log2_32(Imm); 00122 assert(bitPos >= 0 && bitPos < 32 && 00123 "Constant out of range for 32 BitPos Memops"); 00124 return CurDAG->getTargetConstant(bitPos, MVT::i32); 00125 } 00126 00127 // XformMskToBitPosU4Imm - Returns the bit position which the single bit 16 bit 00128 // mask represents. Used in Clr and Set bit immediate memops. 00129 SDValue XformMskToBitPosU4Imm(uint16_t Imm) { 00130 return XformMskToBitPosU5Imm(Imm); 00131 } 00132 00133 // XformMskToBitPosU3Imm - Returns the bit position which the single bit 8 bit 00134 // mask represents. Used in Clr and Set bit immediate memops. 00135 SDValue XformMskToBitPosU3Imm(uint8_t Imm) { 00136 return XformMskToBitPosU5Imm(Imm); 00137 } 00138 00139 // Return true if there is exactly one bit set in V, i.e., if V is one of the 00140 // following integers: 2^0, 2^1, ..., 2^31. 00141 bool ImmIsSingleBit(uint32_t v) const { 00142 uint32_t c = CountPopulation_64(v); 00143 // Only return true if we counted 1 bit. 00144 return c == 1; 00145 } 00146 00147 // XformM5ToU5Imm - Return a target constant with the specified value, of type 00148 // i32 where the negative literal is transformed into a positive literal for 00149 // use in -= memops. 00150 inline SDValue XformM5ToU5Imm(signed Imm) { 00151 assert( (Imm >= -31 && Imm <= -1) && "Constant out of range for Memops"); 00152 return CurDAG->getTargetConstant( - Imm, MVT::i32); 00153 } 00154 00155 00156 // XformU7ToU7M1Imm - Return a target constant decremented by 1, in range 00157 // [1..128], used in cmpb.gtu instructions. 00158 inline SDValue XformU7ToU7M1Imm(signed Imm) { 00159 assert((Imm >= 1 && Imm <= 128) && "Constant out of range for cmpb op"); 00160 return CurDAG->getTargetConstant(Imm - 1, MVT::i8); 00161 } 00162 00163 // XformS8ToS8M1Imm - Return a target constant decremented by 1. 00164 inline SDValue XformSToSM1Imm(signed Imm) { 00165 return CurDAG->getTargetConstant(Imm - 1, MVT::i32); 00166 } 00167 00168 // XformU8ToU8M1Imm - Return a target constant decremented by 1. 00169 inline SDValue XformUToUM1Imm(unsigned Imm) { 00170 assert((Imm >= 1) && "Cannot decrement unsigned int less than 1"); 00171 return CurDAG->getTargetConstant(Imm - 1, MVT::i32); 00172 } 00173 00174 // Include the pieces autogenerated from the target description. 00175 #include "HexagonGenDAGISel.inc" 00176 }; 00177 } // end anonymous namespace 00178 00179 00180 /// createHexagonISelDag - This pass converts a legalized DAG into a 00181 /// Hexagon-specific DAG, ready for instruction scheduling. 00182 /// 00183 FunctionPass *llvm::createHexagonISelDag(const HexagonTargetMachine &TM, 00184 CodeGenOpt::Level OptLevel) { 00185 return new HexagonDAGToDAGISel(TM, OptLevel); 00186 } 00187 00188 static void initializePassOnce(PassRegistry &Registry) { 00189 const char *Name = "Hexagon DAG->DAG Pattern Instruction Selection"; 00190 PassInfo *PI = new PassInfo(Name, "hexagon-isel", 00191 &SelectionDAGISel::ID, 0, false, false); 00192 Registry.registerPass(*PI, true); 00193 } 00194 00195 void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) { 00196 CALL_ONCE_INITIALIZATION(initializePassOnce) 00197 } 00198 00199 00200 static bool IsS11_0_Offset(SDNode * S) { 00201 ConstantSDNode *N = cast<ConstantSDNode>(S); 00202 00203 // immS16 predicate - True if the immediate fits in a 16-bit sign extended 00204 // field. 00205 int64_t v = (int64_t)N->getSExtValue(); 00206 return isInt<11>(v); 00207 } 00208 00209 00210 static bool IsS11_1_Offset(SDNode * S) { 00211 ConstantSDNode *N = cast<ConstantSDNode>(S); 00212 00213 // immS16 predicate - True if the immediate fits in a 16-bit sign extended 00214 // field. 00215 int64_t v = (int64_t)N->getSExtValue(); 00216 return isShiftedInt<11,1>(v); 00217 } 00218 00219 00220 static bool IsS11_2_Offset(SDNode * S) { 00221 ConstantSDNode *N = cast<ConstantSDNode>(S); 00222 00223 // immS16 predicate - True if the immediate fits in a 16-bit sign extended 00224 // field. 00225 int64_t v = (int64_t)N->getSExtValue(); 00226 return isShiftedInt<11,2>(v); 00227 } 00228 00229 00230 static bool IsS11_3_Offset(SDNode * S) { 00231 ConstantSDNode *N = cast<ConstantSDNode>(S); 00232 00233 // immS16 predicate - True if the immediate fits in a 16-bit sign extended 00234 // field. 00235 int64_t v = (int64_t)N->getSExtValue(); 00236 return isShiftedInt<11,3>(v); 00237 } 00238 00239 00240 static bool IsU6_0_Offset(SDNode * S) { 00241 ConstantSDNode *N = cast<ConstantSDNode>(S); 00242 00243 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended 00244 // field. 00245 int64_t v = (int64_t)N->getSExtValue(); 00246 return isUInt<6>(v); 00247 } 00248 00249 00250 static bool IsU6_1_Offset(SDNode * S) { 00251 ConstantSDNode *N = cast<ConstantSDNode>(S); 00252 00253 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended 00254 // field. 00255 int64_t v = (int64_t)N->getSExtValue(); 00256 return isShiftedUInt<6,1>(v); 00257 } 00258 00259 00260 static bool IsU6_2_Offset(SDNode * S) { 00261 ConstantSDNode *N = cast<ConstantSDNode>(S); 00262 00263 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended 00264 // field. 00265 int64_t v = (int64_t)N->getSExtValue(); 00266 return isShiftedUInt<6,2>(v); 00267 } 00268 00269 00270 // Intrinsics that return a a predicate. 00271 static unsigned doesIntrinsicReturnPredicate(unsigned ID) 00272 { 00273 switch (ID) { 00274 default: 00275 return 0; 00276 case Intrinsic::hexagon_C2_cmpeq: 00277 case Intrinsic::hexagon_C2_cmpgt: 00278 case Intrinsic::hexagon_C2_cmpgtu: 00279 case Intrinsic::hexagon_C2_cmpgtup: 00280 case Intrinsic::hexagon_C2_cmpgtp: 00281 case Intrinsic::hexagon_C2_cmpeqp: 00282 case Intrinsic::hexagon_C2_bitsset: 00283 case Intrinsic::hexagon_C2_bitsclr: 00284 case Intrinsic::hexagon_C2_cmpeqi: 00285 case Intrinsic::hexagon_C2_cmpgti: 00286 case Intrinsic::hexagon_C2_cmpgtui: 00287 case Intrinsic::hexagon_C2_cmpgei: 00288 case Intrinsic::hexagon_C2_cmpgeui: 00289 case Intrinsic::hexagon_C2_cmplt: 00290 case Intrinsic::hexagon_C2_cmpltu: 00291 case Intrinsic::hexagon_C2_bitsclri: 00292 case Intrinsic::hexagon_C2_and: 00293 case Intrinsic::hexagon_C2_or: 00294 case Intrinsic::hexagon_C2_xor: 00295 case Intrinsic::hexagon_C2_andn: 00296 case Intrinsic::hexagon_C2_not: 00297 case Intrinsic::hexagon_C2_orn: 00298 case Intrinsic::hexagon_C2_pxfer_map: 00299 case Intrinsic::hexagon_C2_any8: 00300 case Intrinsic::hexagon_C2_all8: 00301 case Intrinsic::hexagon_A2_vcmpbeq: 00302 case Intrinsic::hexagon_A2_vcmpbgtu: 00303 case Intrinsic::hexagon_A2_vcmpheq: 00304 case Intrinsic::hexagon_A2_vcmphgt: 00305 case Intrinsic::hexagon_A2_vcmphgtu: 00306 case Intrinsic::hexagon_A2_vcmpweq: 00307 case Intrinsic::hexagon_A2_vcmpwgt: 00308 case Intrinsic::hexagon_A2_vcmpwgtu: 00309 case Intrinsic::hexagon_C2_tfrrp: 00310 case Intrinsic::hexagon_S2_tstbit_i: 00311 case Intrinsic::hexagon_S2_tstbit_r: 00312 return 1; 00313 } 00314 } 00315 00316 00317 // Intrinsics that have predicate operands. 00318 static unsigned doesIntrinsicContainPredicate(unsigned ID) 00319 { 00320 switch (ID) { 00321 default: 00322 return 0; 00323 case Intrinsic::hexagon_C2_tfrpr: 00324 return Hexagon::TFR_RsPd; 00325 case Intrinsic::hexagon_C2_and: 00326 return Hexagon::AND_pp; 00327 case Intrinsic::hexagon_C2_xor: 00328 return Hexagon::XOR_pp; 00329 case Intrinsic::hexagon_C2_or: 00330 return Hexagon::OR_pp; 00331 case Intrinsic::hexagon_C2_not: 00332 return Hexagon::NOT_p; 00333 case Intrinsic::hexagon_C2_any8: 00334 return Hexagon::ANY_pp; 00335 case Intrinsic::hexagon_C2_all8: 00336 return Hexagon::ALL_pp; 00337 case Intrinsic::hexagon_C2_vitpack: 00338 return Hexagon::VITPACK_pp; 00339 case Intrinsic::hexagon_C2_mask: 00340 return Hexagon::MASK_p; 00341 case Intrinsic::hexagon_C2_mux: 00342 return Hexagon::MUX_rr; 00343 00344 // Mapping hexagon_C2_muxir to MUX_pri. This is pretty weird - but 00345 // that's how it's mapped in q6protos.h. 00346 case Intrinsic::hexagon_C2_muxir: 00347 return Hexagon::MUX_ri; 00348 00349 // Mapping hexagon_C2_muxri to MUX_pir. This is pretty weird - but 00350 // that's how it's mapped in q6protos.h. 00351 case Intrinsic::hexagon_C2_muxri: 00352 return Hexagon::MUX_ir; 00353 00354 case Intrinsic::hexagon_C2_muxii: 00355 return Hexagon::MUX_ii; 00356 case Intrinsic::hexagon_C2_vmux: 00357 return Hexagon::VMUX_prr64; 00358 case Intrinsic::hexagon_S2_valignrb: 00359 return Hexagon::VALIGN_rrp; 00360 case Intrinsic::hexagon_S2_vsplicerb: 00361 return Hexagon::VSPLICE_rrp; 00362 } 00363 } 00364 00365 00366 static bool OffsetFitsS11(EVT MemType, int64_t Offset) { 00367 if (MemType == MVT::i64 && isShiftedInt<11,3>(Offset)) { 00368 return true; 00369 } 00370 if (MemType == MVT::i32 && isShiftedInt<11,2>(Offset)) { 00371 return true; 00372 } 00373 if (MemType == MVT::i16 && isShiftedInt<11,1>(Offset)) { 00374 return true; 00375 } 00376 if (MemType == MVT::i8 && isInt<11>(Offset)) { 00377 return true; 00378 } 00379 return false; 00380 } 00381 00382 00383 // 00384 // Try to lower loads of GlobalAdresses into base+offset loads. Custom 00385 // lowering for GlobalAddress nodes has already turned it into a 00386 // CONST32. 00387 // 00388 SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl) { 00389 SDValue Chain = LD->getChain(); 00390 SDNode* Const32 = LD->getBasePtr().getNode(); 00391 unsigned Opcode = 0; 00392 00393 if (Const32->getOpcode() == HexagonISD::CONST32 && 00394 ISD::isNormalLoad(LD)) { 00395 SDValue Base = Const32->getOperand(0); 00396 EVT LoadedVT = LD->getMemoryVT(); 00397 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset(); 00398 if (Offset != 0 && OffsetFitsS11(LoadedVT, Offset)) { 00399 MVT PointerTy = TLI.getPointerTy(); 00400 const GlobalValue* GV = 00401 cast<GlobalAddressSDNode>(Base)->getGlobal(); 00402 SDValue TargAddr = 00403 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0); 00404 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set, 00405 dl, PointerTy, 00406 TargAddr); 00407 // Figure out base + offset opcode 00408 if (LoadedVT == MVT::i64) Opcode = Hexagon::LDrid_indexed; 00409 else if (LoadedVT == MVT::i32) Opcode = Hexagon::LDriw_indexed; 00410 else if (LoadedVT == MVT::i16) Opcode = Hexagon::LDrih_indexed; 00411 else if (LoadedVT == MVT::i8) Opcode = Hexagon::LDrib_indexed; 00412 else llvm_unreachable("unknown memory type"); 00413 00414 // Build indexed load. 00415 SDValue TargetConstOff = CurDAG->getTargetConstant(Offset, PointerTy); 00416 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, 00417 LD->getValueType(0), 00418 MVT::Other, 00419 SDValue(NewBase,0), 00420 TargetConstOff, 00421 Chain); 00422 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 00423 MemOp[0] = LD->getMemOperand(); 00424 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); 00425 ReplaceUses(LD, Result); 00426 return Result; 00427 } 00428 } 00429 00430 return SelectCode(LD); 00431 } 00432 00433 00434 SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD, 00435 unsigned Opcode, 00436 DebugLoc dl) 00437 { 00438 SDValue Chain = LD->getChain(); 00439 EVT LoadedVT = LD->getMemoryVT(); 00440 SDValue Base = LD->getBasePtr(); 00441 SDValue Offset = LD->getOffset(); 00442 SDNode *OffsetNode = Offset.getNode(); 00443 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); 00444 SDValue N1 = LD->getOperand(1); 00445 SDValue CPTmpN1_0; 00446 SDValue CPTmpN1_1; 00447 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) && 00448 N1.getNode()->getValueType(0) == MVT::i32) { 00449 if (TII->isValidAutoIncImm(LoadedVT, Val)) { 00450 SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32); 00451 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32, 00452 MVT::Other, Base, TargetConst, 00453 Chain); 00454 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, MVT::i64, 00455 SDValue(Result_1, 0)); 00456 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 00457 MemOp[0] = LD->getMemOperand(); 00458 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); 00459 const SDValue Froms[] = { SDValue(LD, 0), 00460 SDValue(LD, 1), 00461 SDValue(LD, 2) 00462 }; 00463 const SDValue Tos[] = { SDValue(Result_2, 0), 00464 SDValue(Result_1, 1), 00465 SDValue(Result_1, 2) 00466 }; 00467 ReplaceUses(Froms, Tos, 3); 00468 return Result_2; 00469 } 00470 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 00471 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); 00472 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, 00473 MVT::Other, Base, TargetConst0, 00474 Chain); 00475 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, 00476 MVT::i64, SDValue(Result_1, 0)); 00477 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, 00478 MVT::i32, Base, TargetConstVal, 00479 SDValue(Result_1, 1)); 00480 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 00481 MemOp[0] = LD->getMemOperand(); 00482 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); 00483 const SDValue Froms[] = { SDValue(LD, 0), 00484 SDValue(LD, 1), 00485 SDValue(LD, 2) 00486 }; 00487 const SDValue Tos[] = { SDValue(Result_2, 0), 00488 SDValue(Result_3, 0), 00489 SDValue(Result_1, 1) 00490 }; 00491 ReplaceUses(Froms, Tos, 3); 00492 return Result_2; 00493 } 00494 return SelectCode(LD); 00495 } 00496 00497 00498 SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD, 00499 unsigned Opcode, 00500 DebugLoc dl) 00501 { 00502 SDValue Chain = LD->getChain(); 00503 EVT LoadedVT = LD->getMemoryVT(); 00504 SDValue Base = LD->getBasePtr(); 00505 SDValue Offset = LD->getOffset(); 00506 SDNode *OffsetNode = Offset.getNode(); 00507 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); 00508 SDValue N1 = LD->getOperand(1); 00509 SDValue CPTmpN1_0; 00510 SDValue CPTmpN1_1; 00511 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) && 00512 N1.getNode()->getValueType(0) == MVT::i32) { 00513 if (TII->isValidAutoIncImm(LoadedVT, Val)) { 00514 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); 00515 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 00516 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, 00517 MVT::i32, MVT::Other, Base, 00518 TargetConstVal, Chain); 00519 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, 00520 TargetConst0); 00521 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, 00522 MVT::i64, MVT::Other, 00523 SDValue(Result_2,0), 00524 SDValue(Result_1,0)); 00525 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 00526 MemOp[0] = LD->getMemOperand(); 00527 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); 00528 const SDValue Froms[] = { SDValue(LD, 0), 00529 SDValue(LD, 1), 00530 SDValue(LD, 2) 00531 }; 00532 const SDValue Tos[] = { SDValue(Result_3, 0), 00533 SDValue(Result_1, 1), 00534 SDValue(Result_1, 2) 00535 }; 00536 ReplaceUses(Froms, Tos, 3); 00537 return Result_3; 00538 } 00539 00540 // Generate an indirect load. 00541 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 00542 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); 00543 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, 00544 MVT::Other, 00545 Base, TargetConst0, Chain); 00546 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, 00547 TargetConst0); 00548 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, 00549 MVT::i64, MVT::Other, 00550 SDValue(Result_2,0), 00551 SDValue(Result_1,0)); 00552 // Add offset to base. 00553 SDNode* Result_4 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, 00554 Base, TargetConstVal, 00555 SDValue(Result_1, 1)); 00556 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 00557 MemOp[0] = LD->getMemOperand(); 00558 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); 00559 const SDValue Froms[] = { SDValue(LD, 0), 00560 SDValue(LD, 1), 00561 SDValue(LD, 2) 00562 }; 00563 const SDValue Tos[] = { SDValue(Result_3, 0), // Load value. 00564 SDValue(Result_4, 0), // New address. 00565 SDValue(Result_1, 1) 00566 }; 00567 ReplaceUses(Froms, Tos, 3); 00568 return Result_3; 00569 } 00570 00571 return SelectCode(LD); 00572 } 00573 00574 00575 SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl) { 00576 SDValue Chain = LD->getChain(); 00577 SDValue Base = LD->getBasePtr(); 00578 SDValue Offset = LD->getOffset(); 00579 SDNode *OffsetNode = Offset.getNode(); 00580 // Get the constant value. 00581 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); 00582 EVT LoadedVT = LD->getMemoryVT(); 00583 unsigned Opcode = 0; 00584 00585 // Check for zero ext loads. 00586 bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD); 00587 00588 // Figure out the opcode. 00589 if (LoadedVT == MVT::i64) { 00590 if (TII->isValidAutoIncImm(LoadedVT, Val)) 00591 Opcode = Hexagon::POST_LDrid; 00592 else 00593 Opcode = Hexagon::LDrid; 00594 } else if (LoadedVT == MVT::i32) { 00595 if (TII->isValidAutoIncImm(LoadedVT, Val)) 00596 Opcode = Hexagon::POST_LDriw; 00597 else 00598 Opcode = Hexagon::LDriw; 00599 } else if (LoadedVT == MVT::i16) { 00600 if (TII->isValidAutoIncImm(LoadedVT, Val)) 00601 Opcode = zextval ? Hexagon::POST_LDriuh : Hexagon::POST_LDrih; 00602 else 00603 Opcode = zextval ? Hexagon::LDriuh : Hexagon::LDrih; 00604 } else if (LoadedVT == MVT::i8) { 00605 if (TII->isValidAutoIncImm(LoadedVT, Val)) 00606 Opcode = zextval ? Hexagon::POST_LDriub : Hexagon::POST_LDrib; 00607 else 00608 Opcode = zextval ? Hexagon::LDriub : Hexagon::LDrib; 00609 } else 00610 llvm_unreachable("unknown memory type"); 00611 00612 // For zero ext i64 loads, we need to add combine instructions. 00613 if (LD->getValueType(0) == MVT::i64 && 00614 LD->getExtensionType() == ISD::ZEXTLOAD) { 00615 return SelectIndexedLoadZeroExtend64(LD, Opcode, dl); 00616 } 00617 if (LD->getValueType(0) == MVT::i64 && 00618 LD->getExtensionType() == ISD::SEXTLOAD) { 00619 // Handle sign ext i64 loads. 00620 return SelectIndexedLoadSignExtend64(LD, Opcode, dl); 00621 } 00622 if (TII->isValidAutoIncImm(LoadedVT, Val)) { 00623 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); 00624 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, 00625 LD->getValueType(0), 00626 MVT::i32, MVT::Other, Base, 00627 TargetConstVal, Chain); 00628 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 00629 MemOp[0] = LD->getMemOperand(); 00630 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); 00631 const SDValue Froms[] = { SDValue(LD, 0), 00632 SDValue(LD, 1), 00633 SDValue(LD, 2) 00634 }; 00635 const SDValue Tos[] = { SDValue(Result, 0), 00636 SDValue(Result, 1), 00637 SDValue(Result, 2) 00638 }; 00639 ReplaceUses(Froms, Tos, 3); 00640 return Result; 00641 } else { 00642 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 00643 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); 00644 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, 00645 LD->getValueType(0), 00646 MVT::Other, Base, TargetConst0, 00647 Chain); 00648 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, 00649 Base, TargetConstVal, 00650 SDValue(Result_1, 1)); 00651 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 00652 MemOp[0] = LD->getMemOperand(); 00653 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); 00654 const SDValue Froms[] = { SDValue(LD, 0), 00655 SDValue(LD, 1), 00656 SDValue(LD, 2) 00657 }; 00658 const SDValue Tos[] = { SDValue(Result_1, 0), 00659 SDValue(Result_2, 0), 00660 SDValue(Result_1, 1) 00661 }; 00662 ReplaceUses(Froms, Tos, 3); 00663 return Result_1; 00664 } 00665 } 00666 00667 00668 SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) { 00669 SDNode *result; 00670 DebugLoc dl = N->getDebugLoc(); 00671 LoadSDNode *LD = cast<LoadSDNode>(N); 00672 ISD::MemIndexedMode AM = LD->getAddressingMode(); 00673 00674 // Handle indexed loads. 00675 if (AM != ISD::UNINDEXED) { 00676 result = SelectIndexedLoad(LD, dl); 00677 } else { 00678 result = SelectBaseOffsetLoad(LD, dl); 00679 } 00680 00681 return result; 00682 } 00683 00684 00685 SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) { 00686 SDValue Chain = ST->getChain(); 00687 SDValue Base = ST->getBasePtr(); 00688 SDValue Offset = ST->getOffset(); 00689 SDValue Value = ST->getValue(); 00690 SDNode *OffsetNode = Offset.getNode(); 00691 // Get the constant value. 00692 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); 00693 EVT StoredVT = ST->getMemoryVT(); 00694 00695 // Offset value must be within representable range 00696 // and must have correct alignment properties. 00697 if (TII->isValidAutoIncImm(StoredVT, Val)) { 00698 SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, MVT::i32), Value, 00699 Chain}; 00700 unsigned Opcode = 0; 00701 00702 // Figure out the post inc version of opcode. 00703 if (StoredVT == MVT::i64) Opcode = Hexagon::POST_STdri; 00704 else if (StoredVT == MVT::i32) Opcode = Hexagon::POST_STwri; 00705 else if (StoredVT == MVT::i16) Opcode = Hexagon::POST_SThri; 00706 else if (StoredVT == MVT::i8) Opcode = Hexagon::POST_STbri; 00707 else llvm_unreachable("unknown memory type"); 00708 00709 // Build post increment store. 00710 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32, 00711 MVT::Other, Ops); 00712 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 00713 MemOp[0] = ST->getMemOperand(); 00714 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); 00715 00716 ReplaceUses(ST, Result); 00717 ReplaceUses(SDValue(ST,1), SDValue(Result,1)); 00718 return Result; 00719 } 00720 00721 // Note: Order of operands matches the def of instruction: 00722 // def STrid : STInst<(outs), (ins MEMri:$addr, DoubleRegs:$src1), ... 00723 // and it differs for POST_ST* for instance. 00724 SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, MVT::i32), Value, 00725 Chain}; 00726 unsigned Opcode = 0; 00727 00728 // Figure out the opcode. 00729 if (StoredVT == MVT::i64) Opcode = Hexagon::STrid; 00730 else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed; 00731 else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih; 00732 else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib; 00733 else llvm_unreachable("unknown memory type"); 00734 00735 // Build regular store. 00736 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); 00737 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops); 00738 // Build splitted incriment instruction. 00739 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, 00740 Base, 00741 TargetConstVal, 00742 SDValue(Result_1, 0)); 00743 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 00744 MemOp[0] = ST->getMemOperand(); 00745 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); 00746 00747 ReplaceUses(SDValue(ST,0), SDValue(Result_2,0)); 00748 ReplaceUses(SDValue(ST,1), SDValue(Result_1,0)); 00749 return Result_2; 00750 } 00751 00752 00753 SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST, 00754 DebugLoc dl) { 00755 SDValue Chain = ST->getChain(); 00756 SDNode* Const32 = ST->getBasePtr().getNode(); 00757 SDValue Value = ST->getValue(); 00758 unsigned Opcode = 0; 00759 00760 // Try to lower stores of GlobalAdresses into indexed stores. Custom 00761 // lowering for GlobalAddress nodes has already turned it into a 00762 // CONST32. Avoid truncating stores for the moment. Post-inc stores 00763 // do the same. Don't think there's a reason for it, so will file a 00764 // bug to fix. 00765 if ((Const32->getOpcode() == HexagonISD::CONST32) && 00766 !(Value.getValueType() == MVT::i64 && ST->isTruncatingStore())) { 00767 SDValue Base = Const32->getOperand(0); 00768 if (Base.getOpcode() == ISD::TargetGlobalAddress) { 00769 EVT StoredVT = ST->getMemoryVT(); 00770 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset(); 00771 if (Offset != 0 && OffsetFitsS11(StoredVT, Offset)) { 00772 MVT PointerTy = TLI.getPointerTy(); 00773 const GlobalValue* GV = 00774 cast<GlobalAddressSDNode>(Base)->getGlobal(); 00775 SDValue TargAddr = 00776 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0); 00777 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set, 00778 dl, PointerTy, 00779 TargAddr); 00780 00781 // Figure out base + offset opcode 00782 if (StoredVT == MVT::i64) Opcode = Hexagon::STrid_indexed; 00783 else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed; 00784 else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih_indexed; 00785 else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib_indexed; 00786 else llvm_unreachable("unknown memory type"); 00787 00788 SDValue Ops[] = {SDValue(NewBase,0), 00789 CurDAG->getTargetConstant(Offset,PointerTy), 00790 Value, Chain}; 00791 // build indexed store 00792 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, 00793 MVT::Other, Ops); 00794 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 00795 MemOp[0] = ST->getMemOperand(); 00796 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); 00797 ReplaceUses(ST, Result); 00798 return Result; 00799 } 00800 } 00801 } 00802 00803 return SelectCode(ST); 00804 } 00805 00806 00807 SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) { 00808 DebugLoc dl = N->getDebugLoc(); 00809 StoreSDNode *ST = cast<StoreSDNode>(N); 00810 ISD::MemIndexedMode AM = ST->getAddressingMode(); 00811 00812 // Handle indexed stores. 00813 if (AM != ISD::UNINDEXED) { 00814 return SelectIndexedStore(ST, dl); 00815 } 00816 00817 return SelectBaseOffsetStore(ST, dl); 00818 } 00819 00820 SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) { 00821 DebugLoc dl = N->getDebugLoc(); 00822 00823 // 00824 // %conv.i = sext i32 %tmp1 to i64 00825 // %conv2.i = sext i32 %add to i64 00826 // %mul.i = mul nsw i64 %conv2.i, %conv.i 00827 // 00828 // --- match with the following --- 00829 // 00830 // %mul.i = mpy (%tmp1, %add) 00831 // 00832 00833 if (N->getValueType(0) == MVT::i64) { 00834 // Shifting a i64 signed multiply. 00835 SDValue MulOp0 = N->getOperand(0); 00836 SDValue MulOp1 = N->getOperand(1); 00837 00838 SDValue OP0; 00839 SDValue OP1; 00840 00841 // Handle sign_extend and sextload. 00842 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) { 00843 SDValue Sext0 = MulOp0.getOperand(0); 00844 if (Sext0.getNode()->getValueType(0) != MVT::i32) { 00845 return SelectCode(N); 00846 } 00847 00848 OP0 = Sext0; 00849 } else if (MulOp0.getOpcode() == ISD::LOAD) { 00850 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode()); 00851 if (LD->getMemoryVT() != MVT::i32 || 00852 LD->getExtensionType() != ISD::SEXTLOAD || 00853 LD->getAddressingMode() != ISD::UNINDEXED) { 00854 return SelectCode(N); 00855 } 00856 00857 SDValue Chain = LD->getChain(); 00858 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 00859 OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, 00860 MVT::Other, 00861 LD->getBasePtr(), TargetConst0, 00862 Chain), 0); 00863 } else { 00864 return SelectCode(N); 00865 } 00866 00867 // Same goes for the second operand. 00868 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) { 00869 SDValue Sext1 = MulOp1.getOperand(0); 00870 if (Sext1.getNode()->getValueType(0) != MVT::i32) { 00871 return SelectCode(N); 00872 } 00873 00874 OP1 = Sext1; 00875 } else if (MulOp1.getOpcode() == ISD::LOAD) { 00876 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode()); 00877 if (LD->getMemoryVT() != MVT::i32 || 00878 LD->getExtensionType() != ISD::SEXTLOAD || 00879 LD->getAddressingMode() != ISD::UNINDEXED) { 00880 return SelectCode(N); 00881 } 00882 00883 SDValue Chain = LD->getChain(); 00884 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 00885 OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, 00886 MVT::Other, 00887 LD->getBasePtr(), TargetConst0, 00888 Chain), 0); 00889 } else { 00890 return SelectCode(N); 00891 } 00892 00893 // Generate a mpy instruction. 00894 SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY64, dl, MVT::i64, 00895 OP0, OP1); 00896 ReplaceUses(N, Result); 00897 return Result; 00898 } 00899 00900 return SelectCode(N); 00901 } 00902 00903 00904 SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) { 00905 DebugLoc dl = N->getDebugLoc(); 00906 SDValue N0 = N->getOperand(0); 00907 if (N0.getOpcode() == ISD::SETCC) { 00908 SDValue N00 = N0.getOperand(0); 00909 if (N00.getOpcode() == ISD::SIGN_EXTEND_INREG) { 00910 SDValue N000 = N00.getOperand(0); 00911 SDValue N001 = N00.getOperand(1); 00912 if (cast<VTSDNode>(N001)->getVT() == MVT::i16) { 00913 SDValue N01 = N0.getOperand(1); 00914 SDValue N02 = N0.getOperand(2); 00915 00916 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2, 00917 // i16:Other),IntRegs:i32:$src1, SETLT:Other),IntRegs:i32:$src1, 00918 // IntRegs:i32:$src2) 00919 // Emits: (MAXh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2) 00920 // Pattern complexity = 9 cost = 1 size = 0. 00921 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETLT) { 00922 SDValue N1 = N->getOperand(1); 00923 if (N01 == N1) { 00924 SDValue N2 = N->getOperand(2); 00925 if (N000 == N2 && 00926 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 && 00927 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) { 00928 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl, 00929 MVT::i32, N000); 00930 SDNode *Result = CurDAG->getMachineNode(Hexagon::MAXw_rr, dl, 00931 MVT::i32, 00932 SDValue(SextNode, 0), 00933 N1); 00934 ReplaceUses(N, Result); 00935 return Result; 00936 } 00937 } 00938 } 00939 00940 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2, 00941 // i16:Other), IntRegs:i32:$src1, SETGT:Other), IntRegs:i32:$src1, 00942 // IntRegs:i32:$src2) 00943 // Emits: (MINh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2) 00944 // Pattern complexity = 9 cost = 1 size = 0. 00945 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETGT) { 00946 SDValue N1 = N->getOperand(1); 00947 if (N01 == N1) { 00948 SDValue N2 = N->getOperand(2); 00949 if (N000 == N2 && 00950 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 && 00951 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) { 00952 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl, 00953 MVT::i32, N000); 00954 SDNode *Result = CurDAG->getMachineNode(Hexagon::MINw_rr, dl, 00955 MVT::i32, 00956 SDValue(SextNode, 0), 00957 N1); 00958 ReplaceUses(N, Result); 00959 return Result; 00960 } 00961 } 00962 } 00963 } 00964 } 00965 } 00966 00967 return SelectCode(N); 00968 } 00969 00970 00971 SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) { 00972 DebugLoc dl = N->getDebugLoc(); 00973 SDValue Shift = N->getOperand(0); 00974 00975 // 00976 // %conv.i = sext i32 %tmp1 to i64 00977 // %conv2.i = sext i32 %add to i64 00978 // %mul.i = mul nsw i64 %conv2.i, %conv.i 00979 // %shr5.i = lshr i64 %mul.i, 32 00980 // %conv3.i = trunc i64 %shr5.i to i32 00981 // 00982 // --- match with the following --- 00983 // 00984 // %conv3.i = mpy (%tmp1, %add) 00985 // 00986 // Trunc to i32. 00987 if (N->getValueType(0) == MVT::i32) { 00988 // Trunc from i64. 00989 if (Shift.getNode()->getValueType(0) == MVT::i64) { 00990 // Trunc child is logical shift right. 00991 if (Shift.getOpcode() != ISD::SRL) { 00992 return SelectCode(N); 00993 } 00994 00995 SDValue ShiftOp0 = Shift.getOperand(0); 00996 SDValue ShiftOp1 = Shift.getOperand(1); 00997 00998 // Shift by const 32 00999 if (ShiftOp1.getOpcode() != ISD::Constant) { 01000 return SelectCode(N); 01001 } 01002 01003 int32_t ShiftConst = 01004 cast<ConstantSDNode>(ShiftOp1.getNode())->getSExtValue(); 01005 if (ShiftConst != 32) { 01006 return SelectCode(N); 01007 } 01008 01009 // Shifting a i64 signed multiply 01010 SDValue Mul = ShiftOp0; 01011 if (Mul.getOpcode() != ISD::MUL) { 01012 return SelectCode(N); 01013 } 01014 01015 SDValue MulOp0 = Mul.getOperand(0); 01016 SDValue MulOp1 = Mul.getOperand(1); 01017 01018 SDValue OP0; 01019 SDValue OP1; 01020 01021 // Handle sign_extend and sextload 01022 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) { 01023 SDValue Sext0 = MulOp0.getOperand(0); 01024 if (Sext0.getNode()->getValueType(0) != MVT::i32) { 01025 return SelectCode(N); 01026 } 01027 01028 OP0 = Sext0; 01029 } else if (MulOp0.getOpcode() == ISD::LOAD) { 01030 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode()); 01031 if (LD->getMemoryVT() != MVT::i32 || 01032 LD->getExtensionType() != ISD::SEXTLOAD || 01033 LD->getAddressingMode() != ISD::UNINDEXED) { 01034 return SelectCode(N); 01035 } 01036 01037 SDValue Chain = LD->getChain(); 01038 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 01039 OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, 01040 MVT::Other, 01041 LD->getBasePtr(), 01042 TargetConst0, Chain), 0); 01043 } else { 01044 return SelectCode(N); 01045 } 01046 01047 // Same goes for the second operand. 01048 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) { 01049 SDValue Sext1 = MulOp1.getOperand(0); 01050 if (Sext1.getNode()->getValueType(0) != MVT::i32) 01051 return SelectCode(N); 01052 01053 OP1 = Sext1; 01054 } else if (MulOp1.getOpcode() == ISD::LOAD) { 01055 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode()); 01056 if (LD->getMemoryVT() != MVT::i32 || 01057 LD->getExtensionType() != ISD::SEXTLOAD || 01058 LD->getAddressingMode() != ISD::UNINDEXED) { 01059 return SelectCode(N); 01060 } 01061 01062 SDValue Chain = LD->getChain(); 01063 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 01064 OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, 01065 MVT::Other, 01066 LD->getBasePtr(), 01067 TargetConst0, Chain), 0); 01068 } else { 01069 return SelectCode(N); 01070 } 01071 01072 // Generate a mpy instruction. 01073 SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY, dl, MVT::i32, 01074 OP0, OP1); 01075 ReplaceUses(N, Result); 01076 return Result; 01077 } 01078 } 01079 01080 return SelectCode(N); 01081 } 01082 01083 01084 SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) { 01085 DebugLoc dl = N->getDebugLoc(); 01086 if (N->getValueType(0) == MVT::i32) { 01087 SDValue Shl_0 = N->getOperand(0); 01088 SDValue Shl_1 = N->getOperand(1); 01089 // RHS is const. 01090 if (Shl_1.getOpcode() == ISD::Constant) { 01091 if (Shl_0.getOpcode() == ISD::MUL) { 01092 SDValue Mul_0 = Shl_0.getOperand(0); // Val 01093 SDValue Mul_1 = Shl_0.getOperand(1); // Const 01094 // RHS of mul is const. 01095 if (Mul_1.getOpcode() == ISD::Constant) { 01096 int32_t ShlConst = 01097 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue(); 01098 int32_t MulConst = 01099 cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue(); 01100 int32_t ValConst = MulConst << ShlConst; 01101 SDValue Val = CurDAG->getTargetConstant(ValConst, 01102 MVT::i32); 01103 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode())) 01104 if (isInt<9>(CN->getSExtValue())) { 01105 SDNode* Result = 01106 CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, 01107 MVT::i32, Mul_0, Val); 01108 ReplaceUses(N, Result); 01109 return Result; 01110 } 01111 01112 } 01113 } else if (Shl_0.getOpcode() == ISD::SUB) { 01114 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0 01115 SDValue Sub_1 = Shl_0.getOperand(1); // Val 01116 if (Sub_0.getOpcode() == ISD::Constant) { 01117 int32_t SubConst = 01118 cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue(); 01119 if (SubConst == 0) { 01120 if (Sub_1.getOpcode() == ISD::SHL) { 01121 SDValue Shl2_0 = Sub_1.getOperand(0); // Val 01122 SDValue Shl2_1 = Sub_1.getOperand(1); // Const 01123 if (Shl2_1.getOpcode() == ISD::Constant) { 01124 int32_t ShlConst = 01125 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue(); 01126 int32_t Shl2Const = 01127 cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue(); 01128 int32_t ValConst = 1 << (ShlConst+Shl2Const); 01129 SDValue Val = CurDAG->getTargetConstant(-ValConst, MVT::i32); 01130 if (ConstantSDNode *CN = 01131 dyn_cast<ConstantSDNode>(Val.getNode())) 01132 if (isInt<9>(CN->getSExtValue())) { 01133 SDNode* Result = 01134 CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, MVT::i32, 01135 Shl2_0, Val); 01136 ReplaceUses(N, Result); 01137 return Result; 01138 } 01139 } 01140 } 01141 } 01142 } 01143 } 01144 } 01145 } 01146 return SelectCode(N); 01147 } 01148 01149 01150 // 01151 // If there is an zero_extend followed an intrinsic in DAG (this means - the 01152 // result of the intrinsic is predicate); convert the zero_extend to 01153 // transfer instruction. 01154 // 01155 // Zero extend -> transfer is lowered here. Otherwise, zero_extend will be 01156 // converted into a MUX as predicate registers defined as 1 bit in the 01157 // compiler. Architecture defines them as 8-bit registers. 01158 // We want to preserve all the lower 8-bits and, not just 1 LSB bit. 01159 // 01160 SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) { 01161 DebugLoc dl = N->getDebugLoc(); 01162 SDNode *IsIntrinsic = N->getOperand(0).getNode(); 01163 if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) { 01164 unsigned ID = 01165 cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue(); 01166 if (doesIntrinsicReturnPredicate(ID)) { 01167 // Now we need to differentiate target data types. 01168 if (N->getValueType(0) == MVT::i64) { 01169 // Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs). 01170 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 01171 SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl, 01172 MVT::i32, 01173 SDValue(IsIntrinsic, 0)); 01174 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, 01175 MVT::i32, 01176 TargetConst0); 01177 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, 01178 MVT::i64, MVT::Other, 01179 SDValue(Result_2, 0), 01180 SDValue(Result_1, 0)); 01181 ReplaceUses(N, Result_3); 01182 return Result_3; 01183 } 01184 if (N->getValueType(0) == MVT::i32) { 01185 // Convert the zero_extend to Rs = Pd 01186 SDNode* RsPd = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl, 01187 MVT::i32, 01188 SDValue(IsIntrinsic, 0)); 01189 ReplaceUses(N, RsPd); 01190 return RsPd; 01191 } 01192 llvm_unreachable("Unexpected value type"); 01193 } 01194 } 01195 return SelectCode(N); 01196 } 01197 01198 01199 // 01200 // Checking for intrinsics which have predicate registers as operand(s) 01201 // and lowering to the actual intrinsic. 01202 // 01203 SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) { 01204 DebugLoc dl = N->getDebugLoc(); 01205 unsigned ID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); 01206 unsigned IntrinsicWithPred = doesIntrinsicContainPredicate(ID); 01207 01208 // We are concerned with only those intrinsics that have predicate registers 01209 // as at least one of the operands. 01210 if (IntrinsicWithPred) { 01211 SmallVector<SDValue, 8> Ops; 01212 const MCInstrDesc &MCID = TII->get(IntrinsicWithPred); 01213 const TargetRegisterInfo *TRI = TM.getRegisterInfo(); 01214 01215 // Iterate over all the operands of the intrinsics. 01216 // For PredRegs, do the transfer. 01217 // For Double/Int Regs, just preserve the value 01218 // For immediates, lower it. 01219 for (unsigned i = 1; i < N->getNumOperands(); ++i) { 01220 SDNode *Arg = N->getOperand(i).getNode(); 01221 const TargetRegisterClass *RC = TII->getRegClass(MCID, i, TRI, *MF); 01222 01223 if (RC == &Hexagon::IntRegsRegClass || 01224 RC == &Hexagon::DoubleRegsRegClass) { 01225 Ops.push_back(SDValue(Arg, 0)); 01226 } else if (RC == &Hexagon::PredRegsRegClass) { 01227 // Do the transfer. 01228 SDNode *PdRs = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1, 01229 SDValue(Arg, 0)); 01230 Ops.push_back(SDValue(PdRs,0)); 01231 } else if (RC == NULL && (dyn_cast<ConstantSDNode>(Arg) != NULL)) { 01232 // This is immediate operand. Lower it here making sure that we DO have 01233 // const SDNode for immediate value. 01234 int32_t Val = cast<ConstantSDNode>(Arg)->getSExtValue(); 01235 SDValue SDVal = CurDAG->getTargetConstant(Val, MVT::i32); 01236 Ops.push_back(SDVal); 01237 } else { 01238 llvm_unreachable("Unimplemented"); 01239 } 01240 } 01241 EVT ReturnValueVT = N->getValueType(0); 01242 SDNode *Result = CurDAG->getMachineNode(IntrinsicWithPred, dl, 01243 ReturnValueVT, Ops); 01244 ReplaceUses(N, Result); 01245 return Result; 01246 } 01247 return SelectCode(N); 01248 } 01249 01250 // 01251 // Map floating point constant values. 01252 // 01253 SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) { 01254 DebugLoc dl = N->getDebugLoc(); 01255 ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N); 01256 APFloat APF = CN->getValueAPF(); 01257 if (N->getValueType(0) == MVT::f32) { 01258 return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32, 01259 CurDAG->getTargetConstantFP(APF.convertToFloat(), MVT::f32)); 01260 } 01261 else if (N->getValueType(0) == MVT::f64) { 01262 return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64, 01263 CurDAG->getTargetConstantFP(APF.convertToDouble(), MVT::f64)); 01264 } 01265 01266 return SelectCode(N); 01267 } 01268 01269 01270 // 01271 // Map predicate true (encoded as -1 in LLVM) to a XOR. 01272 // 01273 SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) { 01274 DebugLoc dl = N->getDebugLoc(); 01275 if (N->getValueType(0) == MVT::i1) { 01276 SDNode* Result; 01277 int32_t Val = cast<ConstantSDNode>(N)->getSExtValue(); 01278 if (Val == -1) { 01279 // Create the IntReg = 1 node. 01280 SDNode* IntRegTFR = 01281 CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, 01282 CurDAG->getTargetConstant(0, MVT::i32)); 01283 01284 // Pd = IntReg 01285 SDNode* Pd = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1, 01286 SDValue(IntRegTFR, 0)); 01287 01288 // not(Pd) 01289 SDNode* NotPd = CurDAG->getMachineNode(Hexagon::NOT_p, dl, MVT::i1, 01290 SDValue(Pd, 0)); 01291 01292 // xor(not(Pd)) 01293 Result = CurDAG->getMachineNode(Hexagon::XOR_pp, dl, MVT::i1, 01294 SDValue(Pd, 0), SDValue(NotPd, 0)); 01295 01296 // We have just built: 01297 // Rs = Pd 01298 // Pd = xor(not(Pd), Pd) 01299 01300 ReplaceUses(N, Result); 01301 return Result; 01302 } 01303 } 01304 01305 return SelectCode(N); 01306 } 01307 01308 01309 // 01310 // Map add followed by a asr -> asr +=. 01311 // 01312 SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) { 01313 DebugLoc dl = N->getDebugLoc(); 01314 if (N->getValueType(0) != MVT::i32) { 01315 return SelectCode(N); 01316 } 01317 // Identify nodes of the form: add(asr(...)). 01318 SDNode* Src1 = N->getOperand(0).getNode(); 01319 if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse() 01320 || Src1->getValueType(0) != MVT::i32) { 01321 return SelectCode(N); 01322 } 01323 01324 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that 01325 // Rd and Rd' are assigned to the same register 01326 SDNode* Result = CurDAG->getMachineNode(Hexagon::ASR_ADD_rr, dl, MVT::i32, 01327 N->getOperand(1), 01328 Src1->getOperand(0), 01329 Src1->getOperand(1)); 01330 ReplaceUses(N, Result); 01331 01332 return Result; 01333 } 01334 01335 01336 SDNode *HexagonDAGToDAGISel::Select(SDNode *N) { 01337 if (N->isMachineOpcode()) 01338 return NULL; // Already selected. 01339 01340 01341 switch (N->getOpcode()) { 01342 case ISD::Constant: 01343 return SelectConstant(N); 01344 01345 case ISD::ConstantFP: 01346 return SelectConstantFP(N); 01347 01348 case ISD::ADD: 01349 return SelectAdd(N); 01350 01351 case ISD::SHL: 01352 return SelectSHL(N); 01353 01354 case ISD::LOAD: 01355 return SelectLoad(N); 01356 01357 case ISD::STORE: 01358 return SelectStore(N); 01359 01360 case ISD::SELECT: 01361 return SelectSelect(N); 01362 01363 case ISD::TRUNCATE: 01364 return SelectTruncate(N); 01365 01366 case ISD::MUL: 01367 return SelectMul(N); 01368 01369 case ISD::ZERO_EXTEND: 01370 return SelectZeroExtend(N); 01371 01372 case ISD::INTRINSIC_WO_CHAIN: 01373 return SelectIntrinsicWOChain(N); 01374 } 01375 01376 return SelectCode(N); 01377 } 01378 01379 01380 // 01381 // Hexagon_TODO: Five functions for ADDRri?! Surely there must be a better way 01382 // to define these instructions. 01383 // 01384 bool HexagonDAGToDAGISel::SelectADDRri(SDValue& Addr, SDValue &Base, 01385 SDValue &Offset) { 01386 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 01387 Addr.getOpcode() == ISD::TargetGlobalAddress) 01388 return false; // Direct calls. 01389 01390 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 01391 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 01392 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01393 return true; 01394 } 01395 Base = Addr; 01396 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01397 return true; 01398 } 01399 01400 01401 bool HexagonDAGToDAGISel::SelectADDRriS11_0(SDValue& Addr, SDValue &Base, 01402 SDValue &Offset) { 01403 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 01404 Addr.getOpcode() == ISD::TargetGlobalAddress) 01405 return false; // Direct calls. 01406 01407 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 01408 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 01409 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01410 return (IsS11_0_Offset(Offset.getNode())); 01411 } 01412 Base = Addr; 01413 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01414 return (IsS11_0_Offset(Offset.getNode())); 01415 } 01416 01417 01418 bool HexagonDAGToDAGISel::SelectADDRriS11_1(SDValue& Addr, SDValue &Base, 01419 SDValue &Offset) { 01420 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 01421 Addr.getOpcode() == ISD::TargetGlobalAddress) 01422 return false; // Direct calls. 01423 01424 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 01425 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 01426 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01427 return (IsS11_1_Offset(Offset.getNode())); 01428 } 01429 Base = Addr; 01430 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01431 return (IsS11_1_Offset(Offset.getNode())); 01432 } 01433 01434 01435 bool HexagonDAGToDAGISel::SelectADDRriS11_2(SDValue& Addr, SDValue &Base, 01436 SDValue &Offset) { 01437 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 01438 Addr.getOpcode() == ISD::TargetGlobalAddress) 01439 return false; // Direct calls. 01440 01441 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 01442 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 01443 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01444 return (IsS11_2_Offset(Offset.getNode())); 01445 } 01446 Base = Addr; 01447 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01448 return (IsS11_2_Offset(Offset.getNode())); 01449 } 01450 01451 01452 bool HexagonDAGToDAGISel::SelectADDRriU6_0(SDValue& Addr, SDValue &Base, 01453 SDValue &Offset) { 01454 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 01455 Addr.getOpcode() == ISD::TargetGlobalAddress) 01456 return false; // Direct calls. 01457 01458 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 01459 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 01460 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01461 return (IsU6_0_Offset(Offset.getNode())); 01462 } 01463 Base = Addr; 01464 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01465 return (IsU6_0_Offset(Offset.getNode())); 01466 } 01467 01468 01469 bool HexagonDAGToDAGISel::SelectADDRriU6_1(SDValue& Addr, SDValue &Base, 01470 SDValue &Offset) { 01471 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 01472 Addr.getOpcode() == ISD::TargetGlobalAddress) 01473 return false; // Direct calls. 01474 01475 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 01476 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 01477 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01478 return (IsU6_1_Offset(Offset.getNode())); 01479 } 01480 Base = Addr; 01481 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01482 return (IsU6_1_Offset(Offset.getNode())); 01483 } 01484 01485 01486 bool HexagonDAGToDAGISel::SelectADDRriU6_2(SDValue& Addr, SDValue &Base, 01487 SDValue &Offset) { 01488 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 01489 Addr.getOpcode() == ISD::TargetGlobalAddress) 01490 return false; // Direct calls. 01491 01492 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 01493 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 01494 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01495 return (IsU6_2_Offset(Offset.getNode())); 01496 } 01497 Base = Addr; 01498 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01499 return (IsU6_2_Offset(Offset.getNode())); 01500 } 01501 01502 01503 bool HexagonDAGToDAGISel::SelectMEMriS11_2(SDValue& Addr, SDValue &Base, 01504 SDValue &Offset) { 01505 01506 if (Addr.getOpcode() != ISD::ADD) { 01507 return(SelectADDRriS11_2(Addr, Base, Offset)); 01508 } 01509 01510 return SelectADDRriS11_2(Addr, Base, Offset); 01511 } 01512 01513 01514 bool HexagonDAGToDAGISel::SelectADDRriS11_3(SDValue& Addr, SDValue &Base, 01515 SDValue &Offset) { 01516 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 01517 Addr.getOpcode() == ISD::TargetGlobalAddress) 01518 return false; // Direct calls. 01519 01520 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 01521 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 01522 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01523 return (IsS11_3_Offset(Offset.getNode())); 01524 } 01525 Base = Addr; 01526 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01527 return (IsS11_3_Offset(Offset.getNode())); 01528 } 01529 01530 bool HexagonDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, 01531 SDValue &R2) { 01532 if (Addr.getOpcode() == ISD::FrameIndex) return false; 01533 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 01534 Addr.getOpcode() == ISD::TargetGlobalAddress) 01535 return false; // Direct calls. 01536 01537 if (Addr.getOpcode() == ISD::ADD) { 01538 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 01539 if (isInt<13>(CN->getSExtValue())) 01540 return false; // Let the reg+imm pattern catch this! 01541 R1 = Addr.getOperand(0); 01542 R2 = Addr.getOperand(1); 01543 return true; 01544 } 01545 01546 R1 = Addr; 01547 01548 return true; 01549 } 01550 01551 01552 // Handle generic address case. It is accessed from inlined asm =m constraints, 01553 // which could have any kind of pointer. 01554 bool HexagonDAGToDAGISel::SelectAddr(SDNode *Op, SDValue Addr, 01555 SDValue &Base, SDValue &Offset) { 01556 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 01557 Addr.getOpcode() == ISD::TargetGlobalAddress) 01558 return false; // Direct calls. 01559 01560 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 01561 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 01562 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01563 return true; 01564 } 01565 01566 if (Addr.getOpcode() == ISD::ADD) { 01567 Base = Addr.getOperand(0); 01568 Offset = Addr.getOperand(1); 01569 return true; 01570 } 01571 01572 Base = Addr; 01573 Offset = CurDAG->getTargetConstant(0, MVT::i32); 01574 return true; 01575 } 01576 01577 01578 bool HexagonDAGToDAGISel:: 01579 SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 01580 std::vector<SDValue> &OutOps) { 01581 SDValue Op0, Op1; 01582 01583 switch (ConstraintCode) { 01584 case 'o': // Offsetable. 01585 case 'v': // Not offsetable. 01586 default: return true; 01587 case 'm': // Memory. 01588 if (!SelectAddr(Op.getNode(), Op, Op0, Op1)) 01589 return true; 01590 break; 01591 } 01592 01593 OutOps.push_back(Op0); 01594 OutOps.push_back(Op1); 01595 return false; 01596 } 01597 01598 bool HexagonDAGToDAGISel::isConstExtProfitable(SDNode *N) const { 01599 unsigned UseCount = 0; 01600 for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) { 01601 UseCount++; 01602 } 01603 01604 return (UseCount <= 1); 01605 01606 } 01607 01608 //===--------------------------------------------------------------------===// 01609 // Return 'true' if use count of the global address is below threshold. 01610 //===--------------------------------------------------------------------===// 01611 bool HexagonDAGToDAGISel::hasNumUsesBelowThresGA(SDNode *N) const { 01612 assert(N->getOpcode() == ISD::TargetGlobalAddress && 01613 "Expecting a target global address"); 01614 01615 // Always try to fold the address. 01616 if (TM.getOptLevel() == CodeGenOpt::Aggressive) 01617 return true; 01618 01619 GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N); 01620 DenseMap<const GlobalValue *, unsigned>::const_iterator GI = 01621 GlobalAddressUseCountMap.find(GA->getGlobal()); 01622 01623 if (GI == GlobalAddressUseCountMap.end()) 01624 return false; 01625 01626 return GI->second <= MaxNumOfUsesForConstExtenders; 01627 } 01628 01629 //===--------------------------------------------------------------------===// 01630 // Return true if the non GP-relative global address can be folded. 01631 //===--------------------------------------------------------------------===// 01632 inline bool HexagonDAGToDAGISel::foldGlobalAddress(SDValue &N, SDValue &R) { 01633 return foldGlobalAddressImpl(N, R, false); 01634 } 01635 01636 //===--------------------------------------------------------------------===// 01637 // Return true if the GP-relative global address can be folded. 01638 //===--------------------------------------------------------------------===// 01639 inline bool HexagonDAGToDAGISel::foldGlobalAddressGP(SDValue &N, SDValue &R) { 01640 return foldGlobalAddressImpl(N, R, true); 01641 } 01642 01643 //===--------------------------------------------------------------------===// 01644 // Fold offset of the global address if number of uses are below threshold. 01645 //===--------------------------------------------------------------------===// 01646 bool HexagonDAGToDAGISel::foldGlobalAddressImpl(SDValue &N, SDValue &R, 01647 bool ShouldLookForGP) { 01648 if (N.getOpcode() == ISD::ADD) { 01649 SDValue N0 = N.getOperand(0); 01650 SDValue N1 = N.getOperand(1); 01651 if ((ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32_GP)) || 01652 (!ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32))) { 01653 ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1); 01654 GlobalAddressSDNode *GA = 01655 dyn_cast<GlobalAddressSDNode>(N0.getOperand(0)); 01656 01657 if (Const && GA && 01658 (GA->getOpcode() == ISD::TargetGlobalAddress)) { 01659 if ((N0.getOpcode() == HexagonISD::CONST32) && 01660 !hasNumUsesBelowThresGA(GA)) 01661 return false; 01662 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), 01663 Const->getDebugLoc(), 01664 N.getValueType(), 01665 GA->getOffset() + 01666 (uint64_t)Const->getSExtValue()); 01667 return true; 01668 } 01669 } 01670 } 01671 return false; 01672 }