1 //===-- HexagonISelDAGToDAG.cpp - A dag to dag inst selector for Hexagon --===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines an instruction selector for the Hexagon target. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #define DEBUG_TYPE "hexagon-isel" 15 #include "HexagonISelLowering.h" 16 #include "HexagonTargetMachine.h" 17 #include "llvm/Intrinsics.h" 18 #include "llvm/CodeGen/SelectionDAGISel.h" 19 #include "llvm/Support/Compiler.h" 20 #include "llvm/Support/Debug.h" 21 22 using namespace llvm; 23 24 25 //===----------------------------------------------------------------------===// 26 // Instruction Selector Implementation 27 //===----------------------------------------------------------------------===// 28 29 //===--------------------------------------------------------------------===// 30 /// HexagonDAGToDAGISel - Hexagon specific code to select Hexagon machine 31 /// instructions for SelectionDAG operations. 32 /// 33 namespace { 34 class HexagonDAGToDAGISel : public SelectionDAGISel { 35 /// Subtarget - Keep a pointer to the Hexagon Subtarget around so that we can 36 /// make the right decision when generating code for different targets. 37 const HexagonSubtarget &Subtarget; 38 39 // Keep a reference to HexagonTargetMachine. 40 HexagonTargetMachine& TM; 41 const HexagonInstrInfo *TII; 42 43 public: 44 explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine) 45 : SelectionDAGISel(targetmachine), 46 Subtarget(targetmachine.getSubtarget<HexagonSubtarget>()), 47 TM(targetmachine), 48 TII(static_cast<const HexagonInstrInfo*>(TM.getInstrInfo())) { 49 50 } 51 52 SDNode *Select(SDNode *N); 53 54 // Complex Pattern Selectors. 55 bool SelectADDRri(SDValue& N, SDValue &R1, SDValue &R2); 56 bool SelectADDRriS11_0(SDValue& N, SDValue &R1, SDValue &R2); 57 bool SelectADDRriS11_1(SDValue& N, SDValue &R1, SDValue &R2); 58 bool SelectADDRriS11_2(SDValue& N, SDValue &R1, SDValue &R2); 59 bool SelectMEMriS11_2(SDValue& Addr, SDValue &Base, SDValue &Offset); 60 bool SelectADDRriS11_3(SDValue& N, SDValue &R1, SDValue &R2); 61 bool SelectADDRrr(SDValue &Addr, SDValue &Base, SDValue &Offset); 62 bool SelectADDRriU6_0(SDValue& N, SDValue &R1, SDValue &R2); 63 bool SelectADDRriU6_1(SDValue& N, SDValue &R1, SDValue &R2); 64 bool SelectADDRriU6_2(SDValue& N, SDValue &R1, SDValue &R2); 65 66 virtual const char *getPassName() const { 67 return "Hexagon DAG->DAG Pattern Instruction Selection"; 68 } 69 70 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for 71 /// inline asm expressions. 72 virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, 73 char ConstraintCode, 74 std::vector<SDValue> &OutOps); 75 bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Offset); 76 77 SDNode *SelectLoad(SDNode *N); 78 SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl); 79 SDNode *SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl); 80 SDNode *SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode, 81 DebugLoc dl); 82 SDNode *SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode, 83 DebugLoc dl); 84 SDNode *SelectBaseOffsetStore(StoreSDNode *ST, DebugLoc dl); 85 SDNode *SelectIndexedStore(StoreSDNode *ST, DebugLoc dl); 86 SDNode *SelectStore(SDNode *N); 87 SDNode *SelectSHL(SDNode *N); 88 SDNode *SelectSelect(SDNode *N); 89 SDNode *SelectTruncate(SDNode *N); 90 SDNode *SelectMul(SDNode *N); 91 SDNode *SelectZeroExtend(SDNode *N); 92 SDNode *SelectIntrinsicWOChain(SDNode *N); 93 SDNode *SelectConstant(SDNode *N); 94 SDNode *SelectAdd(SDNode *N); 95 96 // Include the pieces autogenerated from the target description. 97 #include "HexagonGenDAGISel.inc" 98 }; 99 } // end anonymous namespace 100 101 102 /// createHexagonISelDag - This pass converts a legalized DAG into a 103 /// Hexagon-specific DAG, ready for instruction scheduling. 104 /// 105 FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM) { 106 return new HexagonDAGToDAGISel(TM); 107 } 108 109 static bool IsS11_0_Offset(SDNode * S) { 110 ConstantSDNode *N = cast<ConstantSDNode>(S); 111 112 // immS16 predicate - True if the immediate fits in a 16-bit sign extended 113 // field. 114 int64_t v = (int64_t)N->getSExtValue(); 115 return isInt<11>(v); 116 } 117 118 119 static bool IsS11_1_Offset(SDNode * S) { 120 ConstantSDNode *N = cast<ConstantSDNode>(S); 121 122 // immS16 predicate - True if the immediate fits in a 16-bit sign extended 123 // field. 124 int64_t v = (int64_t)N->getSExtValue(); 125 return isShiftedInt<11,1>(v); 126 } 127 128 129 static bool IsS11_2_Offset(SDNode * S) { 130 ConstantSDNode *N = cast<ConstantSDNode>(S); 131 132 // immS16 predicate - True if the immediate fits in a 16-bit sign extended 133 // field. 134 int64_t v = (int64_t)N->getSExtValue(); 135 return isShiftedInt<11,2>(v); 136 } 137 138 139 static bool IsS11_3_Offset(SDNode * S) { 140 ConstantSDNode *N = cast<ConstantSDNode>(S); 141 142 // immS16 predicate - True if the immediate fits in a 16-bit sign extended 143 // field. 144 int64_t v = (int64_t)N->getSExtValue(); 145 return isShiftedInt<11,3>(v); 146 } 147 148 149 static bool IsU6_0_Offset(SDNode * S) { 150 ConstantSDNode *N = cast<ConstantSDNode>(S); 151 152 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended 153 // field. 154 int64_t v = (int64_t)N->getSExtValue(); 155 return isUInt<6>(v); 156 } 157 158 159 static bool IsU6_1_Offset(SDNode * S) { 160 ConstantSDNode *N = cast<ConstantSDNode>(S); 161 162 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended 163 // field. 164 int64_t v = (int64_t)N->getSExtValue(); 165 return isShiftedUInt<6,1>(v); 166 } 167 168 169 static bool IsU6_2_Offset(SDNode * S) { 170 ConstantSDNode *N = cast<ConstantSDNode>(S); 171 172 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended 173 // field. 174 int64_t v = (int64_t)N->getSExtValue(); 175 return isShiftedUInt<6,2>(v); 176 } 177 178 179 // Intrinsics that return a a predicate. 180 static unsigned doesIntrinsicReturnPredicate(unsigned ID) 181 { 182 switch (ID) { 183 default: 184 return 0; 185 case Intrinsic::hexagon_C2_cmpeq: 186 case Intrinsic::hexagon_C2_cmpgt: 187 case Intrinsic::hexagon_C2_cmpgtu: 188 case Intrinsic::hexagon_C2_cmpgtup: 189 case Intrinsic::hexagon_C2_cmpgtp: 190 case Intrinsic::hexagon_C2_cmpeqp: 191 case Intrinsic::hexagon_C2_bitsset: 192 case Intrinsic::hexagon_C2_bitsclr: 193 case Intrinsic::hexagon_C2_cmpeqi: 194 case Intrinsic::hexagon_C2_cmpgti: 195 case Intrinsic::hexagon_C2_cmpgtui: 196 case Intrinsic::hexagon_C2_cmpgei: 197 case Intrinsic::hexagon_C2_cmpgeui: 198 case Intrinsic::hexagon_C2_cmplt: 199 case Intrinsic::hexagon_C2_cmpltu: 200 case Intrinsic::hexagon_C2_bitsclri: 201 case Intrinsic::hexagon_C2_and: 202 case Intrinsic::hexagon_C2_or: 203 case Intrinsic::hexagon_C2_xor: 204 case Intrinsic::hexagon_C2_andn: 205 case Intrinsic::hexagon_C2_not: 206 case Intrinsic::hexagon_C2_orn: 207 case Intrinsic::hexagon_C2_pxfer_map: 208 case Intrinsic::hexagon_C2_any8: 209 case Intrinsic::hexagon_C2_all8: 210 case Intrinsic::hexagon_A2_vcmpbeq: 211 case Intrinsic::hexagon_A2_vcmpbgtu: 212 case Intrinsic::hexagon_A2_vcmpheq: 213 case Intrinsic::hexagon_A2_vcmphgt: 214 case Intrinsic::hexagon_A2_vcmphgtu: 215 case Intrinsic::hexagon_A2_vcmpweq: 216 case Intrinsic::hexagon_A2_vcmpwgt: 217 case Intrinsic::hexagon_A2_vcmpwgtu: 218 case Intrinsic::hexagon_C2_tfrrp: 219 case Intrinsic::hexagon_S2_tstbit_i: 220 case Intrinsic::hexagon_S2_tstbit_r: 221 return 1; 222 } 223 } 224 225 226 // Intrinsics that have predicate operands. 227 static unsigned doesIntrinsicContainPredicate(unsigned ID) 228 { 229 switch (ID) { 230 default: 231 return 0; 232 case Intrinsic::hexagon_C2_tfrpr: 233 return Hexagon::TFR_RsPd; 234 case Intrinsic::hexagon_C2_and: 235 return Hexagon::AND_pp; 236 case Intrinsic::hexagon_C2_xor: 237 return Hexagon::XOR_pp; 238 case Intrinsic::hexagon_C2_or: 239 return Hexagon::OR_pp; 240 case Intrinsic::hexagon_C2_not: 241 return Hexagon::NOT_p; 242 case Intrinsic::hexagon_C2_any8: 243 return Hexagon::ANY_pp; 244 case Intrinsic::hexagon_C2_all8: 245 return Hexagon::ALL_pp; 246 case Intrinsic::hexagon_C2_vitpack: 247 return Hexagon::VITPACK_pp; 248 case Intrinsic::hexagon_C2_mask: 249 return Hexagon::MASK_p; 250 case Intrinsic::hexagon_C2_mux: 251 return Hexagon::MUX_rr; 252 253 // Mapping hexagon_C2_muxir to MUX_pri. This is pretty weird - but 254 // that's how it's mapped in q6protos.h. 255 case Intrinsic::hexagon_C2_muxir: 256 return Hexagon::MUX_ri; 257 258 // Mapping hexagon_C2_muxri to MUX_pir. This is pretty weird - but 259 // that's how it's mapped in q6protos.h. 260 case Intrinsic::hexagon_C2_muxri: 261 return Hexagon::MUX_ir; 262 263 case Intrinsic::hexagon_C2_muxii: 264 return Hexagon::MUX_ii; 265 case Intrinsic::hexagon_C2_vmux: 266 return Hexagon::VMUX_prr64; 267 case Intrinsic::hexagon_S2_valignrb: 268 return Hexagon::VALIGN_rrp; 269 case Intrinsic::hexagon_S2_vsplicerb: 270 return Hexagon::VSPLICE_rrp; 271 } 272 } 273 274 275 static bool OffsetFitsS11(EVT MemType, int64_t Offset) { 276 if (MemType == MVT::i64 && isShiftedInt<11,3>(Offset)) { 277 return true; 278 } 279 if (MemType == MVT::i32 && isShiftedInt<11,2>(Offset)) { 280 return true; 281 } 282 if (MemType == MVT::i16 && isShiftedInt<11,1>(Offset)) { 283 return true; 284 } 285 if (MemType == MVT::i8 && isInt<11>(Offset)) { 286 return true; 287 } 288 return false; 289 } 290 291 292 // 293 // Try to lower loads of GlobalAdresses into base+offset loads. Custom 294 // lowering for GlobalAddress nodes has already turned it into a 295 // CONST32. 296 // 297 SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl) { 298 SDValue Chain = LD->getChain(); 299 SDNode* Const32 = LD->getBasePtr().getNode(); 300 unsigned Opcode = 0; 301 302 if (Const32->getOpcode() == HexagonISD::CONST32 && 303 ISD::isNormalLoad(LD)) { 304 SDValue Base = Const32->getOperand(0); 305 EVT LoadedVT = LD->getMemoryVT(); 306 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset(); 307 if (Offset != 0 && OffsetFitsS11(LoadedVT, Offset)) { 308 MVT PointerTy = TLI.getPointerTy(); 309 const GlobalValue* GV = 310 cast<GlobalAddressSDNode>(Base)->getGlobal(); 311 SDValue TargAddr = 312 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0); 313 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set, 314 dl, PointerTy, 315 TargAddr); 316 // Figure out base + offset opcode 317 if (LoadedVT == MVT::i64) Opcode = Hexagon::LDrid_indexed; 318 else if (LoadedVT == MVT::i32) Opcode = Hexagon::LDriw_indexed; 319 else if (LoadedVT == MVT::i16) Opcode = Hexagon::LDrih_indexed; 320 else if (LoadedVT == MVT::i8) Opcode = Hexagon::LDrib_indexed; 321 else assert (0 && "unknown memory type"); 322 323 // Build indexed load. 324 SDValue TargetConstOff = CurDAG->getTargetConstant(Offset, PointerTy); 325 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, 326 LD->getValueType(0), 327 MVT::Other, 328 SDValue(NewBase,0), 329 TargetConstOff, 330 Chain); 331 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 332 MemOp[0] = LD->getMemOperand(); 333 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); 334 ReplaceUses(LD, Result); 335 return Result; 336 } 337 } 338 339 return SelectCode(LD); 340 } 341 342 343 SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD, 344 unsigned Opcode, 345 DebugLoc dl) 346 { 347 SDValue Chain = LD->getChain(); 348 EVT LoadedVT = LD->getMemoryVT(); 349 SDValue Base = LD->getBasePtr(); 350 SDValue Offset = LD->getOffset(); 351 SDNode *OffsetNode = Offset.getNode(); 352 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); 353 SDValue N1 = LD->getOperand(1); 354 SDValue CPTmpN1_0; 355 SDValue CPTmpN1_1; 356 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) && 357 N1.getNode()->getValueType(0) == MVT::i32) { 358 if (TII->isValidAutoIncImm(LoadedVT, Val)) { 359 SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32); 360 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32, 361 MVT::Other, Base, TargetConst, 362 Chain); 363 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, MVT::i64, 364 SDValue(Result_1, 0)); 365 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 366 MemOp[0] = LD->getMemOperand(); 367 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); 368 const SDValue Froms[] = { SDValue(LD, 0), 369 SDValue(LD, 1), 370 SDValue(LD, 2) 371 }; 372 const SDValue Tos[] = { SDValue(Result_2, 0), 373 SDValue(Result_1, 1), 374 SDValue(Result_1, 2) 375 }; 376 ReplaceUses(Froms, Tos, 3); 377 return Result_2; 378 } 379 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 380 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); 381 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, 382 MVT::Other, Base, TargetConst0, 383 Chain); 384 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, 385 MVT::i64, SDValue(Result_1, 0)); 386 SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, 387 MVT::i32, Base, TargetConstVal, 388 SDValue(Result_1, 1)); 389 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 390 MemOp[0] = LD->getMemOperand(); 391 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); 392 const SDValue Froms[] = { SDValue(LD, 0), 393 SDValue(LD, 1), 394 SDValue(LD, 2) 395 }; 396 const SDValue Tos[] = { SDValue(Result_2, 0), 397 SDValue(Result_3, 0), 398 SDValue(Result_1, 1) 399 }; 400 ReplaceUses(Froms, Tos, 3); 401 return Result_2; 402 } 403 return SelectCode(LD); 404 } 405 406 407 SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD, 408 unsigned Opcode, 409 DebugLoc dl) 410 { 411 SDValue Chain = LD->getChain(); 412 EVT LoadedVT = LD->getMemoryVT(); 413 SDValue Base = LD->getBasePtr(); 414 SDValue Offset = LD->getOffset(); 415 SDNode *OffsetNode = Offset.getNode(); 416 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); 417 SDValue N1 = LD->getOperand(1); 418 SDValue CPTmpN1_0; 419 SDValue CPTmpN1_1; 420 if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) && 421 N1.getNode()->getValueType(0) == MVT::i32) { 422 if (TII->isValidAutoIncImm(LoadedVT, Val)) { 423 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); 424 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 425 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, 426 MVT::i32, MVT::Other, Base, 427 TargetConstVal, Chain); 428 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, 429 TargetConst0); 430 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, 431 MVT::i64, MVT::Other, 432 SDValue(Result_2,0), 433 SDValue(Result_1,0)); 434 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 435 MemOp[0] = LD->getMemOperand(); 436 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); 437 const SDValue Froms[] = { SDValue(LD, 0), 438 SDValue(LD, 1), 439 SDValue(LD, 2) 440 }; 441 const SDValue Tos[] = { SDValue(Result_3, 0), 442 SDValue(Result_1, 1), 443 SDValue(Result_1, 2) 444 }; 445 ReplaceUses(Froms, Tos, 3); 446 return Result_3; 447 } 448 449 // Generate an indirect load. 450 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 451 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); 452 SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, 453 MVT::Other, 454 Base, TargetConst0, Chain); 455 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, 456 TargetConst0); 457 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, 458 MVT::i64, MVT::Other, 459 SDValue(Result_2,0), 460 SDValue(Result_1,0)); 461 // Add offset to base. 462 SDNode* Result_4 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, 463 Base, TargetConstVal, 464 SDValue(Result_1, 1)); 465 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 466 MemOp[0] = LD->getMemOperand(); 467 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); 468 const SDValue Froms[] = { SDValue(LD, 0), 469 SDValue(LD, 1), 470 SDValue(LD, 2) 471 }; 472 const SDValue Tos[] = { SDValue(Result_3, 0), // Load value. 473 SDValue(Result_4, 0), // New address. 474 SDValue(Result_1, 1) 475 }; 476 ReplaceUses(Froms, Tos, 3); 477 return Result_3; 478 } 479 480 return SelectCode(LD); 481 } 482 483 484 SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl) { 485 SDValue Chain = LD->getChain(); 486 SDValue Base = LD->getBasePtr(); 487 SDValue Offset = LD->getOffset(); 488 SDNode *OffsetNode = Offset.getNode(); 489 // Get the constant value. 490 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); 491 EVT LoadedVT = LD->getMemoryVT(); 492 unsigned Opcode = 0; 493 494 // Check for zero ext loads. 495 bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD); 496 497 // Figure out the opcode. 498 if (LoadedVT == MVT::i64) { 499 if (TII->isValidAutoIncImm(LoadedVT, Val)) 500 Opcode = Hexagon::POST_LDrid; 501 else 502 Opcode = Hexagon::LDrid; 503 } else if (LoadedVT == MVT::i32) { 504 if (TII->isValidAutoIncImm(LoadedVT, Val)) 505 Opcode = Hexagon::POST_LDriw; 506 else 507 Opcode = Hexagon::LDriw; 508 } else if (LoadedVT == MVT::i16) { 509 if (TII->isValidAutoIncImm(LoadedVT, Val)) 510 Opcode = zextval ? Hexagon::POST_LDriuh : Hexagon::POST_LDrih; 511 else 512 Opcode = zextval ? Hexagon::LDriuh : Hexagon::LDrih; 513 } else if (LoadedVT == MVT::i8) { 514 if (TII->isValidAutoIncImm(LoadedVT, Val)) 515 Opcode = zextval ? Hexagon::POST_LDriub : Hexagon::POST_LDrib; 516 else 517 Opcode = zextval ? Hexagon::LDriub : Hexagon::LDrib; 518 } else 519 assert (0 && "unknown memory type"); 520 521 // For zero ext i64 loads, we need to add combine instructions. 522 if (LD->getValueType(0) == MVT::i64 && 523 LD->getExtensionType() == ISD::ZEXTLOAD) { 524 return SelectIndexedLoadZeroExtend64(LD, Opcode, dl); 525 } 526 if (LD->getValueType(0) == MVT::i64 && 527 LD->getExtensionType() == ISD::SEXTLOAD) { 528 // Handle sign ext i64 loads. 529 return SelectIndexedLoadSignExtend64(LD, Opcode, dl); 530 } 531 if (TII->isValidAutoIncImm(LoadedVT, Val)) { 532 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); 533 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, 534 LD->getValueType(0), 535 MVT::i32, MVT::Other, Base, 536 TargetConstVal, Chain); 537 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 538 MemOp[0] = LD->getMemOperand(); 539 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); 540 const SDValue Froms[] = { SDValue(LD, 0), 541 SDValue(LD, 1), 542 SDValue(LD, 2) 543 }; 544 const SDValue Tos[] = { SDValue(Result, 0), 545 SDValue(Result, 1), 546 SDValue(Result, 2) 547 }; 548 ReplaceUses(Froms, Tos, 3); 549 return Result; 550 } else { 551 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 552 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); 553 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, 554 LD->getValueType(0), 555 MVT::Other, Base, TargetConst0, 556 Chain); 557 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, 558 Base, TargetConstVal, 559 SDValue(Result_1, 1)); 560 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 561 MemOp[0] = LD->getMemOperand(); 562 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); 563 const SDValue Froms[] = { SDValue(LD, 0), 564 SDValue(LD, 1), 565 SDValue(LD, 2) 566 }; 567 const SDValue Tos[] = { SDValue(Result_1, 0), 568 SDValue(Result_2, 0), 569 SDValue(Result_1, 1) 570 }; 571 ReplaceUses(Froms, Tos, 3); 572 return Result_1; 573 } 574 } 575 576 577 SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) { 578 SDNode *result; 579 DebugLoc dl = N->getDebugLoc(); 580 LoadSDNode *LD = cast<LoadSDNode>(N); 581 ISD::MemIndexedMode AM = LD->getAddressingMode(); 582 583 // Handle indexed loads. 584 if (AM != ISD::UNINDEXED) { 585 result = SelectIndexedLoad(LD, dl); 586 } else { 587 result = SelectBaseOffsetLoad(LD, dl); 588 } 589 590 return result; 591 } 592 593 594 SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) { 595 SDValue Chain = ST->getChain(); 596 SDValue Base = ST->getBasePtr(); 597 SDValue Offset = ST->getOffset(); 598 SDValue Value = ST->getValue(); 599 SDNode *OffsetNode = Offset.getNode(); 600 // Get the constant value. 601 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); 602 EVT StoredVT = ST->getMemoryVT(); 603 604 // Offset value must be within representable range 605 // and must have correct alignment properties. 606 if (TII->isValidAutoIncImm(StoredVT, Val)) { 607 SDValue Ops[] = { Value, Base, 608 CurDAG->getTargetConstant(Val, MVT::i32), Chain}; 609 unsigned Opcode = 0; 610 611 // Figure out the post inc version of opcode. 612 if (StoredVT == MVT::i64) Opcode = Hexagon::POST_STdri; 613 else if (StoredVT == MVT::i32) Opcode = Hexagon::POST_STwri; 614 else if (StoredVT == MVT::i16) Opcode = Hexagon::POST_SThri; 615 else if (StoredVT == MVT::i8) Opcode = Hexagon::POST_STbri; 616 else assert (0 && "unknown memory type"); 617 618 // Build post increment store. 619 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32, 620 MVT::Other, Ops, 4); 621 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 622 MemOp[0] = ST->getMemOperand(); 623 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); 624 625 ReplaceUses(ST, Result); 626 ReplaceUses(SDValue(ST,1), SDValue(Result,1)); 627 return Result; 628 } 629 630 // Note: Order of operands matches the def of instruction: 631 // def STrid : STInst<(outs), (ins MEMri:$addr, DoubleRegs:$src1), ... 632 // and it differs for POST_ST* for instance. 633 SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, MVT::i32), Value, 634 Chain}; 635 unsigned Opcode = 0; 636 637 // Figure out the opcode. 638 if (StoredVT == MVT::i64) Opcode = Hexagon::STrid; 639 else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw; 640 else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih; 641 else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib; 642 else assert (0 && "unknown memory type"); 643 644 // Build regular store. 645 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); 646 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops, 647 4); 648 // Build splitted incriment instruction. 649 SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, 650 Base, 651 TargetConstVal, 652 SDValue(Result_1, 0)); 653 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 654 MemOp[0] = ST->getMemOperand(); 655 cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); 656 657 ReplaceUses(SDValue(ST,0), SDValue(Result_2,0)); 658 ReplaceUses(SDValue(ST,1), SDValue(Result_1,0)); 659 return Result_2; 660 } 661 662 663 SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST, 664 DebugLoc dl) { 665 SDValue Chain = ST->getChain(); 666 SDNode* Const32 = ST->getBasePtr().getNode(); 667 SDValue Value = ST->getValue(); 668 unsigned Opcode = 0; 669 670 // Try to lower stores of GlobalAdresses into indexed stores. Custom 671 // lowering for GlobalAddress nodes has already turned it into a 672 // CONST32. Avoid truncating stores for the moment. Post-inc stores 673 // do the same. Don't think there's a reason for it, so will file a 674 // bug to fix. 675 if ((Const32->getOpcode() == HexagonISD::CONST32) && 676 !(Value.getValueType() == MVT::i64 && ST->isTruncatingStore())) { 677 SDValue Base = Const32->getOperand(0); 678 if (Base.getOpcode() == ISD::TargetGlobalAddress) { 679 EVT StoredVT = ST->getMemoryVT(); 680 int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset(); 681 if (Offset != 0 && OffsetFitsS11(StoredVT, Offset)) { 682 MVT PointerTy = TLI.getPointerTy(); 683 const GlobalValue* GV = 684 cast<GlobalAddressSDNode>(Base)->getGlobal(); 685 SDValue TargAddr = 686 CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0); 687 SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set, 688 dl, PointerTy, 689 TargAddr); 690 691 // Figure out base + offset opcode 692 if (StoredVT == MVT::i64) Opcode = Hexagon::STrid_indexed; 693 else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed; 694 else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih_indexed; 695 else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib_indexed; 696 else assert (0 && "unknown memory type"); 697 698 SDValue Ops[] = {SDValue(NewBase,0), 699 CurDAG->getTargetConstant(Offset,PointerTy), 700 Value, Chain}; 701 // build indexed store 702 SDNode* Result = CurDAG->getMachineNode(Opcode, dl, 703 MVT::Other, Ops, 4); 704 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); 705 MemOp[0] = ST->getMemOperand(); 706 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); 707 ReplaceUses(ST, Result); 708 return Result; 709 } 710 } 711 } 712 713 return SelectCode(ST); 714 } 715 716 717 SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) { 718 DebugLoc dl = N->getDebugLoc(); 719 StoreSDNode *ST = cast<StoreSDNode>(N); 720 ISD::MemIndexedMode AM = ST->getAddressingMode(); 721 722 // Handle indexed stores. 723 if (AM != ISD::UNINDEXED) { 724 return SelectIndexedStore(ST, dl); 725 } 726 727 return SelectBaseOffsetStore(ST, dl); 728 } 729 730 SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) { 731 DebugLoc dl = N->getDebugLoc(); 732 733 // 734 // %conv.i = sext i32 %tmp1 to i64 735 // %conv2.i = sext i32 %add to i64 736 // %mul.i = mul nsw i64 %conv2.i, %conv.i 737 // 738 // --- match with the following --- 739 // 740 // %mul.i = mpy (%tmp1, %add) 741 // 742 743 if (N->getValueType(0) == MVT::i64) { 744 // Shifting a i64 signed multiply. 745 SDValue MulOp0 = N->getOperand(0); 746 SDValue MulOp1 = N->getOperand(1); 747 748 SDValue OP0; 749 SDValue OP1; 750 751 // Handle sign_extend and sextload. 752 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) { 753 SDValue Sext0 = MulOp0.getOperand(0); 754 if (Sext0.getNode()->getValueType(0) != MVT::i32) { 755 SelectCode(N); 756 } 757 758 OP0 = Sext0; 759 } else if (MulOp0.getOpcode() == ISD::LOAD) { 760 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode()); 761 if (LD->getMemoryVT() != MVT::i32 || 762 LD->getExtensionType() != ISD::SEXTLOAD || 763 LD->getAddressingMode() != ISD::UNINDEXED) { 764 SelectCode(N); 765 } 766 767 SDValue Chain = LD->getChain(); 768 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 769 OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, 770 MVT::Other, 771 LD->getBasePtr(), TargetConst0, 772 Chain), 0); 773 } else { 774 return SelectCode(N); 775 } 776 777 // Same goes for the second operand. 778 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) { 779 SDValue Sext1 = MulOp1.getOperand(0); 780 if (Sext1.getNode()->getValueType(0) != MVT::i32) { 781 return SelectCode(N); 782 } 783 784 OP1 = Sext1; 785 } else if (MulOp1.getOpcode() == ISD::LOAD) { 786 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode()); 787 if (LD->getMemoryVT() != MVT::i32 || 788 LD->getExtensionType() != ISD::SEXTLOAD || 789 LD->getAddressingMode() != ISD::UNINDEXED) { 790 return SelectCode(N); 791 } 792 793 SDValue Chain = LD->getChain(); 794 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 795 OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, 796 MVT::Other, 797 LD->getBasePtr(), TargetConst0, 798 Chain), 0); 799 } else { 800 return SelectCode(N); 801 } 802 803 // Generate a mpy instruction. 804 SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY64, dl, MVT::i64, 805 OP0, OP1); 806 ReplaceUses(N, Result); 807 return Result; 808 } 809 810 return SelectCode(N); 811 } 812 813 814 SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) { 815 DebugLoc dl = N->getDebugLoc(); 816 SDValue N0 = N->getOperand(0); 817 if (N0.getOpcode() == ISD::SETCC) { 818 SDValue N00 = N0.getOperand(0); 819 if (N00.getOpcode() == ISD::SIGN_EXTEND_INREG) { 820 SDValue N000 = N00.getOperand(0); 821 SDValue N001 = N00.getOperand(1); 822 if (cast<VTSDNode>(N001)->getVT() == MVT::i16) { 823 SDValue N01 = N0.getOperand(1); 824 SDValue N02 = N0.getOperand(2); 825 826 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2, 827 // i16:Other),IntRegs:i32:$src1, SETLT:Other),IntRegs:i32:$src1, 828 // IntRegs:i32:$src2) 829 // Emits: (MAXh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2) 830 // Pattern complexity = 9 cost = 1 size = 0. 831 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETLT) { 832 SDValue N1 = N->getOperand(1); 833 if (N01 == N1) { 834 SDValue N2 = N->getOperand(2); 835 if (N000 == N2 && 836 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 && 837 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) { 838 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl, 839 MVT::i32, N000); 840 SDNode *Result = CurDAG->getMachineNode(Hexagon::MAXw_rr, dl, 841 MVT::i32, 842 SDValue(SextNode, 0), 843 N1); 844 ReplaceUses(N, Result); 845 return Result; 846 } 847 } 848 } 849 850 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2, 851 // i16:Other), IntRegs:i32:$src1, SETGT:Other), IntRegs:i32:$src1, 852 // IntRegs:i32:$src2) 853 // Emits: (MINh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2) 854 // Pattern complexity = 9 cost = 1 size = 0. 855 if (cast<CondCodeSDNode>(N02)->get() == ISD::SETGT) { 856 SDValue N1 = N->getOperand(1); 857 if (N01 == N1) { 858 SDValue N2 = N->getOperand(2); 859 if (N000 == N2 && 860 N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 && 861 N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) { 862 SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl, 863 MVT::i32, N000); 864 SDNode *Result = CurDAG->getMachineNode(Hexagon::MINw_rr, dl, 865 MVT::i32, 866 SDValue(SextNode, 0), 867 N1); 868 ReplaceUses(N, Result); 869 return Result; 870 } 871 } 872 } 873 } 874 } 875 } 876 877 return SelectCode(N); 878 } 879 880 881 SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) { 882 DebugLoc dl = N->getDebugLoc(); 883 SDValue Shift = N->getOperand(0); 884 885 // 886 // %conv.i = sext i32 %tmp1 to i64 887 // %conv2.i = sext i32 %add to i64 888 // %mul.i = mul nsw i64 %conv2.i, %conv.i 889 // %shr5.i = lshr i64 %mul.i, 32 890 // %conv3.i = trunc i64 %shr5.i to i32 891 // 892 // --- match with the following --- 893 // 894 // %conv3.i = mpy (%tmp1, %add) 895 // 896 // Trunc to i32. 897 if (N->getValueType(0) == MVT::i32) { 898 // Trunc from i64. 899 if (Shift.getNode()->getValueType(0) == MVT::i64) { 900 // Trunc child is logical shift right. 901 if (Shift.getOpcode() != ISD::SRL) { 902 return SelectCode(N); 903 } 904 905 SDValue ShiftOp0 = Shift.getOperand(0); 906 SDValue ShiftOp1 = Shift.getOperand(1); 907 908 // Shift by const 32 909 if (ShiftOp1.getOpcode() != ISD::Constant) { 910 return SelectCode(N); 911 } 912 913 int32_t ShiftConst = 914 cast<ConstantSDNode>(ShiftOp1.getNode())->getSExtValue(); 915 if (ShiftConst != 32) { 916 return SelectCode(N); 917 } 918 919 // Shifting a i64 signed multiply 920 SDValue Mul = ShiftOp0; 921 if (Mul.getOpcode() != ISD::MUL) { 922 return SelectCode(N); 923 } 924 925 SDValue MulOp0 = Mul.getOperand(0); 926 SDValue MulOp1 = Mul.getOperand(1); 927 928 SDValue OP0; 929 SDValue OP1; 930 931 // Handle sign_extend and sextload 932 if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) { 933 SDValue Sext0 = MulOp0.getOperand(0); 934 if (Sext0.getNode()->getValueType(0) != MVT::i32) { 935 return SelectCode(N); 936 } 937 938 OP0 = Sext0; 939 } else if (MulOp0.getOpcode() == ISD::LOAD) { 940 LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode()); 941 if (LD->getMemoryVT() != MVT::i32 || 942 LD->getExtensionType() != ISD::SEXTLOAD || 943 LD->getAddressingMode() != ISD::UNINDEXED) { 944 return SelectCode(N); 945 } 946 947 SDValue Chain = LD->getChain(); 948 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 949 OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, 950 MVT::Other, 951 LD->getBasePtr(), 952 TargetConst0, Chain), 0); 953 } else { 954 return SelectCode(N); 955 } 956 957 // Same goes for the second operand. 958 if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) { 959 SDValue Sext1 = MulOp1.getOperand(0); 960 if (Sext1.getNode()->getValueType(0) != MVT::i32) 961 return SelectCode(N); 962 963 OP1 = Sext1; 964 } else if (MulOp1.getOpcode() == ISD::LOAD) { 965 LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode()); 966 if (LD->getMemoryVT() != MVT::i32 || 967 LD->getExtensionType() != ISD::SEXTLOAD || 968 LD->getAddressingMode() != ISD::UNINDEXED) { 969 return SelectCode(N); 970 } 971 972 SDValue Chain = LD->getChain(); 973 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 974 OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, 975 MVT::Other, 976 LD->getBasePtr(), 977 TargetConst0, Chain), 0); 978 } else { 979 return SelectCode(N); 980 } 981 982 // Generate a mpy instruction. 983 SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY, dl, MVT::i32, 984 OP0, OP1); 985 ReplaceUses(N, Result); 986 return Result; 987 } 988 } 989 990 return SelectCode(N); 991 } 992 993 994 SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) { 995 DebugLoc dl = N->getDebugLoc(); 996 if (N->getValueType(0) == MVT::i32) { 997 SDValue Shl_0 = N->getOperand(0); 998 SDValue Shl_1 = N->getOperand(1); 999 // RHS is const. 1000 if (Shl_1.getOpcode() == ISD::Constant) { 1001 if (Shl_0.getOpcode() == ISD::MUL) { 1002 SDValue Mul_0 = Shl_0.getOperand(0); // Val 1003 SDValue Mul_1 = Shl_0.getOperand(1); // Const 1004 // RHS of mul is const. 1005 if (Mul_1.getOpcode() == ISD::Constant) { 1006 int32_t ShlConst = 1007 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue(); 1008 int32_t MulConst = 1009 cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue(); 1010 int32_t ValConst = MulConst << ShlConst; 1011 SDValue Val = CurDAG->getTargetConstant(ValConst, 1012 MVT::i32); 1013 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode())) 1014 if (isInt<9>(CN->getSExtValue())) { 1015 SDNode* Result = 1016 CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, 1017 MVT::i32, Mul_0, Val); 1018 ReplaceUses(N, Result); 1019 return Result; 1020 } 1021 1022 } 1023 } else if (Shl_0.getOpcode() == ISD::SUB) { 1024 SDValue Sub_0 = Shl_0.getOperand(0); // Const 0 1025 SDValue Sub_1 = Shl_0.getOperand(1); // Val 1026 if (Sub_0.getOpcode() == ISD::Constant) { 1027 int32_t SubConst = 1028 cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue(); 1029 if (SubConst == 0) { 1030 if (Sub_1.getOpcode() == ISD::SHL) { 1031 SDValue Shl2_0 = Sub_1.getOperand(0); // Val 1032 SDValue Shl2_1 = Sub_1.getOperand(1); // Const 1033 if (Shl2_1.getOpcode() == ISD::Constant) { 1034 int32_t ShlConst = 1035 cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue(); 1036 int32_t Shl2Const = 1037 cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue(); 1038 int32_t ValConst = 1 << (ShlConst+Shl2Const); 1039 SDValue Val = CurDAG->getTargetConstant(-ValConst, MVT::i32); 1040 if (ConstantSDNode *CN = 1041 dyn_cast<ConstantSDNode>(Val.getNode())) 1042 if (isInt<9>(CN->getSExtValue())) { 1043 SDNode* Result = 1044 CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, MVT::i32, 1045 Shl2_0, Val); 1046 ReplaceUses(N, Result); 1047 return Result; 1048 } 1049 } 1050 } 1051 } 1052 } 1053 } 1054 } 1055 } 1056 return SelectCode(N); 1057 } 1058 1059 1060 // 1061 // If there is an zero_extend followed an intrinsic in DAG (this means - the 1062 // result of the intrinsic is predicate); convert the zero_extend to 1063 // transfer instruction. 1064 // 1065 // Zero extend -> transfer is lowered here. Otherwise, zero_extend will be 1066 // converted into a MUX as predicate registers defined as 1 bit in the 1067 // compiler. Architecture defines them as 8-bit registers. 1068 // We want to preserve all the lower 8-bits and, not just 1 LSB bit. 1069 // 1070 SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) { 1071 DebugLoc dl = N->getDebugLoc(); 1072 SDNode *IsIntrinsic = N->getOperand(0).getNode(); 1073 if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) { 1074 unsigned ID = 1075 cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue(); 1076 if (doesIntrinsicReturnPredicate(ID)) { 1077 // Now we need to differentiate target data types. 1078 if (N->getValueType(0) == MVT::i64) { 1079 // Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs). 1080 SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); 1081 SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl, 1082 MVT::i32, 1083 SDValue(IsIntrinsic, 0)); 1084 SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, 1085 MVT::i32, 1086 TargetConst0); 1087 SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, 1088 MVT::i64, MVT::Other, 1089 SDValue(Result_2, 0), 1090 SDValue(Result_1, 0)); 1091 ReplaceUses(N, Result_3); 1092 return Result_3; 1093 } 1094 if (N->getValueType(0) == MVT::i32) { 1095 // Convert the zero_extend to Rs = Pd 1096 SDNode* RsPd = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl, 1097 MVT::i32, 1098 SDValue(IsIntrinsic, 0)); 1099 ReplaceUses(N, RsPd); 1100 return RsPd; 1101 } 1102 llvm_unreachable("Unexpected value type"); 1103 } 1104 } 1105 return SelectCode(N); 1106 } 1107 1108 1109 // 1110 // Checking for intrinsics which have predicate registers as operand(s) 1111 // and lowering to the actual intrinsic. 1112 // 1113 SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) { 1114 DebugLoc dl = N->getDebugLoc(); 1115 unsigned ID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); 1116 unsigned IntrinsicWithPred = doesIntrinsicContainPredicate(ID); 1117 1118 // We are concerned with only those intrinsics that have predicate registers 1119 // as at least one of the operands. 1120 if (IntrinsicWithPred) { 1121 SmallVector<SDValue, 8> Ops; 1122 const MCInstrDesc &MCID = TII->get(IntrinsicWithPred); 1123 const TargetRegisterInfo *TRI = TM.getRegisterInfo(); 1124 1125 // Iterate over all the operands of the intrinsics. 1126 // For PredRegs, do the transfer. 1127 // For Double/Int Regs, just preserve the value 1128 // For immediates, lower it. 1129 for (unsigned i = 1; i < N->getNumOperands(); ++i) { 1130 SDNode *Arg = N->getOperand(i).getNode(); 1131 const TargetRegisterClass *RC = TII->getRegClass(MCID, i, TRI); 1132 1133 if (RC == Hexagon::IntRegsRegisterClass || 1134 RC == Hexagon::DoubleRegsRegisterClass) { 1135 Ops.push_back(SDValue(Arg, 0)); 1136 } else if (RC == Hexagon::PredRegsRegisterClass) { 1137 // Do the transfer. 1138 SDNode *PdRs = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1, 1139 SDValue(Arg, 0)); 1140 Ops.push_back(SDValue(PdRs,0)); 1141 } else if (RC == NULL && (dyn_cast<ConstantSDNode>(Arg) != NULL)) { 1142 // This is immediate operand. Lower it here making sure that we DO have 1143 // const SDNode for immediate value. 1144 int32_t Val = cast<ConstantSDNode>(Arg)->getSExtValue(); 1145 SDValue SDVal = CurDAG->getTargetConstant(Val, MVT::i32); 1146 Ops.push_back(SDVal); 1147 } else { 1148 llvm_unreachable("Unimplemented"); 1149 } 1150 } 1151 EVT ReturnValueVT = N->getValueType(0); 1152 SDNode *Result = CurDAG->getMachineNode(IntrinsicWithPred, dl, 1153 ReturnValueVT, 1154 Ops.data(), Ops.size()); 1155 ReplaceUses(N, Result); 1156 return Result; 1157 } 1158 return SelectCode(N); 1159 } 1160 1161 1162 // 1163 // Map predicate true (encoded as -1 in LLVM) to a XOR. 1164 // 1165 SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) { 1166 DebugLoc dl = N->getDebugLoc(); 1167 if (N->getValueType(0) == MVT::i1) { 1168 SDNode* Result; 1169 int32_t Val = cast<ConstantSDNode>(N)->getSExtValue(); 1170 if (Val == -1) { 1171 // Create the IntReg = 1 node. 1172 SDNode* IntRegTFR = 1173 CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, 1174 CurDAG->getTargetConstant(0, MVT::i32)); 1175 1176 // Pd = IntReg 1177 SDNode* Pd = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1, 1178 SDValue(IntRegTFR, 0)); 1179 1180 // not(Pd) 1181 SDNode* NotPd = CurDAG->getMachineNode(Hexagon::NOT_p, dl, MVT::i1, 1182 SDValue(Pd, 0)); 1183 1184 // xor(not(Pd)) 1185 Result = CurDAG->getMachineNode(Hexagon::XOR_pp, dl, MVT::i1, 1186 SDValue(Pd, 0), SDValue(NotPd, 0)); 1187 1188 // We have just built: 1189 // Rs = Pd 1190 // Pd = xor(not(Pd), Pd) 1191 1192 ReplaceUses(N, Result); 1193 return Result; 1194 } 1195 } 1196 1197 return SelectCode(N); 1198 } 1199 1200 1201 // 1202 // Map add followed by a asr -> asr +=. 1203 // 1204 SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) { 1205 DebugLoc dl = N->getDebugLoc(); 1206 if (N->getValueType(0) != MVT::i32) { 1207 return SelectCode(N); 1208 } 1209 // Identify nodes of the form: add(asr(...)). 1210 SDNode* Src1 = N->getOperand(0).getNode(); 1211 if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse() 1212 || Src1->getValueType(0) != MVT::i32) { 1213 return SelectCode(N); 1214 } 1215 1216 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that 1217 // Rd and Rd' are assigned to the same register 1218 SDNode* Result = CurDAG->getMachineNode(Hexagon::ASR_rr_acc, dl, MVT::i32, 1219 N->getOperand(1), 1220 Src1->getOperand(0), 1221 Src1->getOperand(1)); 1222 ReplaceUses(N, Result); 1223 1224 return Result; 1225 } 1226 1227 1228 SDNode *HexagonDAGToDAGISel::Select(SDNode *N) { 1229 if (N->isMachineOpcode()) 1230 return NULL; // Already selected. 1231 1232 1233 switch (N->getOpcode()) { 1234 case ISD::Constant: 1235 return SelectConstant(N); 1236 1237 case ISD::ADD: 1238 return SelectAdd(N); 1239 1240 case ISD::SHL: 1241 return SelectSHL(N); 1242 1243 case ISD::LOAD: 1244 return SelectLoad(N); 1245 1246 case ISD::STORE: 1247 return SelectStore(N); 1248 1249 case ISD::SELECT: 1250 return SelectSelect(N); 1251 1252 case ISD::TRUNCATE: 1253 return SelectTruncate(N); 1254 1255 case ISD::MUL: 1256 return SelectMul(N); 1257 1258 case ISD::ZERO_EXTEND: 1259 return SelectZeroExtend(N); 1260 1261 case ISD::INTRINSIC_WO_CHAIN: 1262 return SelectIntrinsicWOChain(N); 1263 } 1264 1265 return SelectCode(N); 1266 } 1267 1268 1269 // 1270 // Hexagon_TODO: Five functions for ADDRri?! Surely there must be a better way 1271 // to define these instructions. 1272 // 1273 bool HexagonDAGToDAGISel::SelectADDRri(SDValue& Addr, SDValue &Base, 1274 SDValue &Offset) { 1275 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 1276 Addr.getOpcode() == ISD::TargetGlobalAddress) 1277 return false; // Direct calls. 1278 1279 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 1280 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 1281 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1282 return true; 1283 } 1284 Base = Addr; 1285 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1286 return true; 1287 } 1288 1289 1290 bool HexagonDAGToDAGISel::SelectADDRriS11_0(SDValue& Addr, SDValue &Base, 1291 SDValue &Offset) { 1292 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 1293 Addr.getOpcode() == ISD::TargetGlobalAddress) 1294 return false; // Direct calls. 1295 1296 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 1297 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 1298 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1299 return (IsS11_0_Offset(Offset.getNode())); 1300 } 1301 Base = Addr; 1302 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1303 return (IsS11_0_Offset(Offset.getNode())); 1304 } 1305 1306 1307 bool HexagonDAGToDAGISel::SelectADDRriS11_1(SDValue& Addr, SDValue &Base, 1308 SDValue &Offset) { 1309 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 1310 Addr.getOpcode() == ISD::TargetGlobalAddress) 1311 return false; // Direct calls. 1312 1313 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 1314 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 1315 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1316 return (IsS11_1_Offset(Offset.getNode())); 1317 } 1318 Base = Addr; 1319 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1320 return (IsS11_1_Offset(Offset.getNode())); 1321 } 1322 1323 1324 bool HexagonDAGToDAGISel::SelectADDRriS11_2(SDValue& Addr, SDValue &Base, 1325 SDValue &Offset) { 1326 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 1327 Addr.getOpcode() == ISD::TargetGlobalAddress) 1328 return false; // Direct calls. 1329 1330 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 1331 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 1332 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1333 return (IsS11_2_Offset(Offset.getNode())); 1334 } 1335 Base = Addr; 1336 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1337 return (IsS11_2_Offset(Offset.getNode())); 1338 } 1339 1340 1341 bool HexagonDAGToDAGISel::SelectADDRriU6_0(SDValue& Addr, SDValue &Base, 1342 SDValue &Offset) { 1343 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 1344 Addr.getOpcode() == ISD::TargetGlobalAddress) 1345 return false; // Direct calls. 1346 1347 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 1348 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 1349 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1350 return (IsU6_0_Offset(Offset.getNode())); 1351 } 1352 Base = Addr; 1353 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1354 return (IsU6_0_Offset(Offset.getNode())); 1355 } 1356 1357 1358 bool HexagonDAGToDAGISel::SelectADDRriU6_1(SDValue& Addr, SDValue &Base, 1359 SDValue &Offset) { 1360 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 1361 Addr.getOpcode() == ISD::TargetGlobalAddress) 1362 return false; // Direct calls. 1363 1364 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 1365 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 1366 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1367 return (IsU6_1_Offset(Offset.getNode())); 1368 } 1369 Base = Addr; 1370 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1371 return (IsU6_1_Offset(Offset.getNode())); 1372 } 1373 1374 1375 bool HexagonDAGToDAGISel::SelectADDRriU6_2(SDValue& Addr, SDValue &Base, 1376 SDValue &Offset) { 1377 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 1378 Addr.getOpcode() == ISD::TargetGlobalAddress) 1379 return false; // Direct calls. 1380 1381 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 1382 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 1383 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1384 return (IsU6_2_Offset(Offset.getNode())); 1385 } 1386 Base = Addr; 1387 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1388 return (IsU6_2_Offset(Offset.getNode())); 1389 } 1390 1391 1392 bool HexagonDAGToDAGISel::SelectMEMriS11_2(SDValue& Addr, SDValue &Base, 1393 SDValue &Offset) { 1394 1395 if (Addr.getOpcode() != ISD::ADD) { 1396 return(SelectADDRriS11_2(Addr, Base, Offset)); 1397 } 1398 1399 return SelectADDRriS11_2(Addr, Base, Offset); 1400 } 1401 1402 1403 bool HexagonDAGToDAGISel::SelectADDRriS11_3(SDValue& Addr, SDValue &Base, 1404 SDValue &Offset) { 1405 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 1406 Addr.getOpcode() == ISD::TargetGlobalAddress) 1407 return false; // Direct calls. 1408 1409 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 1410 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 1411 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1412 return (IsS11_3_Offset(Offset.getNode())); 1413 } 1414 Base = Addr; 1415 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1416 return (IsS11_3_Offset(Offset.getNode())); 1417 } 1418 1419 bool HexagonDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, 1420 SDValue &R2) { 1421 if (Addr.getOpcode() == ISD::FrameIndex) return false; 1422 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 1423 Addr.getOpcode() == ISD::TargetGlobalAddress) 1424 return false; // Direct calls. 1425 1426 if (Addr.getOpcode() == ISD::ADD) { 1427 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) 1428 if (isInt<13>(CN->getSExtValue())) 1429 return false; // Let the reg+imm pattern catch this! 1430 R1 = Addr.getOperand(0); 1431 R2 = Addr.getOperand(1); 1432 return true; 1433 } 1434 1435 R1 = Addr; 1436 1437 return true; 1438 } 1439 1440 1441 // Handle generic address case. It is accessed from inlined asm =m constraints, 1442 // which could have any kind of pointer. 1443 bool HexagonDAGToDAGISel::SelectAddr(SDNode *Op, SDValue Addr, 1444 SDValue &Base, SDValue &Offset) { 1445 if (Addr.getOpcode() == ISD::TargetExternalSymbol || 1446 Addr.getOpcode() == ISD::TargetGlobalAddress) 1447 return false; // Direct calls. 1448 1449 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { 1450 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); 1451 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1452 return true; 1453 } 1454 1455 if (Addr.getOpcode() == ISD::ADD) { 1456 Base = Addr.getOperand(0); 1457 Offset = Addr.getOperand(1); 1458 return true; 1459 } 1460 1461 Base = Addr; 1462 Offset = CurDAG->getTargetConstant(0, MVT::i32); 1463 return true; 1464 } 1465 1466 1467 bool HexagonDAGToDAGISel:: 1468 SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, 1469 std::vector<SDValue> &OutOps) { 1470 SDValue Op0, Op1; 1471 1472 switch (ConstraintCode) { 1473 case 'o': // Offsetable. 1474 case 'v': // Not offsetable. 1475 default: return true; 1476 case 'm': // Memory. 1477 if (!SelectAddr(Op.getNode(), Op, Op0, Op1)) 1478 return true; 1479 break; 1480 } 1481 1482 OutOps.push_back(Op0); 1483 OutOps.push_back(Op1); 1484 return false; 1485 } 1486