LLVM: lib/Target/ARM/ARMInstructionSelector.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

22

23#define DEBUG_TYPE "arm-isel"

24

25using namespace llvm;

26

27namespace {

28

29#define GET_GLOBALISEL_PREDICATE_BITSET

30#include "ARMGenGlobalISel.inc"

31#undef GET_GLOBALISEL_PREDICATE_BITSET

32

34public:

37

40

41private:

43

44 struct CmpConstants;

45 struct InsertInfo;

46

49

50

51

52

53 bool insertComparison(CmpConstants Helper, InsertInfo I, unsigned ResReg,

55 unsigned PrevRes) const;

56

57

58 void putConstant(InsertInfo I, unsigned DestReg, unsigned Constant) const;

59

63

64

65

67 unsigned ExpectedSize, unsigned ExpectedRegBankID) const;

68

69

71 unsigned ExpectedRegBankID) const;

72

78

79

80

81

83

84

85

86 struct OpcodeCache {

87 unsigned ZEXT16;

88 unsigned SEXT16;

89

90 unsigned ZEXT8;

91 unsigned SEXT8;

92

93

94 unsigned AND;

95 unsigned RSB;

96

97 unsigned STORE32;

98 unsigned LOAD32;

99

100 unsigned STORE16;

101 unsigned LOAD16;

102

103 unsigned STORE8;

104 unsigned LOAD8;

105

106 unsigned ADDrr;

107 unsigned ADDri;

108

109

110 unsigned CMPrr;

111 unsigned MOVi;

112 unsigned MOVCCi;

113

114

115 unsigned MOVCCr;

116

117 unsigned TSTri;

118 unsigned Bcc;

119

120

121 unsigned MOVi32imm;

122 unsigned ConstPoolLoad;

123 unsigned MOV_ga_pcrel;

124 unsigned LDRLIT_ga_pcrel;

125 unsigned LDRLIT_ga_abs;

126

128 } const Opcodes;

129

130

131

132

133

134 unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) const;

135

136

137

138 unsigned selectLoadStoreOpCode(unsigned Opc, unsigned RegBank,

139 unsigned Size) const;

140

142 int OpIdx = -1) const;

144 int OpIdx = -1) const;

146 int OpIdx = -1) const;

147

148#define GET_GLOBALISEL_PREDICATES_DECL

149#include "ARMGenGlobalISel.inc"

150#undef GET_GLOBALISEL_PREDICATES_DECL

151

152

153

154#define GET_GLOBALISEL_TEMPORARIES_DECL

155#include "ARMGenGlobalISel.inc"

156#undef GET_GLOBALISEL_TEMPORARIES_DECL

157};

158}

159

160namespace llvm {

165 return new ARMInstructionSelector(TM, STI, RBI);

166}

167}

168

169#define GET_GLOBALISEL_IMPL

170#include "ARMGenGlobalISel.inc"

171#undef GET_GLOBALISEL_IMPL

172

173ARMInstructionSelector::ARMInstructionSelector(const ARMBaseTargetMachine &TM,

176 : TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), TM(TM), RBI(RBI),

177 STI(STI), Opcodes(STI),

179#include "ARMGenGlobalISel.inc"

182#include "ARMGenGlobalISel.inc"

184{

185}

186

192 assert(RegBank && "Can't get reg bank for virtual register");

193

194 const unsigned Size = MRI.getType(Reg).getSizeInBits();

195 assert((RegBank->getID() == ARM::GPRRegBankID ||

196 RegBank->getID() == ARM::FPRRegBankID) &&

197 "Unsupported reg bank");

198

199 if (RegBank->getID() == ARM::FPRRegBankID) {

200 if (Size == 32)

201 return &ARM::SPRRegClass;

202 else if (Size == 64)

203 return &ARM::DPRRegClass;

204 else if (Size == 128)

205 return &ARM::QPRRegClass;

206 else

208 }

209

210 return &ARM::GPRRegClass;

211}

212

216 Register DstReg = I.getOperand(0).getReg();

218 return true;

219

221

222

223

224

226 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())

227 << " operand\n");

228 return false;

229 }

230 return true;

231}

232

238 assert(TII.getSubtarget().hasVFP2Base() && "Can't select merge without VFP");

239

240

241

243 (void)VReg0;

244 assert(MRI.getType(VReg0).getSizeInBits() == 64 &&

246 "Unsupported operand for G_MERGE_VALUES");

248 (void)VReg1;

249 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&

251 "Unsupported operand for G_MERGE_VALUES");

253 (void)VReg2;

254 assert(MRI.getType(VReg2).getSizeInBits() == 32 &&

256 "Unsupported operand for G_MERGE_VALUES");

257

260

261 return true;

262}

263

269 assert(TII.getSubtarget().hasVFP2Base() &&

270 "Can't select unmerge without VFP");

271

272

273

275 (void)VReg0;

276 assert(MRI.getType(VReg0).getSizeInBits() == 32 &&

278 "Unsupported operand for G_UNMERGE_VALUES");

280 (void)VReg1;

281 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&

283 "Unsupported operand for G_UNMERGE_VALUES");

285 (void)VReg2;

286 assert(MRI.getType(VReg2).getSizeInBits() == 64 &&

288 "Unsupported operand for G_UNMERGE_VALUES");

289

292

293 return true;

294}

295

296ARMInstructionSelector::OpcodeCache::OpcodeCache(const ARMSubtarget &STI) {

297 bool isThumb = STI.isThumb();

298

299 using namespace TargetOpcode;

300

301#define STORE_OPCODE(VAR, OPC) VAR = isThumb ? ARM::t2##OPC : ARM::OPC

304

307

310

313

314

315 STORE16 = isThumb ? ARM::t2STRHi12 : ARM::STRH;

316 LOAD16 = isThumb ? ARM::t2LDRHi12 : ARM::LDRH;

317

320

323

327

329

332

334 ConstPoolLoad = isThumb ? ARM::t2LDRpci : ARM::LDRi12;

336 LDRLIT_ga_pcrel = isThumb ? ARM::tLDRLIT_ga_pcrel : ARM::LDRLIT_ga_pcrel;

337 LDRLIT_ga_abs = isThumb ? ARM::tLDRLIT_ga_abs : ARM::LDRLIT_ga_abs;

338#undef MAP_OPCODE

339}

340

341unsigned ARMInstructionSelector::selectSimpleExtOpc(unsigned Opc,

342 unsigned Size) const {

343 using namespace TargetOpcode;

344

346 return Opc;

347

348 if (Opc == G_SEXT)

349 return Size == 8 ? Opcodes.SEXT8 : Opcodes.SEXT16;

350

351 if (Opc == G_ZEXT)

352 return Size == 8 ? Opcodes.ZEXT8 : Opcodes.ZEXT16;

353

354 return Opc;

355}

356

357unsigned ARMInstructionSelector::selectLoadStoreOpCode(unsigned Opc,

358 unsigned RegBank,

359 unsigned Size) const {

360 bool isStore = Opc == TargetOpcode::G_STORE;

361

362 if (RegBank == ARM::GPRRegBankID) {

363 switch (Size) {

364 case 1:

365 case 8:

366 return isStore ? Opcodes.STORE8 : Opcodes.LOAD8;

367 case 16:

368 return isStore ? Opcodes.STORE16 : Opcodes.LOAD16;

369 case 32:

370 return isStore ? Opcodes.STORE32 : Opcodes.LOAD32;

371 default:

372 return Opc;

373 }

374 }

375

376 if (RegBank == ARM::FPRRegBankID) {

377 switch (Size) {

378 case 32:

379 return isStore ? ARM::VSTRS : ARM::VLDRS;

380 case 64:

381 return isStore ? ARM::VSTRD : ARM::VLDRD;

382 default:

383 return Opc;

384 }

385 }

386

387 return Opc;

388}

389

390

391

392

393static std::pair<ARMCC::CondCodes, ARMCC::CondCodes>

395 std::pair<ARMCC::CondCodes, ARMCC::CondCodes> Preds = {ARMCC::AL, ARMCC::AL};

396 switch (Pred) {

399 break;

402 break;

406 break;

410 break;

414 break;

418 break;

421 break;

425 break;

428 break;

431 break;

434 break;

438 break;

442 break;

446 break;

449 break;

452 break;

453 default:

454 break;

455 }

456 assert(Preds.first != ARMCC::AL && "No comparisons needed?");

457 return Preds;

458}

459

461 CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned SelectOpcode,

462 unsigned OpRegBank, unsigned OpSize)

466

467

469

470

471

473

474

476

477

479

480

482};

483

493

494void ARMInstructionSelector::putConstant(InsertInfo I, unsigned DestReg,

496 (void)BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Opcodes.MOVi))

501}

502

504 unsigned LHSReg, unsigned RHSReg,

505 unsigned ExpectedSize,

506 unsigned ExpectedRegBankID) const {

507 return MRI.getType(LHSReg) == MRI.getType(RHSReg) &&

508 validReg(MRI, LHSReg, ExpectedSize, ExpectedRegBankID) &&

509 validReg(MRI, RHSReg, ExpectedSize, ExpectedRegBankID);

510}

511

512bool ARMInstructionSelector::validReg(MachineRegisterInfo &MRI, unsigned Reg,

513 unsigned ExpectedSize,

514 unsigned ExpectedRegBankID) const {

515 if (MRI.getType(Reg).getSizeInBits() != ExpectedSize) {

516 LLVM_DEBUG(dbgs() << "Unexpected size for register");

517 return false;

518 }

519

521 LLVM_DEBUG(dbgs() << "Unexpected register bank for register");

522 return false;

523 }

524

525 return true;

526}

527

528bool ARMInstructionSelector::selectCmp(CmpConstants Helper,

529 MachineInstrBuilder &MIB,

530 MachineRegisterInfo &MRI) const {

531 const InsertInfo I(MIB);

532

533 auto ResReg = MIB.getReg(0);

534 if (!validReg(MRI, ResReg, 1, ARM::GPRRegBankID))

535 return false;

536

542 return true;

543 }

544

545 auto LHSReg = MIB.getReg(2);

546 auto RHSReg = MIB.getReg(3);

547 if (!validOpRegPair(MRI, LHSReg, RHSReg, Helper.OperandSize,

548 Helper.OperandRegBankID))

549 return false;

550

552 auto ZeroReg = MRI.createVirtualRegister(&ARM::GPRRegClass);

553 putConstant(I, ZeroReg, 0);

554

555 if (ARMConds.second == ARMCC::AL) {

556

557 if (!insertComparison(Helper, I, ResReg, ARMConds.first, LHSReg, RHSReg,

558 ZeroReg))

559 return false;

560 } else {

561

562 auto IntermediateRes = MRI.createVirtualRegister(&ARM::GPRRegClass);

563 if (!insertComparison(Helper, I, IntermediateRes, ARMConds.first, LHSReg,

564 RHSReg, ZeroReg))

565 return false;

566 if (!insertComparison(Helper, I, ResReg, ARMConds.second, LHSReg, RHSReg,

567 IntermediateRes))

568 return false;

569 }

570

572 return true;

573}

574

575bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo I,

576 unsigned ResReg,

578 unsigned LHSReg, unsigned RHSReg,

579 unsigned PrevRes) const {

580

581 auto CmpI =

582 BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Helper.ComparisonOpcode))

587 return false;

588

589

590 if (Helper.ReadFlagsOpcode != ARM::INSTRUCTION_LIST_END) {

591 auto ReadI = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,

592 TII.get(Helper.ReadFlagsOpcode))

595 return false;

596 }

597

598

599 auto Mov1I = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,

600 TII.get(Helper.SelectResultOpcode))

606 return false;

607

608 return true;

609}

610

611bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,

612 MachineRegisterInfo &MRI) const {

614 LLVM_DEBUG(dbgs() << "ROPI and RWPI only supported for ELF\n");

615 return false;

616 }

617

619 if (GV->isThreadLocal()) {

620 LLVM_DEBUG(dbgs() << "TLS variables not supported yet\n");

621 return false;

622 }

623

626

627 bool UseMovt = STI.useMovt();

628

630 const Align Alignment(4);

631

632 auto addOpsForConstantPoolLoad = [&MF, Alignment, PtrTy](

633 MachineInstrBuilder &MIB,

634 const GlobalValue *GV, bool IsSBREL) {

635 assert((MIB->getOpcode() == ARM::LDRi12 ||

636 MIB->getOpcode() == ARM::t2LDRpci) &&

637 "Unsupported instruction");

638 auto ConstPool = MF.getConstantPool();

639 auto CPIndex =

640

641

642 IsSBREL

643 ? ConstPool->getConstantPoolIndex(

645 : ConstPool->getConstantPoolIndex(GV, Alignment);

646 MIB.addConstantPoolIndex(CPIndex, 0, 0)

647 .addMemOperand(MF.getMachineMemOperand(

649 PtrTy, Alignment));

650 if (MIB->getOpcode() == ARM::LDRi12)

651 MIB.addImm(0);

653 };

654

655 auto addGOTMemOperand = [this, &MF, Alignment](MachineInstrBuilder &MIB) {

656 MIB.addMemOperand(MF.getMachineMemOperand(

659 };

660

663

664

665

666

667

668

669 bool UseOpcodeThatLoads = Indirect && !STI.isThumb();

670

671

672

673 unsigned Opc =

675 ? (UseOpcodeThatLoads ? (unsigned)ARM::MOV_ga_pcrel_ldr

676 : Opcodes.MOV_ga_pcrel)

677 : (UseOpcodeThatLoads ? (unsigned)ARM::LDRLIT_ga_pcrel_ldr

678 : Opcodes.LDRLIT_ga_pcrel);

680

686 MIB->getOperand(1).setTargetFlags(TargetFlags);

687

688 if (Indirect) {

689 if (!UseOpcodeThatLoads) {

690 auto ResultReg = MIB.getReg(0);

691 auto AddressReg = MRI.createVirtualRegister(&ARM::GPRRegClass);

692

693 MIB->getOperand(0).setReg(AddressReg);

694

695 auto InsertBefore = std::next(MIB->getIterator());

696 auto MIBLoad = BuildMI(MBB, InsertBefore, MIB->getDebugLoc(),

697 TII.get(Opcodes.LOAD32))

702 addGOTMemOperand(MIBLoad);

703

705 return false;

706 } else {

707 addGOTMemOperand(MIB);

708 }

709 }

710

712 }

713

715 if (STI.isROPI() && isReadOnly) {

716 unsigned Opc = UseMovt ? Opcodes.MOV_ga_pcrel : Opcodes.LDRLIT_ga_pcrel;

719 }

720 if (STI.isRWPI() && !isReadOnly) {

721 auto Offset = MRI.createVirtualRegister(&ARM::GPRRegClass);

722 MachineInstrBuilder OffsetMIB;

723 if (UseMovt) {

724 OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),

727 } else {

728

729 OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),

731 addOpsForConstantPoolLoad(OffsetMIB, GV, true);

732 }

734 return false;

735

736

737 MIB->setDesc(TII.get(Opcodes.ADDrr));

738 MIB->removeOperand(1);

739 MIB.addReg(ARM::R9)

743

745 }

746

748 if (UseMovt) {

749 MIB->setDesc(TII.get(Opcodes.MOVi32imm));

750 } else {

751

752 MIB->setDesc(TII.get(Opcodes.ConstPoolLoad));

753 MIB->removeOperand(1);

754 addOpsForConstantPoolLoad(MIB, GV, false);

755 }

757 if (UseMovt)

758 MIB->setDesc(TII.get(Opcodes.MOVi32imm));

759 else

760 MIB->setDesc(TII.get(Opcodes.LDRLIT_ga_abs));

761 } else {

762 LLVM_DEBUG(dbgs() << "Object format not supported yet\n");

763 return false;

764 }

765

767}

768

769bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,

770 MachineRegisterInfo &MRI) const {

772 auto InsertBefore = std::next(MIB->getIterator());

774

775

776 auto CondReg = MIB.getReg(1);

777 assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) &&

778 "Unsupported types for select operation");

779 auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(Opcodes.TSTri))

784 return false;

785

786

787

788 auto ResReg = MIB.getReg(0);

789 auto TrueReg = MIB.getReg(2);

790 auto FalseReg = MIB.getReg(3);

791 assert(validOpRegPair(MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) &&

792 validOpRegPair(MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) &&

793 "Unsupported types for select operation");

794 auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(Opcodes.MOVCCr))

800 return false;

801

803 return true;

804}

805

806bool ARMInstructionSelector::selectShift(unsigned ShiftOpc,

807 MachineInstrBuilder &MIB) const {

808 assert(!STI.isThumb() && "Unsupported subtarget");

810 MIB.addImm(ShiftOpc);

813}

814

815void ARMInstructionSelector::renderVFPF32Imm(

816 MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst,

817 int OpIdx) const {

818 assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&

819 OpIdx == -1 && "Expected G_FCONSTANT");

820

823 assert(FPImmEncoding != -1 && "Invalid immediate value");

824

825 NewInstBuilder.addImm(FPImmEncoding);

826}

827

828void ARMInstructionSelector::renderVFPF64Imm(

829 MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst, int OpIdx) const {

830 assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&

831 OpIdx == -1 && "Expected G_FCONSTANT");

832

835 assert(FPImmEncoding != -1 && "Invalid immediate value");

836

837 NewInstBuilder.addImm(FPImmEncoding);

838}

839

840void ARMInstructionSelector::renderInvertedImm(MachineInstrBuilder &MIB,

841 const MachineInstr &MI,

842 int OpIdx) const {

843 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&

844 "Expected G_CONSTANT");

845 int64_t CVal = MI.getOperand(1).getCImm()->getSExtValue();

847}

848

849bool ARMInstructionSelector::select(MachineInstr &I) {

850 assert(I.getParent() && "Instruction should be in a basic block!");

851 assert(I.getParent()->getParent() && "Instruction should be in a function!");

852

855 auto &MRI = MF.getRegInfo();

856

858 if (I.isCopy())

860

861 return true;

862 }

863

864 using namespace TargetOpcode;

865

866 if (selectImpl(I, *CoverageInfo))

867 return true;

868

869 MachineInstrBuilder MIB{MF, I};

870 bool isSExt = false;

871

872 switch (I.getOpcode()) {

873 case G_SEXT:

874 isSExt = true;

875 [[fallthrough]];

876 case G_ZEXT: {

877 assert(MRI.getType(I.getOperand(0).getReg()).getSizeInBits() <= 32 &&

878 "Unsupported destination size for extension");

879

880 LLT SrcTy = MRI.getType(I.getOperand(1).getReg());

882 switch (SrcSize) {

883 case 1: {

884

885 I.setDesc(TII.get(Opcodes.AND));

887

888 if (isSExt) {

889 Register SExtResult = I.getOperand(0).getReg();

890

891

892 Register AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass);

893 I.getOperand(0).setReg(AndResult);

894

895 auto InsertBefore = std::next(I.getIterator());

896 auto SubI =

897 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(Opcodes.RSB))

904 return false;

905 }

906 break;

907 }

908 case 8:

909 case 16: {

910 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);

911 if (NewOpc == I.getOpcode())

912 return false;

913 I.setDesc(TII.get(NewOpc));

915 break;

916 }

917 default:

918 LLVM_DEBUG(dbgs() << "Unsupported source size for extension");

919 return false;

920 }

921 break;

922 }

923 case G_ANYEXT:

924 case G_TRUNC: {

925

926

927 auto SrcReg = I.getOperand(1).getReg();

928 auto DstReg = I.getOperand(0).getReg();

929

932

933 if (SrcRegBank.getID() == ARM::FPRRegBankID) {

934

935

936

937 assert(I.getOpcode() == G_TRUNC && "Unsupported operand for G_ANYEXT");

938 assert(DstRegBank.getID() == ARM::GPRRegBankID &&

939 "Unsupported combination of register banks");

940 assert(MRI.getType(SrcReg).getSizeInBits() == 64 && "Unsupported size");

941 assert(MRI.getType(DstReg).getSizeInBits() <= 32 && "Unsupported size");

942

943 Register IgnoredBits = MRI.createVirtualRegister(&ARM::GPRRegClass);

944 auto InsertBefore = std::next(I.getIterator());

945 auto MovI =

946 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::VMOVRRD))

952 return false;

953

955 return true;

956 }

957

958 if (SrcRegBank.getID() != DstRegBank.getID()) {

960 dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");

961 return false;

962 }

963

964 if (SrcRegBank.getID() != ARM::GPRRegBankID) {

965 LLVM_DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");

966 return false;

967 }

968

969 I.setDesc(TII.get(COPY));

971 }

972 case G_CONSTANT: {

973 if (MRI.getType(I.getOperand(0).getReg()).isPointer()) {

974

976 return false;

977 }

978

979 auto &Val = I.getOperand(1);

980 if (Val.isCImm()) {

981 if (!Val.getCImm()->isZero()) {

982 LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");

983 return false;

984 }

985 Val.ChangeToImmediate(0);

986 } else {

987 assert(Val.isImm() && "Unexpected operand for G_CONSTANT");

988 if (Val.getImm() != 0) {

989 LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");

990 return false;

991 }

992 }

993

994 assert(!STI.isThumb() && "Unsupported subtarget");

995 I.setDesc(TII.get(ARM::MOVi));

997 break;

998 }

999 case G_FCONSTANT: {

1000

1001 unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits() / 8;

1003

1004 assert((Size == 4 || Size == 8) && "Unsupported FP constant type");

1005 auto LoadOpcode = Size == 4 ? ARM::VLDRS : ARM::VLDRD;

1006

1007 auto ConstPool = MF.getConstantPool();

1008 auto CPIndex =

1009 ConstPool->getConstantPoolIndex(I.getOperand(1).getFPImm(), Alignment);

1018 break;

1019 }

1020 case G_INTTOPTR:

1021 case G_PTRTOINT: {

1022 auto SrcReg = I.getOperand(1).getReg();

1023 auto DstReg = I.getOperand(0).getReg();

1024

1027

1028 if (SrcRegBank.getID() != DstRegBank.getID()) {

1031 << "G_INTTOPTR/G_PTRTOINT operands on different register banks\n");

1032 return false;

1033 }

1034

1035 if (SrcRegBank.getID() != ARM::GPRRegBankID) {

1037 dbgs() << "G_INTTOPTR/G_PTRTOINT on non-GPR not supported yet\n");

1038 return false;

1039 }

1040

1041 I.setDesc(TII.get(COPY));

1043 }

1044 case G_SELECT:

1045 return selectSelect(MIB, MRI);

1046 case G_ICMP: {

1047 CmpConstants Helper(Opcodes.CMPrr, ARM::INSTRUCTION_LIST_END,

1048 Opcodes.MOVCCi, ARM::GPRRegBankID, 32);

1049 return selectCmp(Helper, MIB, MRI);

1050 }

1051 case G_FCMP: {

1053

1054 Register OpReg = I.getOperand(2).getReg();

1055 unsigned Size = MRI.getType(OpReg).getSizeInBits();

1056

1057 if (Size == 64 && !STI.hasFP64()) {

1058 LLVM_DEBUG(dbgs() << "Subtarget only supports single precision");

1059 return false;

1060 }

1061 if (Size != 32 && Size != 64) {

1062 LLVM_DEBUG(dbgs() << "Unsupported size for G_FCMP operand");

1063 return false;

1064 }

1065

1066 CmpConstants Helper(Size == 32 ? ARM::VCMPS : ARM::VCMPD, ARM::FMSTAT,

1067 Opcodes.MOVCCi, ARM::FPRRegBankID, Size);

1068 return selectCmp(Helper, MIB, MRI);

1069 }

1070 case G_LSHR:

1071 return selectShift(ARM_AM::ShiftOpc::lsr, MIB);

1072 case G_ASHR:

1073 return selectShift(ARM_AM::ShiftOpc::asr, MIB);

1074 case G_SHL: {

1075 return selectShift(ARM_AM::ShiftOpc::lsl, MIB);

1076 }

1077 case G_PTR_ADD:

1078 I.setDesc(TII.get(Opcodes.ADDrr));

1080 break;

1081 case G_FRAME_INDEX:

1082

1083

1084 I.setDesc(TII.get(Opcodes.ADDri));

1086 break;

1087 case G_GLOBAL_VALUE:

1088 return selectGlobal(MIB, MRI);

1089 case G_STORE:

1090 case G_LOAD: {

1091 auto &MemOp = **I.memoperands_begin();

1092 if (MemOp.isAtomic()) {

1093 LLVM_DEBUG(dbgs() << "Atomic load/store not supported yet\n");

1094 return false;

1095 }

1096

1099

1100 LLT ValTy = MRI.getType(Reg);

1102

1104 "Don't know how to load/store 64-bit value without VFP");

1105

1107 Register PtrReg = LoadMI->getPointerReg();

1108 MachineInstr *Ptr = MRI.getVRegDef(PtrReg);

1109 if (Ptr->getOpcode() == TargetOpcode::G_CONSTANT_POOL) {

1111 unsigned Opcode = Subtarget->isThumb() ? ARM::tLDRpci : ARM::LDRcp;

1112

1115 .add(Index)

1120 return false;

1121 I.eraseFromParent();

1122 return true;

1123 }

1124 }

1125

1126 const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);

1127 if (NewOpc == G_LOAD || NewOpc == G_STORE)

1128 return false;

1129

1130 I.setDesc(TII.get(NewOpc));

1131

1132 if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)

1133

1136 break;

1137 }

1138 case G_MERGE_VALUES: {

1140 return false;

1141 break;

1142 }

1143 case G_UNMERGE_VALUES: {

1145 return false;

1146 break;

1147 }

1148 case G_BRCOND: {

1149 if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {

1150 LLVM_DEBUG(dbgs() << "Unsupported condition register for G_BRCOND");

1151 return false;

1152 }

1153

1154

1156 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.TSTri))

1157 .addReg(I.getOperand(0).getReg())

1161 return false;

1162

1163

1165 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.Bcc))

1166 .add(I.getOperand(1))

1169 return false;

1170 I.eraseFromParent();

1171 return true;

1172 }

1173 case G_PHI: {

1175

1176 Register DstReg = I.getOperand(0).getReg();

1177 const TargetRegisterClass *RC = guessRegClass(DstReg, MRI, TRI, RBI);

1179 break;

1180 }

1181

1182 return true;

1183 }

1184 default:

1185 return false;

1186 }

1187

1189}

unsigned const MachineRegisterInfo * MRI

#define GET_GLOBALISEL_PREDICATES_INIT

#define GET_GLOBALISEL_TEMPORARIES_INIT

static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

const TargetInstrInfo & TII

static bool isStore(int Opcode)

static bool isThumb(const MCSubtargetInfo &STI)

static std::pair< ARMCC::CondCodes, ARMCC::CondCodes > getComparePreds(CmpInst::Predicate Pred)

Definition ARMInstructionSelector.cpp:394

static bool selectMergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)

Definition ARMInstructionSelector.cpp:233

static bool selectUnmergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)

Definition ARMInstructionSelector.cpp:264

static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)

Definition ARMInstructionSelector.cpp:213

#define STORE_OPCODE(VAR, OPC)

This file declares the targeting of the RegisterBankInfo class for ARM.

static const Function * getParent(const Value *V)

Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...

This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...

static DebugLoc getDebugLoc(MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)

Return the first DebugLoc that has line number information, given a range of instructions.

Register const TargetRegisterInfo * TRI

Promote Memory to Register

MachineInstr unsigned OpIdx

static StringRef getName(Value *V)

const SmallVectorImpl< MachineOperand > & Cond

static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)

This class provides the information for the target register banks.

bool isTargetMachO() const

bool isGVIndirectSymbol(const GlobalValue *GV) const

True if the GV will be accessed via an indirect symbol.

const ARMTargetLowering * getTargetLowering() const override

bool isTargetDarwin() const

bool isGVInGOT(const GlobalValue *GV) const

Returns the constant pool modifier needed to access the GV.

bool isReadOnly(const GlobalValue *GV) const

Predicate

This enumeration lists the possible predicates for CmpInst subclasses.

@ FCMP_OEQ

0 0 0 1 True if ordered and equal

@ FCMP_TRUE

1 1 1 1 Always true (always folded)

@ ICMP_SLT

signed less than

@ ICMP_SLE

signed less or equal

@ FCMP_OLT

0 1 0 0 True if ordered and less than

@ FCMP_ULE

1 1 0 1 True if unordered, less than, or equal

@ FCMP_OGT

0 0 1 0 True if ordered and greater than

@ FCMP_OGE

0 0 1 1 True if ordered and greater than or equal

@ ICMP_UGE

unsigned greater or equal

@ ICMP_UGT

unsigned greater than

@ ICMP_SGT

signed greater than

@ FCMP_ULT

1 1 0 0 True if unordered or less than

@ FCMP_ONE

0 1 1 0 True if ordered and operands are unequal

@ FCMP_UEQ

1 0 0 1 True if unordered or equal

@ ICMP_ULT

unsigned less than

@ FCMP_UGT

1 0 1 0 True if unordered or greater than

@ FCMP_OLE

0 1 0 1 True if ordered and less than or equal

@ FCMP_ORD

0 1 1 1 True if ordered (no nans)

@ ICMP_SGE

signed greater or equal

@ FCMP_UNE

1 1 1 0 True if unordered or not equal

@ ICMP_ULE

unsigned less or equal

@ FCMP_UGE

1 0 1 1 True if unordered, greater than, or equal

@ FCMP_FALSE

0 0 0 0 Always false (always folded)

@ FCMP_UNO

1 0 0 0 True if unordered: isnan(X) | isnan(Y)

const APFloat & getValueAPF() const

This is an important base class in LLVM.

constexpr TypeSize getSizeInBits() const

Returns the total size of the type. Must only be called on sized types.

const MCInstrDesc & get(unsigned Opcode) const

Return the machine instruction descriptor that corresponds to the specified instruction opcode.

Instructions::iterator instr_iterator

const MachineFunction * getParent() const

Return the MachineFunction containing this basic block.

Register getReg(unsigned Idx) const

Get the register for the operand index.

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & add(const MachineOperand &MO) const

const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const

const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const

Add a virtual register use operand.

const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const

const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const

Add a virtual register definition operand.

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

const MachineBasicBlock * getParent() const

LLVM_ABI void setDesc(const MCInstrDesc &TID)

Replace the instruction descriptor (thus opcode) of the current instruction with a new one.

const DebugLoc & getDebugLoc() const

Returns the debug location id of this MachineInstr.

LLVM_ABI void eraseFromParent()

Unlink 'this' from the containing basic block and delete it.

LLVM_ABI void removeOperand(unsigned OpNo)

Erase an operand from an instruction, leaving it with one fewer operand than it started with.

const MachineOperand & getOperand(unsigned i) const

@ MOLoad

The memory access reads data.

const GlobalValue * getGlobal() const

Register getReg() const

getReg - Returns the register number.

const ConstantFP * getFPImm() const

MachineRegisterInfo - Keep track of information for virtual and physical registers,...

Holds all the information related to register banks.

static const TargetRegisterClass * constrainGenericRegister(Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI)

Constrain the (possibly generic) virtual register Reg to RC.

const RegisterBank & getRegBank(unsigned ID)

Get the register bank identified by ID.

This class implements the register bank concept.

unsigned getID() const

Get the identifier of this register bank.

Wrapper class representing virtual and physical registers.

constexpr bool isPhysical() const

Return true if the specified register number is in the physical register namespace.

TargetInstrInfo - Interface to description of machine instruction set.

bool isPositionIndependent() const

unsigned getProgramPointerSize() const

TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...

self_iterator getIterator()

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

@ SBREL

Section Relative (Windows TLS)

@ MO_NONLAZY

MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...

@ MO_SBREL

MO_SBREL - On a symbol operand, this represents a static base relative relocation.

@ MO_GOT

MO_GOT - On a symbol operand, this represents a GOT relative relocation.

int getFP32Imm(const APInt &Imm)

getFP32Imm - Return an 8-bit floating-point version of the 32-bit floating-point value.

int getFP64Imm(const APInt &Imm)

getFP64Imm - Return an 8-bit floating-point version of the 64-bit floating-point value.

Predicate getPredicate(unsigned Condition, unsigned Hint)

Return predicate consisting of specified condition and hint bits.

NodeAddr< InstrNode * > Instr

This is an optimization pass for GlobalISel generic memory operations.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

InstructionSelector * createARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI, const ARMRegisterBankInfo &RBI)

Definition ARMInstructionSelector.cpp:162

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

LLVM_ABI bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)

Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...

bool isPreISelGenericOpcode(unsigned Opcode)

Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.

static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)

Get the operands corresponding to the given Pred value.

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

static MachineOperand condCodeOp(unsigned CCReg=0)

Get the operand corresponding to the conditional code result.

Implement std::hash so that hash_code can be used in STL containers.

CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned SelectOpcode, unsigned OpRegBank, unsigned OpSize)

Definition ARMInstructionSelector.cpp:461

const unsigned OperandRegBankID

Definition ARMInstructionSelector.cpp:478

const unsigned ReadFlagsOpcode

Definition ARMInstructionSelector.cpp:472

const unsigned SelectResultOpcode

Definition ARMInstructionSelector.cpp:475

const unsigned ComparisonOpcode

Definition ARMInstructionSelector.cpp:468

const unsigned OperandSize

Definition ARMInstructionSelector.cpp:481

MachineBasicBlock & MBB

Definition ARMInstructionSelector.cpp:489

const MachineBasicBlock::instr_iterator InsertBefore

Definition ARMInstructionSelector.cpp:490

InsertInfo(MachineInstrBuilder &MIB)

Definition ARMInstructionSelector.cpp:485

const DebugLoc & DbgLoc

Definition ARMInstructionSelector.cpp:491

static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)

Return a MachinePointerInfo record that refers to the constant pool.

static LLVM_ABI MachinePointerInfo getGOT(MachineFunction &MF)

Return a MachinePointerInfo record that refers to a GOT entry.