LLVM 23.0.0git
ARMInstructionSelector.cpp
Go to the documentation of this file.
1//===- ARMInstructionSelector.cpp ----------------------------*- C++ -*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements the targeting of the InstructionSelector class for ARM.
10/// \todo This should be generated by TableGen.
11//===----------------------------------------------------------------------===//
12
13#include "ARMRegisterBankInfo.h"
14#include "ARMSubtarget.h"
15#include "ARMTargetMachine.h"
21#include "llvm/Support/Debug.h"
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
33class ARMInstructionSelector : public InstructionSelector {
34public:
35 ARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI,
36 const ARMRegisterBankInfo &RBI);
37
38 bool select(MachineInstr &I) override;
39 static const char *getName() { return DEBUG_TYPE; }
40
41private:
42 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
43
44 struct CmpConstants;
45 struct InsertInfo;
46
47 bool selectCmp(CmpConstants Helper, MachineInstrBuilder &MIB,
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 bool selectShift(unsigned ShiftOpc, MachineInstrBuilder &MIB) const;
63
64 // Check if the types match and both operands have the expected size and
65 // register bank.
66 bool validOpRegPair(MachineRegisterInfo &MRI, unsigned LHS, unsigned RHS,
67 unsigned ExpectedSize, unsigned ExpectedRegBankID) const;
68
69 // Check if the register has the expected size and register bank.
70 bool validReg(MachineRegisterInfo &MRI, unsigned Reg, unsigned ExpectedSize,
71 unsigned ExpectedRegBankID) const;
72
73 const ARMBaseInstrInfo &TII;
75 const ARMBaseTargetMachine &TM;
76 const ARMRegisterBankInfo &RBI;
77 const ARMSubtarget &STI;
78
79 // FIXME: This is necessary because DAGISel uses "Subtarget->" and GlobalISel
80 // uses "STI." in the code generated by TableGen. If we want to reuse some of
81 // the custom C++ predicates written for DAGISel, we need to have both around.
82 const ARMSubtarget *Subtarget = &STI;
83
84 // Store the opcodes that we might need, so we don't have to check what kind
85 // of subtarget (ARM vs Thumb) we have all the time.
86 struct OpcodeCache {
87 unsigned ZEXT16;
88 unsigned SEXT16;
89
90 unsigned ZEXT8;
91 unsigned SEXT8;
92
93 // Used for implementing ZEXT/SEXT from i1
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 // Used for G_ICMP
110 unsigned CMPrr;
111 unsigned MOVi;
112 unsigned MOVCCi;
113
114 // Used for G_SELECT
115 unsigned MOVCCr;
116
117 unsigned TSTri;
118 unsigned Bcc;
119
120 // Used for G_GLOBAL_VALUE
121 unsigned MOVi32imm;
122 unsigned ConstPoolLoad;
123 unsigned MOV_ga_pcrel;
124 unsigned LDRLIT_ga_pcrel;
125 unsigned LDRLIT_ga_abs;
126
127 OpcodeCache(const ARMSubtarget &STI);
128 } const Opcodes;
129
130 // Select the opcode for simple extensions (that translate to a single SXT/UXT
131 // instruction). Extension operations more complicated than that should not
132 // invoke this. Returns the original opcode if it doesn't know how to select a
133 // better one.
134 unsigned selectSimpleExtOpc(unsigned Opc, unsigned Size) const;
135
136 // Select the opcode for simple loads and stores. Returns the original opcode
137 // if it doesn't know how to select a better one.
138 unsigned selectLoadStoreOpCode(unsigned Opc, unsigned RegBank,
139 unsigned Size) const;
140
141 void renderVFPF32Imm(MachineInstrBuilder &New, const MachineInstr &Old,
142 int OpIdx = -1) const;
143 void renderVFPF64Imm(MachineInstrBuilder &New, const MachineInstr &Old,
144 int OpIdx = -1) const;
145 void renderInvertedImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
146 int OpIdx = -1) const;
147
148#define GET_GLOBALISEL_PREDICATES_DECL
149#include "ARMGenGlobalISel.inc"
150#undef GET_GLOBALISEL_PREDICATES_DECL
151
152// We declare the temporaries used by selectImpl() in the class to minimize the
153// cost of constructing placeholder values.
154#define GET_GLOBALISEL_TEMPORARIES_DECL
155#include "ARMGenGlobalISel.inc"
156#undef GET_GLOBALISEL_TEMPORARIES_DECL
157};
158} // end anonymous namespace
159
160namespace llvm {
163 const ARMSubtarget &STI,
164 const ARMRegisterBankInfo &RBI) {
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,
174 const ARMSubtarget &STI,
175 const ARMRegisterBankInfo &RBI)
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
187static const TargetRegisterClass *guessRegClass(unsigned Reg,
189 const TargetRegisterInfo &TRI,
190 const RegisterBankInfo &RBI) {
191 const RegisterBank *RegBank = RBI.getRegBank(Reg, MRI, TRI);
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
207 llvm_unreachable("Unsupported destination size");
208 }
209
210 return &ARM::GPRRegClass;
211}
212
215 const RegisterBankInfo &RBI) {
216 Register DstReg = I.getOperand(0).getReg();
217 if (DstReg.isPhysical())
218 return true;
219
220 const TargetRegisterClass *RC = guessRegClass(DstReg, MRI, TRI, RBI);
221
222 // No need to constrain SrcReg. It will get constrained when
223 // we hit another of its uses or its defs.
224 // Copies do not have constraints.
225 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
226 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
227 << " operand\n");
228 return false;
229 }
230 return true;
231}
232
234 const ARMBaseInstrInfo &TII,
236 const TargetRegisterInfo &TRI,
237 const RegisterBankInfo &RBI) {
238 assert(TII.getSubtarget().hasVFP2Base() && "Can't select merge without VFP");
239
240 // We only support G_MERGE_VALUES as a way to stick together two scalar GPRs
241 // into one DPR.
242 Register VReg0 = MIB.getReg(0);
243 (void)VReg0;
244 assert(MRI.getType(VReg0).getSizeInBits() == 64 &&
245 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::FPRRegBankID &&
246 "Unsupported operand for G_MERGE_VALUES");
247 Register VReg1 = MIB.getReg(1);
248 (void)VReg1;
249 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
250 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
251 "Unsupported operand for G_MERGE_VALUES");
252 Register VReg2 = MIB.getReg(2);
253 (void)VReg2;
254 assert(MRI.getType(VReg2).getSizeInBits() == 32 &&
255 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::GPRRegBankID &&
256 "Unsupported operand for G_MERGE_VALUES");
257
258 MIB->setDesc(TII.get(ARM::VMOVDRR));
259 MIB.add(predOps(ARMCC::AL));
260
261 return true;
262}
263
265 const ARMBaseInstrInfo &TII,
267 const TargetRegisterInfo &TRI,
268 const RegisterBankInfo &RBI) {
269 assert(TII.getSubtarget().hasVFP2Base() &&
270 "Can't select unmerge without VFP");
271
272 // We only support G_UNMERGE_VALUES as a way to break up one DPR into two
273 // GPRs.
274 Register VReg0 = MIB.getReg(0);
275 (void)VReg0;
276 assert(MRI.getType(VReg0).getSizeInBits() == 32 &&
277 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::GPRRegBankID &&
278 "Unsupported operand for G_UNMERGE_VALUES");
279 Register VReg1 = MIB.getReg(1);
280 (void)VReg1;
281 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
282 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
283 "Unsupported operand for G_UNMERGE_VALUES");
284 Register VReg2 = MIB.getReg(2);
285 (void)VReg2;
286 assert(MRI.getType(VReg2).getSizeInBits() == 64 &&
287 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID &&
288 "Unsupported operand for G_UNMERGE_VALUES");
289
290 MIB->setDesc(TII.get(ARM::VMOVRRD));
291 MIB.add(predOps(ARMCC::AL));
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
302 STORE_OPCODE(SEXT16, SXTH);
303 STORE_OPCODE(ZEXT16, UXTH);
304
305 STORE_OPCODE(SEXT8, SXTB);
306 STORE_OPCODE(ZEXT8, UXTB);
307
308 STORE_OPCODE(AND, ANDri);
309 STORE_OPCODE(RSB, RSBri);
310
311 STORE_OPCODE(STORE32, STRi12);
312 STORE_OPCODE(LOAD32, LDRi12);
313
314 // LDRH/STRH are special...
315 STORE16 = isThumb ? ARM::t2STRHi12 : ARM::STRH;
316 LOAD16 = isThumb ? ARM::t2LDRHi12 : ARM::LDRH;
317
318 STORE_OPCODE(STORE8, STRBi12);
319 STORE_OPCODE(LOAD8, LDRBi12);
320
321 STORE_OPCODE(ADDrr, ADDrr);
322 STORE_OPCODE(ADDri, ADDri);
323
324 STORE_OPCODE(CMPrr, CMPrr);
325 STORE_OPCODE(MOVi, MOVi);
326 STORE_OPCODE(MOVCCi, MOVCCi);
327
328 STORE_OPCODE(MOVCCr, MOVCCr);
329
330 STORE_OPCODE(TSTri, TSTri);
331 STORE_OPCODE(Bcc, Bcc);
332
333 STORE_OPCODE(MOVi32imm, MOVi32imm);
334 ConstPoolLoad = isThumb ? ARM::t2LDRpci : ARM::LDRi12;
335 STORE_OPCODE(MOV_ga_pcrel, MOV_ga_pcrel);
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
345 if (Size != 8 && Size != 16)
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// When lowering comparisons, we sometimes need to perform two compares instead
391// of just one. Get the condition codes for both comparisons. If only one is
392// needed, the second member of the pair is ARMCC::AL.
393static std::pair<ARMCC::CondCodes, ARMCC::CondCodes>
395 std::pair<ARMCC::CondCodes, ARMCC::CondCodes> Preds = {ARMCC::AL, ARMCC::AL};
396 switch (Pred) {
398 Preds = {ARMCC::GT, ARMCC::MI};
399 break;
401 Preds = {ARMCC::EQ, ARMCC::VS};
402 break;
403 case CmpInst::ICMP_EQ:
405 Preds.first = ARMCC::EQ;
406 break;
409 Preds.first = ARMCC::GT;
410 break;
413 Preds.first = ARMCC::GE;
414 break;
417 Preds.first = ARMCC::HI;
418 break;
420 Preds.first = ARMCC::MI;
421 break;
424 Preds.first = ARMCC::LS;
425 break;
427 Preds.first = ARMCC::VC;
428 break;
430 Preds.first = ARMCC::VS;
431 break;
433 Preds.first = ARMCC::PL;
434 break;
437 Preds.first = ARMCC::LT;
438 break;
441 Preds.first = ARMCC::LE;
442 break;
444 case CmpInst::ICMP_NE:
445 Preds.first = ARMCC::NE;
446 break;
448 Preds.first = ARMCC::HS;
449 break;
451 Preds.first = ARMCC::LO;
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)
463 : ComparisonOpcode(CmpOpcode), ReadFlagsOpcode(FlagsOpcode),
464 SelectResultOpcode(SelectOpcode), OperandRegBankID(OpRegBank),
465 OperandSize(OpSize) {}
466
467 // The opcode used for performing the comparison.
468 const unsigned ComparisonOpcode;
469
470 // The opcode used for reading the flags set by the comparison. May be
471 // ARM::INSTRUCTION_LIST_END if we don't need to read the flags.
472 const unsigned ReadFlagsOpcode;
473
474 // The opcode used for materializing the result of the comparison.
475 const unsigned SelectResultOpcode;
476
477 // The assumed register bank ID for the operands.
478 const unsigned OperandRegBankID;
479
480 // The assumed size in bits for the operands.
481 const unsigned OperandSize;
482};
483
493
494void ARMInstructionSelector::putConstant(InsertInfo I, unsigned DestReg,
495 unsigned Constant) const {
496 (void)BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Opcodes.MOVi))
497 .addDef(DestReg)
500 .add(condCodeOp());
501}
502
503bool ARMInstructionSelector::validOpRegPair(MachineRegisterInfo &MRI,
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
520 if (RBI.getRegBank(Reg, MRI, TRI)->getID() != ExpectedRegBankID) {
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
537 auto Cond =
538 static_cast<CmpInst::Predicate>(MIB->getOperand(1).getPredicate());
540 putConstant(I, ResReg, Cond == CmpInst::FCMP_TRUE ? 1 : 0);
541 MIB->eraseFromParent();
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
551 auto ARMConds = getComparePreds(Cond);
552 auto ZeroReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
553 putConstant(I, ZeroReg, 0);
554
555 if (ARMConds.second == ARMCC::AL) {
556 // Simple case, we only need one comparison and we're done.
557 if (!insertComparison(Helper, I, ResReg, ARMConds.first, LHSReg, RHSReg,
558 ZeroReg))
559 return false;
560 } else {
561 // Not so simple, we need two successive comparisons.
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
571 MIB->eraseFromParent();
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 // Perform the comparison.
581 auto CmpI =
582 BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Helper.ComparisonOpcode))
583 .addUse(LHSReg)
584 .addUse(RHSReg)
587
588 // Read the comparison flags (if necessary).
589 if (Helper.ReadFlagsOpcode != ARM::INSTRUCTION_LIST_END) {
590 auto ReadI = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
591 TII.get(Helper.ReadFlagsOpcode))
594 }
595
596 // Select either 1 or the previous result based on the value of the flags.
597 auto Mov1I = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
598 TII.get(Helper.SelectResultOpcode))
599 .addDef(ResReg)
600 .addUse(PrevRes)
601 .addImm(1)
602 .add(predOps(Cond, ARM::CPSR));
604
605 return true;
606}
607
608bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
609 MachineRegisterInfo &MRI) const {
610 if ((STI.isROPI() || STI.isRWPI()) && !STI.isTargetELF()) {
611 LLVM_DEBUG(dbgs() << "ROPI and RWPI only supported for ELF\n");
612 return false;
613 }
614
615 auto GV = MIB->getOperand(1).getGlobal();
616 if (GV->isThreadLocal()) {
617 LLVM_DEBUG(dbgs() << "TLS variables not supported yet\n");
618 return false;
619 }
620
621 auto &MBB = *MIB->getParent();
622 auto &MF = *MBB.getParent();
623
624 bool UseMovt = STI.useMovt();
625
626 LLT PtrTy = MRI.getType(MIB->getOperand(0).getReg());
627 const Align Alignment(4);
628
629 auto addOpsForConstantPoolLoad = [&MF, Alignment, PtrTy](
630 MachineInstrBuilder &MIB,
631 const GlobalValue *GV, bool IsSBREL) {
632 assert((MIB->getOpcode() == ARM::LDRi12 ||
633 MIB->getOpcode() == ARM::t2LDRpci) &&
634 "Unsupported instruction");
635 auto ConstPool = MF.getConstantPool();
636 auto CPIndex =
637 // For SB relative entries we need a target-specific constant pool.
638 // Otherwise, just use a regular constant pool entry.
639 IsSBREL
640 ? ConstPool->getConstantPoolIndex(
642 : ConstPool->getConstantPoolIndex(GV, Alignment);
643 MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
644 .addMemOperand(MF.getMachineMemOperand(
646 PtrTy, Alignment));
647 if (MIB->getOpcode() == ARM::LDRi12)
648 MIB.addImm(0);
649 MIB.add(predOps(ARMCC::AL));
650 };
651
652 auto addGOTMemOperand = [this, &MF, Alignment](MachineInstrBuilder &MIB) {
653 MIB.addMemOperand(MF.getMachineMemOperand(
655 TM.getProgramPointerSize(), Alignment));
656 };
657
658 if (TM.isPositionIndependent()) {
659 bool Indirect = STI.isGVIndirectSymbol(GV);
660
661 // For ARM mode, we have different pseudoinstructions for direct accesses
662 // and indirect accesses, and the ones for indirect accesses include the
663 // load from GOT. For Thumb mode, we use the same pseudoinstruction for both
664 // direct and indirect accesses, and we need to manually generate the load
665 // from GOT.
666 bool UseOpcodeThatLoads = Indirect && !STI.isThumb();
667
668 // FIXME: Taking advantage of MOVT for ELF is pretty involved, so we don't
669 // support it yet. See PR28229.
670 unsigned Opc =
671 UseMovt && !STI.isTargetELF()
672 ? (UseOpcodeThatLoads ? (unsigned)ARM::MOV_ga_pcrel_ldr
673 : Opcodes.MOV_ga_pcrel)
674 : (UseOpcodeThatLoads ? (unsigned)ARM::LDRLIT_ga_pcrel_ldr
675 : Opcodes.LDRLIT_ga_pcrel);
676 MIB->setDesc(TII.get(Opc));
677
678 int TargetFlags = ARMII::MO_NO_FLAG;
679 if (STI.isTargetDarwin())
680 TargetFlags |= ARMII::MO_NONLAZY;
681 if (STI.isGVInGOT(GV))
682 TargetFlags |= ARMII::MO_GOT;
683 MIB->getOperand(1).setTargetFlags(TargetFlags);
684
685 if (Indirect) {
686 if (!UseOpcodeThatLoads) {
687 auto ResultReg = MIB.getReg(0);
688 auto AddressReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
689
690 MIB->getOperand(0).setReg(AddressReg);
691
692 auto InsertBefore = std::next(MIB->getIterator());
693 auto MIBLoad = BuildMI(MBB, InsertBefore, MIB->getDebugLoc(),
694 TII.get(Opcodes.LOAD32))
695 .addDef(ResultReg)
696 .addReg(AddressReg)
697 .addImm(0)
699 addGOTMemOperand(MIBLoad);
700
702 } else {
703 addGOTMemOperand(MIB);
704 }
705 }
706
708 return true;
709 }
710
711 bool isReadOnly = STI.getTargetLowering()->isReadOnly(GV);
712 if (STI.isROPI() && isReadOnly) {
713 unsigned Opc = UseMovt ? Opcodes.MOV_ga_pcrel : Opcodes.LDRLIT_ga_pcrel;
714 MIB->setDesc(TII.get(Opc));
716 return true;
717 }
718 if (STI.isRWPI() && !isReadOnly) {
719 auto Offset = MRI.createVirtualRegister(&ARM::GPRRegClass);
720 MachineInstrBuilder OffsetMIB;
721 if (UseMovt) {
722 OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
723 TII.get(Opcodes.MOVi32imm), Offset);
724 OffsetMIB.addGlobalAddress(GV, /*Offset*/ 0, ARMII::MO_SBREL);
725 } else {
726 // Load the offset from the constant pool.
727 OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
728 TII.get(Opcodes.ConstPoolLoad), Offset);
729 addOpsForConstantPoolLoad(OffsetMIB, GV, /*IsSBREL*/ true);
730 }
731 constrainSelectedInstRegOperands(*OffsetMIB, TII, TRI, RBI);
732
733 // Add the offset to the SB register.
734 MIB->setDesc(TII.get(Opcodes.ADDrr));
735 MIB->removeOperand(1);
736 MIB.addReg(ARM::R9) // FIXME: don't hardcode R9
737 .addReg(Offset)
738 .add(predOps(ARMCC::AL))
739 .add(condCodeOp());
740
742 return true;
743 }
744
745 if (STI.isTargetELF()) {
746 if (UseMovt) {
747 MIB->setDesc(TII.get(Opcodes.MOVi32imm));
748 } else {
749 // Load the global's address from the constant pool.
750 MIB->setDesc(TII.get(Opcodes.ConstPoolLoad));
751 MIB->removeOperand(1);
752 addOpsForConstantPoolLoad(MIB, GV, /*IsSBREL*/ false);
753 }
754 } else if (STI.isTargetMachO()) {
755 if (UseMovt)
756 MIB->setDesc(TII.get(Opcodes.MOVi32imm));
757 else
758 MIB->setDesc(TII.get(Opcodes.LDRLIT_ga_abs));
759 } else {
760 LLVM_DEBUG(dbgs() << "Object format not supported yet\n");
761 return false;
762 }
763
765 return true;
766}
767
768bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,
769 MachineRegisterInfo &MRI) const {
770 auto &MBB = *MIB->getParent();
771 auto InsertBefore = std::next(MIB->getIterator());
772 auto &DbgLoc = MIB->getDebugLoc();
773
774 // Compare the condition to 1.
775 auto CondReg = MIB.getReg(1);
776 assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) &&
777 "Unsupported types for select operation");
778 auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(Opcodes.TSTri))
779 .addUse(CondReg)
780 .addImm(1)
783
784 // Move a value into the result register based on the result of the
785 // comparison.
786 auto ResReg = MIB.getReg(0);
787 auto TrueReg = MIB.getReg(2);
788 auto FalseReg = MIB.getReg(3);
789 assert(validOpRegPair(MRI, ResReg, TrueReg, 32, ARM::GPRRegBankID) &&
790 validOpRegPair(MRI, TrueReg, FalseReg, 32, ARM::GPRRegBankID) &&
791 "Unsupported types for select operation");
792 auto Mov1I = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(Opcodes.MOVCCr))
793 .addDef(ResReg)
794 .addUse(TrueReg)
795 .addUse(FalseReg)
796 .add(predOps(ARMCC::EQ, ARM::CPSR));
798
799 MIB->eraseFromParent();
800 return true;
801}
802
803bool ARMInstructionSelector::selectShift(unsigned ShiftOpc,
804 MachineInstrBuilder &MIB) const {
805 assert(!STI.isThumb() && "Unsupported subtarget");
806 MIB->setDesc(TII.get(ARM::MOVsr));
807 MIB.addImm(ShiftOpc);
810 return true;
811}
812
813void ARMInstructionSelector::renderVFPF32Imm(
814 MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst,
815 int OpIdx) const {
816 assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&
817 OpIdx == -1 && "Expected G_FCONSTANT");
818
819 APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF();
820 int FPImmEncoding = ARM_AM::getFP32Imm(FPImmValue);
821 assert(FPImmEncoding != -1 && "Invalid immediate value");
822
823 NewInstBuilder.addImm(FPImmEncoding);
824}
825
826void ARMInstructionSelector::renderVFPF64Imm(
827 MachineInstrBuilder &NewInstBuilder, const MachineInstr &OldInst, int OpIdx) const {
828 assert(OldInst.getOpcode() == TargetOpcode::G_FCONSTANT &&
829 OpIdx == -1 && "Expected G_FCONSTANT");
830
831 APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF();
832 int FPImmEncoding = ARM_AM::getFP64Imm(FPImmValue);
833 assert(FPImmEncoding != -1 && "Invalid immediate value");
834
835 NewInstBuilder.addImm(FPImmEncoding);
836}
837
838void ARMInstructionSelector::renderInvertedImm(MachineInstrBuilder &MIB,
839 const MachineInstr &MI,
840 int OpIdx) const {
841 assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
842 "Expected G_CONSTANT");
843 int64_t CVal = MI.getOperand(1).getCImm()->getSExtValue();
844 MIB.addImm(~CVal);
845}
846
847bool ARMInstructionSelector::select(MachineInstr &I) {
848 assert(I.getParent() && "Instruction should be in a basic block!");
849 assert(I.getParent()->getParent() && "Instruction should be in a function!");
850
851 auto &MBB = *I.getParent();
852 auto &MF = *MBB.getParent();
853 auto &MRI = MF.getRegInfo();
854
855 if (!isPreISelGenericOpcode(I.getOpcode())) {
856 if (I.isCopy())
857 return selectCopy(I, TII, MRI, TRI, RBI);
858
859 return true;
860 }
861
862 using namespace TargetOpcode;
863
864 if (selectImpl(I, *CoverageInfo))
865 return true;
866
867 MachineInstrBuilder MIB{MF, I};
868 bool isSExt = false;
869
870 switch (I.getOpcode()) {
871 case G_SEXT:
872 isSExt = true;
873 [[fallthrough]];
874 case G_ZEXT: {
875 assert(MRI.getType(I.getOperand(0).getReg()).getSizeInBits() <= 32 &&
876 "Unsupported destination size for extension");
877
878 LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
879 unsigned SrcSize = SrcTy.getSizeInBits();
880 switch (SrcSize) {
881 case 1: {
882 // ZExt boils down to & 0x1; for SExt we also subtract that from 0
883 I.setDesc(TII.get(Opcodes.AND));
885
886 if (isSExt) {
887 Register SExtResult = I.getOperand(0).getReg();
888
889 // Use a new virtual register for the result of the AND
890 Register AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass);
891 I.getOperand(0).setReg(AndResult);
892
893 auto InsertBefore = std::next(I.getIterator());
894 auto SubI =
895 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(Opcodes.RSB))
896 .addDef(SExtResult)
897 .addUse(AndResult)
898 .addImm(0)
900 .add(condCodeOp());
902 }
903 break;
904 }
905 case 8:
906 case 16: {
907 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);
908 if (NewOpc == I.getOpcode())
909 return false;
910 I.setDesc(TII.get(NewOpc));
911 MIB.addImm(0).add(predOps(ARMCC::AL));
912 break;
913 }
914 default:
915 LLVM_DEBUG(dbgs() << "Unsupported source size for extension");
916 return false;
917 }
918 break;
919 }
920 case G_ANYEXT:
921 case G_TRUNC: {
922 // The high bits are undefined, so there's nothing special to do, just
923 // treat it as a copy.
924 auto SrcReg = I.getOperand(1).getReg();
925 auto DstReg = I.getOperand(0).getReg();
926
927 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
928 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
929
930 if (SrcRegBank.getID() == ARM::FPRRegBankID) {
931 // This should only happen in the obscure case where we have put a 64-bit
932 // integer into a D register. Get it out of there and keep only the
933 // interesting part.
934 assert(I.getOpcode() == G_TRUNC && "Unsupported operand for G_ANYEXT");
935 assert(DstRegBank.getID() == ARM::GPRRegBankID &&
936 "Unsupported combination of register banks");
937 assert(MRI.getType(SrcReg).getSizeInBits() == 64 && "Unsupported size");
938 assert(MRI.getType(DstReg).getSizeInBits() <= 32 && "Unsupported size");
939
940 Register IgnoredBits = MRI.createVirtualRegister(&ARM::GPRRegClass);
941 auto InsertBefore = std::next(I.getIterator());
942 auto MovI =
943 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::VMOVRRD))
944 .addDef(DstReg)
945 .addDef(IgnoredBits)
946 .addUse(SrcReg)
949
950 MIB->eraseFromParent();
951 return true;
952 }
953
954 if (SrcRegBank.getID() != DstRegBank.getID()) {
956 dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");
957 return false;
958 }
959
960 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
961 LLVM_DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
962 return false;
963 }
964
965 I.setDesc(TII.get(COPY));
966 return selectCopy(I, TII, MRI, TRI, RBI);
967 }
968 case G_CONSTANT: {
969 if (!MRI.getType(I.getOperand(0).getReg()).isPointer()) {
970 // Non-pointer constants should be handled by TableGen.
971 LLVM_DEBUG(dbgs() << "Unsupported constant type\n");
972 return false;
973 }
974
975 auto &Val = I.getOperand(1);
976 if (Val.isCImm()) {
977 if (!Val.getCImm()->isZero()) {
978 LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
979 return false;
980 }
981 Val.ChangeToImmediate(0);
982 } else {
983 assert(Val.isImm() && "Unexpected operand for G_CONSTANT");
984 if (Val.getImm() != 0) {
985 LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
986 return false;
987 }
988 }
989
990 assert(!STI.isThumb() && "Unsupported subtarget");
991 I.setDesc(TII.get(ARM::MOVi));
993 break;
994 }
995 case G_FCONSTANT: {
996 // Load from constant pool
997 unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits() / 8;
998 Align Alignment(Size);
999
1000 assert((Size == 4 || Size == 8) && "Unsupported FP constant type");
1001 auto LoadOpcode = Size == 4 ? ARM::VLDRS : ARM::VLDRD;
1002
1003 auto ConstPool = MF.getConstantPool();
1004 auto CPIndex =
1005 ConstPool->getConstantPoolIndex(I.getOperand(1).getFPImm(), Alignment);
1006 MIB->setDesc(TII.get(LoadOpcode));
1007 MIB->removeOperand(1);
1008 MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
1010 MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
1011 MachineMemOperand::MOLoad, Size, Alignment))
1012 .addImm(0)
1014 break;
1015 }
1016 case G_INTTOPTR:
1017 case G_PTRTOINT: {
1018 auto SrcReg = I.getOperand(1).getReg();
1019 auto DstReg = I.getOperand(0).getReg();
1020
1021 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
1022 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
1023
1024 if (SrcRegBank.getID() != DstRegBank.getID()) {
1025 LLVM_DEBUG(
1026 dbgs()
1027 << "G_INTTOPTR/G_PTRTOINT operands on different register banks\n");
1028 return false;
1029 }
1030
1031 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
1032 LLVM_DEBUG(
1033 dbgs() << "G_INTTOPTR/G_PTRTOINT on non-GPR not supported yet\n");
1034 return false;
1035 }
1036
1037 I.setDesc(TII.get(COPY));
1038 return selectCopy(I, TII, MRI, TRI, RBI);
1039 }
1040 case G_SELECT:
1041 return selectSelect(MIB, MRI);
1042 case G_ICMP: {
1043 CmpConstants Helper(Opcodes.CMPrr, ARM::INSTRUCTION_LIST_END,
1044 Opcodes.MOVCCi, ARM::GPRRegBankID, 32);
1045 return selectCmp(Helper, MIB, MRI);
1046 }
1047 case G_FCMP: {
1048 assert(STI.hasVFP2Base() && "Can't select fcmp without VFP");
1049
1050 Register OpReg = I.getOperand(2).getReg();
1051 unsigned Size = MRI.getType(OpReg).getSizeInBits();
1052
1053 if (Size == 64 && !STI.hasFP64()) {
1054 LLVM_DEBUG(dbgs() << "Subtarget only supports single precision");
1055 return false;
1056 }
1057 if (Size != 32 && Size != 64) {
1058 LLVM_DEBUG(dbgs() << "Unsupported size for G_FCMP operand");
1059 return false;
1060 }
1061
1062 CmpConstants Helper(Size == 32 ? ARM::VCMPS : ARM::VCMPD, ARM::FMSTAT,
1063 Opcodes.MOVCCi, ARM::FPRRegBankID, Size);
1064 return selectCmp(Helper, MIB, MRI);
1065 }
1066 case G_LSHR:
1067 return selectShift(ARM_AM::ShiftOpc::lsr, MIB);
1068 case G_ASHR:
1069 return selectShift(ARM_AM::ShiftOpc::asr, MIB);
1070 case G_SHL: {
1071 return selectShift(ARM_AM::ShiftOpc::lsl, MIB);
1072 }
1073 case G_PTR_ADD:
1074 I.setDesc(TII.get(Opcodes.ADDrr));
1076 break;
1077 case G_FRAME_INDEX:
1078 // Add 0 to the given frame index and hope it will eventually be folded into
1079 // the user(s).
1080 I.setDesc(TII.get(Opcodes.ADDri));
1082 break;
1083 case G_GLOBAL_VALUE:
1084 return selectGlobal(MIB, MRI);
1085 case G_STORE:
1086 case G_LOAD: {
1087 auto &MemOp = **I.memoperands_begin();
1088 if (MemOp.isAtomic()) {
1089 LLVM_DEBUG(dbgs() << "Atomic load/store not supported yet\n");
1090 return false;
1091 }
1092
1093 Register Reg = I.getOperand(0).getReg();
1094 unsigned RegBank = RBI.getRegBank(Reg, MRI, TRI)->getID();
1095
1096 LLT ValTy = MRI.getType(Reg);
1097 const auto ValSize = ValTy.getSizeInBits();
1098
1099 assert((ValSize != 64 || STI.hasVFP2Base()) &&
1100 "Don't know how to load/store 64-bit value without VFP");
1101
1102 if (auto *LoadMI = dyn_cast<GLoad>(&I)) {
1103 Register PtrReg = LoadMI->getPointerReg();
1104 MachineInstr *Ptr = MRI.getVRegDef(PtrReg);
1105 if (Ptr->getOpcode() == TargetOpcode::G_CONSTANT_POOL) {
1106 const MachineOperand &Index = Ptr->getOperand(1);
1107 unsigned Opcode = Subtarget->isThumb() ? ARM::tLDRpci : ARM::LDRcp;
1108
1109 auto Instr = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
1110 .addDef(Reg)
1111 .add(Index)
1112 .addImm(0)
1114 .addMemOperand(&MemOp);
1116 I.eraseFromParent();
1117 return true;
1118 }
1119 }
1120
1121 const auto NewOpc = selectLoadStoreOpCode(I.getOpcode(), RegBank, ValSize);
1122 if (NewOpc == G_LOAD || NewOpc == G_STORE)
1123 return false;
1124
1125 I.setDesc(TII.get(NewOpc));
1126
1127 if (NewOpc == ARM::LDRH || NewOpc == ARM::STRH)
1128 // LDRH has a funny addressing mode (there's already a FIXME for it).
1129 MIB.addReg(0);
1130 MIB.addImm(0).add(predOps(ARMCC::AL));
1131 break;
1132 }
1133 case G_MERGE_VALUES: {
1134 if (!selectMergeValues(MIB, TII, MRI, TRI, RBI))
1135 return false;
1136 break;
1137 }
1138 case G_UNMERGE_VALUES: {
1139 if (!selectUnmergeValues(MIB, TII, MRI, TRI, RBI))
1140 return false;
1141 break;
1142 }
1143 case G_BRCOND: {
1144 if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {
1145 LLVM_DEBUG(dbgs() << "Unsupported condition register for G_BRCOND");
1146 return false;
1147 }
1148
1149 // Set the flags.
1150 auto Test =
1151 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.TSTri))
1152 .addReg(I.getOperand(0).getReg())
1153 .addImm(1)
1156
1157 // Branch conditionally.
1158 auto Branch =
1159 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.Bcc))
1160 .add(I.getOperand(1))
1161 .add(predOps(ARMCC::NE, ARM::CPSR));
1163 I.eraseFromParent();
1164 return true;
1165 }
1166 case G_PHI: {
1167 I.setDesc(TII.get(PHI));
1168
1169 Register DstReg = I.getOperand(0).getReg();
1170 const TargetRegisterClass *RC = guessRegClass(DstReg, MRI, TRI, RBI);
1171 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
1172 break;
1173 }
1174
1175 return true;
1176 }
1177 default:
1178 return false;
1179 }
1180
1182 return true;
1183}
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!")
Rewrite undef for PHI
static bool isStore(int Opcode)
static bool isThumb(const MCSubtargetInfo &STI)
static std::pair< ARMCC::CondCodes, ARMCC::CondCodes > getComparePreds(CmpInst::Predicate Pred)
static bool selectMergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
static bool selectUnmergeValues(MachineInstrBuilder &MIB, const ARMBaseInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
#define STORE_OPCODE(VAR, OPC)
This file declares the targeting of the RegisterBankInfo class for ARM.
MachineBasicBlock & MBB
static const Function * getParent(const Value *V)
#define DEBUG_TYPE
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
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 Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
MachineInstr unsigned OpIdx
if(PassOpts->AAPipeline)
static StringRef getName(Value *V)
const SmallVectorImpl< MachineOperand > & Cond
#define LLVM_DEBUG(...)
Definition Debug.h:114
Value * RHS
Value * LHS
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 hasVFP2Base() const
bool isGVInGOT(const GlobalValue *GV) const
Returns the constant pool modifier needed to access the GV.
bool isTargetELF() const
bool isReadOnly(const GlobalValue *GV) const
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:676
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
Definition InstrTypes.h:679
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
Definition InstrTypes.h:693
@ ICMP_SLT
signed less than
Definition InstrTypes.h:705
@ ICMP_SLE
signed less or equal
Definition InstrTypes.h:706
@ FCMP_OLT
0 1 0 0 True if ordered and less than
Definition InstrTypes.h:682
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
Definition InstrTypes.h:691
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
Definition InstrTypes.h:680
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
Definition InstrTypes.h:681
@ ICMP_UGE
unsigned greater or equal
Definition InstrTypes.h:700
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:699
@ ICMP_SGT
signed greater than
Definition InstrTypes.h:703
@ FCMP_ULT
1 1 0 0 True if unordered or less than
Definition InstrTypes.h:690
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
Definition InstrTypes.h:684
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
Definition InstrTypes.h:687
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:701
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
Definition InstrTypes.h:688
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
Definition InstrTypes.h:683
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
Definition InstrTypes.h:685
@ ICMP_NE
not equal
Definition InstrTypes.h:698
@ ICMP_SGE
signed greater or equal
Definition InstrTypes.h:704
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
Definition InstrTypes.h:692
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:702
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
Definition InstrTypes.h:689
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
Definition InstrTypes.h:678
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition InstrTypes.h:686
const APFloat & getValueAPF() const
Definition Constants.h:325
This is an important base class in LLVM.
Definition Constant.h:43
A debug info location.
Definition DebugLoc.h:123
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
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 & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
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 & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
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.
Definition Register.h:20
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
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()
Definition ilist_node.h:123
#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.
@ ARM
Windows AXP64.
Definition MCAsmInfo.h:47
NodeAddr< InstrNode * > Instr
Definition RDFGraph.h:389
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
@ Offset
Definition DWP.cpp:532
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)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI void 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...
Definition Utils.cpp:155
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.
Definition Debug.cpp:207
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.
Definition BitVector.h:870
CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned SelectOpcode, unsigned OpRegBank, unsigned OpSize)
const MachineBasicBlock::instr_iterator InsertBefore
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.