LLVM 24.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().hasFPRegs() &&
239 "Can't select merge without FP Regs");
240
241 // We only support G_MERGE_VALUES as a way to stick together two scalar GPRs
242 // into one DPR.
243 Register VReg0 = MIB.getReg(0);
244 (void)VReg0;
245 assert(MRI.getType(VReg0).getSizeInBits() == 64 &&
246 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::FPRRegBankID &&
247 "Unsupported operand for G_MERGE_VALUES");
248 Register VReg1 = MIB.getReg(1);
249 (void)VReg1;
250 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
251 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
252 "Unsupported operand for G_MERGE_VALUES");
253 Register VReg2 = MIB.getReg(2);
254 (void)VReg2;
255 assert(MRI.getType(VReg2).getSizeInBits() == 32 &&
256 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::GPRRegBankID &&
257 "Unsupported operand for G_MERGE_VALUES");
258
259 MIB->setDesc(TII.get(ARM::VMOVDRR));
260 MIB.add(predOps(ARMCC::AL));
261
262 return true;
263}
264
266 const ARMBaseInstrInfo &TII,
268 const TargetRegisterInfo &TRI,
269 const RegisterBankInfo &RBI) {
270 assert(TII.getSubtarget().hasFPRegs() &&
271 "Can't select unmerge without FP Regs");
272
273 // We only support G_UNMERGE_VALUES as a way to break up one DPR into two
274 // GPRs.
275 Register VReg0 = MIB.getReg(0);
276 (void)VReg0;
277 assert(MRI.getType(VReg0).getSizeInBits() == 32 &&
278 RBI.getRegBank(VReg0, MRI, TRI)->getID() == ARM::GPRRegBankID &&
279 "Unsupported operand for G_UNMERGE_VALUES");
280 Register VReg1 = MIB.getReg(1);
281 (void)VReg1;
282 assert(MRI.getType(VReg1).getSizeInBits() == 32 &&
283 RBI.getRegBank(VReg1, MRI, TRI)->getID() == ARM::GPRRegBankID &&
284 "Unsupported operand for G_UNMERGE_VALUES");
285 Register VReg2 = MIB.getReg(2);
286 (void)VReg2;
287 assert(MRI.getType(VReg2).getSizeInBits() == 64 &&
288 RBI.getRegBank(VReg2, MRI, TRI)->getID() == ARM::FPRRegBankID &&
289 "Unsupported operand for G_UNMERGE_VALUES");
290
291 MIB->setDesc(TII.get(ARM::VMOVRRD));
292 MIB.add(predOps(ARMCC::AL));
293
294 return true;
295}
296
297ARMInstructionSelector::OpcodeCache::OpcodeCache(const ARMSubtarget &STI) {
298 bool isThumb = STI.isThumb();
299
300 using namespace TargetOpcode;
301
302#define STORE_OPCODE(VAR, OPC) VAR = isThumb ? ARM::t2##OPC : ARM::OPC
303 STORE_OPCODE(SEXT16, SXTH);
304 STORE_OPCODE(ZEXT16, UXTH);
305
306 STORE_OPCODE(SEXT8, SXTB);
307 STORE_OPCODE(ZEXT8, UXTB);
308
309 STORE_OPCODE(AND, ANDri);
310 STORE_OPCODE(RSB, RSBri);
311
312 STORE_OPCODE(STORE32, STRi12);
313 STORE_OPCODE(LOAD32, LDRi12);
314
315 // LDRH/STRH are special...
316 STORE16 = isThumb ? ARM::t2STRHi12 : ARM::STRH;
317 LOAD16 = isThumb ? ARM::t2LDRHi12 : ARM::LDRH;
318
319 STORE_OPCODE(STORE8, STRBi12);
320 STORE_OPCODE(LOAD8, LDRBi12);
321
322 STORE_OPCODE(ADDrr, ADDrr);
323 STORE_OPCODE(ADDri, ADDri);
324
325 STORE_OPCODE(CMPrr, CMPrr);
326 STORE_OPCODE(MOVi, MOVi);
327 STORE_OPCODE(MOVCCi, MOVCCi);
328
329 STORE_OPCODE(MOVCCr, MOVCCr);
330
331 STORE_OPCODE(TSTri, TSTri);
332 STORE_OPCODE(Bcc, Bcc);
333
334 STORE_OPCODE(MOVi32imm, MOVi32imm);
335 ConstPoolLoad = isThumb ? ARM::t2LDRpci : ARM::LDRi12;
336 STORE_OPCODE(MOV_ga_pcrel, MOV_ga_pcrel);
337 LDRLIT_ga_pcrel = isThumb ? ARM::tLDRLIT_ga_pcrel : ARM::LDRLIT_ga_pcrel;
338 LDRLIT_ga_abs = isThumb ? ARM::tLDRLIT_ga_abs : ARM::LDRLIT_ga_abs;
339#undef MAP_OPCODE
340}
341
342unsigned ARMInstructionSelector::selectSimpleExtOpc(unsigned Opc,
343 unsigned Size) const {
344 using namespace TargetOpcode;
345
346 if (Size != 8 && Size != 16)
347 return Opc;
348
349 if (Opc == G_SEXT)
350 return Size == 8 ? Opcodes.SEXT8 : Opcodes.SEXT16;
351
352 if (Opc == G_ZEXT)
353 return Size == 8 ? Opcodes.ZEXT8 : Opcodes.ZEXT16;
354
355 return Opc;
356}
357
358unsigned ARMInstructionSelector::selectLoadStoreOpCode(unsigned Opc,
359 unsigned RegBank,
360 unsigned Size) const {
361 bool isStore = Opc == TargetOpcode::G_STORE;
362
363 if (RegBank == ARM::GPRRegBankID) {
364 switch (Size) {
365 case 1:
366 case 8:
367 return isStore ? Opcodes.STORE8 : Opcodes.LOAD8;
368 case 16:
369 return isStore ? Opcodes.STORE16 : Opcodes.LOAD16;
370 case 32:
371 return isStore ? Opcodes.STORE32 : Opcodes.LOAD32;
372 default:
373 return Opc;
374 }
375 }
376
377 if (RegBank == ARM::FPRRegBankID) {
378 switch (Size) {
379 case 32:
380 return isStore ? ARM::VSTRS : ARM::VLDRS;
381 case 64:
382 return isStore ? ARM::VSTRD : ARM::VLDRD;
383 default:
384 return Opc;
385 }
386 }
387
388 return Opc;
389}
390
391// When lowering comparisons, we sometimes need to perform two compares instead
392// of just one. Get the condition codes for both comparisons. If only one is
393// needed, the second member of the pair is ARMCC::AL.
394static std::pair<ARMCC::CondCodes, ARMCC::CondCodes>
396 std::pair<ARMCC::CondCodes, ARMCC::CondCodes> Preds = {ARMCC::AL, ARMCC::AL};
397 switch (Pred) {
399 Preds = {ARMCC::GT, ARMCC::MI};
400 break;
402 Preds = {ARMCC::EQ, ARMCC::VS};
403 break;
404 case CmpInst::ICMP_EQ:
406 Preds.first = ARMCC::EQ;
407 break;
410 Preds.first = ARMCC::GT;
411 break;
414 Preds.first = ARMCC::GE;
415 break;
418 Preds.first = ARMCC::HI;
419 break;
421 Preds.first = ARMCC::MI;
422 break;
425 Preds.first = ARMCC::LS;
426 break;
428 Preds.first = ARMCC::VC;
429 break;
431 Preds.first = ARMCC::VS;
432 break;
434 Preds.first = ARMCC::PL;
435 break;
438 Preds.first = ARMCC::LT;
439 break;
442 Preds.first = ARMCC::LE;
443 break;
445 case CmpInst::ICMP_NE:
446 Preds.first = ARMCC::NE;
447 break;
449 Preds.first = ARMCC::HS;
450 break;
452 Preds.first = ARMCC::LO;
453 break;
454 default:
455 break;
456 }
457 assert(Preds.first != ARMCC::AL && "No comparisons needed?");
458 return Preds;
459}
460
462 CmpConstants(unsigned CmpOpcode, unsigned FlagsOpcode, unsigned SelectOpcode,
463 unsigned OpRegBank, unsigned OpSize)
464 : ComparisonOpcode(CmpOpcode), ReadFlagsOpcode(FlagsOpcode),
465 SelectResultOpcode(SelectOpcode), OperandRegBankID(OpRegBank),
466 OperandSize(OpSize) {}
467
468 // The opcode used for performing the comparison.
469 const unsigned ComparisonOpcode;
470
471 // The opcode used for reading the flags set by the comparison. May be
472 // ARM::INSTRUCTION_LIST_END if we don't need to read the flags.
473 const unsigned ReadFlagsOpcode;
474
475 // The opcode used for materializing the result of the comparison.
476 const unsigned SelectResultOpcode;
477
478 // The assumed register bank ID for the operands.
479 const unsigned OperandRegBankID;
480
481 // The assumed size in bits for the operands.
482 const unsigned OperandSize;
483};
484
494
495void ARMInstructionSelector::putConstant(InsertInfo I, unsigned DestReg,
496 unsigned Constant) const {
497 (void)BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Opcodes.MOVi))
498 .addDef(DestReg)
501 .add(condCodeOp());
502}
503
504bool ARMInstructionSelector::validOpRegPair(MachineRegisterInfo &MRI,
505 unsigned LHSReg, unsigned RHSReg,
506 unsigned ExpectedSize,
507 unsigned ExpectedRegBankID) const {
508 return MRI.getType(LHSReg) == MRI.getType(RHSReg) &&
509 validReg(MRI, LHSReg, ExpectedSize, ExpectedRegBankID) &&
510 validReg(MRI, RHSReg, ExpectedSize, ExpectedRegBankID);
511}
512
513bool ARMInstructionSelector::validReg(MachineRegisterInfo &MRI, unsigned Reg,
514 unsigned ExpectedSize,
515 unsigned ExpectedRegBankID) const {
516 if (MRI.getType(Reg).getSizeInBits() != ExpectedSize) {
517 LLVM_DEBUG(dbgs() << "Unexpected size for register");
518 return false;
519 }
520
521 if (RBI.getRegBank(Reg, MRI, TRI)->getID() != ExpectedRegBankID) {
522 LLVM_DEBUG(dbgs() << "Unexpected register bank for register");
523 return false;
524 }
525
526 return true;
527}
528
529bool ARMInstructionSelector::selectCmp(CmpConstants Helper,
530 MachineInstrBuilder &MIB,
531 MachineRegisterInfo &MRI) const {
532 const InsertInfo I(MIB);
533
534 auto ResReg = MIB.getReg(0);
535 if (!validReg(MRI, ResReg, 1, ARM::GPRRegBankID))
536 return false;
537
538 auto Cond =
539 static_cast<CmpInst::Predicate>(MIB->getOperand(1).getPredicate());
541 putConstant(I, ResReg, Cond == CmpInst::FCMP_TRUE ? 1 : 0);
542 MIB->eraseFromParent();
543 return true;
544 }
545
546 auto LHSReg = MIB.getReg(2);
547 auto RHSReg = MIB.getReg(3);
548 if (!validOpRegPair(MRI, LHSReg, RHSReg, Helper.OperandSize,
549 Helper.OperandRegBankID))
550 return false;
551
552 auto ARMConds = getComparePreds(Cond);
553 auto ZeroReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
554 putConstant(I, ZeroReg, 0);
555
556 if (ARMConds.second == ARMCC::AL) {
557 // Simple case, we only need one comparison and we're done.
558 if (!insertComparison(Helper, I, ResReg, ARMConds.first, LHSReg, RHSReg,
559 ZeroReg))
560 return false;
561 } else {
562 // Not so simple, we need two successive comparisons.
563 auto IntermediateRes = MRI.createVirtualRegister(&ARM::GPRRegClass);
564 if (!insertComparison(Helper, I, IntermediateRes, ARMConds.first, LHSReg,
565 RHSReg, ZeroReg))
566 return false;
567 if (!insertComparison(Helper, I, ResReg, ARMConds.second, LHSReg, RHSReg,
568 IntermediateRes))
569 return false;
570 }
571
572 MIB->eraseFromParent();
573 return true;
574}
575
576bool ARMInstructionSelector::insertComparison(CmpConstants Helper, InsertInfo I,
577 unsigned ResReg,
579 unsigned LHSReg, unsigned RHSReg,
580 unsigned PrevRes) const {
581 // Perform the comparison.
582 auto CmpI =
583 BuildMI(I.MBB, I.InsertBefore, I.DbgLoc, TII.get(Helper.ComparisonOpcode))
584 .addUse(LHSReg)
585 .addUse(RHSReg)
588
589 // Read the comparison flags (if necessary).
590 if (Helper.ReadFlagsOpcode != ARM::INSTRUCTION_LIST_END) {
591 auto ReadI = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
592 TII.get(Helper.ReadFlagsOpcode))
595 }
596
597 // Select either 1 or the previous result based on the value of the flags.
598 auto Mov1I = BuildMI(I.MBB, I.InsertBefore, I.DbgLoc,
599 TII.get(Helper.SelectResultOpcode))
600 .addDef(ResReg)
601 .addUse(PrevRes)
602 .addImm(1)
603 .add(predOps(Cond, ARM::CPSR));
605
606 return true;
607}
608
609bool ARMInstructionSelector::selectGlobal(MachineInstrBuilder &MIB,
610 MachineRegisterInfo &MRI) const {
611 if ((STI.isROPI() || STI.isRWPI()) && !STI.isTargetELF()) {
612 LLVM_DEBUG(dbgs() << "ROPI and RWPI only supported for ELF\n");
613 return false;
614 }
615
616 auto GV = MIB->getOperand(1).getGlobal();
617 if (GV->isThreadLocal()) {
618 LLVM_DEBUG(dbgs() << "TLS variables not supported yet\n");
619 return false;
620 }
621
622 auto &MBB = *MIB->getParent();
623 auto &MF = *MBB.getParent();
624
625 bool UseMovt = STI.useMovt();
626
627 LLT PtrTy = MRI.getType(MIB->getOperand(0).getReg());
628 const Align Alignment(4);
629
630 auto addOpsForConstantPoolLoad = [&MF, Alignment, PtrTy](
631 MachineInstrBuilder &MIB,
632 const GlobalValue *GV, bool IsSBREL) {
633 assert((MIB->getOpcode() == ARM::LDRi12 ||
634 MIB->getOpcode() == ARM::t2LDRpci) &&
635 "Unsupported instruction");
636 auto ConstPool = MF.getConstantPool();
637 auto CPIndex =
638 // For SB relative entries we need a target-specific constant pool.
639 // Otherwise, just use a regular constant pool entry.
640 IsSBREL
641 ? ConstPool->getConstantPoolIndex(
643 : ConstPool->getConstantPoolIndex(GV, Alignment);
644 MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
645 .addMemOperand(MF.getMachineMemOperand(
647 PtrTy, Alignment));
648 if (MIB->getOpcode() == ARM::LDRi12)
649 MIB.addImm(0);
650 MIB.add(predOps(ARMCC::AL));
651 };
652
653 auto addGOTMemOperand = [&MF, Alignment](MachineInstrBuilder &MIB) {
654 const DataLayout &DL = MF.getDataLayout();
655 MIB.addMemOperand(MF.getMachineMemOperand(
657 DL.getPointerSize(DL.getProgramAddressSpace()), Alignment));
658 };
659
660 if (TM.isPositionIndependent()) {
661 bool Indirect = STI.isGVIndirectSymbol(GV);
662
663 // For ARM mode, we have different pseudoinstructions for direct accesses
664 // and indirect accesses, and the ones for indirect accesses include the
665 // load from GOT. For Thumb mode, we use the same pseudoinstruction for both
666 // direct and indirect accesses, and we need to manually generate the load
667 // from GOT.
668 bool UseOpcodeThatLoads = Indirect && !STI.isThumb();
669
670 // FIXME: Taking advantage of MOVT for ELF is pretty involved, so we don't
671 // support it yet. See PR28229.
672 unsigned Opc =
673 UseMovt && !STI.isTargetELF()
674 ? (UseOpcodeThatLoads ? (unsigned)ARM::MOV_ga_pcrel_ldr
675 : Opcodes.MOV_ga_pcrel)
676 : (UseOpcodeThatLoads ? (unsigned)ARM::LDRLIT_ga_pcrel_ldr
677 : Opcodes.LDRLIT_ga_pcrel);
678 MIB->setDesc(TII.get(Opc));
679
680 int TargetFlags = ARMII::MO_NO_FLAG;
681 if (STI.isTargetDarwin())
682 TargetFlags |= ARMII::MO_NONLAZY;
683 if (STI.isGVInGOT(GV))
684 TargetFlags |= ARMII::MO_GOT;
685 MIB->getOperand(1).setTargetFlags(TargetFlags);
686
687 if (Indirect) {
688 if (!UseOpcodeThatLoads) {
689 auto ResultReg = MIB.getReg(0);
690 auto AddressReg = MRI.createVirtualRegister(&ARM::GPRRegClass);
691
692 MIB->getOperand(0).setReg(AddressReg);
693
694 auto InsertBefore = std::next(MIB->getIterator());
695 auto MIBLoad = BuildMI(MBB, InsertBefore, MIB->getDebugLoc(),
696 TII.get(Opcodes.LOAD32))
697 .addDef(ResultReg)
698 .addReg(AddressReg)
699 .addImm(0)
701 addGOTMemOperand(MIBLoad);
702
704 } else {
705 addGOTMemOperand(MIB);
706 }
707 }
708
710 return true;
711 }
712
713 bool isReadOnly = STI.getTargetLowering()->isReadOnly(GV);
714 if (STI.isROPI() && isReadOnly) {
715 unsigned Opc = UseMovt ? Opcodes.MOV_ga_pcrel : Opcodes.LDRLIT_ga_pcrel;
716 MIB->setDesc(TII.get(Opc));
718 return true;
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(),
725 TII.get(Opcodes.MOVi32imm), Offset);
726 OffsetMIB.addGlobalAddress(GV, /*Offset*/ 0, ARMII::MO_SBREL);
727 } else {
728 // Load the offset from the constant pool.
729 OffsetMIB = BuildMI(MBB, *MIB, MIB->getDebugLoc(),
730 TII.get(Opcodes.ConstPoolLoad), Offset);
731 addOpsForConstantPoolLoad(OffsetMIB, GV, /*IsSBREL*/ true);
732 }
733 constrainSelectedInstRegOperands(*OffsetMIB, TII, TRI, RBI);
734
735 // Add the offset to the SB register.
736 MIB->setDesc(TII.get(Opcodes.ADDrr));
737 MIB->removeOperand(1);
738 MIB.addReg(ARM::R9) // FIXME: don't hardcode R9
739 .addReg(Offset)
740 .add(predOps(ARMCC::AL))
741 .add(condCodeOp());
742
744 return true;
745 }
746
747 if (STI.isTargetELF()) {
748 if (UseMovt) {
749 MIB->setDesc(TII.get(Opcodes.MOVi32imm));
750 } else {
751 // Load the global's address from the constant pool.
752 MIB->setDesc(TII.get(Opcodes.ConstPoolLoad));
753 MIB->removeOperand(1);
754 addOpsForConstantPoolLoad(MIB, GV, /*IsSBREL*/ false);
755 }
756 } else if (STI.isTargetMachO()) {
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 return true;
768}
769
770bool ARMInstructionSelector::selectSelect(MachineInstrBuilder &MIB,
771 MachineRegisterInfo &MRI) const {
772 auto &MBB = *MIB->getParent();
773 auto InsertBefore = std::next(MIB->getIterator());
774 auto &DbgLoc = MIB->getDebugLoc();
775
776 // Compare the condition to 1.
777 auto CondReg = MIB.getReg(1);
778 assert(validReg(MRI, CondReg, 1, ARM::GPRRegBankID) &&
779 "Unsupported types for select operation");
780 auto CmpI = BuildMI(MBB, InsertBefore, DbgLoc, TII.get(Opcodes.TSTri))
781 .addUse(CondReg)
782 .addImm(1)
785
786 // Move a value into the result register based on the result of the
787 // comparison.
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))
795 .addDef(ResReg)
796 .addUse(TrueReg)
797 .addUse(FalseReg)
798 .add(predOps(ARMCC::EQ, ARM::CPSR));
800
801 MIB->eraseFromParent();
802 return true;
803}
804
805bool ARMInstructionSelector::selectShift(unsigned ShiftOpc,
806 MachineInstrBuilder &MIB) const {
807 assert(!STI.isThumb() && "Unsupported subtarget");
808 MIB->setDesc(TII.get(ARM::MOVsr));
809 MIB.addImm(ShiftOpc);
812 return true;
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
821 APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF();
822 int FPImmEncoding = ARM_AM::getFP32Imm(FPImmValue);
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
833 APFloat FPImmValue = OldInst.getOperand(1).getFPImm()->getValueAPF();
834 int FPImmEncoding = ARM_AM::getFP64Imm(FPImmValue);
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();
846 MIB.addImm(~CVal);
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
853 auto &MBB = *I.getParent();
854 auto &MF = *MBB.getParent();
855 auto &MRI = MF.getRegInfo();
856
857 if (!isPreISelGenericOpcode(I.getOpcode())) {
858 if (I.isCopy())
859 return selectCopy(I, TII, MRI, TRI, RBI);
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 TargetOpcode::G_BITCAST:
874 I.setDesc(TII.get(COPY));
875 return selectCopy(I, TII, MRI, TRI, RBI);
876 case G_SEXT:
877 isSExt = true;
878 [[fallthrough]];
879 case G_ZEXT: {
880 assert(MRI.getType(I.getOperand(0).getReg()).getSizeInBits() <= 32 &&
881 "Unsupported destination size for extension");
882
883 LLT SrcTy = MRI.getType(I.getOperand(1).getReg());
884 unsigned SrcSize = SrcTy.getSizeInBits();
885 switch (SrcSize) {
886 case 1: {
887 // ZExt boils down to & 0x1; for SExt we also subtract that from 0
888 I.setDesc(TII.get(Opcodes.AND));
890
891 if (isSExt) {
892 Register SExtResult = I.getOperand(0).getReg();
893
894 // Use a new virtual register for the result of the AND
895 Register AndResult = MRI.createVirtualRegister(&ARM::GPRRegClass);
896 I.getOperand(0).setReg(AndResult);
897
898 auto InsertBefore = std::next(I.getIterator());
899 auto SubI =
900 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(Opcodes.RSB))
901 .addDef(SExtResult)
902 .addUse(AndResult)
903 .addImm(0)
905 .add(condCodeOp());
907 }
908 break;
909 }
910 case 8:
911 case 16: {
912 unsigned NewOpc = selectSimpleExtOpc(I.getOpcode(), SrcSize);
913 if (NewOpc == I.getOpcode())
914 return false;
915 I.setDesc(TII.get(NewOpc));
916 MIB.addImm(0).add(predOps(ARMCC::AL));
917 break;
918 }
919 default:
920 LLVM_DEBUG(dbgs() << "Unsupported source size for extension");
921 return false;
922 }
923 break;
924 }
925 case G_ANYEXT:
926 case G_TRUNC: {
927 // The high bits are undefined, so there's nothing special to do, just
928 // treat it as a copy.
929 auto SrcReg = I.getOperand(1).getReg();
930 auto DstReg = I.getOperand(0).getReg();
931
932 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
933 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
934
935 if (SrcRegBank.getID() == ARM::FPRRegBankID) {
936 // This should only happen in the obscure case where we have put a 64-bit
937 // integer into a D register. Get it out of there and keep only the
938 // interesting part.
939 assert(I.getOpcode() == G_TRUNC && "Unsupported operand for G_ANYEXT");
940 assert(DstRegBank.getID() == ARM::GPRRegBankID &&
941 "Unsupported combination of register banks");
942 assert(MRI.getType(SrcReg).getSizeInBits() == 64 && "Unsupported size");
943 assert(MRI.getType(DstReg).getSizeInBits() <= 32 && "Unsupported size");
944
945 Register IgnoredBits = MRI.createVirtualRegister(&ARM::GPRRegClass);
946 auto InsertBefore = std::next(I.getIterator());
947 auto MovI =
948 BuildMI(MBB, InsertBefore, I.getDebugLoc(), TII.get(ARM::VMOVRRD))
949 .addDef(DstReg)
950 .addDef(IgnoredBits)
951 .addUse(SrcReg)
954
955 MIB->eraseFromParent();
956 return true;
957 }
958
959 if (SrcRegBank.getID() != DstRegBank.getID()) {
961 dbgs() << "G_TRUNC/G_ANYEXT operands on different register banks\n");
962 return false;
963 }
964
965 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
966 LLVM_DEBUG(dbgs() << "G_TRUNC/G_ANYEXT on non-GPR not supported yet\n");
967 return false;
968 }
969
970 I.setDesc(TII.get(COPY));
971 return selectCopy(I, TII, MRI, TRI, RBI);
972 }
973 case G_CONSTANT: {
974 if (!MRI.getType(I.getOperand(0).getReg()).isPointer()) {
975 // Non-pointer constants should be handled by TableGen.
976 LLVM_DEBUG(dbgs() << "Unsupported constant type\n");
977 return false;
978 }
979
980 auto &Val = I.getOperand(1);
981 if (Val.isCImm()) {
982 if (!Val.getCImm()->isZero()) {
983 LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
984 return false;
985 }
986 Val.ChangeToImmediate(0);
987 } else {
988 assert(Val.isImm() && "Unexpected operand for G_CONSTANT");
989 if (Val.getImm() != 0) {
990 LLVM_DEBUG(dbgs() << "Unsupported pointer constant value\n");
991 return false;
992 }
993 }
994
995 assert(!STI.isThumb() && "Unsupported subtarget");
996 I.setDesc(TII.get(ARM::MOVi));
998 break;
999 }
1000 case G_FCONSTANT: {
1001 // Load from constant pool
1002 unsigned Size = MRI.getType(I.getOperand(0).getReg()).getSizeInBits() / 8;
1004
1005 assert((Size == 4 || Size == 8) && "Unsupported FP constant type");
1006 auto LoadOpcode = Size == 4 ? ARM::VLDRS : ARM::VLDRD;
1007
1008 auto ConstPool = MF.getConstantPool();
1009 auto CPIndex =
1010 ConstPool->getConstantPoolIndex(I.getOperand(1).getFPImm(), Alignment);
1011 MIB->setDesc(TII.get(LoadOpcode));
1012 MIB->removeOperand(1);
1013 MIB.addConstantPoolIndex(CPIndex, /*Offset*/ 0, /*TargetFlags*/ 0)
1015 MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
1016 MachineMemOperand::MOLoad, Size, Alignment))
1017 .addImm(0)
1019 break;
1020 }
1021 case G_INTTOPTR:
1022 case G_PTRTOINT: {
1023 auto SrcReg = I.getOperand(1).getReg();
1024 auto DstReg = I.getOperand(0).getReg();
1025
1026 const auto &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
1027 const auto &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
1028
1029 if (SrcRegBank.getID() != DstRegBank.getID()) {
1030 LLVM_DEBUG(
1031 dbgs()
1032 << "G_INTTOPTR/G_PTRTOINT operands on different register banks\n");
1033 return false;
1034 }
1035
1036 if (SrcRegBank.getID() != ARM::GPRRegBankID) {
1037 LLVM_DEBUG(
1038 dbgs() << "G_INTTOPTR/G_PTRTOINT on non-GPR not supported yet\n");
1039 return false;
1040 }
1041
1042 I.setDesc(TII.get(COPY));
1043 return selectCopy(I, TII, MRI, TRI, RBI);
1044 }
1045 case G_SELECT:
1046 return selectSelect(MIB, MRI);
1047 case G_ICMP: {
1048 CmpConstants Helper(Opcodes.CMPrr, ARM::INSTRUCTION_LIST_END,
1049 Opcodes.MOVCCi, ARM::GPRRegBankID, 32);
1050 return selectCmp(Helper, MIB, MRI);
1051 }
1052 case G_FCMP: {
1053 assert(STI.hasVFP2Base() && "Can't select fcmp without VFP");
1054
1055 Register OpReg = I.getOperand(2).getReg();
1056 unsigned Size = MRI.getType(OpReg).getSizeInBits();
1057
1058 if (Size == 64 && !STI.hasFP64()) {
1059 LLVM_DEBUG(dbgs() << "Subtarget only supports single precision");
1060 return false;
1061 }
1062 if (Size != 32 && Size != 64) {
1063 LLVM_DEBUG(dbgs() << "Unsupported size for G_FCMP operand");
1064 return false;
1065 }
1066
1067 CmpConstants Helper(Size == 32 ? ARM::VCMPS : ARM::VCMPD, ARM::FMSTAT,
1068 Opcodes.MOVCCi, ARM::FPRRegBankID, Size);
1069 return selectCmp(Helper, MIB, MRI);
1070 }
1071 case G_LSHR:
1072 return selectShift(ARM_AM::ShiftOpc::lsr, MIB);
1073 case G_ASHR:
1074 return selectShift(ARM_AM::ShiftOpc::asr, MIB);
1075 case G_SHL: {
1076 return selectShift(ARM_AM::ShiftOpc::lsl, MIB);
1077 }
1078 case G_PTR_ADD:
1079 I.setDesc(TII.get(Opcodes.ADDrr));
1081 break;
1082 case G_FRAME_INDEX:
1083 // Add 0 to the given frame index and hope it will eventually be folded into
1084 // the user(s).
1085 I.setDesc(TII.get(Opcodes.ADDri));
1087 break;
1088 case G_GLOBAL_VALUE:
1089 return selectGlobal(MIB, MRI);
1090 case G_STORE:
1091 case G_LOAD: {
1092 auto &MemOp = **I.memoperands_begin();
1093 if (MemOp.isAtomic()) {
1094 LLVM_DEBUG(dbgs() << "Atomic load/store not supported yet\n");
1095 return false;
1096 }
1097
1098 Register Reg = I.getOperand(0).getReg();
1099 unsigned RegBank = RBI.getRegBank(Reg, MRI, TRI)->getID();
1100
1101 LLT ValTy = MRI.getType(Reg);
1102 const auto ValSize = ValTy.getSizeInBits();
1103
1104 assert((ValSize != 64 || STI.hasVFP2Base()) &&
1105 "Don't know how to load/store 64-bit value without VFP");
1106
1107 if (auto *LoadMI = dyn_cast<GLoad>(&I)) {
1108 Register PtrReg = LoadMI->getPointerReg();
1109 MachineInstr *Ptr = MRI.getVRegDef(PtrReg);
1110 if (Ptr->getOpcode() == TargetOpcode::G_CONSTANT_POOL) {
1111 const MachineOperand &Index = Ptr->getOperand(1);
1112 unsigned Opcode = Subtarget->isThumb() ? ARM::tLDRpci : ARM::LDRcp;
1113
1114 auto Instr = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Opcode))
1115 .addDef(Reg)
1116 .add(Index)
1117 .addImm(0)
1119 .addMemOperand(&MemOp);
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 // LDRH has a funny addressing mode (there's already a FIXME for it).
1134 MIB.addReg(0);
1135 MIB.addImm(0).add(predOps(ARMCC::AL));
1136 break;
1137 }
1138 case G_MERGE_VALUES: {
1139 if (!selectMergeValues(MIB, TII, MRI, TRI, RBI))
1140 return false;
1141 break;
1142 }
1143 case G_UNMERGE_VALUES: {
1144 if (!selectUnmergeValues(MIB, TII, MRI, TRI, RBI))
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 // Set the flags.
1155 auto Test =
1156 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.TSTri))
1157 .addReg(I.getOperand(0).getReg())
1158 .addImm(1)
1161
1162 // Branch conditionally.
1163 auto Branch =
1164 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcodes.Bcc))
1165 .add(I.getOperand(1))
1166 .add(predOps(ARMCC::NE, ARM::CPSR));
1168 I.eraseFromParent();
1169 return true;
1170 }
1171 case G_PHI: {
1172 I.setDesc(TII.get(PHI));
1173
1174 Register DstReg = I.getOperand(0).getReg();
1175 const TargetRegisterClass *RC = guessRegClass(DstReg, MRI, TRI, RBI);
1176 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
1177 break;
1178 }
1179
1180 return true;
1181 }
1182 default:
1183 return false;
1184 }
1185
1187 return true;
1188}
const AArch64Subtarget & Subtarget
SDValue Pred
#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
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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
if(PassOpts->AAPipeline)
static StringRef getName(Value *V)
SmallVector< MachineOperand, 4 > Cond
MachineRegisterInfo & MRI
#define LLVM_DEBUG(...)
Definition Debug.h:119
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:740
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
Definition InstrTypes.h:743
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
Definition InstrTypes.h:757
@ ICMP_SLT
signed less than
Definition InstrTypes.h:769
@ ICMP_SLE
signed less or equal
Definition InstrTypes.h:770
@ FCMP_OLT
0 1 0 0 True if ordered and less than
Definition InstrTypes.h:746
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
Definition InstrTypes.h:755
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
Definition InstrTypes.h:744
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
Definition InstrTypes.h:745
@ ICMP_UGE
unsigned greater or equal
Definition InstrTypes.h:764
@ ICMP_UGT
unsigned greater than
Definition InstrTypes.h:763
@ ICMP_SGT
signed greater than
Definition InstrTypes.h:767
@ FCMP_ULT
1 1 0 0 True if unordered or less than
Definition InstrTypes.h:754
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
Definition InstrTypes.h:748
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
Definition InstrTypes.h:751
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
Definition InstrTypes.h:752
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
Definition InstrTypes.h:747
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
Definition InstrTypes.h:749
@ ICMP_NE
not equal
Definition InstrTypes.h:762
@ ICMP_SGE
signed greater or equal
Definition InstrTypes.h:768
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
Definition InstrTypes.h:756
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:766
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
Definition InstrTypes.h:753
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
Definition InstrTypes.h:742
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition InstrTypes.h:750
const APFloat & getValueAPF() const
Definition Constants.h:463
This is an important base class in LLVM.
Definition Constant.h:44
A debug info location.
Definition DebugLoc.h:126
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
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 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
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
@ 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,...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
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
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:50
NodeAddr< InstrNode * > Instr
Definition RDFGraph.h:389
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
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:163
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:209
static MachineOperand condCodeOp(unsigned CCReg=0)
Get the operand corresponding to the conditional code result.
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:879
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.