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