LLVM 17.0.0git
X86InstructionSelector.cpp
Go to the documentation of this file.
1//===- X86InstructionSelector.cpp -----------------------------------------===//
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
10/// X86.
11/// \todo This should be generated by TableGen.
12//===----------------------------------------------------------------------===//
13
15#include "X86.h"
16#include "X86InstrBuilder.h"
17#include "X86InstrInfo.h"
18#include "X86RegisterBankInfo.h"
19#include "X86RegisterInfo.h"
20#include "X86Subtarget.h"
21#include "X86TargetMachine.h"
36#include "llvm/IR/DataLayout.h"
37#include "llvm/IR/InstrTypes.h"
38#include "llvm/IR/IntrinsicsX86.h"
41#include "llvm/Support/Debug.h"
46#include <cassert>
47#include <cstdint>
48#include <tuple>
49
50#define DEBUG_TYPE "X86-isel"
51
52using namespace llvm;
53
54namespace {
55
56#define GET_GLOBALISEL_PREDICATE_BITSET
57#include "X86GenGlobalISel.inc"
58#undef GET_GLOBALISEL_PREDICATE_BITSET
59
60class X86InstructionSelector : public InstructionSelector {
61public:
62 X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
63 const X86RegisterBankInfo &RBI);
64
65 bool select(MachineInstr &I) override;
66 static const char *getName() { return DEBUG_TYPE; }
67
68private:
69 /// tblgen-erated 'select' implementation, used as the initial selector for
70 /// the patterns that don't require complex C++.
71 bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
72
73 // TODO: remove after supported by Tablegen-erated instruction selection.
74 unsigned getLoadStoreOp(const LLT &Ty, const RegisterBank &RB, unsigned Opc,
75 Align Alignment) const;
76
78 MachineFunction &MF) const;
79 bool selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI,
80 MachineFunction &MF) const;
81 bool selectGlobalValue(MachineInstr &I, MachineRegisterInfo &MRI,
82 MachineFunction &MF) const;
83 bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
84 MachineFunction &MF) const;
85 bool selectTruncOrPtrToInt(MachineInstr &I, MachineRegisterInfo &MRI,
86 MachineFunction &MF) const;
87 bool selectZext(MachineInstr &I, MachineRegisterInfo &MRI,
88 MachineFunction &MF) const;
89 bool selectAnyext(MachineInstr &I, MachineRegisterInfo &MRI,
90 MachineFunction &MF) const;
91 bool selectCmp(MachineInstr &I, MachineRegisterInfo &MRI,
92 MachineFunction &MF) const;
93 bool selectFCmp(MachineInstr &I, MachineRegisterInfo &MRI,
94 MachineFunction &MF) const;
95 bool selectUadde(MachineInstr &I, MachineRegisterInfo &MRI,
96 MachineFunction &MF) const;
100 MachineFunction &MF);
102 MachineFunction &MF);
103 bool selectInsert(MachineInstr &I, MachineRegisterInfo &MRI,
104 MachineFunction &MF) const;
105 bool selectExtract(MachineInstr &I, MachineRegisterInfo &MRI,
106 MachineFunction &MF) const;
107 bool selectCondBranch(MachineInstr &I, MachineRegisterInfo &MRI,
108 MachineFunction &MF) const;
109 bool selectTurnIntoCOPY(MachineInstr &I, MachineRegisterInfo &MRI,
110 const unsigned DstReg,
111 const TargetRegisterClass *DstRC,
112 const unsigned SrcReg,
113 const TargetRegisterClass *SrcRC) const;
114 bool materializeFP(MachineInstr &I, MachineRegisterInfo &MRI,
115 MachineFunction &MF) const;
116 bool selectImplicitDefOrPHI(MachineInstr &I, MachineRegisterInfo &MRI) const;
117 bool selectDivRem(MachineInstr &I, MachineRegisterInfo &MRI,
118 MachineFunction &MF) const;
119 bool selectIntrinsicWSideEffects(MachineInstr &I, MachineRegisterInfo &MRI,
120 MachineFunction &MF) const;
121
122 // emit insert subreg instruction and insert it before MachineInstr &I
123 bool emitInsertSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
125 // emit extract subreg instruction and insert it before MachineInstr &I
126 bool emitExtractSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
128
129 const TargetRegisterClass *getRegClass(LLT Ty, const RegisterBank &RB) const;
130 const TargetRegisterClass *getRegClass(LLT Ty, unsigned Reg,
131 MachineRegisterInfo &MRI) const;
132
133 const X86TargetMachine &TM;
134 const X86Subtarget &STI;
135 const X86InstrInfo &TII;
136 const X86RegisterInfo &TRI;
137 const X86RegisterBankInfo &RBI;
138
139#define GET_GLOBALISEL_PREDICATES_DECL
140#include "X86GenGlobalISel.inc"
141#undef GET_GLOBALISEL_PREDICATES_DECL
142
143#define GET_GLOBALISEL_TEMPORARIES_DECL
144#include "X86GenGlobalISel.inc"
145#undef GET_GLOBALISEL_TEMPORARIES_DECL
146};
147
148} // end anonymous namespace
149
150#define GET_GLOBALISEL_IMPL
151#include "X86GenGlobalISel.inc"
152#undef GET_GLOBALISEL_IMPL
153
154X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
155 const X86Subtarget &STI,
156 const X86RegisterBankInfo &RBI)
157 : TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()),
158 RBI(RBI),
160#include "X86GenGlobalISel.inc"
163#include "X86GenGlobalISel.inc"
165{
166}
167
168// FIXME: This should be target-independent, inferred from the types declared
169// for each class in the bank.
171X86InstructionSelector::getRegClass(LLT Ty, const RegisterBank &RB) const {
172 if (RB.getID() == X86::GPRRegBankID) {
173 if (Ty.getSizeInBits() <= 8)
174 return &X86::GR8RegClass;
175 if (Ty.getSizeInBits() == 16)
176 return &X86::GR16RegClass;
177 if (Ty.getSizeInBits() == 32)
178 return &X86::GR32RegClass;
179 if (Ty.getSizeInBits() == 64)
180 return &X86::GR64RegClass;
181 }
182 if (RB.getID() == X86::VECRRegBankID) {
183 if (Ty.getSizeInBits() == 16)
184 return STI.hasAVX512() ? &X86::FR16XRegClass : &X86::FR16RegClass;
185 if (Ty.getSizeInBits() == 32)
186 return STI.hasAVX512() ? &X86::FR32XRegClass : &X86::FR32RegClass;
187 if (Ty.getSizeInBits() == 64)
188 return STI.hasAVX512() ? &X86::FR64XRegClass : &X86::FR64RegClass;
189 if (Ty.getSizeInBits() == 128)
190 return STI.hasAVX512() ? &X86::VR128XRegClass : &X86::VR128RegClass;
191 if (Ty.getSizeInBits() == 256)
192 return STI.hasAVX512() ? &X86::VR256XRegClass : &X86::VR256RegClass;
193 if (Ty.getSizeInBits() == 512)
194 return &X86::VR512RegClass;
195 }
196
197 llvm_unreachable("Unknown RegBank!");
198}
199
201X86InstructionSelector::getRegClass(LLT Ty, unsigned Reg,
202 MachineRegisterInfo &MRI) const {
203 const RegisterBank &RegBank = *RBI.getRegBank(Reg, MRI, TRI);
204 return getRegClass(Ty, RegBank);
205}
206
207static unsigned getSubRegIndex(const TargetRegisterClass *RC) {
208 unsigned SubIdx = X86::NoSubRegister;
209 if (RC == &X86::GR32RegClass) {
210 SubIdx = X86::sub_32bit;
211 } else if (RC == &X86::GR16RegClass) {
212 SubIdx = X86::sub_16bit;
213 } else if (RC == &X86::GR8RegClass) {
214 SubIdx = X86::sub_8bit;
215 }
216
217 return SubIdx;
218}
219
221 assert(Reg.isPhysical());
222 if (X86::GR64RegClass.contains(Reg))
223 return &X86::GR64RegClass;
224 if (X86::GR32RegClass.contains(Reg))
225 return &X86::GR32RegClass;
226 if (X86::GR16RegClass.contains(Reg))
227 return &X86::GR16RegClass;
228 if (X86::GR8RegClass.contains(Reg))
229 return &X86::GR8RegClass;
230
231 llvm_unreachable("Unknown RegClass for PhysReg!");
232}
233
234// FIXME: We need some sort of API in RBI/TRI to allow generic code to
235// constrain operands of simple instructions given a TargetRegisterClass
236// and LLT
237bool X86InstructionSelector::selectDebugInstr(MachineInstr &I,
238 MachineRegisterInfo &MRI) const {
239 for (MachineOperand &MO : I.operands()) {
240 if (!MO.isReg())
241 continue;
242 Register Reg = MO.getReg();
243 if (!Reg)
244 continue;
245 if (Reg.isPhysical())
246 continue;
247 LLT Ty = MRI.getType(Reg);
248 const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(Reg);
249 const TargetRegisterClass *RC =
250 RegClassOrBank.dyn_cast<const TargetRegisterClass *>();
251 if (!RC) {
252 const RegisterBank &RB = *RegClassOrBank.get<const RegisterBank *>();
253 RC = getRegClass(Ty, RB);
254 if (!RC) {
256 dbgs() << "Warning: DBG_VALUE operand has unexpected size/bank\n");
257 break;
258 }
259 }
260 RBI.constrainGenericRegister(Reg, *RC, MRI);
261 }
262
263 return true;
264}
265
266// Set X86 Opcode and constrain DestReg.
267bool X86InstructionSelector::selectCopy(MachineInstr &I,
268 MachineRegisterInfo &MRI) const {
269 Register DstReg = I.getOperand(0).getReg();
270 const unsigned DstSize = RBI.getSizeInBits(DstReg, MRI, TRI);
271 const RegisterBank &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
272
273 Register SrcReg = I.getOperand(1).getReg();
274 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
275 const RegisterBank &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
276
277 if (DstReg.isPhysical()) {
278 assert(I.isCopy() && "Generic operators do not allow physical registers");
279
280 if (DstSize > SrcSize && SrcRegBank.getID() == X86::GPRRegBankID &&
281 DstRegBank.getID() == X86::GPRRegBankID) {
282
283 const TargetRegisterClass *SrcRC =
284 getRegClass(MRI.getType(SrcReg), SrcRegBank);
285 const TargetRegisterClass *DstRC = getRegClassFromGRPhysReg(DstReg);
286
287 if (SrcRC != DstRC) {
288 // This case can be generated by ABI lowering, performe anyext
289 Register ExtSrc = MRI.createVirtualRegister(DstRC);
290 BuildMI(*I.getParent(), I, I.getDebugLoc(),
291 TII.get(TargetOpcode::SUBREG_TO_REG))
292 .addDef(ExtSrc)
293 .addImm(0)
294 .addReg(SrcReg)
295 .addImm(getSubRegIndex(SrcRC));
296
297 I.getOperand(1).setReg(ExtSrc);
298 }
299 }
300
301 return true;
302 }
303
304 assert((!SrcReg.isPhysical() || I.isCopy()) &&
305 "No phys reg on generic operators");
306 assert((DstSize == SrcSize ||
307 // Copies are a mean to setup initial types, the number of
308 // bits may not exactly match.
309 (SrcReg.isPhysical() &&
310 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
311 "Copy with different width?!");
312
313 const TargetRegisterClass *DstRC =
314 getRegClass(MRI.getType(DstReg), DstRegBank);
315
316 if (SrcRegBank.getID() == X86::GPRRegBankID &&
317 DstRegBank.getID() == X86::GPRRegBankID && SrcSize > DstSize &&
318 SrcReg.isPhysical()) {
319 // Change the physical register to performe truncate.
320
321 const TargetRegisterClass *SrcRC = getRegClassFromGRPhysReg(SrcReg);
322
323 if (DstRC != SrcRC) {
324 I.getOperand(1).setSubReg(getSubRegIndex(DstRC));
325 I.getOperand(1).substPhysReg(SrcReg, TRI);
326 }
327 }
328
329 // No need to constrain SrcReg. It will get constrained when
330 // we hit another of its use or its defs.
331 // Copies do not have constraints.
332 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
333 if (!OldRC || !DstRC->hasSubClassEq(OldRC)) {
334 if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
335 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
336 << " operand\n");
337 return false;
338 }
339 }
340 I.setDesc(TII.get(X86::COPY));
341 return true;
342}
343
344bool X86InstructionSelector::select(MachineInstr &I) {
345 assert(I.getParent() && "Instruction should be in a basic block!");
346 assert(I.getParent()->getParent() && "Instruction should be in a function!");
347
348 MachineBasicBlock &MBB = *I.getParent();
351
352 unsigned Opcode = I.getOpcode();
353 if (!isPreISelGenericOpcode(Opcode)) {
354 // Certain non-generic instructions also need some special handling.
355
356 if (Opcode == TargetOpcode::LOAD_STACK_GUARD)
357 return false;
358
359 if (I.isCopy())
360 return selectCopy(I, MRI);
361
362 if (I.isDebugInstr())
363 return selectDebugInstr(I, MRI);
364
365 return true;
366 }
367
368 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
369 "Generic instruction has unexpected implicit operands\n");
370
371 if (selectImpl(I, *CoverageInfo))
372 return true;
373
374 LLVM_DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));
375
376 // TODO: This should be implemented by tblgen.
377 switch (I.getOpcode()) {
378 default:
379 return false;
380 case TargetOpcode::G_STORE:
381 case TargetOpcode::G_LOAD:
382 return selectLoadStoreOp(I, MRI, MF);
383 case TargetOpcode::G_PTR_ADD:
384 case TargetOpcode::G_FRAME_INDEX:
385 return selectFrameIndexOrGep(I, MRI, MF);
386 case TargetOpcode::G_GLOBAL_VALUE:
387 return selectGlobalValue(I, MRI, MF);
388 case TargetOpcode::G_CONSTANT:
389 return selectConstant(I, MRI, MF);
390 case TargetOpcode::G_FCONSTANT:
391 return materializeFP(I, MRI, MF);
392 case TargetOpcode::G_PTRTOINT:
393 case TargetOpcode::G_TRUNC:
394 return selectTruncOrPtrToInt(I, MRI, MF);
395 case TargetOpcode::G_INTTOPTR:
396 return selectCopy(I, MRI);
397 case TargetOpcode::G_ZEXT:
398 return selectZext(I, MRI, MF);
399 case TargetOpcode::G_ANYEXT:
400 return selectAnyext(I, MRI, MF);
401 case TargetOpcode::G_ICMP:
402 return selectCmp(I, MRI, MF);
403 case TargetOpcode::G_FCMP:
404 return selectFCmp(I, MRI, MF);
405 case TargetOpcode::G_UADDE:
406 return selectUadde(I, MRI, MF);
407 case TargetOpcode::G_UNMERGE_VALUES:
408 return selectUnmergeValues(I, MRI, MF);
409 case TargetOpcode::G_MERGE_VALUES:
410 case TargetOpcode::G_CONCAT_VECTORS:
411 return selectMergeValues(I, MRI, MF);
412 case TargetOpcode::G_EXTRACT:
413 return selectExtract(I, MRI, MF);
414 case TargetOpcode::G_INSERT:
415 return selectInsert(I, MRI, MF);
416 case TargetOpcode::G_BRCOND:
417 return selectCondBranch(I, MRI, MF);
418 case TargetOpcode::G_IMPLICIT_DEF:
419 case TargetOpcode::G_PHI:
420 return selectImplicitDefOrPHI(I, MRI);
421 case TargetOpcode::G_SDIV:
422 case TargetOpcode::G_UDIV:
423 case TargetOpcode::G_SREM:
424 case TargetOpcode::G_UREM:
425 return selectDivRem(I, MRI, MF);
426 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
427 return selectIntrinsicWSideEffects(I, MRI, MF);
428 }
429
430 return false;
431}
432
433unsigned X86InstructionSelector::getLoadStoreOp(const LLT &Ty,
434 const RegisterBank &RB,
435 unsigned Opc,
436 Align Alignment) const {
437 bool Isload = (Opc == TargetOpcode::G_LOAD);
438 bool HasAVX = STI.hasAVX();
439 bool HasAVX512 = STI.hasAVX512();
440 bool HasVLX = STI.hasVLX();
441
442 if (Ty == LLT::scalar(8)) {
443 if (X86::GPRRegBankID == RB.getID())
444 return Isload ? X86::MOV8rm : X86::MOV8mr;
445 } else if (Ty == LLT::scalar(16)) {
446 if (X86::GPRRegBankID == RB.getID())
447 return Isload ? X86::MOV16rm : X86::MOV16mr;
448 } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {
449 if (X86::GPRRegBankID == RB.getID())
450 return Isload ? X86::MOV32rm : X86::MOV32mr;
451 if (X86::VECRRegBankID == RB.getID())
452 return Isload ? (HasAVX512 ? X86::VMOVSSZrm_alt :
453 HasAVX ? X86::VMOVSSrm_alt :
454 X86::MOVSSrm_alt)
455 : (HasAVX512 ? X86::VMOVSSZmr :
456 HasAVX ? X86::VMOVSSmr :
457 X86::MOVSSmr);
458 } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
459 if (X86::GPRRegBankID == RB.getID())
460 return Isload ? X86::MOV64rm : X86::MOV64mr;
461 if (X86::VECRRegBankID == RB.getID())
462 return Isload ? (HasAVX512 ? X86::VMOVSDZrm_alt :
463 HasAVX ? X86::VMOVSDrm_alt :
464 X86::MOVSDrm_alt)
465 : (HasAVX512 ? X86::VMOVSDZmr :
466 HasAVX ? X86::VMOVSDmr :
467 X86::MOVSDmr);
468 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
469 if (Alignment >= Align(16))
470 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
471 : HasAVX512
472 ? X86::VMOVAPSZ128rm_NOVLX
473 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
474 : (HasVLX ? X86::VMOVAPSZ128mr
475 : HasAVX512
476 ? X86::VMOVAPSZ128mr_NOVLX
477 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
478 else
479 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
480 : HasAVX512
481 ? X86::VMOVUPSZ128rm_NOVLX
482 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
483 : (HasVLX ? X86::VMOVUPSZ128mr
484 : HasAVX512
485 ? X86::VMOVUPSZ128mr_NOVLX
486 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
487 } else if (Ty.isVector() && Ty.getSizeInBits() == 256) {
488 if (Alignment >= Align(32))
489 return Isload ? (HasVLX ? X86::VMOVAPSZ256rm
490 : HasAVX512 ? X86::VMOVAPSZ256rm_NOVLX
491 : X86::VMOVAPSYrm)
492 : (HasVLX ? X86::VMOVAPSZ256mr
493 : HasAVX512 ? X86::VMOVAPSZ256mr_NOVLX
494 : X86::VMOVAPSYmr);
495 else
496 return Isload ? (HasVLX ? X86::VMOVUPSZ256rm
497 : HasAVX512 ? X86::VMOVUPSZ256rm_NOVLX
498 : X86::VMOVUPSYrm)
499 : (HasVLX ? X86::VMOVUPSZ256mr
500 : HasAVX512 ? X86::VMOVUPSZ256mr_NOVLX
501 : X86::VMOVUPSYmr);
502 } else if (Ty.isVector() && Ty.getSizeInBits() == 512) {
503 if (Alignment >= Align(64))
504 return Isload ? X86::VMOVAPSZrm : X86::VMOVAPSZmr;
505 else
506 return Isload ? X86::VMOVUPSZrm : X86::VMOVUPSZmr;
507 }
508 return Opc;
509}
510
511// Fill in an address from the given instruction.
512static void X86SelectAddress(const MachineInstr &I,
514 X86AddressMode &AM) {
515 assert(I.getOperand(0).isReg() && "unsupported opperand.");
516 assert(MRI.getType(I.getOperand(0).getReg()).isPointer() &&
517 "unsupported type.");
518
519 if (I.getOpcode() == TargetOpcode::G_PTR_ADD) {
520 if (auto COff = getIConstantVRegSExtVal(I.getOperand(2).getReg(), MRI)) {
521 int64_t Imm = *COff;
522 if (isInt<32>(Imm)) { // Check for displacement overflow.
523 AM.Disp = static_cast<int32_t>(Imm);
524 AM.Base.Reg = I.getOperand(1).getReg();
525 return;
526 }
527 }
528 } else if (I.getOpcode() == TargetOpcode::G_FRAME_INDEX) {
529 AM.Base.FrameIndex = I.getOperand(1).getIndex();
531 return;
532 }
533
534 // Default behavior.
535 AM.Base.Reg = I.getOperand(0).getReg();
536}
537
538bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
540 MachineFunction &MF) const {
541 unsigned Opc = I.getOpcode();
542
543 assert((Opc == TargetOpcode::G_STORE || Opc == TargetOpcode::G_LOAD) &&
544 "unexpected instruction");
545
546 const Register DefReg = I.getOperand(0).getReg();
547 LLT Ty = MRI.getType(DefReg);
548 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
549
550 assert(I.hasOneMemOperand());
551 auto &MemOp = **I.memoperands_begin();
552 if (MemOp.isAtomic()) {
553 // Note: for unordered operations, we rely on the fact the appropriate MMO
554 // is already on the instruction we're mutating, and thus we don't need to
555 // make any changes. So long as we select an opcode which is capable of
556 // loading or storing the appropriate size atomically, the rest of the
557 // backend is required to respect the MMO state.
558 if (!MemOp.isUnordered()) {
559 LLVM_DEBUG(dbgs() << "Atomic ordering not supported yet\n");
560 return false;
561 }
562 if (MemOp.getAlign() < Ty.getSizeInBits() / 8) {
563 LLVM_DEBUG(dbgs() << "Unaligned atomics not supported yet\n");
564 return false;
565 }
566 }
567
568 unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlign());
569 if (NewOpc == Opc)
570 return false;
571
573 X86SelectAddress(*MRI.getVRegDef(I.getOperand(1).getReg()), MRI, AM);
574
575 I.setDesc(TII.get(NewOpc));
576 MachineInstrBuilder MIB(MF, I);
577 if (Opc == TargetOpcode::G_LOAD) {
578 I.removeOperand(1);
579 addFullAddress(MIB, AM);
580 } else {
581 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
582 I.removeOperand(1);
583 I.removeOperand(0);
584 addFullAddress(MIB, AM).addUse(DefReg);
585 }
587}
588
589static unsigned getLeaOP(LLT Ty, const X86Subtarget &STI) {
590 if (Ty == LLT::pointer(0, 64))
591 return X86::LEA64r;
592 else if (Ty == LLT::pointer(0, 32))
593 return STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
594 else
595 llvm_unreachable("Can't get LEA opcode. Unsupported type.");
596}
597
598bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I,
600 MachineFunction &MF) const {
601 unsigned Opc = I.getOpcode();
602
603 assert((Opc == TargetOpcode::G_FRAME_INDEX || Opc == TargetOpcode::G_PTR_ADD) &&
604 "unexpected instruction");
605
606 const Register DefReg = I.getOperand(0).getReg();
607 LLT Ty = MRI.getType(DefReg);
608
609 // Use LEA to calculate frame index and GEP
610 unsigned NewOpc = getLeaOP(Ty, STI);
611 I.setDesc(TII.get(NewOpc));
612 MachineInstrBuilder MIB(MF, I);
613
614 if (Opc == TargetOpcode::G_FRAME_INDEX) {
615 addOffset(MIB, 0);
616 } else {
617 MachineOperand &InxOp = I.getOperand(2);
618 I.addOperand(InxOp); // set IndexReg
619 InxOp.ChangeToImmediate(1); // set Scale
620 MIB.addImm(0).addReg(0);
621 }
622
624}
625
626bool X86InstructionSelector::selectGlobalValue(MachineInstr &I,
628 MachineFunction &MF) const {
629 assert((I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE) &&
630 "unexpected instruction");
631
632 auto GV = I.getOperand(1).getGlobal();
633 if (GV->isThreadLocal()) {
634 return false; // TODO: we don't support TLS yet.
635 }
636
637 // Can't handle alternate code models yet.
638 if (TM.getCodeModel() != CodeModel::Small)
639 return false;
640
642 AM.GV = GV;
643 AM.GVOpFlags = STI.classifyGlobalReference(GV);
644
645 // TODO: The ABI requires an extra load. not supported yet.
647 return false;
648
649 // TODO: This reference is relative to the pic base. not supported yet.
651 return false;
652
653 if (STI.isPICStyleRIPRel()) {
654 // Use rip-relative addressing.
655 assert(AM.Base.Reg == 0 && AM.IndexReg == 0);
656 AM.Base.Reg = X86::RIP;
657 }
658
659 const Register DefReg = I.getOperand(0).getReg();
660 LLT Ty = MRI.getType(DefReg);
661 unsigned NewOpc = getLeaOP(Ty, STI);
662
663 I.setDesc(TII.get(NewOpc));
664 MachineInstrBuilder MIB(MF, I);
665
666 I.removeOperand(1);
667 addFullAddress(MIB, AM);
668
670}
671
672bool X86InstructionSelector::selectConstant(MachineInstr &I,
674 MachineFunction &MF) const {
675 assert((I.getOpcode() == TargetOpcode::G_CONSTANT) &&
676 "unexpected instruction");
677
678 const Register DefReg = I.getOperand(0).getReg();
679 LLT Ty = MRI.getType(DefReg);
680
681 if (RBI.getRegBank(DefReg, MRI, TRI)->getID() != X86::GPRRegBankID)
682 return false;
683
684 uint64_t Val = 0;
685 if (I.getOperand(1).isCImm()) {
686 Val = I.getOperand(1).getCImm()->getZExtValue();
687 I.getOperand(1).ChangeToImmediate(Val);
688 } else if (I.getOperand(1).isImm()) {
689 Val = I.getOperand(1).getImm();
690 } else
691 llvm_unreachable("Unsupported operand type.");
692
693 unsigned NewOpc;
694 switch (Ty.getSizeInBits()) {
695 case 8:
696 NewOpc = X86::MOV8ri;
697 break;
698 case 16:
699 NewOpc = X86::MOV16ri;
700 break;
701 case 32:
702 NewOpc = X86::MOV32ri;
703 break;
704 case 64:
705 // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
706 if (isInt<32>(Val))
707 NewOpc = X86::MOV64ri32;
708 else
709 NewOpc = X86::MOV64ri;
710 break;
711 default:
712 llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
713 }
714
715 I.setDesc(TII.get(NewOpc));
717}
718
719// Helper function for selectTruncOrPtrToInt and selectAnyext.
720// Returns true if DstRC lives on a floating register class and
721// SrcRC lives on a 128-bit vector class.
722static bool canTurnIntoCOPY(const TargetRegisterClass *DstRC,
723 const TargetRegisterClass *SrcRC) {
724 return (DstRC == &X86::FR32RegClass || DstRC == &X86::FR32XRegClass ||
725 DstRC == &X86::FR64RegClass || DstRC == &X86::FR64XRegClass) &&
726 (SrcRC == &X86::VR128RegClass || SrcRC == &X86::VR128XRegClass);
727}
728
729bool X86InstructionSelector::selectTurnIntoCOPY(
730 MachineInstr &I, MachineRegisterInfo &MRI, const unsigned DstReg,
731 const TargetRegisterClass *DstRC, const unsigned SrcReg,
732 const TargetRegisterClass *SrcRC) const {
733
734 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
735 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
736 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
737 << " operand\n");
738 return false;
739 }
740 I.setDesc(TII.get(X86::COPY));
741 return true;
742}
743
744bool X86InstructionSelector::selectTruncOrPtrToInt(MachineInstr &I,
746 MachineFunction &MF) const {
747 assert((I.getOpcode() == TargetOpcode::G_TRUNC ||
748 I.getOpcode() == TargetOpcode::G_PTRTOINT) &&
749 "unexpected instruction");
750
751 const Register DstReg = I.getOperand(0).getReg();
752 const Register SrcReg = I.getOperand(1).getReg();
753
754 const LLT DstTy = MRI.getType(DstReg);
755 const LLT SrcTy = MRI.getType(SrcReg);
756
757 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
758 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
759
760 if (DstRB.getID() != SrcRB.getID()) {
761 LLVM_DEBUG(dbgs() << TII.getName(I.getOpcode())
762 << " input/output on different banks\n");
763 return false;
764 }
765
766 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
767 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);
768
769 if (!DstRC || !SrcRC)
770 return false;
771
772 // If that's truncation of the value that lives on the vector class and goes
773 // into the floating class, just replace it with copy, as we are able to
774 // select it as a regular move.
775 if (canTurnIntoCOPY(DstRC, SrcRC))
776 return selectTurnIntoCOPY(I, MRI, DstReg, DstRC, SrcReg, SrcRC);
777
778 if (DstRB.getID() != X86::GPRRegBankID)
779 return false;
780
781 unsigned SubIdx;
782 if (DstRC == SrcRC) {
783 // Nothing to be done
784 SubIdx = X86::NoSubRegister;
785 } else if (DstRC == &X86::GR32RegClass) {
786 SubIdx = X86::sub_32bit;
787 } else if (DstRC == &X86::GR16RegClass) {
788 SubIdx = X86::sub_16bit;
789 } else if (DstRC == &X86::GR8RegClass) {
790 SubIdx = X86::sub_8bit;
791 } else {
792 return false;
793 }
794
795 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
796
797 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
798 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
799 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
800 << "\n");
801 return false;
802 }
803
804 I.getOperand(1).setSubReg(SubIdx);
805
806 I.setDesc(TII.get(X86::COPY));
807 return true;
808}
809
810bool X86InstructionSelector::selectZext(MachineInstr &I,
812 MachineFunction &MF) const {
813 assert((I.getOpcode() == TargetOpcode::G_ZEXT) && "unexpected instruction");
814
815 const Register DstReg = I.getOperand(0).getReg();
816 const Register SrcReg = I.getOperand(1).getReg();
817
818 const LLT DstTy = MRI.getType(DstReg);
819 const LLT SrcTy = MRI.getType(SrcReg);
820
821 assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(16)) &&
822 "8=>16 Zext is handled by tablegen");
823 assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(32)) &&
824 "8=>32 Zext is handled by tablegen");
825 assert(!(SrcTy == LLT::scalar(16) && DstTy == LLT::scalar(32)) &&
826 "16=>32 Zext is handled by tablegen");
827 assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(64)) &&
828 "8=>64 Zext is handled by tablegen");
829 assert(!(SrcTy == LLT::scalar(16) && DstTy == LLT::scalar(64)) &&
830 "16=>64 Zext is handled by tablegen");
831 assert(!(SrcTy == LLT::scalar(32) && DstTy == LLT::scalar(64)) &&
832 "32=>64 Zext is handled by tablegen");
833
834 if (SrcTy != LLT::scalar(1))
835 return false;
836
837 unsigned AndOpc;
838 if (DstTy == LLT::scalar(8))
839 AndOpc = X86::AND8ri;
840 else if (DstTy == LLT::scalar(16))
841 AndOpc = X86::AND16ri8;
842 else if (DstTy == LLT::scalar(32))
843 AndOpc = X86::AND32ri8;
844 else if (DstTy == LLT::scalar(64))
845 AndOpc = X86::AND64ri8;
846 else
847 return false;
848
849 Register DefReg = SrcReg;
850 if (DstTy != LLT::scalar(8)) {
851 Register ImpDefReg =
852 MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI));
853 BuildMI(*I.getParent(), I, I.getDebugLoc(),
854 TII.get(TargetOpcode::IMPLICIT_DEF), ImpDefReg);
855
856 DefReg = MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI));
857 BuildMI(*I.getParent(), I, I.getDebugLoc(),
858 TII.get(TargetOpcode::INSERT_SUBREG), DefReg)
859 .addReg(ImpDefReg)
860 .addReg(SrcReg)
861 .addImm(X86::sub_8bit);
862 }
863
864 MachineInstr &AndInst =
865 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AndOpc), DstReg)
866 .addReg(DefReg)
867 .addImm(1);
868
870
871 I.eraseFromParent();
872 return true;
873}
874
875bool X86InstructionSelector::selectAnyext(MachineInstr &I,
877 MachineFunction &MF) const {
878 assert((I.getOpcode() == TargetOpcode::G_ANYEXT) && "unexpected instruction");
879
880 const Register DstReg = I.getOperand(0).getReg();
881 const Register SrcReg = I.getOperand(1).getReg();
882
883 const LLT DstTy = MRI.getType(DstReg);
884 const LLT SrcTy = MRI.getType(SrcReg);
885
886 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
887 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
888
889 assert(DstRB.getID() == SrcRB.getID() &&
890 "G_ANYEXT input/output on different banks\n");
891
892 assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() &&
893 "G_ANYEXT incorrect operand size");
894
895 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
896 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);
897
898 // If that's ANY_EXT of the value that lives on the floating class and goes
899 // into the vector class, just replace it with copy, as we are able to select
900 // it as a regular move.
901 if (canTurnIntoCOPY(SrcRC, DstRC))
902 return selectTurnIntoCOPY(I, MRI, SrcReg, SrcRC, DstReg, DstRC);
903
904 if (DstRB.getID() != X86::GPRRegBankID)
905 return false;
906
907 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
908 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
909 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
910 << " operand\n");
911 return false;
912 }
913
914 if (SrcRC == DstRC) {
915 I.setDesc(TII.get(X86::COPY));
916 return true;
917 }
918
919 BuildMI(*I.getParent(), I, I.getDebugLoc(),
920 TII.get(TargetOpcode::SUBREG_TO_REG))
921 .addDef(DstReg)
922 .addImm(0)
923 .addReg(SrcReg)
924 .addImm(getSubRegIndex(SrcRC));
925
926 I.eraseFromParent();
927 return true;
928}
929
930bool X86InstructionSelector::selectCmp(MachineInstr &I,
932 MachineFunction &MF) const {
933 assert((I.getOpcode() == TargetOpcode::G_ICMP) && "unexpected instruction");
934
936 bool SwapArgs;
937 std::tie(CC, SwapArgs) = X86::getX86ConditionCode(
938 (CmpInst::Predicate)I.getOperand(1).getPredicate());
939
940 Register LHS = I.getOperand(2).getReg();
941 Register RHS = I.getOperand(3).getReg();
942
943 if (SwapArgs)
944 std::swap(LHS, RHS);
945
946 unsigned OpCmp;
947 LLT Ty = MRI.getType(LHS);
948
949 switch (Ty.getSizeInBits()) {
950 default:
951 return false;
952 case 8:
953 OpCmp = X86::CMP8rr;
954 break;
955 case 16:
956 OpCmp = X86::CMP16rr;
957 break;
958 case 32:
959 OpCmp = X86::CMP32rr;
960 break;
961 case 64:
962 OpCmp = X86::CMP64rr;
963 break;
964 }
965
967 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
968 .addReg(LHS)
969 .addReg(RHS);
970
971 MachineInstr &SetInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
972 TII.get(X86::SETCCr), I.getOperand(0).getReg()).addImm(CC);
973
976
977 I.eraseFromParent();
978 return true;
979}
980
981bool X86InstructionSelector::selectFCmp(MachineInstr &I,
983 MachineFunction &MF) const {
984 assert((I.getOpcode() == TargetOpcode::G_FCMP) && "unexpected instruction");
985
986 Register LhsReg = I.getOperand(2).getReg();
987 Register RhsReg = I.getOperand(3).getReg();
989 (CmpInst::Predicate)I.getOperand(1).getPredicate();
990
991 // FCMP_OEQ and FCMP_UNE cannot be checked with a single instruction.
992 static const uint16_t SETFOpcTable[2][3] = {
993 {X86::COND_E, X86::COND_NP, X86::AND8rr},
994 {X86::COND_NE, X86::COND_P, X86::OR8rr}};
995 const uint16_t *SETFOpc = nullptr;
996 switch (Predicate) {
997 default:
998 break;
1000 SETFOpc = &SETFOpcTable[0][0];
1001 break;
1002 case CmpInst::FCMP_UNE:
1003 SETFOpc = &SETFOpcTable[1][0];
1004 break;
1005 }
1006
1007 // Compute the opcode for the CMP instruction.
1008 unsigned OpCmp;
1009 LLT Ty = MRI.getType(LhsReg);
1010 switch (Ty.getSizeInBits()) {
1011 default:
1012 return false;
1013 case 32:
1014 OpCmp = X86::UCOMISSrr;
1015 break;
1016 case 64:
1017 OpCmp = X86::UCOMISDrr;
1018 break;
1019 }
1020
1021 Register ResultReg = I.getOperand(0).getReg();
1022 RBI.constrainGenericRegister(
1023 ResultReg,
1024 *getRegClass(LLT::scalar(8), *RBI.getRegBank(ResultReg, MRI, TRI)), MRI);
1025 if (SETFOpc) {
1027 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
1028 .addReg(LhsReg)
1029 .addReg(RhsReg);
1030
1031 Register FlagReg1 = MRI.createVirtualRegister(&X86::GR8RegClass);
1032 Register FlagReg2 = MRI.createVirtualRegister(&X86::GR8RegClass);
1033 MachineInstr &Set1 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1034 TII.get(X86::SETCCr), FlagReg1).addImm(SETFOpc[0]);
1035 MachineInstr &Set2 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1036 TII.get(X86::SETCCr), FlagReg2).addImm(SETFOpc[1]);
1037 MachineInstr &Set3 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1038 TII.get(SETFOpc[2]), ResultReg)
1039 .addReg(FlagReg1)
1040 .addReg(FlagReg2);
1045
1046 I.eraseFromParent();
1047 return true;
1048 }
1049
1051 bool SwapArgs;
1052 std::tie(CC, SwapArgs) = X86::getX86ConditionCode(Predicate);
1053 assert(CC <= X86::LAST_VALID_COND && "Unexpected condition code.");
1054
1055 if (SwapArgs)
1056 std::swap(LhsReg, RhsReg);
1057
1058 // Emit a compare of LHS/RHS.
1060 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
1061 .addReg(LhsReg)
1062 .addReg(RhsReg);
1063
1064 MachineInstr &Set =
1065 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::SETCCr), ResultReg).addImm(CC);
1068 I.eraseFromParent();
1069 return true;
1070}
1071
1072bool X86InstructionSelector::selectUadde(MachineInstr &I,
1074 MachineFunction &MF) const {
1075 assert((I.getOpcode() == TargetOpcode::G_UADDE) && "unexpected instruction");
1076
1077 const Register DstReg = I.getOperand(0).getReg();
1078 const Register CarryOutReg = I.getOperand(1).getReg();
1079 const Register Op0Reg = I.getOperand(2).getReg();
1080 const Register Op1Reg = I.getOperand(3).getReg();
1081 Register CarryInReg = I.getOperand(4).getReg();
1082
1083 const LLT DstTy = MRI.getType(DstReg);
1084
1085 if (DstTy != LLT::scalar(32))
1086 return false;
1087
1088 // find CarryIn def instruction.
1089 MachineInstr *Def = MRI.getVRegDef(CarryInReg);
1090 while (Def->getOpcode() == TargetOpcode::G_TRUNC) {
1091 CarryInReg = Def->getOperand(1).getReg();
1092 Def = MRI.getVRegDef(CarryInReg);
1093 }
1094
1095 unsigned Opcode;
1096 if (Def->getOpcode() == TargetOpcode::G_UADDE) {
1097 // carry set by prev ADD.
1098
1099 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), X86::EFLAGS)
1100 .addReg(CarryInReg);
1101
1102 if (!RBI.constrainGenericRegister(CarryInReg, X86::GR32RegClass, MRI))
1103 return false;
1104
1105 Opcode = X86::ADC32rr;
1106 } else if (auto val = getIConstantVRegVal(CarryInReg, MRI)) {
1107 // carry is constant, support only 0.
1108 if (*val != 0)
1109 return false;
1110
1111 Opcode = X86::ADD32rr;
1112 } else
1113 return false;
1114
1115 MachineInstr &AddInst =
1116 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)
1117 .addReg(Op0Reg)
1118 .addReg(Op1Reg);
1119
1120 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), CarryOutReg)
1121 .addReg(X86::EFLAGS);
1122
1123 if (!constrainSelectedInstRegOperands(AddInst, TII, TRI, RBI) ||
1124 !RBI.constrainGenericRegister(CarryOutReg, X86::GR32RegClass, MRI))
1125 return false;
1126
1127 I.eraseFromParent();
1128 return true;
1129}
1130
1131bool X86InstructionSelector::selectExtract(MachineInstr &I,
1133 MachineFunction &MF) const {
1134 assert((I.getOpcode() == TargetOpcode::G_EXTRACT) &&
1135 "unexpected instruction");
1136
1137 const Register DstReg = I.getOperand(0).getReg();
1138 const Register SrcReg = I.getOperand(1).getReg();
1139 int64_t Index = I.getOperand(2).getImm();
1140
1141 const LLT DstTy = MRI.getType(DstReg);
1142 const LLT SrcTy = MRI.getType(SrcReg);
1143
1144 // Meanwile handle vector type only.
1145 if (!DstTy.isVector())
1146 return false;
1147
1148 if (Index % DstTy.getSizeInBits() != 0)
1149 return false; // Not extract subvector.
1150
1151 if (Index == 0) {
1152 // Replace by extract subreg copy.
1153 if (!emitExtractSubreg(DstReg, SrcReg, I, MRI, MF))
1154 return false;
1155
1156 I.eraseFromParent();
1157 return true;
1158 }
1159
1160 bool HasAVX = STI.hasAVX();
1161 bool HasAVX512 = STI.hasAVX512();
1162 bool HasVLX = STI.hasVLX();
1163
1164 if (SrcTy.getSizeInBits() == 256 && DstTy.getSizeInBits() == 128) {
1165 if (HasVLX)
1166 I.setDesc(TII.get(X86::VEXTRACTF32x4Z256rr));
1167 else if (HasAVX)
1168 I.setDesc(TII.get(X86::VEXTRACTF128rr));
1169 else
1170 return false;
1171 } else if (SrcTy.getSizeInBits() == 512 && HasAVX512) {
1172 if (DstTy.getSizeInBits() == 128)
1173 I.setDesc(TII.get(X86::VEXTRACTF32x4Zrr));
1174 else if (DstTy.getSizeInBits() == 256)
1175 I.setDesc(TII.get(X86::VEXTRACTF64x4Zrr));
1176 else
1177 return false;
1178 } else
1179 return false;
1180
1181 // Convert to X86 VEXTRACT immediate.
1182 Index = Index / DstTy.getSizeInBits();
1183 I.getOperand(2).setImm(Index);
1184
1186}
1187
1188bool X86InstructionSelector::emitExtractSubreg(unsigned DstReg, unsigned SrcReg,
1189 MachineInstr &I,
1191 MachineFunction &MF) const {
1192 const LLT DstTy = MRI.getType(DstReg);
1193 const LLT SrcTy = MRI.getType(SrcReg);
1194 unsigned SubIdx = X86::NoSubRegister;
1195
1196 if (!DstTy.isVector() || !SrcTy.isVector())
1197 return false;
1198
1199 assert(SrcTy.getSizeInBits() > DstTy.getSizeInBits() &&
1200 "Incorrect Src/Dst register size");
1201
1202 if (DstTy.getSizeInBits() == 128)
1203 SubIdx = X86::sub_xmm;
1204 else if (DstTy.getSizeInBits() == 256)
1205 SubIdx = X86::sub_ymm;
1206 else
1207 return false;
1208
1209 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);
1210 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);
1211
1212 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
1213
1214 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
1215 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
1216 LLVM_DEBUG(dbgs() << "Failed to constrain EXTRACT_SUBREG\n");
1217 return false;
1218 }
1219
1220 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), DstReg)
1221 .addReg(SrcReg, 0, SubIdx);
1222
1223 return true;
1224}
1225
1226bool X86InstructionSelector::emitInsertSubreg(unsigned DstReg, unsigned SrcReg,
1227 MachineInstr &I,
1229 MachineFunction &MF) const {
1230 const LLT DstTy = MRI.getType(DstReg);
1231 const LLT SrcTy = MRI.getType(SrcReg);
1232 unsigned SubIdx = X86::NoSubRegister;
1233
1234 // TODO: support scalar types
1235 if (!DstTy.isVector() || !SrcTy.isVector())
1236 return false;
1237
1238 assert(SrcTy.getSizeInBits() < DstTy.getSizeInBits() &&
1239 "Incorrect Src/Dst register size");
1240
1241 if (SrcTy.getSizeInBits() == 128)
1242 SubIdx = X86::sub_xmm;
1243 else if (SrcTy.getSizeInBits() == 256)
1244 SubIdx = X86::sub_ymm;
1245 else
1246 return false;
1247
1248 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);
1249 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);
1250
1251 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
1252 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
1253 LLVM_DEBUG(dbgs() << "Failed to constrain INSERT_SUBREG\n");
1254 return false;
1255 }
1256
1257 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY))
1258 .addReg(DstReg, RegState::DefineNoRead, SubIdx)
1259 .addReg(SrcReg);
1260
1261 return true;
1262}
1263
1264bool X86InstructionSelector::selectInsert(MachineInstr &I,
1266 MachineFunction &MF) const {
1267 assert((I.getOpcode() == TargetOpcode::G_INSERT) && "unexpected instruction");
1268
1269 const Register DstReg = I.getOperand(0).getReg();
1270 const Register SrcReg = I.getOperand(1).getReg();
1271 const Register InsertReg = I.getOperand(2).getReg();
1272 int64_t Index = I.getOperand(3).getImm();
1273
1274 const LLT DstTy = MRI.getType(DstReg);
1275 const LLT InsertRegTy = MRI.getType(InsertReg);
1276
1277 // Meanwile handle vector type only.
1278 if (!DstTy.isVector())
1279 return false;
1280
1281 if (Index % InsertRegTy.getSizeInBits() != 0)
1282 return false; // Not insert subvector.
1283
1284 if (Index == 0 && MRI.getVRegDef(SrcReg)->isImplicitDef()) {
1285 // Replace by subreg copy.
1286 if (!emitInsertSubreg(DstReg, InsertReg, I, MRI, MF))
1287 return false;
1288
1289 I.eraseFromParent();
1290 return true;
1291 }
1292
1293 bool HasAVX = STI.hasAVX();
1294 bool HasAVX512 = STI.hasAVX512();
1295 bool HasVLX = STI.hasVLX();
1296
1297 if (DstTy.getSizeInBits() == 256 && InsertRegTy.getSizeInBits() == 128) {
1298 if (HasVLX)
1299 I.setDesc(TII.get(X86::VINSERTF32x4Z256rr));
1300 else if (HasAVX)
1301 I.setDesc(TII.get(X86::VINSERTF128rr));
1302 else
1303 return false;
1304 } else if (DstTy.getSizeInBits() == 512 && HasAVX512) {
1305 if (InsertRegTy.getSizeInBits() == 128)
1306 I.setDesc(TII.get(X86::VINSERTF32x4Zrr));
1307 else if (InsertRegTy.getSizeInBits() == 256)
1308 I.setDesc(TII.get(X86::VINSERTF64x4Zrr));
1309 else
1310 return false;
1311 } else
1312 return false;
1313
1314 // Convert to X86 VINSERT immediate.
1315 Index = Index / InsertRegTy.getSizeInBits();
1316
1317 I.getOperand(3).setImm(Index);
1318
1320}
1321
1322bool X86InstructionSelector::selectUnmergeValues(
1324 assert((I.getOpcode() == TargetOpcode::G_UNMERGE_VALUES) &&
1325 "unexpected instruction");
1326
1327 // Split to extracts.
1328 unsigned NumDefs = I.getNumOperands() - 1;
1329 Register SrcReg = I.getOperand(NumDefs).getReg();
1330 unsigned DefSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
1331
1332 for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1333 MachineInstr &ExtrInst =
1334 *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1335 TII.get(TargetOpcode::G_EXTRACT), I.getOperand(Idx).getReg())
1336 .addReg(SrcReg)
1337 .addImm(Idx * DefSize);
1338
1339 if (!select(ExtrInst))
1340 return false;
1341 }
1342
1343 I.eraseFromParent();
1344 return true;
1345}
1346
1347bool X86InstructionSelector::selectMergeValues(
1349 assert((I.getOpcode() == TargetOpcode::G_MERGE_VALUES ||
1350 I.getOpcode() == TargetOpcode::G_CONCAT_VECTORS) &&
1351 "unexpected instruction");
1352
1353 // Split to inserts.
1354 Register DstReg = I.getOperand(0).getReg();
1355 Register SrcReg0 = I.getOperand(1).getReg();
1356
1357 const LLT DstTy = MRI.getType(DstReg);
1358 const LLT SrcTy = MRI.getType(SrcReg0);
1359 unsigned SrcSize = SrcTy.getSizeInBits();
1360
1361 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
1362
1363 // For the first src use insertSubReg.
1364 Register DefReg = MRI.createGenericVirtualRegister(DstTy);
1365 MRI.setRegBank(DefReg, RegBank);
1366 if (!emitInsertSubreg(DefReg, I.getOperand(1).getReg(), I, MRI, MF))
1367 return false;
1368
1369 for (unsigned Idx = 2; Idx < I.getNumOperands(); ++Idx) {
1370 Register Tmp = MRI.createGenericVirtualRegister(DstTy);
1371 MRI.setRegBank(Tmp, RegBank);
1372
1373 MachineInstr &InsertInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1374 TII.get(TargetOpcode::G_INSERT), Tmp)
1375 .addReg(DefReg)
1376 .addReg(I.getOperand(Idx).getReg())
1377 .addImm((Idx - 1) * SrcSize);
1378
1379 DefReg = Tmp;
1380
1381 if (!select(InsertInst))
1382 return false;
1383 }
1384
1385 MachineInstr &CopyInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1386 TII.get(TargetOpcode::COPY), DstReg)
1387 .addReg(DefReg);
1388
1389 if (!select(CopyInst))
1390 return false;
1391
1392 I.eraseFromParent();
1393 return true;
1394}
1395
1396bool X86InstructionSelector::selectCondBranch(MachineInstr &I,
1398 MachineFunction &MF) const {
1399 assert((I.getOpcode() == TargetOpcode::G_BRCOND) && "unexpected instruction");
1400
1401 const Register CondReg = I.getOperand(0).getReg();
1402 MachineBasicBlock *DestMBB = I.getOperand(1).getMBB();
1403
1404 MachineInstr &TestInst =
1405 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::TEST8ri))
1406 .addReg(CondReg)
1407 .addImm(1);
1408 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::JCC_1))
1409 .addMBB(DestMBB).addImm(X86::COND_NE);
1410
1411 constrainSelectedInstRegOperands(TestInst, TII, TRI, RBI);
1412
1413 I.eraseFromParent();
1414 return true;
1415}
1416
1417bool X86InstructionSelector::materializeFP(MachineInstr &I,
1419 MachineFunction &MF) const {
1420 assert((I.getOpcode() == TargetOpcode::G_FCONSTANT) &&
1421 "unexpected instruction");
1422
1423 // Can't handle alternate code models yet.
1424 CodeModel::Model CM = TM.getCodeModel();
1425 if (CM != CodeModel::Small && CM != CodeModel::Large)
1426 return false;
1427
1428 const Register DstReg = I.getOperand(0).getReg();
1429 const LLT DstTy = MRI.getType(DstReg);
1430 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
1431 Align Alignment = Align(DstTy.getSizeInBytes());
1432 const DebugLoc &DbgLoc = I.getDebugLoc();
1433
1434 unsigned Opc =
1435 getLoadStoreOp(DstTy, RegBank, TargetOpcode::G_LOAD, Alignment);
1436
1437 // Create the load from the constant pool.
1438 const ConstantFP *CFP = I.getOperand(1).getFPImm();
1439 unsigned CPI = MF.getConstantPool()->getConstantPoolIndex(CFP, Alignment);
1440 MachineInstr *LoadInst = nullptr;
1441 unsigned char OpFlag = STI.classifyLocalReference(nullptr);
1442
1443 if (CM == CodeModel::Large && STI.is64Bit()) {
1444 // Under X86-64 non-small code model, GV (and friends) are 64-bits, so
1445 // they cannot be folded into immediate fields.
1446
1447 Register AddrReg = MRI.createVirtualRegister(&X86::GR64RegClass);
1448 BuildMI(*I.getParent(), I, DbgLoc, TII.get(X86::MOV64ri), AddrReg)
1449 .addConstantPoolIndex(CPI, 0, OpFlag);
1450
1453 LLT::pointer(0, MF.getDataLayout().getPointerSizeInBits()), Alignment);
1454
1455 LoadInst =
1456 addDirectMem(BuildMI(*I.getParent(), I, DbgLoc, TII.get(Opc), DstReg),
1457 AddrReg)
1458 .addMemOperand(MMO);
1459
1460 } else if (CM == CodeModel::Small || !STI.is64Bit()) {
1461 // Handle the case when globals fit in our immediate field.
1462 // This is true for X86-32 always and X86-64 when in -mcmodel=small mode.
1463
1464 // x86-32 PIC requires a PIC base register for constant pools.
1465 unsigned PICBase = 0;
1466 if (OpFlag == X86II::MO_PIC_BASE_OFFSET || OpFlag == X86II::MO_GOTOFF) {
1467 // PICBase can be allocated by TII.getGlobalBaseReg(&MF).
1468 // In DAGISEL the code that initialize it generated by the CGBR pass.
1469 return false; // TODO support the mode.
1470 } else if (STI.is64Bit() && TM.getCodeModel() == CodeModel::Small)
1471 PICBase = X86::RIP;
1472
1474 BuildMI(*I.getParent(), I, DbgLoc, TII.get(Opc), DstReg), CPI, PICBase,
1475 OpFlag);
1476 } else
1477 return false;
1478
1480 I.eraseFromParent();
1481 return true;
1482}
1483
1484bool X86InstructionSelector::selectImplicitDefOrPHI(
1486 assert((I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF ||
1487 I.getOpcode() == TargetOpcode::G_PHI) &&
1488 "unexpected instruction");
1489
1490 Register DstReg = I.getOperand(0).getReg();
1491
1492 if (!MRI.getRegClassOrNull(DstReg)) {
1493 const LLT DstTy = MRI.getType(DstReg);
1494 const TargetRegisterClass *RC = getRegClass(DstTy, DstReg, MRI);
1495
1496 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
1497 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
1498 << " operand\n");
1499 return false;
1500 }
1501 }
1502
1503 if (I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
1504 I.setDesc(TII.get(X86::IMPLICIT_DEF));
1505 else
1506 I.setDesc(TII.get(X86::PHI));
1507
1508 return true;
1509}
1510
1511bool X86InstructionSelector::selectDivRem(MachineInstr &I,
1513 MachineFunction &MF) const {
1514 // The implementation of this function is taken from X86FastISel.
1515 assert((I.getOpcode() == TargetOpcode::G_SDIV ||
1516 I.getOpcode() == TargetOpcode::G_SREM ||
1517 I.getOpcode() == TargetOpcode::G_UDIV ||
1518 I.getOpcode() == TargetOpcode::G_UREM) &&
1519 "unexpected instruction");
1520
1521 const Register DstReg = I.getOperand(0).getReg();
1522 const Register Op1Reg = I.getOperand(1).getReg();
1523 const Register Op2Reg = I.getOperand(2).getReg();
1524
1525 const LLT RegTy = MRI.getType(DstReg);
1526 assert(RegTy == MRI.getType(Op1Reg) && RegTy == MRI.getType(Op2Reg) &&
1527 "Arguments and return value types must match");
1528
1529 const RegisterBank *RegRB = RBI.getRegBank(DstReg, MRI, TRI);
1530 if (!RegRB || RegRB->getID() != X86::GPRRegBankID)
1531 return false;
1532
1533 const static unsigned NumTypes = 4; // i8, i16, i32, i64
1534 const static unsigned NumOps = 4; // SDiv, SRem, UDiv, URem
1535 const static bool S = true; // IsSigned
1536 const static bool U = false; // !IsSigned
1537 const static unsigned Copy = TargetOpcode::COPY;
1538 // For the X86 IDIV instruction, in most cases the dividend
1539 // (numerator) must be in a specific register pair highreg:lowreg,
1540 // producing the quotient in lowreg and the remainder in highreg.
1541 // For most data types, to set up the instruction, the dividend is
1542 // copied into lowreg, and lowreg is sign-extended into highreg. The
1543 // exception is i8, where the dividend is defined as a single register rather
1544 // than a register pair, and we therefore directly sign-extend the dividend
1545 // into lowreg, instead of copying, and ignore the highreg.
1546 const static struct DivRemEntry {
1547 // The following portion depends only on the data type.
1548 unsigned SizeInBits;
1549 unsigned LowInReg; // low part of the register pair
1550 unsigned HighInReg; // high part of the register pair
1551 // The following portion depends on both the data type and the operation.
1552 struct DivRemResult {
1553 unsigned OpDivRem; // The specific DIV/IDIV opcode to use.
1554 unsigned OpSignExtend; // Opcode for sign-extending lowreg into
1555 // highreg, or copying a zero into highreg.
1556 unsigned OpCopy; // Opcode for copying dividend into lowreg, or
1557 // zero/sign-extending into lowreg for i8.
1558 unsigned DivRemResultReg; // Register containing the desired result.
1559 bool IsOpSigned; // Whether to use signed or unsigned form.
1560 } ResultTable[NumOps];
1561 } OpTable[NumTypes] = {
1562 {8,
1563 X86::AX,
1564 0,
1565 {
1566 {X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AL, S}, // SDiv
1567 {X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AH, S}, // SRem
1568 {X86::DIV8r, 0, X86::MOVZX16rr8, X86::AL, U}, // UDiv
1569 {X86::DIV8r, 0, X86::MOVZX16rr8, X86::AH, U}, // URem
1570 }}, // i8
1571 {16,
1572 X86::AX,
1573 X86::DX,
1574 {
1575 {X86::IDIV16r, X86::CWD, Copy, X86::AX, S}, // SDiv
1576 {X86::IDIV16r, X86::CWD, Copy, X86::DX, S}, // SRem
1577 {X86::DIV16r, X86::MOV32r0, Copy, X86::AX, U}, // UDiv
1578 {X86::DIV16r, X86::MOV32r0, Copy, X86::DX, U}, // URem
1579 }}, // i16
1580 {32,
1581 X86::EAX,
1582 X86::EDX,
1583 {
1584 {X86::IDIV32r, X86::CDQ, Copy, X86::EAX, S}, // SDiv
1585 {X86::IDIV32r, X86::CDQ, Copy, X86::EDX, S}, // SRem
1586 {X86::DIV32r, X86::MOV32r0, Copy, X86::EAX, U}, // UDiv
1587 {X86::DIV32r, X86::MOV32r0, Copy, X86::EDX, U}, // URem
1588 }}, // i32
1589 {64,
1590 X86::RAX,
1591 X86::RDX,
1592 {
1593 {X86::IDIV64r, X86::CQO, Copy, X86::RAX, S}, // SDiv
1594 {X86::IDIV64r, X86::CQO, Copy, X86::RDX, S}, // SRem
1595 {X86::DIV64r, X86::MOV32r0, Copy, X86::RAX, U}, // UDiv
1596 {X86::DIV64r, X86::MOV32r0, Copy, X86::RDX, U}, // URem
1597 }}, // i64
1598 };
1599
1600 auto OpEntryIt = llvm::find_if(OpTable, [RegTy](const DivRemEntry &El) {
1601 return El.SizeInBits == RegTy.getSizeInBits();
1602 });
1603 if (OpEntryIt == std::end(OpTable))
1604 return false;
1605
1606 unsigned OpIndex;
1607 switch (I.getOpcode()) {
1608 default:
1609 llvm_unreachable("Unexpected div/rem opcode");
1610 case TargetOpcode::G_SDIV:
1611 OpIndex = 0;
1612 break;
1613 case TargetOpcode::G_SREM:
1614 OpIndex = 1;
1615 break;
1616 case TargetOpcode::G_UDIV:
1617 OpIndex = 2;
1618 break;
1619 case TargetOpcode::G_UREM:
1620 OpIndex = 3;
1621 break;
1622 }
1623
1624 const DivRemEntry &TypeEntry = *OpEntryIt;
1625 const DivRemEntry::DivRemResult &OpEntry = TypeEntry.ResultTable[OpIndex];
1626
1627 const TargetRegisterClass *RegRC = getRegClass(RegTy, *RegRB);
1628 if (!RBI.constrainGenericRegister(Op1Reg, *RegRC, MRI) ||
1629 !RBI.constrainGenericRegister(Op2Reg, *RegRC, MRI) ||
1630 !RBI.constrainGenericRegister(DstReg, *RegRC, MRI)) {
1631 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
1632 << " operand\n");
1633 return false;
1634 }
1635
1636 // Move op1 into low-order input register.
1637 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpEntry.OpCopy),
1638 TypeEntry.LowInReg)
1639 .addReg(Op1Reg);
1640 // Zero-extend or sign-extend into high-order input register.
1641 if (OpEntry.OpSignExtend) {
1642 if (OpEntry.IsOpSigned)
1643 BuildMI(*I.getParent(), I, I.getDebugLoc(),
1644 TII.get(OpEntry.OpSignExtend));
1645 else {
1646 Register Zero32 = MRI.createVirtualRegister(&X86::GR32RegClass);
1647 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::MOV32r0),
1648 Zero32);
1649
1650 // Copy the zero into the appropriate sub/super/identical physical
1651 // register. Unfortunately the operations needed are not uniform enough
1652 // to fit neatly into the table above.
1653 if (RegTy.getSizeInBits() == 16) {
1654 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Copy),
1655 TypeEntry.HighInReg)
1656 .addReg(Zero32, 0, X86::sub_16bit);
1657 } else if (RegTy.getSizeInBits() == 32) {
1658 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Copy),
1659 TypeEntry.HighInReg)
1660 .addReg(Zero32);
1661 } else if (RegTy.getSizeInBits() == 64) {
1662 BuildMI(*I.getParent(), I, I.getDebugLoc(),
1663 TII.get(TargetOpcode::SUBREG_TO_REG), TypeEntry.HighInReg)
1664 .addImm(0)
1665 .addReg(Zero32)
1666 .addImm(X86::sub_32bit);
1667 }
1668 }
1669 }
1670 // Generate the DIV/IDIV instruction.
1671 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpEntry.OpDivRem))
1672 .addReg(Op2Reg);
1673 // For i8 remainder, we can't reference ah directly, as we'll end
1674 // up with bogus copies like %r9b = COPY %ah. Reference ax
1675 // instead to prevent ah references in a rex instruction.
1676 //
1677 // The current assumption of the fast register allocator is that isel
1678 // won't generate explicit references to the GR8_NOREX registers. If
1679 // the allocator and/or the backend get enhanced to be more robust in
1680 // that regard, this can be, and should be, removed.
1681 if ((I.getOpcode() == Instruction::SRem ||
1682 I.getOpcode() == Instruction::URem) &&
1683 OpEntry.DivRemResultReg == X86::AH && STI.is64Bit()) {
1684 Register SourceSuperReg = MRI.createVirtualRegister(&X86::GR16RegClass);
1685 Register ResultSuperReg = MRI.createVirtualRegister(&X86::GR16RegClass);
1686 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Copy), SourceSuperReg)
1687 .addReg(X86::AX);
1688
1689 // Shift AX right by 8 bits instead of using AH.
1690 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::SHR16ri),
1691 ResultSuperReg)
1692 .addReg(SourceSuperReg)
1693 .addImm(8);
1694
1695 // Now reference the 8-bit subreg of the result.
1696 BuildMI(*I.getParent(), I, I.getDebugLoc(),
1697 TII.get(TargetOpcode::SUBREG_TO_REG))
1698 .addDef(DstReg)
1699 .addImm(0)
1700 .addReg(ResultSuperReg)
1701 .addImm(X86::sub_8bit);
1702 } else {
1703 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(TargetOpcode::COPY),
1704 DstReg)
1705 .addReg(OpEntry.DivRemResultReg);
1706 }
1707 I.eraseFromParent();
1708 return true;
1709}
1710
1711bool X86InstructionSelector::selectIntrinsicWSideEffects(
1713
1714 assert(I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS &&
1715 "unexpected instruction");
1716
1717 if (I.getOperand(0).getIntrinsicID() != Intrinsic::trap)
1718 return false;
1719
1720 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::TRAP));
1721
1722 I.eraseFromParent();
1723 return true;
1724}
1725
1728 X86Subtarget &Subtarget,
1729 X86RegisterBankInfo &RBI) {
1730 return new X86InstructionSelector(TM, Subtarget, RBI);
1731}
unsigned const MachineRegisterInfo * MRI
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
static bool selectDebugInstr(MachineInstr &I, MachineRegisterInfo &MRI, const RegisterBankInfo &RBI)
MachineBasicBlock & MBB
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)
Atomic ordering constants.
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
#define LLVM_DEBUG(X)
Definition: Debug.h:101
#define DEBUG_TYPE
const HexagonInstrInfo * TII
Implement a low-level type suitable for MachineInstr level instruction selection.
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
unsigned const TargetRegisterInfo * TRI
static unsigned selectLoadStoreOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
const char LLVMTargetMachineRef TM
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
unsigned OpIndex
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:467
#define GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
static bool canTurnIntoCOPY(const TargetRegisterClass *DstRC, const TargetRegisterClass *SrcRC)
static unsigned getLeaOP(LLT Ty, const X86Subtarget &STI)
static const TargetRegisterClass * getRegClassFromGRPhysReg(Register Reg)
static void X86SelectAddress(const MachineInstr &I, const MachineRegisterInfo &MRI, X86AddressMode &AM)
Value * RHS
Value * LHS
This file declares the targeting of the RegisterBankInfo class for X86.
This class is the base class for the comparison instructions.
Definition: InstrTypes.h:708
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition: InstrTypes.h:718
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
Definition: InstrTypes.h:721
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
Definition: InstrTypes.h:734
ConstantFP - Floating Point Values [float, double].
Definition: Constants.h:256
unsigned getPointerSizeInBits(unsigned AS=0) const
Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...
Definition: DataLayout.h:406
A debug info location.
Definition: DebugLoc.h:33
Provides the logic to select generic machine instructions.
virtual bool select(MachineInstr &I)=0
Select the (possibly generic) instruction I to only use target-specific opcodes.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr bool isVector() const
static constexpr LLT pointer(unsigned AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space.
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr TypeSize getSizeInBytes() const
Returns the total size of the type in bytes, i.e.
An instruction for reading from memory.
Definition: Instructions.h:177
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
Definition: MachineInstr.h:68
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
MachineOperand class - Representation of each machine instruction operand.
void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
A discriminated union of two or more pointer types, with the discriminator in the low bit of the poin...
Definition: PointerUnion.h:118
T get() const
Returns the value of the specified pointer type.
Definition: PointerUnion.h:155
T dyn_cast() const
Returns the current pointer if it is of the specified pointer type, otherwise returns null.
Definition: PointerUnion.h:162
This class implements the register bank concept.
Definition: RegisterBank.h:28
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:47
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition: Register.h:97
bool hasSubClassEq(const TargetRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
This class provides the information for the target register banks.
bool isTarget64BitILP32() const
Is this x86_64 with the ILP32 programming model (x32 ABI)?
Definition: X86Subtarget.h:179
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
Definition: PPCPredicates.h:26
Reg
All possible values of the reg field in the ModR/M byte.
@ MO_GOTOFF
MO_GOTOFF - On a symbol operand this indicates that the immediate is the offset to the location of th...
Definition: X86BaseInfo.h:434
@ MO_PIC_BASE_OFFSET
MO_PIC_BASE_OFFSET - On a symbol operand this indicates that the immediate should get the value of th...
Definition: X86BaseInfo.h:420
@ LAST_VALID_COND
Definition: X86BaseInfo.h:97
std::pair< CondCode, bool > getX86ConditionCode(CmpInst::Predicate Predicate)
Return a pair of condition code for the given predicate and whether the instruction operands should b...
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
static bool isGlobalStubReference(unsigned char TargetFlag)
isGlobalStubReference - Return true if the specified TargetFlag operand is a reference to a stub for ...
Definition: X86InstrInfo.h:82
static bool isGlobalRelativeToPICBase(unsigned char TargetFlag)
isGlobalRelativeToPICBase - Return true if the specified global value reference is relative to a 32-b...
Definition: X86InstrInfo.h:100
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
Definition: Utils.cpp:288
bool constrainSelectedInstRegOperands(MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, const RegisterBankInfo &RBI)
Mutate the newly-selected instruction I to constrain its (possibly generic) virtual register operands...
Definition: Utils.cpp:152
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.
Definition: TargetOpcodes.h:30
static const MachineInstrBuilder & addFullAddress(const MachineInstrBuilder &MIB, const X86AddressMode &AM)
InstructionSelector * createX86InstructionSelector(const X86TargetMachine &TM, X86Subtarget &, X86RegisterBankInfo &)
std::optional< int64_t > getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT fits in int64_t returns it.
Definition: Utils.cpp:300
static const MachineInstrBuilder & addConstantPoolReference(const MachineInstrBuilder &MIB, unsigned CPI, unsigned GlobalBaseReg, unsigned char OpFlags)
addConstantPoolReference - This function is used to add a reference to the base of a constant value s...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
static const MachineInstrBuilder & addOffset(const MachineInstrBuilder &MIB, int Offset)
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1809
static const MachineInstrBuilder & addDirectMem(const MachineInstrBuilder &MIB, unsigned Reg)
addDirectMem - This function is used to add a direct memory reference to the current instruction – th...
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:853
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
static MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
X86AddressMode - This struct holds a generalized full x86 address mode.
const GlobalValue * GV
union llvm::X86AddressMode::@599 Base
enum llvm::X86AddressMode::@598 BaseType