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