1 //===- ARMInstructionSelector.cpp ----------------------------*- C++ -*-==// 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 /// \file 10 /// This file implements the targeting of the InstructionSelector class for ARM. 11 /// \todo This should be generated by TableGen. 12 //===----------------------------------------------------------------------===// 13 14 #include "ARMRegisterBankInfo.h" 15 #include "ARMSubtarget.h" 16 #include "ARMTargetMachine.h" 17 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" 18 #include "llvm/CodeGen/MachineRegisterInfo.h" 19 #include "llvm/Support/Debug.h" 20 21 #define DEBUG_TYPE "arm-isel" 22 23 #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h" 24 25 using namespace llvm; 26 27 #ifndef LLVM_BUILD_GLOBAL_ISEL 28 #error "You shouldn't build this" 29 #endif 30 31 namespace { 32 33 #define GET_GLOBALISEL_PREDICATE_BITSET 34 #include "ARMGenGlobalISel.inc" 35 #undef GET_GLOBALISEL_PREDICATE_BITSET 36 37 class ARMInstructionSelector : public InstructionSelector { 38 public: 39 ARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI, 40 const ARMRegisterBankInfo &RBI); 41 42 bool select(MachineInstr &I) const override; 43 44 private: 45 bool selectImpl(MachineInstr &I) const; 46 47 template <typename T> struct CmpHelper; 48 49 template <typename T> 50 bool selectCmp(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, 51 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, 52 const RegisterBankInfo &RBI) const; 53 54 bool selectSelect(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, 55 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, 56 const RegisterBankInfo &RBI) const; 57 58 const ARMBaseInstrInfo &TII; 59 const ARMBaseRegisterInfo &TRI; 60 const ARMBaseTargetMachine &TM; 61 const ARMRegisterBankInfo &RBI; 62 const ARMSubtarget &STI; 63 64 #define GET_GLOBALISEL_PREDICATES_DECL 65 #include "ARMGenGlobalISel.inc" 66 #undef GET_GLOBALISEL_PREDICATES_DECL 67 68 // We declare the temporaries used by selectImpl() in the class to minimize the 69 // cost of constructing placeholder values. 70 #define GET_GLOBALISEL_TEMPORARIES_DECL 71 #include "ARMGenGlobalISel.inc" 72 #undef GET_GLOBALISEL_TEMPORARIES_DECL 73 }; 74 } // end anonymous namespace 75 76 namespace llvm { 77 InstructionSelector * 78 createARMInstructionSelector(const ARMBaseTargetMachine &TM, 79 const ARMSubtarget &STI, 80 const ARMRegisterBankInfo &RBI) { 81 return new ARMInstructionSelector(TM, STI, RBI); 82 } 83 } 84 85 unsigned zero_reg = 0; 86 87 #define GET_GLOBALISEL_IMPL 88 #include "ARMGenGlobalISel.inc" 89 #undef GET_GLOBALISEL_IMPL 90 91 ARMInstructionSelector::ARMInstructionSelector(const ARMBaseTargetMachine &TM, 92 const ARMSubtarget &STI, 93 const ARMRegisterBankInfo &RBI) 94 : InstructionSelector(), TII(*STI.getInstrInfo()), 95 TRI(*STI.getRegisterInfo()), TM(TM), RBI(RBI), STI(STI), 96 #define GET_GLOBALISEL_PREDICATES_INIT 97 #include "ARMGenGlobalISel.inc" 98 #undef GET_GLOBALISEL_PREDICATES_INIT 99 #define GET_GLOBALISEL_TEMPORARIES_INIT 100 #include "ARMGenGlobalISel.inc" 101 #undef GET_GLOBALISEL_TEMPORARIES_INIT 102 { 103 } 104 105 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, 106 MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, 107 const RegisterBankInfo &RBI) { 108 unsigned DstReg = I.getOperand(0).getReg(); 109 if (TargetRegisterInfo::isPhysicalRegister(DstReg)) 110 return true; 111 112 const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI); 113 (void)RegBank; 114 assert(RegBank && "Can't get reg bank for virtual register"); 115 116 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits(); 117 assert((RegBank->getID() == ARM::GPRRegBankID || 118 RegBank->getID() == ARM::FPRRegBankID) && 119 "Unsupported reg bank"); 120 121 const TargetRegisterClass *RC = &ARM::GPRRegClass; 122 123 if (RegBank->getID() == ARM::FPRRegBankID) { 124 if (DstSize == 32) 125 RC = &ARM::SPRRegClass; 126 else if (DstSize == 64) 127 RC = &ARM::DPRRegClass; 128 else 129 llvm_unreachable("Unsupported destination size"); 130 } 131 132 // No need to constrain SrcReg. It will get constrained when 133 // we hit another of its uses or its defs. 134 // Copies do not have constraints. 135 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) { 136 DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) 137 << " operand\n"); 138 return false; 139 } 140 return true; 141 } 142 143 static bool selectMergeValues(MachineInstrBuilder &MIB, 144 const ARMBaseInstrInfo &TII, 145 MachineRegisterInfo &MRI, 146 const TargetRegisterInfo &TRI, 147 const RegisterBankInfo &RBI) { 148 assert(TII.getSubtarget().hasVFP2() && "Can't select merge without VFP"); 149 150 // We only support G_MERGE_VALUES as a way to stick together two scalar GPRs 151 // into one DPR. 152 unsigned VReg0 = MIB->getOperand(0).getReg(); 153 (void)VReg0; 154 assert(MRI.getType(VReg0).getSizeInBits() == 64 && 155 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::FPRRegBankID && 156 "Unsupported operand for G_MERGE_VALUES"); 157 unsigned VReg1 = MIB->getOperand(1).getReg(); 158 (void)VReg1; 159 assert(MRI.getType(VReg1).getSizeInBits() == 32 && 160 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID && 161 "Unsupported operand for G_MERGE_VALUES"); 162 unsigned VReg2 = MIB->getOperand(2).getReg(); 163 (void)VReg2; 164 assert(MRI.getType(VReg2).getSizeInBits() == 32 && 165 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::GPRRegBankID && 166 "Unsupported operand for G_MERGE_VALUES"); 167 168 MIB->setDesc(TII.get(ARM::VMOVDRR)); 169 MIB.add(predOps(ARMCC::AL)); 170 171 return true; 172 } 173 174 static bool selectUnmergeValues(MachineInstrBuilder &MIB, 175 const ARMBaseInstrInfo &TII, 176 MachineRegisterInfo &MRI, 177 const TargetRegisterInfo &TRI, 178 const RegisterBankInfo &RBI) { 179 assert(TII.getSubtarget().hasVFP2() && "Can't select unmerge without VFP"); 180 181 // We only support G_UNMERGE_VALUES as a way to break up one DPR into two 182 // GPRs. 183 unsigned VReg0 = MIB->getOperand(0).getReg(); 184 (void)VReg0; 185 assert(MRI.getType(VReg0).getSizeInBits() == 32 && 186 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::GPRRegBankID && 187 "Unsupported operand for G_UNMERGE_VALUES"); 188 unsigned VReg1 = MIB->getOperand(1).getReg(); 189 (void)VReg1; 190 assert(MRI.getType(VReg1).getSizeInBits() == 32 && 191 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID && 192 "Unsupported operand for G_UNMERGE_VALUES"); 193 unsigned VReg2 = MIB->getOperand(2).getReg(); 194 (void)VReg2; 195 assert(MRI.getType(VReg2).getSizeInBits() == 64 && 196 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID && 197 "Unsupported operand for G_UNMERGE_VALUES"); 198 199 MIB->setDesc(TII.get(ARM::VMOVRRD)); 200 MIB.add(predOps(ARMCC::AL)); 201 202 return true; 203 } 204 205 /// Select the opcode for simple extensions (that translate to a single SXT/UXT 206 /// instruction). Extension operations more complicated than that should not 207 /// invoke this. Returns the original opcode if it doesn't know how to select a 208 /// better one. 209 static unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) { 210 using namespace TargetOpcode; 211 212 if (Size != 8 && Size != 16) 213 return Opc; 214 215 if (Opc == G_SEXT) 216 return Size == 8 ? ARM::SXTB : ARM::SXTH; 217 218 if (Opc == G_ZEXT) 219 return Size == 8 ? ARM::UXTB : ARM::UXTH; 220 221 return Opc; 222 } 223 224 /// Select the opcode for simple loads and stores. For types smaller than 32 225 /// bits, the value will be zero extended. Returns the original opcode if it 226 /// doesn't know how to select a better one. 227 static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned RegBank, 228 unsigned Size) { 229 bool isStore = Opc == TargetOpcode::G_STORE; 230 231 if (RegBank == ARM::GPRRegBankID) { 232 switch (Size) { 233 case 1: 234 case 8: 235 return isStore ? ARM::STRBi12 : ARM::LDRBi12; 236 case 16: 237 return isStore ? ARM::STRH : ARM::LDRH; 238 case 32: 239 return isStore ? ARM::STRi12 : ARM::LDRi12; 240 default: 241 return Opc; 242 } 243 } 244 245 if (RegBank == ARM::FPRRegBankID) { 246 switch (Size) { 247 case 32: 248 return isStore ? ARM::VSTRS : ARM::VLDRS; 249 case 64: 250 return isStore ? ARM::VSTRD : ARM::VLDRD; 251 default: 252 return Opc; 253 } 254 } 255 256 return Opc; 257 } 258 259 // When lowering comparisons, we sometimes need to perform two compares instead 260 // of just one. Get the condition codes for both comparisons. If only one is 261 // needed, the second member of the pair is ARMCC::AL. 262 static std::pair<ARMCC::CondCodes, ARMCC::CondCodes> 263 getComparePreds(CmpInst::Predicate Pred) { 264 std::pair<ARMCC::CondCodes, ARMCC::CondCodes> Preds = {ARMCC::AL, ARMCC::AL}; 265 switch (Pred) { 266 case CmpInst::FCMP_ONE: 267 Preds = {ARMCC::GT, ARMCC::MI}; 268 break; 269 case CmpInst::FCMP_UEQ: 270 Preds = {ARMCC::EQ, ARMCC::VS}; 271 break; 272 case CmpInst::ICMP_EQ: 273 case CmpInst::FCMP_OEQ: 274 Preds.first = ARMCC::EQ; 275 break; 276 case CmpInst::ICMP_SGT: 277 case CmpInst::FCMP_OGT: 278 Preds.first = ARMCC::GT; 279 break; 280 case CmpInst::ICMP_SGE: 281 case CmpInst::FCMP_OGE: 282 Preds.first = ARMCC::GE; 283 break; 284 case CmpInst::ICMP_UGT: 285 case CmpInst::FCMP_UGT: 286 Preds.first = ARMCC::HI; 287 break; 288 case CmpInst::FCMP_OLT: 289 Preds.first = ARMCC::MI; 290 break; 291 case CmpInst::ICMP_ULE: 292 case CmpInst::FCMP_OLE: 293 Preds.first = ARMCC::LS; 294 break; 295 case CmpInst::FCMP_ORD: 296 Preds.first = ARMCC::VC; 297 break; 298 case CmpInst::FCMP_UNO: 299 Preds.first = ARMCC::VS; 300 break; 301 case CmpInst::FCMP_UGE: 302 Preds.first = ARMCC::PL; 303 break; 304 case CmpInst::ICMP_SLT: 305 case CmpInst::FCMP_ULT: 306 Preds.first = ARMCC::LT; 307 break; 308 case CmpInst::ICMP_SLE: 309 case CmpInst::FCMP_ULE: 310 Preds.first = ARMCC::LE; 311 break; 312 case CmpInst::FCMP_UNE: 313 case CmpInst::ICMP_NE: 314 Preds.first = ARMCC::NE; 315 break; 316 case CmpInst::ICMP_UGE: 317 Preds.first = ARMCC::HS; 318 break; 319 case CmpInst::ICMP_ULT: 320 Preds.first = ARMCC::LO; 321 break; 322 default: 323 break; 324 } 325 assert(Preds.first != ARMCC::AL && "No comparisons needed?"); 326 return Preds; 327 } 328 329 template <typename T> struct ARMInstructionSelector::CmpHelper { 330 CmpHelper(const ARMInstructionSelector &Selector, MachineInstrBuilder &MIB, 331 const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, 332 const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI) 333 : MBB(*MIB->getParent()), InsertBefore(std::next(MIB->getIterator())), 334 DbgLoc(MIB->getDebugLoc()), TII(TII), MRI(MRI), TRI(TRI), RBI(RBI), 335 Selector(Selector) {} 336 337 // The opcode used for performing the comparison. 338 static const unsigned ComparisonOpcode; 339 340 // The opcode used for reading the flags set by the comparison. May be 341 // ARM::INSTRUCTION_LIST_END if we don't need to read the flags. 342 static const unsigned ReadFlagsOpcode; 343 344 // The opcode used for selecting the result register, based on the value 345 // of the flags. 346 static const unsigned SetResultOpcode = ARM::MOVCCi; 347 348 // The assumed register bank ID for the operands. 349 static const unsigned OperandRegBankID; 350 351 // The assumed register bank ID for the result. 352 static const unsigned ResultRegBankID = ARM::GPRRegBankID; 353 354 unsigned getZeroRegister() { 355 unsigned Reg = MRI.createVirtualRegister(&ARM::GPRRegClass); 356 putConstant(Reg, 0); 357 return Reg; 358 } 359 360 void putConstant(unsigned DestReg, unsigned Constant) { 361 (void)BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::MOVi)) 362 .addDef(DestReg) 363 .addImm(Constant) 364 .add(predOps(ARMCC::AL)) 365 .add(condCodeOp()); 366 } 367 368 bool insertComparison(unsigned ResReg, ARMCC::CondCodes Cond, unsigned LHSReg, 369 unsigned RHSReg, unsigned PrevRes) { 370 371 // Perform the comparison. 372 auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ComparisonOpcode)) 373 .addUse(LHSReg) 374 .addUse(RHSReg) 375 .add(predOps(ARMCC::AL)); 376 if (!Selector.constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI)) 377 return false; 378 379 // Read the comparison flags (if necessary). 380 if (ReadFlagsOpcode != ARM::INSTRUCTION_LIST_END) { 381 auto ReadI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ReadFlagsOpcode)) 382 .add(predOps(ARMCC::AL)); 383 if (!Selector.constrainSelectedInstRegOperands(*ReadI, TII, TRI, RBI)) 384 return false; 385 } 386 387 // Select either 1 or the previous result based on the value of the flags. 388 auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(SetResultOpcode)) 389 .addDef(ResReg) 390 .addUse(PrevRes) 391 .addImm(1) 392 .add(predOps(Cond, ARM::CPSR)); 393 if (!Selector.constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI)) 394 return false; 395 396 return true; 397 } 398 399 bool validateOpRegs(unsigned LHSReg, unsigned RHSReg) { 400 return MRI.getType(LHSReg) == MRI.getType(RHSReg) && 401 validateOpReg(LHSReg, MRI, TRI, RBI) && 402 validateOpReg(RHSReg, MRI, TRI, RBI); 403 } 404 405 bool validateResReg(unsigned ResReg) { 406 if (MRI.getType(ResReg).getSizeInBits() != 1) { 407 DEBUG(dbgs() << "Unsupported size for comparison operand"); 408 return false; 409 } 410 411 if (RBI.getRegBank(ResReg, MRI, TRI)->getID() != ResultRegBankID) { 412 DEBUG(dbgs() << "Unsupported register bank for comparison operand"); 413 return false; 414 } 415 416 return true; 417 } 418 419 private: 420 bool validateOpReg(unsigned OpReg, MachineRegisterInfo &MRI, 421 const TargetRegisterInfo &TRI, 422 const RegisterBankInfo &RBI) { 423 if (MRI.getType(OpReg).getSizeInBits() != 32) { 424 DEBUG(dbgs() << "Unsupported size for comparison operand"); 425 return false; 426 } 427 428 if (RBI.getRegBank(OpReg, MRI, TRI)->getID() != OperandRegBankID) { 429 DEBUG(dbgs() << "Unsupported register bank for comparison operand"); 430 return false; 431 } 432 433 return true; 434 } 435 436 MachineBasicBlock &MBB; 437 MachineBasicBlock::instr_iterator InsertBefore; 438 const DebugLoc &DbgLoc; 439 440 const ARMBaseInstrInfo &TII; 441 MachineRegisterInfo &MRI; 442 const TargetRegisterInfo &TRI; 443 const RegisterBankInfo &RBI; 444 445 const ARMInstructionSelector &Selector; 446 }; 447 448 // Specialize the opcode to be used for comparing different types of operands. 449 template <> 450 const unsigned ARMInstructionSelector::CmpHelper<int>::ComparisonOpcode = 451 ARM::CMPrr; 452 template <> 453 const unsigned ARMInstructionSelector::CmpHelper<float>::ComparisonOpcode = 454 ARM::VCMPS; 455 456 // Specialize the opcode to be used for reading the comparison flags for 457 // different types of operands. 458 template <> 459 const unsigned ARMInstructionSelector::CmpHelper<int>::ReadFlagsOpcode = 460 ARM::INSTRUCTION_LIST_END; 461 template <> 462 const unsigned ARMInstructionSelector::CmpHelper<float>::ReadFlagsOpcode = 463 ARM::FMSTAT; 464 465 // Specialize the register bank where the operands of the comparison are assumed 466 // to live. 467 template <> 468 const unsigned ARMInstructionSelector::CmpHelper<int>::OperandRegBankID = 469 ARM::GPRRegBankID; 470 template <> 471 const unsigned ARMInstructionSelector::CmpHelper<float>::OperandRegBankID = 472 ARM::FPRRegBankID; 473 474 template <typename T> 475 bool ARMInstructionSelector::selectCmp(MachineInstrBuilder &MIB, 476 const ARMBaseInstrInfo &TII, 477 MachineRegisterInfo &MRI, 478 const TargetRegisterInfo &TRI, 479 const RegisterBankInfo &RBI) const { 480 auto Helper = CmpHelper<T>(*this, MIB, TII, MRI, TRI, RBI); 481 482 auto ResReg = MIB->getOperand(0).getReg(); 483 if (!Helper.validateResReg(ResReg)) 484 return false; 485 486 auto Cond = 487 static_cast<CmpInst::Predicate>(MIB->getOperand(1).getPredicate()); 488 if (Cond == CmpInst::FCMP_TRUE || Cond == CmpInst::FCMP_FALSE) { 489 Helper.putConstant(ResReg, Cond == CmpInst::FCMP_TRUE ? 1 : 0); 490 MIB->eraseFromParent(); 491 return true; 492 } 493 494 auto LHSReg = MIB->getOperand(2).getReg(); 495 auto RHSReg = MIB->getOperand(3).getReg(); 496 if (!Helper.validateOpRegs(LHSReg, RHSReg)) 497 return false; 498 499 auto ARMConds = getComparePreds(Cond); 500 auto ZeroReg = Helper.getZeroRegister(); 501 502 if (ARMConds.second == ARMCC::AL) { 503 // Simple case, we only need one comparison and we're done. 504 if (!Helper.insertComparison(ResReg, ARMConds.first, LHSReg, RHSReg, 505 ZeroReg)) 506 return false; 507 } else { 508 // Not so simple, we need two successive comparisons. 509 auto IntermediateRes = MRI.createVirtualRegister(&ARM::GPRRegClass); 510 if (!Helper.insertComparison(IntermediateRes, ARMConds.first, LHSReg, 511 RHSReg, ZeroReg)) 512 return false; 513 if (!Helper.insertComparison(ResReg, ARMConds.second, LHSReg, RHSReg, 514 IntermediateRes)) 515 return false; 516 } 517 518 MIB->eraseFromParent(); 519 return true; 520 } 521 522 bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB, 523 const ARMBaseInstrInfo &TII, 524 MachineRegisterInfo &MRI, 525 const TargetRegisterInfo &TRI, 526 const RegisterBankInfo &RBI) const { 527 auto &MBB = *MIB->getParent(); 528 auto InsertBefore = std::next(MIB->getIterator()); 529 auto &DbgLoc = MIB->getDebugLoc(); 530 531 // Compare the condition to 0. 532 auto CondReg = MIB->getOperand(1).getReg(); 533 assert(MRI.getType(CondReg).getSizeInBits() == 1 && 534 RBI.getRegBank(CondReg, MRI, TRI)->getID() == ARM::GPRRegBankID && 535 "Unsupported types for select operation"); 536 auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::CMPri)) 537 .addUse(CondReg) 538 .addImm(0) 539 .add(predOps(ARMCC::AL)); 540 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI)) 541 return false; 542 543 // Move a value into the result register based on the result of the 544 // comparison. 545 auto ResReg = MIB->getOperand(0).getReg(); 546 auto TrueReg = MIB->getOperand(2).getReg(); 547 auto FalseReg = MIB->getOperand(3).getReg(); 548 assert(MRI.getType(ResReg) == MRI.getType(TrueReg) && 549 MRI.getType(TrueReg) == MRI.getType(FalseReg) && 550 MRI.getType(FalseReg).getSizeInBits() == 32 && 551 RBI.getRegBank(TrueReg, MRI, TRI)->getID() == ARM::GPRRegBankID && 552 RBI.getRegBank(FalseReg, MRI, TRI)->getID() == ARM::GPRRegBankID && 553 "Unsupported types for select operation"); 554 auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::MOVCCr)) 555 .addDef(ResReg) 556 .addUse(TrueReg) 557 .addUse(FalseReg) 558 .add(predOps(ARMCC::EQ, ARM::CPSR)); 559 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI)) 560 return false; 561 562 MIB->eraseFromParent(); 563 return true; 564 } 565 566 bool ARMInstructionSelector::select(MachineInstr &I) const { 567 assert(I.getParent() && "Instruction should be in a basic block!"); 568 assert(I.getParent()->getParent() && "Instruction should be in a function!"); 569 570 auto &MBB = *I.getParent(); 571 auto &MF = *MBB.getParent(); 572 auto &MRI = MF.getRegInfo(); 573 574 if (!isPreISelGenericOpcode(I.getOpcode())) { 575 if (I.isCopy()) 576 return selectCopy(I, TII, MRI, TRI, RBI); 577 578 return true; 579 } 580 581 if (selectImpl(I)) 582 return true; 583 584 MachineInstrBuilder MIB{MF, I}; 585 bool isSExt = false; 586 587 using namespace TargetOpcode; 588 switch (I.getOpcode()) { 589 case G_SEXT: 590 isSExt = true; 591 LLVM_FALLTHROUGH; 592 case G_ZEXT: { 593 LLT DstTy = MRI.getType(I.getOperand(0).getReg()); 594 // FIXME: Smaller destination sizes coming soon! 595 if (DstTy.getSizeInBits() != 32) { 596 DEBUG(dbgs() << "Unsupported destination size for extension"); 597 return false; 598 } 599 600 LLT SrcTy = MRI.getType(I.getOperand(1).getReg()); 601 unsigned SrcSize = SrcTy.getSizeInBits(); 602 switch (SrcSize) { 603 case 1: { 604 // ZExt boils down to & 0x1; for SExt we also subtract that from 0 605 I.setDesc(TII.get(ARM::ANDri)); 606 MIB.addImm(1).add(predOps(ARMCC::AL)).add(condCodeOp()); 607 608 if (isSExt) { 609 unsigned SExtResult = I.getOperand(0).getReg(); 610 611 // Use a new virtual register for the result of the AND 612 unsigned AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass); 613 I.getOperand(0).setReg(AndResult); 614 615 auto InsertBefore = std::next(I.getIterator()); 616 auto SubI = 617 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::RSBri)) 618 .addDef(SExtResult) 619 .addUse(AndResult) 620 .addImm(0) 621 .add(predOps(ARMCC::AL)) 622 .add(condCodeOp()); 623 if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI)) 624 return false; 625 } 626 break; 627 } 628 case 8: 629 case 16: { 630 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize); 631 if (NewOpc == I.getOpcode()) 632 return false; 633 I.setDesc(TII.get(NewOpc)); 634 MIB.addImm(0).add(predOps(ARMCC::AL)); 635 break; 636 } 637 default: 638 DEBUG(dbgs() << "Unsupported source size for extension"); 639 return false; 640 } 641 break; 642 } 643 case G_ANYEXT: 644 case G_TRUNC: { 645 // The high bits are undefined, so there's nothing special to do, just 646 // treat it as a copy. 647 auto SrcReg = I.getOperand(1).getReg(); 648 auto DstReg = I.getOperand(0).getReg(); 649 650 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI); 651 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI); 652 653 if (SrcRegBank.getID() != DstRegBank.getID()) { 654 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n"); 655 return false; 656 } 657 658 if (SrcRegBank.getID() != ARM::GPRRegBankID) { 659 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n"); 660 return false; 661 } 662 663 I.setDesc(TII.get(COPY)); 664 return selectCopy(I, TII, MRI, TRI, RBI); 665 } 666 case G_SELECT: 667 return selectSelect(MIB, TII, MRI, TRI, RBI); 668 case G_ICMP: 669 return selectCmp<int>(MIB, TII, MRI, TRI, RBI); 670 case G_FCMP: 671 assert(TII.getSubtarget().hasVFP2() && "Can't select fcmp without VFP"); 672 return selectCmp<float>(MIB, TII, MRI, TRI, RBI); 673 case G_GEP: 674 I.setDesc(TII.get(ARM::ADDrr)); 675 MIB.add(predOps(ARMCC::AL)).add(condCodeOp()); 676 break; 677 case G_FRAME_INDEX: 678 // Add 0 to the given frame index and hope it will eventually be folded into 679 // the user(s). 680 I.setDesc(TII.get(ARM::ADDri)); 681 MIB.addImm(0).add(predOps(ARMCC::AL)).add(condCodeOp()); 682 break; 683 case G_CONSTANT: { 684 unsigned Reg = I.getOperand(0).getReg(); 685 if (MRI.getType(Reg).getSizeInBits() != 32) 686 return false; 687 688 assert(RBI.getRegBank(Reg, MRI, TRI)->getID() == ARM::GPRRegBankID && 689 "Expected constant to live in a GPR"); 690 I.setDesc(TII.get(ARM::MOVi)); 691 MIB.add(predOps(ARMCC::AL)).add(condCodeOp()); 692 693 auto &Val = I.getOperand(1); 694 if (Val.isCImm()) { 695 if (Val.getCImm()->getBitWidth() > 32) 696 return false; 697 Val.ChangeToImmediate(Val.getCImm()->getZExtValue()); 698 } 699 700 if (!Val.isImm()) { 701 return false; 702 } 703 704 break; 705 } 706 case G_STORE: 707 case G_LOAD: { 708 const auto &MemOp = **I.memoperands_begin(); 709 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) { 710 DEBUG(dbgs() << "Atomic load/store not supported yet\n"); 711 return false; 712 } 713 714 unsigned Reg = I.getOperand(0).getReg(); 715 unsigned RegBank = RBI.getRegBank(Reg, MRI, TRI)->getID(); 716 717 LLT ValTy = MRI.getType(Reg); 718 const auto ValSize = ValTy.getSizeInBits(); 719 720 assert((ValSize != 64 || TII.getSubtarget().hasVFP2()) && 721 "Don't know how to load/store 64-bit value without VFP"); 722 723 const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize); 724 if (NewOpc == G_LOAD || NewOpc == G_STORE) 725 return false; 726 727 I.setDesc(TII.get(NewOpc)); 728 729 if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH) 730 // LDRH has a funny addressing mode (there's already a FIXME for it). 731 MIB.addReg(0); 732 MIB.addImm(0).add(predOps(ARMCC::AL)); 733 break; 734 } 735 case G_MERGE_VALUES: { 736 if (!selectMergeValues(MIB, TII, MRI, TRI, RBI)) 737 return false; 738 break; 739 } 740 case G_UNMERGE_VALUES: { 741 if (!selectUnmergeValues(MIB, TII, MRI, TRI, RBI)) 742 return false; 743 break; 744 } 745 default: 746 return false; 747 } 748 749 return constrainSelectedInstRegOperands(I, TII, TRI, RBI); 750 } 751