1 //===- ARMInstructionSelector.cpp ----------------------------*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// This file implements the targeting of the InstructionSelector class for ARM.
11 /// \todo This should be generated by TableGen.
12 //===----------------------------------------------------------------------===//
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"
21 #define DEBUG_TYPE "arm-isel"
23 #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
27 #ifndef LLVM_BUILD_GLOBAL_ISEL
28 #error "You shouldn't build this"
33 #define GET_GLOBALISEL_PREDICATE_BITSET
34 #include "ARMGenGlobalISel.inc"
35 #undef GET_GLOBALISEL_PREDICATE_BITSET
37 class ARMInstructionSelector : public InstructionSelector {
39 ARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI,
40 const ARMRegisterBankInfo &RBI);
42 bool select(MachineInstr &I) const override;
45 bool selectImpl(MachineInstr &I) const;
50 bool selectCmp(CmpConstants Helper, MachineInstrBuilder &MIB,
51 MachineRegisterInfo &MRI) const;
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;
60 // Set \p DestReg to \p Constant.
61 void putConstant(InsertInfo I, unsigned DestReg, unsigned Constant) const;
63 bool selectSelect(MachineInstrBuilder &MIB, MachineRegisterInfo &MRI) const;
65 // Check if the types match and both operands have the expected size and
67 bool validOpRegPair(MachineRegisterInfo &MRI, unsigned LHS, unsigned RHS,
68 unsigned ExpectedSize, unsigned ExpectedRegBankID) const;
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;
74 const ARMBaseInstrInfo &TII;
75 const ARMBaseRegisterInfo &TRI;
76 const ARMBaseTargetMachine &TM;
77 const ARMRegisterBankInfo &RBI;
78 const ARMSubtarget &STI;
80 #define GET_GLOBALISEL_PREDICATES_DECL
81 #include "ARMGenGlobalISel.inc"
82 #undef GET_GLOBALISEL_PREDICATES_DECL
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
90 } // end anonymous namespace
94 createARMInstructionSelector(const ARMBaseTargetMachine &TM,
95 const ARMSubtarget &STI,
96 const ARMRegisterBankInfo &RBI) {
97 return new ARMInstructionSelector(TM, STI, RBI);
101 unsigned zero_reg = 0;
103 #define GET_GLOBALISEL_IMPL
104 #include "ARMGenGlobalISel.inc"
105 #undef GET_GLOBALISEL_IMPL
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
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))
128 const RegisterBank *RegBank = RBI.getRegBank(DstReg, MRI, TRI);
130 assert(RegBank && "Can't get reg bank for virtual register");
132 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
133 assert((RegBank->getID() == ARM::GPRRegBankID ||
134 RegBank->getID() == ARM::FPRRegBankID) &&
135 "Unsupported reg bank");
137 const TargetRegisterClass *RC = &ARM::GPRRegClass;
139 if (RegBank->getID() == ARM::FPRRegBankID) {
141 RC = &ARM::SPRRegClass;
142 else if (DstSize == 64)
143 RC = &ARM::DPRRegClass;
145 llvm_unreachable("Unsupported destination size");
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())
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");
166 // We only support G_MERGE_VALUES as a way to stick together two scalar GPRs
168 unsigned VReg0 = MIB->getOperand(0).getReg();
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();
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();
180 assert(MRI.getType(VReg2).getSizeInBits() == 32 &&
181 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::GPRRegBankID &&
182 "Unsupported operand for G_MERGE_VALUES");
184 MIB->setDesc(TII.get(ARM::VMOVDRR));
185 MIB.add(predOps(ARMCC::AL));
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");
197 // We only support G_UNMERGE_VALUES as a way to break up one DPR into two
199 unsigned VReg0 = MIB->getOperand(0).getReg();
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();
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();
211 assert(MRI.getType(VReg2).getSizeInBits() == 64 &&
212 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID &&
213 "Unsupported operand for G_UNMERGE_VALUES");
215 MIB->setDesc(TII.get(ARM::VMOVRRD));
216 MIB.add(predOps(ARMCC::AL));
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
225 static unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) {
226 using namespace TargetOpcode;
228 if (Size != 8 && Size != 16)
232 return Size == 8 ? ARM::SXTB : ARM::SXTH;
235 return Size == 8 ? ARM::UXTB : ARM::UXTH;
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,
245 bool isStore = Opc == TargetOpcode::G_STORE;
247 if (RegBank == ARM::GPRRegBankID) {
251 return isStore ? ARM::STRBi12 : ARM::LDRBi12;
253 return isStore ? ARM::STRH : ARM::LDRH;
255 return isStore ? ARM::STRi12 : ARM::LDRi12;
261 if (RegBank == ARM::FPRRegBankID) {
264 return isStore ? ARM::VSTRS : ARM::VLDRS;
266 return isStore ? ARM::VSTRD : ARM::VLDRD;
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};
282 case CmpInst::FCMP_ONE:
283 Preds = {ARMCC::GT, ARMCC::MI};
285 case CmpInst::FCMP_UEQ:
286 Preds = {ARMCC::EQ, ARMCC::VS};
288 case CmpInst::ICMP_EQ:
289 case CmpInst::FCMP_OEQ:
290 Preds.first = ARMCC::EQ;
292 case CmpInst::ICMP_SGT:
293 case CmpInst::FCMP_OGT:
294 Preds.first = ARMCC::GT;
296 case CmpInst::ICMP_SGE:
297 case CmpInst::FCMP_OGE:
298 Preds.first = ARMCC::GE;
300 case CmpInst::ICMP_UGT:
301 case CmpInst::FCMP_UGT:
302 Preds.first = ARMCC::HI;
304 case CmpInst::FCMP_OLT:
305 Preds.first = ARMCC::MI;
307 case CmpInst::ICMP_ULE:
308 case CmpInst::FCMP_OLE:
309 Preds.first = ARMCC::LS;
311 case CmpInst::FCMP_ORD:
312 Preds.first = ARMCC::VC;
314 case CmpInst::FCMP_UNO:
315 Preds.first = ARMCC::VS;
317 case CmpInst::FCMP_UGE:
318 Preds.first = ARMCC::PL;
320 case CmpInst::ICMP_SLT:
321 case CmpInst::FCMP_ULT:
322 Preds.first = ARMCC::LT;
324 case CmpInst::ICMP_SLE:
325 case CmpInst::FCMP_ULE:
326 Preds.first = ARMCC::LE;
328 case CmpInst::FCMP_UNE:
329 case CmpInst::ICMP_NE:
330 Preds.first = ARMCC::NE;
332 case CmpInst::ICMP_UGE:
333 Preds.first = ARMCC::HS;
335 case CmpInst::ICMP_ULT:
336 Preds.first = ARMCC::LO;
341 assert(Preds.first != ARMCC::AL && "No comparisons needed?");
345 struct ARMInstructionSelector::CmpConstants {
346 CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned OpRegBank,
348 : ComparisonOpcode(CmpOpcode), ReadFlagsOpcode(FlagsOpcode),
349 OperandRegBankID(OpRegBank), OperandSize(OpSize) {}
351 // The opcode used for performing the comparison.
352 const unsigned ComparisonOpcode;
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;
358 // The assumed register bank ID for the operands.
359 const unsigned OperandRegBankID;
361 // The assumed size in bits for the operands.
362 const unsigned OperandSize;
365 struct ARMInstructionSelector::InsertInfo {
366 InsertInfo(MachineInstrBuilder &MIB)
367 : MBB(*MIB->getParent()), InsertBefore(std::next(MIB->getIterator())),
368 DbgLoc(MIB->getDebugLoc()) {}
370 MachineBasicBlock &MBB;
371 const MachineBasicBlock::instr_iterator InsertBefore;
372 const DebugLoc &DbgLoc;
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))
380 .add(predOps(ARMCC::AL))
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);
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");
401 if (RBI.getRegBank(Reg, MRI, TRI)->getID() != ExpectedRegBankID) {
402 DEBUG(dbgs() << "Unexpected register bank for register");
409 bool ARMInstructionSelector::selectCmp(CmpConstants Helper,
410 MachineInstrBuilder &MIB,
411 MachineRegisterInfo &MRI) const {
412 const InsertInfo I(MIB);
414 auto ResReg = MIB->getOperand(0).getReg();
415 if (!validReg(MRI, ResReg, 1, ARM::GPRRegBankID))
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();
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))
432 auto ARMConds = getComparePreds(Cond);
433 auto ZeroReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
434 putConstant(I, ZeroReg, 0);
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,
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,
447 if (!insertComparison(Helper, I, ResReg, ARMConds.second, LHSReg, RHSReg,
452 MIB->eraseFromParent();
456 bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo I,
458 ARMCC::CondCodes Cond,
459 unsigned LHSReg, unsigned RHSReg,
460 unsigned PrevRes) const {
461 // Perform the comparison.
463 BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Helper.ComparisonOpcode))
466 .add(predOps(ARMCC::AL));
467 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
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))
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))
484 .add(predOps(Cond, ARM::CPSR));
485 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
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();
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))
504 .add(predOps(ARMCC::AL));
505 if (!constrainSelectedInstRegOperands(*CmpI, TII, TRI, RBI))
508 // Move a value into the result register based on the result of the
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))
520 .add(predOps(ARMCC::EQ, ARM::CPSR));
521 if (!constrainSelectedInstRegOperands(*Mov1I, TII, TRI, RBI))
524 MIB->eraseFromParent();
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!");
532 auto &MBB = *I.getParent();
533 auto &MF = *MBB.getParent();
534 auto &MRI = MF.getRegInfo();
536 if (!isPreISelGenericOpcode(I.getOpcode())) {
538 return selectCopy(I, TII, MRI, TRI, RBI);
546 MachineInstrBuilder MIB{MF, I};
549 using namespace TargetOpcode;
550 switch (I.getOpcode()) {
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");
562 LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
563 unsigned SrcSize = SrcTy.getSizeInBits();
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());
571 unsigned SExtResult = I.getOperand(0).getReg();
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);
577 auto InsertBefore = std::next(I.getIterator());
579 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::RSBri))
583 .add(predOps(ARMCC::AL))
585 if (!constrainSelectedInstRegOperands(*SubI, TII, TRI, RBI))
592 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);
593 if (NewOpc == I.getOpcode())
595 I.setDesc(TII.get(NewOpc));
596 MIB.addImm(0).add(predOps(ARMCC::AL));
600 DEBUG(dbgs() << "Unsupported source size for extension");
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();
612 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
613 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
615 if (SrcRegBank.getID() != DstRegBank.getID()) {
616 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");
620 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
621 DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
625 I.setDesc(TII.get(COPY));
626 return selectCopy(I, TII, MRI, TRI, RBI);
629 return selectSelect(MIB, MRI);
631 CmpConstants Helper(ARM::CMPrr, ARM::INSTRUCTION_LIST_END,
632 ARM::GPRRegBankID, 32);
633 return selectCmp(Helper, MIB, MRI);
636 assert(TII.getSubtarget().hasVFP2() && "Can't select fcmp without VFP");
638 unsigned OpReg = I.getOperand(2).getReg();
639 unsigned Size = MRI.getType(OpReg).getSizeInBits();
641 if (Size == 64 && TII.getSubtarget().isFPOnlySP()) {
642 DEBUG(dbgs() << "Subtarget only supports single precision");
645 if (Size != 32 && Size != 64) {
646 DEBUG(dbgs() << "Unsupported size for G_FCMP operand");
650 CmpConstants Helper(Size == 32 ? ARM::VCMPS : ARM::VCMPD, ARM::FMSTAT,
651 ARM::FPRRegBankID, Size);
652 return selectCmp(Helper, MIB, MRI);
655 I.setDesc(TII.get(ARM::ADDrr));
656 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
659 // Add 0 to the given frame index and hope it will eventually be folded into
661 I.setDesc(TII.get(ARM::ADDri));
662 MIB.addImm(0).add(predOps(ARMCC::AL)).add(condCodeOp());
665 unsigned Reg = I.getOperand(0).getReg();
667 if (!validReg(MRI, Reg, 32, ARM::GPRRegBankID))
670 I.setDesc(TII.get(ARM::MOVi));
671 MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
673 auto &Val = I.getOperand(1);
675 if (Val.getCImm()->getBitWidth() > 32)
677 Val.ChangeToImmediate(Val.getCImm()->getZExtValue());
688 const auto &MemOp = **I.memoperands_begin();
689 if (MemOp.getOrdering() != AtomicOrdering::NotAtomic) {
690 DEBUG(dbgs() << "Atomic load/store not supported yet\n");
694 unsigned Reg = I.getOperand(0).getReg();
695 unsigned RegBank = RBI.getRegBank(Reg, MRI, TRI)->getID();
697 LLT ValTy = MRI.getType(Reg);
698 const auto ValSize = ValTy.getSizeInBits();
700 assert((ValSize != 64 || TII.getSubtarget().hasVFP2()) &&
701 "Don't know how to load/store 64-bit value without VFP");
703 const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);
704 if (NewOpc == G_LOAD || NewOpc == G_STORE)
707 I.setDesc(TII.get(NewOpc));
709 if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)
710 // LDRH has a funny addressing mode (there's already a FIXME for it).
712 MIB.addImm(0).add(predOps(ARMCC::AL));
715 case G_MERGE_VALUES: {
716 if (!selectMergeValues(MIB, TII, MRI, TRI, RBI))
720 case G_UNMERGE_VALUES: {
721 if (!selectUnmergeValues(MIB, TII, MRI, TRI, RBI))
726 if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {
727 DEBUG(dbgs() << "Unsupported condition register for G_BRCOND");
732 auto Test = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ARM::TSTri))
733 .addReg(I.getOperand(0).getReg())
735 .add(predOps(ARMCC::AL));
736 if (!constrainSelectedInstRegOperands(*Test, TII, TRI, RBI))
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))
752 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);