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 if (TM.isPositionIndependent()) { 496 DEBUG(dbgs() << "PIC not supported yet\n"); 497 return false; 498 } 499 500 auto GV = MIB->getOperand(1).getGlobal(); 501 if (GV->isThreadLocal()) { 502 DEBUG(dbgs() << "TLS variables not supported yet\n"); 503 return false; 504 } 505 506 auto &MBB = *MIB->getParent(); 507 auto &MF = *MBB.getParent(); 508 509 auto ObjectFormat = TII.getSubtarget().getTargetTriple().getObjectFormat(); 510 bool UseMovt = TII.getSubtarget().useMovt(MF); 511 512 if (ObjectFormat == Triple::ELF) { 513 if (UseMovt) { 514 MIB->setDesc(TII.get(ARM::MOVi32imm)); 515 } else { 516 // Load the global's address from the constant pool. 517 MIB->setDesc(TII.get(ARM::LDRi12)); 518 MIB->RemoveOperand(1); 519 unsigned Alignment = 4; 520 MIB.addConstantPoolIndex( 521 MF.getConstantPool()->getConstantPoolIndex(GV, Alignment), 522 /* Offset */ 0, /* TargetFlags */ 0) 523 .addMemOperand(MF.getMachineMemOperand( 524 MachinePointerInfo::getConstantPool(MF), 525 MachineMemOperand::MOLoad, TM.getPointerSize(), Alignment)) 526 .addImm(0) 527 .add(predOps(ARMCC::AL)); 528 } 529 } else if (ObjectFormat == Triple::MachO) { 530 if (UseMovt) 531 MIB->setDesc(TII.get(ARM::MOVi32imm)); 532 else 533 MIB->setDesc(TII.get(ARM::LDRLIT_ga_abs)); 534 } else { 535 DEBUG(dbgs() << "Object format not supported yet\n"); 536 return false; 537 } 538 539 return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI); 540 } 541 542 bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB, 543 MachineRegisterInfo &MRI) const { 544 auto &MBB = *MIB->getParent(); 545 auto InsertBefore = std::next(MIB->getIterator()); 546 auto &DbgLoc = MIB->getDebugLoc(); 547 548 // Compare the condition to 0. 549 auto CondReg = MIB->getOperand(1).getReg(); 550 assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) && 551 "Unsupported types for select operation"); 552 auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::CMPri)) 553 .addUse(CondReg) 554 .addImm(0) 555 .add(predOps(ARMCC::AL)); 556 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI)) 557 return false; 558 559 // Move a value into the result register based on the result of the 560 // comparison. 561 auto ResReg = MIB->getOperand(0).getReg(); 562 auto TrueReg = MIB->getOperand(2).getReg(); 563 auto FalseReg = MIB->getOperand(3).getReg(); 564 assert(validOpRegPair(MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) && 565 validOpRegPair(MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) && 566 "Unsupported types for select operation"); 567 auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(ARM::MOVCCr)) 568 .addDef(ResReg) 569 .addUse(TrueReg) 570 .addUse(FalseReg) 571 .add(predOps(ARMCC::EQ, ARM::CPSR)); 572 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI)) 573 return false; 574 575 MIB->eraseFromParent(); 576 return true; 577 } 578 579 bool ARMInstructionSelector::select(MachineInstr &I) const { 580 assert(I.getParent() && "Instruction should be in a basic block!"); 581 assert(I.getParent()->getParent() && "Instruction should be in a function!"); 582 583 auto &MBB = *I.getParent(); 584 auto &MF = *MBB.getParent(); 585 auto &MRI = MF.getRegInfo(); 586 587 if (!isPreISelGenericOpcode(I.getOpcode())) { 588 if (I.isCopy()) 589 return selectCopy(I, TII, MRI, TRI, RBI); 590 591 return true; 592 } 593 594 if (selectImpl(I)) 595 return true; 596 597 MachineInstrBuilder MIB{MF, I}; 598 bool isSExt = false; 599 600 using namespace TargetOpcode; 601 switch (I.getOpcode()) { 602 case G_SEXT: 603 isSExt = true; 604 LLVM_FALLTHROUGH; 605 case G_ZEXT: { 606 LLT DstTy = MRI.getType(I.getOperand(0).getReg()); 607 // FIXME: Smaller destination sizes coming soon! 608 if (DstTy.getSizeInBits() != 32) { 609 DEBUG(dbgs() << "Unsupported destination size for extension"); 610 return false; 611 } 612 613 LLT SrcTy = MRI.getType(I.getOperand(1).getReg()); 614 unsigned SrcSize = SrcTy.getSizeInBits(); 615 switch (SrcSize) { 616 case 1: { 617 // ZExt boils down to & 0x1; for SExt we also subtract that from 0 618 I.setDesc(TII.get(ARM::ANDri)); 619 MIB.addImm(1).add(predOps(ARMCC::AL)).add(condCodeOp()); 620 621 if (isSExt) { 622 unsigned SExtResult = I.getOperand(0).getReg(); 623 624 // Use a new virtual register for the result of the AND 625 unsigned AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass); 626 I.getOperand(0).setReg(AndResult); 627 628 auto InsertBefore = std::next(I.getIterator()); 629 auto SubI = 630 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::RSBri)) 631 .addDef(SExtResult) 632 .addUse(AndResult) 633 .addImm(0) 634 .add(predOps(ARMCC::AL)) 635 .add(condCodeOp()); 636 if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI)) 637 return false; 638 } 639 break; 640 } 641 case 8: 642 case 16: { 643 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize); 644 if (NewOpc == I.getOpcode()) 645 return false; 646 I.setDesc(TII.get(NewOpc)); 647 MIB.addImm(0).add(predOps(ARMCC::AL)); 648 break; 649 } 650 default: 651 DEBUG(dbgs() << "Unsupported source size for extension"); 652 return false; 653 } 654 break; 655 } 656 case G_ANYEXT: 657 case G_TRUNC: { 658 // The high bits are undefined, so there's nothing special to do, just 659 // treat it as a copy. 660 auto SrcReg = I.getOperand(1).getReg(); 661 auto DstReg = I.getOperand(0).getReg(); 662 663 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI); 664 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI); 665 666 if (SrcRegBank.getID() != DstRegBank.getID()) { 667 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n"); 668 return false; 669 } 670 671 if (SrcRegBank.getID() != ARM::GPRRegBankID) { 672 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n"); 673 return false; 674 } 675 676 I.setDesc(TII.get(COPY)); 677 return selectCopy(I, TII, MRI, TRI, RBI); 678 } 679 case G_SELECT: 680 return selectSelect(MIB, MRI); 681 case G_ICMP: { 682 CmpConstants Helper(ARM::CMPrr, ARM::INSTRUCTION_LIST_END, 683 ARM::GPRRegBankID, 32); 684 return selectCmp(Helper, MIB, MRI); 685 } 686 case G_FCMP: { 687 assert(TII.getSubtarget().hasVFP2() && "Can't select fcmp without VFP"); 688 689 unsigned OpReg = I.getOperand(2).getReg(); 690 unsigned Size = MRI.getType(OpReg).getSizeInBits(); 691 692 if (Size == 64 && TII.getSubtarget().isFPOnlySP()) { 693 DEBUG(dbgs() << "Subtarget only supports single precision"); 694 return false; 695 } 696 if (Size != 32 && Size != 64) { 697 DEBUG(dbgs() << "Unsupported size for G_FCMP operand"); 698 return false; 699 } 700 701 CmpConstants Helper(Size == 32 ? ARM::VCMPS : ARM::VCMPD, ARM::FMSTAT, 702 ARM::FPRRegBankID, Size); 703 return selectCmp(Helper, MIB, MRI); 704 } 705 case G_GEP: 706 I.setDesc(TII.get(ARM::ADDrr)); 707 MIB.add(predOps(ARMCC::AL)).add(condCodeOp()); 708 break; 709 case G_FRAME_INDEX: 710 // Add 0 to the given frame index and hope it will eventually be folded into 711 // the user(s). 712 I.setDesc(TII.get(ARM::ADDri)); 713 MIB.addImm(0).add(predOps(ARMCC::AL)).add(condCodeOp()); 714 break; 715 case G_CONSTANT: { 716 unsigned Reg = I.getOperand(0).getReg(); 717 718 if (!validReg(MRI, Reg, 32, ARM::GPRRegBankID)) 719 return false; 720 721 I.setDesc(TII.get(ARM::MOVi)); 722 MIB.add(predOps(ARMCC::AL)).add(condCodeOp()); 723 724 auto &Val = I.getOperand(1); 725 if (Val.isCImm()) { 726 if (Val.getCImm()->getBitWidth() > 32) 727 return false; 728 Val.ChangeToImmediate(Val.getCImm()->getZExtValue()); 729 } 730 731 if (!Val.isImm()) { 732 return false; 733 } 734 735 break; 736 } 737 case G_GLOBAL_VALUE: 738 return selectGlobal(MIB, MRI); 739 case G_STORE: 740 case G_LOAD: { 741 const auto &MemOp = **I.memoperands_begin(); 742 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) { 743 DEBUG(dbgs() << "Atomic load/store not supported yet\n"); 744 return false; 745 } 746 747 unsigned Reg = I.getOperand(0).getReg(); 748 unsigned RegBank = RBI.getRegBank(Reg, MRI, TRI)->getID(); 749 750 LLT ValTy = MRI.getType(Reg); 751 const auto ValSize = ValTy.getSizeInBits(); 752 753 assert((ValSize != 64 || TII.getSubtarget().hasVFP2()) && 754 "Don't know how to load/store 64-bit value without VFP"); 755 756 const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize); 757 if (NewOpc == G_LOAD || NewOpc == G_STORE) 758 return false; 759 760 I.setDesc(TII.get(NewOpc)); 761 762 if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH) 763 // LDRH has a funny addressing mode (there's already a FIXME for it). 764 MIB.addReg(0); 765 MIB.addImm(0).add(predOps(ARMCC::AL)); 766 break; 767 } 768 case G_MERGE_VALUES: { 769 if (!selectMergeValues(MIB, TII, MRI, TRI, RBI)) 770 return false; 771 break; 772 } 773 case G_UNMERGE_VALUES: { 774 if (!selectUnmergeValues(MIB, TII, MRI, TRI, RBI)) 775 return false; 776 break; 777 } 778 case G_BRCOND: { 779 if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) { 780 DEBUG(dbgs() << "Unsupported condition register for G_BRCOND"); 781 return false; 782 } 783 784 // Set the flags. 785 auto Test = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ARM::TSTri)) 786 .addReg(I.getOperand(0).getReg()) 787 .addImm(1) 788 .add(predOps(ARMCC::AL)); 789 if (!constrainSelectedInstRegOperands(*Test, TII, TRI, RBI)) 790 return false; 791 792 // Branch conditionally. 793 auto Branch = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ARM::Bcc)) 794 .add(I.getOperand(1)) 795 .add(predOps(ARMCC::EQ, ARM::CPSR)); 796 if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI)) 797 return false; 798 I.eraseFromParent(); 799 return true; 800 } 801 default: 802 return false; 803 } 804 805 return constrainSelectedInstRegOperands(I, TII, TRI, RBI); 806 } 807