LLVM 22.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"
38#include "llvm/IR/DataLayout.h"
39#include "llvm/IR/InstrTypes.h"
40#include "llvm/IR/IntrinsicsX86.h"
42#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 // TODO: remove once p0<->i32/i64 matching is available
77 unsigned getPtrLoadStoreOp(const LLT &Ty, const RegisterBank &RB,
78 unsigned Opc) const;
79
81 MachineFunction &MF) const;
82 bool selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI,
83 MachineFunction &MF) const;
84 bool selectGlobalValue(MachineInstr &I, MachineRegisterInfo &MRI,
85 MachineFunction &MF) const;
86 bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
87 MachineFunction &MF) const;
88 bool selectTruncOrPtrToInt(MachineInstr &I, MachineRegisterInfo &MRI,
89 MachineFunction &MF) const;
90 bool selectZext(MachineInstr &I, MachineRegisterInfo &MRI,
91 MachineFunction &MF) const;
92 bool selectAnyext(MachineInstr &I, MachineRegisterInfo &MRI,
93 MachineFunction &MF) const;
94 bool selectCmp(MachineInstr &I, MachineRegisterInfo &MRI,
95 MachineFunction &MF) const;
96 bool selectFCmp(MachineInstr &I, MachineRegisterInfo &MRI,
97 MachineFunction &MF) const;
98 bool selectUAddSub(MachineInstr &I, MachineRegisterInfo &MRI,
99 MachineFunction &MF) const;
103 MachineFunction &MF);
105 MachineFunction &MF);
106 bool selectInsert(MachineInstr &I, MachineRegisterInfo &MRI,
107 MachineFunction &MF) const;
108 bool selectExtract(MachineInstr &I, MachineRegisterInfo &MRI,
109 MachineFunction &MF) const;
110 bool selectCondBranch(MachineInstr &I, MachineRegisterInfo &MRI,
111 MachineFunction &MF) const;
112 bool selectTurnIntoCOPY(MachineInstr &I, MachineRegisterInfo &MRI,
113 const Register DstReg,
114 const TargetRegisterClass *DstRC,
115 const Register SrcReg,
116 const TargetRegisterClass *SrcRC) const;
117 bool materializeFP(MachineInstr &I, MachineRegisterInfo &MRI,
118 MachineFunction &MF) const;
119 bool selectImplicitDefOrPHI(MachineInstr &I, MachineRegisterInfo &MRI) const;
120 bool selectMulDivRem(MachineInstr &I, MachineRegisterInfo &MRI,
121 MachineFunction &MF) const;
122 bool selectSelect(MachineInstr &I, MachineRegisterInfo &MRI,
123 MachineFunction &MF) const;
124
125 ComplexRendererFns selectAddr(MachineOperand &Root) const;
126
127 // emit insert subreg instruction and insert it before MachineInstr &I
128 bool emitInsertSubreg(Register DstReg, Register SrcReg, MachineInstr &I,
130 // emit extract subreg instruction and insert it before MachineInstr &I
131 bool emitExtractSubreg(Register DstReg, Register SrcReg, MachineInstr &I,
133
134 const TargetRegisterClass *getRegClass(LLT Ty, const RegisterBank &RB) const;
136 MachineRegisterInfo &MRI) const;
137
138 const X86TargetMachine &TM;
139 const X86Subtarget &STI;
140 const X86InstrInfo &TII;
141 const X86RegisterInfo &TRI;
142 const X86RegisterBankInfo &RBI;
143
144#define GET_GLOBALISEL_PREDICATES_DECL
145#include "X86GenGlobalISel.inc"
146#undef GET_GLOBALISEL_PREDICATES_DECL
147
148#define GET_GLOBALISEL_TEMPORARIES_DECL
149#include "X86GenGlobalISel.inc"
150#undef GET_GLOBALISEL_TEMPORARIES_DECL
151};
152
153} // end anonymous namespace
154
155#define GET_GLOBALISEL_IMPL
156#include "X86GenGlobalISel.inc"
157#undef GET_GLOBALISEL_IMPL
158
159X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
160 const X86Subtarget &STI,
161 const X86RegisterBankInfo &RBI)
162 : TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()),
163 RBI(RBI),
165#include "X86GenGlobalISel.inc"
168#include "X86GenGlobalISel.inc"
170{
171}
172
173// FIXME: This should be target-independent, inferred from the types declared
174// for each class in the bank.
176X86InstructionSelector::getRegClass(LLT Ty, const RegisterBank &RB) const {
177 if (RB.getID() == X86::GPRRegBankID) {
178 if (Ty.getSizeInBits() <= 8)
179 return &X86::GR8RegClass;
180 if (Ty.getSizeInBits() == 16)
181 return &X86::GR16RegClass;
182 if (Ty.getSizeInBits() == 32)
183 return &X86::GR32RegClass;
184 if (Ty.getSizeInBits() == 64)
185 return &X86::GR64RegClass;
186 }
187 if (RB.getID() == X86::VECRRegBankID) {
188 if (Ty.getSizeInBits() == 16)
189 return STI.hasAVX512() ? &X86::FR16XRegClass : &X86::FR16RegClass;
190 if (Ty.getSizeInBits() == 32)
191 return STI.hasAVX512() ? &X86::FR32XRegClass : &X86::FR32RegClass;
192 if (Ty.getSizeInBits() == 64)
193 return STI.hasAVX512() ? &X86::FR64XRegClass : &X86::FR64RegClass;
194 if (Ty.getSizeInBits() == 128)
195 return STI.hasAVX512() ? &X86::VR128XRegClass : &X86::VR128RegClass;
196 if (Ty.getSizeInBits() == 256)
197 return STI.hasAVX512() ? &X86::VR256XRegClass : &X86::VR256RegClass;
198 if (Ty.getSizeInBits() == 512)
199 return &X86::VR512RegClass;
200 }
201
202 if (RB.getID() == X86::PSRRegBankID) {
203 if (Ty.getSizeInBits() == 80)
204 return &X86::RFP80RegClass;
205 if (Ty.getSizeInBits() == 64)
206 return &X86::RFP64RegClass;
207 if (Ty.getSizeInBits() == 32)
208 return &X86::RFP32RegClass;
209 }
210
211 llvm_unreachable("Unknown RegBank!");
212}
213
214const TargetRegisterClass *
215X86InstructionSelector::getRegClass(LLT Ty, Register Reg,
216 MachineRegisterInfo &MRI) const {
217 const RegisterBank &RegBank = *RBI.getRegBank(Reg, MRI, TRI);
218 return getRegClass(Ty, RegBank);
219}
220
221static unsigned getSubRegIndex(const TargetRegisterClass *RC) {
222 unsigned SubIdx = X86::NoSubRegister;
223 if (RC == &X86::GR32RegClass) {
224 SubIdx = X86::sub_32bit;
225 } else if (RC == &X86::GR16RegClass) {
226 SubIdx = X86::sub_16bit;
227 } else if (RC == &X86::GR8RegClass) {
228 SubIdx = X86::sub_8bit;
229 }
230
231 return SubIdx;
232}
233
235 assert(Reg.isPhysical());
236 if (X86::GR64RegClass.contains(Reg))
237 return &X86::GR64RegClass;
238 if (X86::GR32RegClass.contains(Reg))
239 return &X86::GR32RegClass;
240 if (X86::GR16RegClass.contains(Reg))
241 return &X86::GR16RegClass;
242 if (X86::GR8RegClass.contains(Reg))
243 return &X86::GR8RegClass;
244
245 llvm_unreachable("Unknown RegClass for PhysReg!");
246}
247
248// FIXME: We need some sort of API in RBI/TRI to allow generic code to
249// constrain operands of simple instructions given a TargetRegisterClass
250// and LLT
251bool X86InstructionSelector::selectDebugInstr(MachineInstr &I,
252 MachineRegisterInfo &MRI) const {
253 for (MachineOperand &MO : I.operands()) {
254 if (!MO.isReg())
255 continue;
256 Register Reg = MO.getReg();
257 if (!Reg)
258 continue;
259 if (Reg.isPhysical())
260 continue;
261 LLT Ty = MRI.getType(Reg);
262 const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(Reg);
263 const TargetRegisterClass *RC =
265 if (!RC) {
266 const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
267 RC = getRegClass(Ty, RB);
268 if (!RC) {
270 dbgs() << "Warning: DBG_VALUE operand has unexpected size/bank\n");
271 break;
272 }
273 }
275 }
276
277 return true;
278}
279
280// Set X86 Opcode and constrain DestReg.
281bool X86InstructionSelector::selectCopy(MachineInstr &I,
282 MachineRegisterInfo &MRI) const {
283 Register DstReg = I.getOperand(0).getReg();
284 const unsigned DstSize = RBI.getSizeInBits(DstReg, MRI, TRI);
285 const RegisterBank &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
286
287 Register SrcReg = I.getOperand(1).getReg();
288 const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
289 const RegisterBank &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
290
291 if (DstReg.isPhysical()) {
292 assert(I.isCopy() && "Generic operators do not allow physical registers");
293
294 if (DstSize > SrcSize && SrcRegBank.getID() == X86::GPRRegBankID &&
295 DstRegBank.getID() == X86::GPRRegBankID) {
296
297 const TargetRegisterClass *SrcRC =
298 getRegClass(MRI.getType(SrcReg), SrcRegBank);
299 const TargetRegisterClass *DstRC = getRegClassFromGRPhysReg(DstReg);
300
301 if (SrcRC != DstRC) {
302 // This case can be generated by ABI lowering, performe anyext
303 Register ExtSrc = MRI.createVirtualRegister(DstRC);
304 BuildMI(*I.getParent(), I, I.getDebugLoc(),
305 TII.get(TargetOpcode::SUBREG_TO_REG))
306 .addDef(ExtSrc)
307 .addImm(0)
308 .addReg(SrcReg)
309 .addImm(getSubRegIndex(SrcRC));
310
311 I.getOperand(1).setReg(ExtSrc);
312 }
313 }
314
315 return true;
316 }
317
318 assert((!SrcReg.isPhysical() || I.isCopy()) &&
319 "No phys reg on generic operators");
320 assert((DstSize == SrcSize ||
321 // Copies are a mean to setup initial types, the number of
322 // bits may not exactly match.
323 (SrcReg.isPhysical() &&
324 DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
325 "Copy with different width?!");
326
327 const TargetRegisterClass *DstRC =
328 getRegClass(MRI.getType(DstReg), DstRegBank);
329
330 if (SrcRegBank.getID() == X86::GPRRegBankID &&
331 DstRegBank.getID() == X86::GPRRegBankID && SrcSize > DstSize &&
332 SrcReg.isPhysical()) {
333 // Change the physical register to performe truncate.
334
335 const TargetRegisterClass *SrcRC = getRegClassFromGRPhysReg(SrcReg);
336
337 if (DstRC != SrcRC) {
338 I.getOperand(1).setSubReg(getSubRegIndex(DstRC));
339 I.getOperand(1).substPhysReg(SrcReg, TRI);
340 }
341 }
342
343 // No need to constrain SrcReg. It will get constrained when
344 // we hit another of its use or its defs.
345 // Copies do not have constraints.
346 const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
347 if (!OldRC || !DstRC->hasSubClassEq(OldRC)) {
348 if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
349 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
350 << " operand\n");
351 return false;
352 }
353 }
354 I.setDesc(TII.get(X86::COPY));
355 return true;
356}
357
358bool X86InstructionSelector::select(MachineInstr &I) {
359 assert(I.getParent() && "Instruction should be in a basic block!");
360 assert(I.getParent()->getParent() && "Instruction should be in a function!");
361
362 MachineBasicBlock &MBB = *I.getParent();
363 MachineFunction &MF = *MBB.getParent();
364 MachineRegisterInfo &MRI = MF.getRegInfo();
365
366 unsigned Opcode = I.getOpcode();
367 if (!isPreISelGenericOpcode(Opcode) && !I.isPreISelOpcode()) {
368 // Certain non-generic instructions also need some special handling.
369
370 if (Opcode == TargetOpcode::LOAD_STACK_GUARD)
371 return false;
372
373 if (I.isCopy())
374 return selectCopy(I, MRI);
375
376 if (I.isDebugInstr())
377 return selectDebugInstr(I, MRI);
378
379 return true;
380 }
381
382 assert(I.getNumOperands() == I.getNumExplicitOperands() &&
383 "Generic instruction has unexpected implicit operands\n");
384
385 if (selectImpl(I, *CoverageInfo))
386 return true;
387
388 LLVM_DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));
389
390 // TODO: This should be implemented by tblgen.
391 switch (I.getOpcode()) {
392 default:
393 return false;
394 case TargetOpcode::G_STORE:
395 case TargetOpcode::G_LOAD:
396 return selectLoadStoreOp(I, MRI, MF);
397 case TargetOpcode::G_PTR_ADD:
398 case TargetOpcode::G_FRAME_INDEX:
399 return selectFrameIndexOrGep(I, MRI, MF);
400 case TargetOpcode::G_GLOBAL_VALUE:
401 return selectGlobalValue(I, MRI, MF);
402 case TargetOpcode::G_CONSTANT:
403 return selectConstant(I, MRI, MF);
404 case TargetOpcode::G_FCONSTANT:
405 return materializeFP(I, MRI, MF);
406 case TargetOpcode::G_PTRTOINT:
407 case TargetOpcode::G_TRUNC:
408 return selectTruncOrPtrToInt(I, MRI, MF);
409 case TargetOpcode::G_INTTOPTR:
410 case TargetOpcode::G_FREEZE:
411 return selectCopy(I, MRI);
412 case TargetOpcode::G_ZEXT:
413 return selectZext(I, MRI, MF);
414 case TargetOpcode::G_ANYEXT:
415 return selectAnyext(I, MRI, MF);
416 case TargetOpcode::G_ICMP:
417 return selectCmp(I, MRI, MF);
418 case TargetOpcode::G_FCMP:
419 return selectFCmp(I, MRI, MF);
420 case TargetOpcode::G_UADDE:
421 case TargetOpcode::G_UADDO:
422 case TargetOpcode::G_USUBE:
423 case TargetOpcode::G_USUBO:
424 return selectUAddSub(I, MRI, MF);
425 case TargetOpcode::G_UNMERGE_VALUES:
426 return selectUnmergeValues(I, MRI, MF);
427 case TargetOpcode::G_MERGE_VALUES:
428 case TargetOpcode::G_CONCAT_VECTORS:
429 return selectMergeValues(I, MRI, MF);
430 case TargetOpcode::G_EXTRACT:
431 return selectExtract(I, MRI, MF);
432 case TargetOpcode::G_INSERT:
433 return selectInsert(I, MRI, MF);
434 case TargetOpcode::G_BRCOND:
435 return selectCondBranch(I, MRI, MF);
436 case TargetOpcode::G_IMPLICIT_DEF:
437 case TargetOpcode::G_PHI:
438 return selectImplicitDefOrPHI(I, MRI);
439 case TargetOpcode::G_MUL:
440 case TargetOpcode::G_SMULH:
441 case TargetOpcode::G_UMULH:
442 case TargetOpcode::G_SDIV:
443 case TargetOpcode::G_UDIV:
444 case TargetOpcode::G_SREM:
445 case TargetOpcode::G_UREM:
446 return selectMulDivRem(I, MRI, MF);
447 case TargetOpcode::G_SELECT:
448 return selectSelect(I, MRI, MF);
449 }
450
451 return false;
452}
453
454unsigned X86InstructionSelector::getPtrLoadStoreOp(const LLT &Ty,
455 const RegisterBank &RB,
456 unsigned Opc) const {
457 assert((Opc == TargetOpcode::G_STORE || Opc == TargetOpcode::G_LOAD) &&
458 "Only G_STORE and G_LOAD are expected for selection");
459 if (Ty.isPointer() && X86::GPRRegBankID == RB.getID()) {
460 bool IsLoad = (Opc == TargetOpcode::G_LOAD);
461 switch (Ty.getSizeInBits()) {
462 default:
463 break;
464 case 32:
465 return IsLoad ? X86::MOV32rm : X86::MOV32mr;
466 case 64:
467 return IsLoad ? X86::MOV64rm : X86::MOV64mr;
468 }
469 }
470 return Opc;
471}
472
473unsigned X86InstructionSelector::getLoadStoreOp(const LLT &Ty,
474 const RegisterBank &RB,
475 unsigned Opc,
476 Align Alignment) const {
477 bool Isload = (Opc == TargetOpcode::G_LOAD);
478 bool HasAVX = STI.hasAVX();
479 bool HasAVX512 = STI.hasAVX512();
480 bool HasVLX = STI.hasVLX();
481
482 if (Ty == LLT::scalar(8)) {
483 if (X86::GPRRegBankID == RB.getID())
484 return Isload ? X86::MOV8rm : X86::MOV8mr;
485 } else if (Ty == LLT::scalar(16)) {
486 if (X86::GPRRegBankID == RB.getID())
487 return Isload ? X86::MOV16rm : X86::MOV16mr;
488 } else if (Ty == LLT::scalar(32)) {
489 if (X86::GPRRegBankID == RB.getID())
490 return Isload ? X86::MOV32rm : X86::MOV32mr;
491 if (X86::VECRRegBankID == RB.getID())
492 return Isload ? (HasAVX512 ? X86::VMOVSSZrm_alt :
493 HasAVX ? X86::VMOVSSrm_alt :
494 X86::MOVSSrm_alt)
495 : (HasAVX512 ? X86::VMOVSSZmr :
496 HasAVX ? X86::VMOVSSmr :
497 X86::MOVSSmr);
498 if (X86::PSRRegBankID == RB.getID())
499 return Isload ? X86::LD_Fp32m : X86::ST_Fp32m;
500 } else if (Ty == LLT::scalar(64)) {
501 if (X86::GPRRegBankID == RB.getID())
502 return Isload ? X86::MOV64rm : X86::MOV64mr;
503 if (X86::VECRRegBankID == RB.getID())
504 return Isload ? (HasAVX512 ? X86::VMOVSDZrm_alt :
505 HasAVX ? X86::VMOVSDrm_alt :
506 X86::MOVSDrm_alt)
507 : (HasAVX512 ? X86::VMOVSDZmr :
508 HasAVX ? X86::VMOVSDmr :
509 X86::MOVSDmr);
510 if (X86::PSRRegBankID == RB.getID())
511 return Isload ? X86::LD_Fp64m : X86::ST_Fp64m;
512 } else if (Ty == LLT::scalar(80)) {
513 return Isload ? X86::LD_Fp80m : X86::ST_FpP80m;
514 } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
515 if (Alignment >= Align(16))
516 return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
517 : HasAVX512
518 ? X86::VMOVAPSZ128rm_NOVLX
519 : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
520 : (HasVLX ? X86::VMOVAPSZ128mr
521 : HasAVX512
522 ? X86::VMOVAPSZ128mr_NOVLX
523 : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
524 else
525 return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
526 : HasAVX512
527 ? X86::VMOVUPSZ128rm_NOVLX
528 : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
529 : (HasVLX ? X86::VMOVUPSZ128mr
530 : HasAVX512
531 ? X86::VMOVUPSZ128mr_NOVLX
532 : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
533 } else if (Ty.isVector() && Ty.getSizeInBits() == 256) {
534 if (Alignment >= Align(32))
535 return Isload ? (HasVLX ? X86::VMOVAPSZ256rm
536 : HasAVX512 ? X86::VMOVAPSZ256rm_NOVLX
537 : X86::VMOVAPSYrm)
538 : (HasVLX ? X86::VMOVAPSZ256mr
539 : HasAVX512 ? X86::VMOVAPSZ256mr_NOVLX
540 : X86::VMOVAPSYmr);
541 else
542 return Isload ? (HasVLX ? X86::VMOVUPSZ256rm
543 : HasAVX512 ? X86::VMOVUPSZ256rm_NOVLX
544 : X86::VMOVUPSYrm)
545 : (HasVLX ? X86::VMOVUPSZ256mr
546 : HasAVX512 ? X86::VMOVUPSZ256mr_NOVLX
547 : X86::VMOVUPSYmr);
548 } else if (Ty.isVector() && Ty.getSizeInBits() == 512) {
549 if (Alignment >= Align(64))
550 return Isload ? X86::VMOVAPSZrm : X86::VMOVAPSZmr;
551 else
552 return Isload ? X86::VMOVUPSZrm : X86::VMOVUPSZmr;
553 }
554 return Opc;
555}
556
557// Fill in an address from the given instruction.
560 const X86Subtarget &STI, X86AddressMode &AM) {
561 assert(I.getOperand(0).isReg() && "unsupported operand.");
562 assert(MRI.getType(I.getOperand(0).getReg()).isPointer() &&
563 "unsupported type.");
564
565 switch (I.getOpcode()) {
566 default:
567 break;
568 case TargetOpcode::G_FRAME_INDEX:
569 AM.Base.FrameIndex = I.getOperand(1).getIndex();
571 return true;
572 case TargetOpcode::G_PTR_ADD: {
573 if (auto COff = getIConstantVRegSExtVal(I.getOperand(2).getReg(), MRI)) {
574 int64_t Imm = *COff;
575 if (isInt<32>(Imm)) { // Check for displacement overflow.
576 AM.Disp = static_cast<int32_t>(Imm);
577 AM.Base.Reg = I.getOperand(1).getReg();
578 return true;
579 }
580 }
581 break;
582 }
583 case TargetOpcode::G_GLOBAL_VALUE: {
584 auto GV = I.getOperand(1).getGlobal();
585 if (GV->isThreadLocal()) {
586 return false; // TODO: we don't support TLS yet.
587 }
588 // Can't handle alternate code models yet.
589 if (TM.getCodeModel() != CodeModel::Small)
590 return false;
591 AM.GV = GV;
593
594 // TODO: The ABI requires an extra load. not supported yet.
596 return false;
597
598 // TODO: This reference is relative to the pic base. not supported yet.
600 return false;
601
602 if (STI.isPICStyleRIPRel()) {
603 // Use rip-relative addressing.
604 assert(AM.Base.Reg == 0 && AM.IndexReg == 0 &&
605 "RIP-relative addresses can't have additional register operands");
606 AM.Base.Reg = X86::RIP;
607 }
608 return true;
609 }
610 case TargetOpcode::G_CONSTANT_POOL: {
611 // TODO: Need a separate move for Large model
612 if (TM.getCodeModel() == CodeModel::Large)
613 return false;
614
615 AM.GVOpFlags = STI.classifyLocalReference(nullptr);
616 if (AM.GVOpFlags == X86II::MO_GOTOFF)
617 AM.Base.Reg = STI.getInstrInfo()->getGlobalBaseReg(I.getMF());
618 else if (STI.is64Bit())
619 AM.Base.Reg = X86::RIP;
620 AM.CP = true;
621 AM.Disp = I.getOperand(1).getIndex();
622 return true;
623 }
624 }
625 // Default behavior.
626 AM.Base.Reg = I.getOperand(0).getReg();
627 return true;
628}
629
630bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
631 MachineRegisterInfo &MRI,
632 MachineFunction &MF) const {
633 unsigned Opc = I.getOpcode();
634
635 assert((Opc == TargetOpcode::G_STORE || Opc == TargetOpcode::G_LOAD) &&
636 "Only G_STORE and G_LOAD are expected for selection");
637
638 const Register DefReg = I.getOperand(0).getReg();
639 LLT Ty = MRI.getType(DefReg);
640 const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
641
642 assert(I.hasOneMemOperand());
643 auto &MemOp = **I.memoperands_begin();
644 if (MemOp.isAtomic()) {
645 // Note: for unordered operations, we rely on the fact the appropriate MMO
646 // is already on the instruction we're mutating, and thus we don't need to
647 // make any changes. So long as we select an opcode which is capable of
648 // loading or storing the appropriate size atomically, the rest of the
649 // backend is required to respect the MMO state.
650 if (!MemOp.isUnordered()) {
651 LLVM_DEBUG(dbgs() << "Atomic ordering not supported yet\n");
652 return false;
653 }
654 if (MemOp.getAlign() < Ty.getSizeInBits() / 8) {
655 LLVM_DEBUG(dbgs() << "Unaligned atomics not supported yet\n");
656 return false;
657 }
658 }
659
660 unsigned NewOpc = getPtrLoadStoreOp(Ty, RB, Opc);
661 if (NewOpc == Opc)
662 return false;
663
664 I.setDesc(TII.get(NewOpc));
665 MachineInstrBuilder MIB(MF, I);
666 MachineInstr *Ptr = MRI.getVRegDef(I.getOperand(1).getReg());
667
668 X86AddressMode AM;
669 if (!X86SelectAddress(*Ptr, TM, MRI, STI, AM))
670 return false;
671
672 if (Opc == TargetOpcode::G_LOAD) {
673 I.removeOperand(1);
674 addFullAddress(MIB, AM);
675 } else {
676 // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
677 I.removeOperand(1);
678 I.removeOperand(0);
679 addFullAddress(MIB, AM).addUse(DefReg);
680 }
681 bool Constrained = constrainSelectedInstRegOperands(I, TII, TRI, RBI);
682 I.addImplicitDefUseOperands(MF);
683 return Constrained;
684}
685
686static unsigned getLeaOP(LLT Ty, const X86Subtarget &STI) {
687 if (Ty == LLT::pointer(0, 64))
688 return X86::LEA64r;
689 else if (Ty == LLT::pointer(0, 32))
690 return STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
691 else
692 llvm_unreachable("Can't get LEA opcode. Unsupported type.");
693}
694
695bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I,
696 MachineRegisterInfo &MRI,
697 MachineFunction &MF) const {
698 unsigned Opc = I.getOpcode();
699
700 assert((Opc == TargetOpcode::G_FRAME_INDEX || Opc == TargetOpcode::G_PTR_ADD) &&
701 "unexpected instruction");
702
703 const Register DefReg = I.getOperand(0).getReg();
704 LLT Ty = MRI.getType(DefReg);
705
706 // Use LEA to calculate frame index and GEP
707 unsigned NewOpc = getLeaOP(Ty, STI);
708 I.setDesc(TII.get(NewOpc));
709 MachineInstrBuilder MIB(MF, I);
710
711 if (Opc == TargetOpcode::G_FRAME_INDEX) {
712 addOffset(MIB, 0);
713 } else {
714 MachineOperand &InxOp = I.getOperand(2);
715 I.addOperand(InxOp); // set IndexReg
716 InxOp.ChangeToImmediate(1); // set Scale
717 MIB.addImm(0).addReg(0);
718 }
719
721}
722
723bool X86InstructionSelector::selectGlobalValue(MachineInstr &I,
724 MachineRegisterInfo &MRI,
725 MachineFunction &MF) const {
726 assert((I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE) &&
727 "unexpected instruction");
728
729 X86AddressMode AM;
730 if (!X86SelectAddress(I, TM, MRI, STI, AM))
731 return false;
732
733 const Register DefReg = I.getOperand(0).getReg();
734 LLT Ty = MRI.getType(DefReg);
735 unsigned NewOpc = getLeaOP(Ty, STI);
736
737 I.setDesc(TII.get(NewOpc));
738 MachineInstrBuilder MIB(MF, I);
739
740 I.removeOperand(1);
741 addFullAddress(MIB, AM);
742
744}
745
746bool X86InstructionSelector::selectConstant(MachineInstr &I,
747 MachineRegisterInfo &MRI,
748 MachineFunction &MF) const {
749 assert((I.getOpcode() == TargetOpcode::G_CONSTANT) &&
750 "unexpected instruction");
751
752 const Register DefReg = I.getOperand(0).getReg();
753 LLT Ty = MRI.getType(DefReg);
754
755 if (RBI.getRegBank(DefReg, MRI, TRI)->getID() != X86::GPRRegBankID)
756 return false;
757
758 uint64_t Val = 0;
759 if (I.getOperand(1).isCImm()) {
760 Val = I.getOperand(1).getCImm()->getZExtValue();
761 I.getOperand(1).ChangeToImmediate(Val);
762 } else if (I.getOperand(1).isImm()) {
763 Val = I.getOperand(1).getImm();
764 } else
765 llvm_unreachable("Unsupported operand type.");
766
767 unsigned NewOpc;
768 switch (Ty.getSizeInBits()) {
769 case 8:
770 NewOpc = X86::MOV8ri;
771 break;
772 case 16:
773 NewOpc = X86::MOV16ri;
774 break;
775 case 32:
776 NewOpc = X86::MOV32ri;
777 break;
778 case 64:
779 // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
780 if (isInt<32>(Val))
781 NewOpc = X86::MOV64ri32;
782 else
783 NewOpc = X86::MOV64ri;
784 break;
785 default:
786 llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
787 }
788
789 I.setDesc(TII.get(NewOpc));
791}
792
793// Helper function for selectTruncOrPtrToInt and selectAnyext.
794// Returns true if DstRC lives on a floating register class and
795// SrcRC lives on a 128-bit vector class.
796static bool canTurnIntoCOPY(const TargetRegisterClass *DstRC,
797 const TargetRegisterClass *SrcRC) {
798 return (DstRC == &X86::FR32RegClass || DstRC == &X86::FR32XRegClass ||
799 DstRC == &X86::FR64RegClass || DstRC == &X86::FR64XRegClass) &&
800 (SrcRC == &X86::VR128RegClass || SrcRC == &X86::VR128XRegClass);
801}
802
803bool X86InstructionSelector::selectTurnIntoCOPY(
804 MachineInstr &I, MachineRegisterInfo &MRI, const Register DstReg,
805 const TargetRegisterClass *DstRC, const Register SrcReg,
806 const TargetRegisterClass *SrcRC) const {
807
808 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
809 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
810 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
811 << " operand\n");
812 return false;
813 }
814 I.setDesc(TII.get(X86::COPY));
815 return true;
816}
817
818bool X86InstructionSelector::selectTruncOrPtrToInt(MachineInstr &I,
819 MachineRegisterInfo &MRI,
820 MachineFunction &MF) const {
821 assert((I.getOpcode() == TargetOpcode::G_TRUNC ||
822 I.getOpcode() == TargetOpcode::G_PTRTOINT) &&
823 "unexpected instruction");
824
825 const Register DstReg = I.getOperand(0).getReg();
826 const Register SrcReg = I.getOperand(1).getReg();
827
828 const LLT DstTy = MRI.getType(DstReg);
829 const LLT SrcTy = MRI.getType(SrcReg);
830
831 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
832 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
833
834 if (DstRB.getID() != SrcRB.getID()) {
835 LLVM_DEBUG(dbgs() << TII.getName(I.getOpcode())
836 << " input/output on different banks\n");
837 return false;
838 }
839
840 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
841 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);
842
843 if (!DstRC || !SrcRC)
844 return false;
845
846 // If that's truncation of the value that lives on the vector class and goes
847 // into the floating class, just replace it with copy, as we are able to
848 // select it as a regular move.
849 if (canTurnIntoCOPY(DstRC, SrcRC))
850 return selectTurnIntoCOPY(I, MRI, DstReg, DstRC, SrcReg, SrcRC);
851
852 if (DstRB.getID() != X86::GPRRegBankID)
853 return false;
854
855 unsigned SubIdx;
856 if (DstRC == SrcRC) {
857 // Nothing to be done
858 SubIdx = X86::NoSubRegister;
859 } else if (DstRC == &X86::GR32RegClass) {
860 SubIdx = X86::sub_32bit;
861 } else if (DstRC == &X86::GR16RegClass) {
862 SubIdx = X86::sub_16bit;
863 } else if (DstRC == &X86::GR8RegClass) {
864 SubIdx = X86::sub_8bit;
865 } else {
866 return false;
867 }
868
869 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
870
871 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
872 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
873 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
874 << "\n");
875 return false;
876 }
877
878 I.getOperand(1).setSubReg(SubIdx);
879
880 I.setDesc(TII.get(X86::COPY));
881 return true;
882}
883
884bool X86InstructionSelector::selectZext(MachineInstr &I,
885 MachineRegisterInfo &MRI,
886 MachineFunction &MF) const {
887 assert((I.getOpcode() == TargetOpcode::G_ZEXT) && "unexpected instruction");
888
889 const Register DstReg = I.getOperand(0).getReg();
890 const Register SrcReg = I.getOperand(1).getReg();
891
892 const LLT DstTy = MRI.getType(DstReg);
893 const LLT SrcTy = MRI.getType(SrcReg);
894
895 assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(16)) &&
896 "8=>16 Zext is handled by tablegen");
897 assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(32)) &&
898 "8=>32 Zext is handled by tablegen");
899 assert(!(SrcTy == LLT::scalar(16) && DstTy == LLT::scalar(32)) &&
900 "16=>32 Zext is handled by tablegen");
901 assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(64)) &&
902 "8=>64 Zext is handled by tablegen");
903 assert(!(SrcTy == LLT::scalar(16) && DstTy == LLT::scalar(64)) &&
904 "16=>64 Zext is handled by tablegen");
905 assert(!(SrcTy == LLT::scalar(32) && DstTy == LLT::scalar(64)) &&
906 "32=>64 Zext is handled by tablegen");
907
908 if (SrcTy != LLT::scalar(1))
909 return false;
910
911 unsigned AndOpc;
912 if (DstTy == LLT::scalar(8))
913 AndOpc = X86::AND8ri;
914 else if (DstTy == LLT::scalar(16))
915 AndOpc = X86::AND16ri;
916 else if (DstTy == LLT::scalar(32))
917 AndOpc = X86::AND32ri;
918 else if (DstTy == LLT::scalar(64))
919 AndOpc = X86::AND64ri32;
920 else
921 return false;
922
923 Register DefReg = SrcReg;
924 if (DstTy != LLT::scalar(8)) {
925 Register ImpDefReg =
926 MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI));
927 BuildMI(*I.getParent(), I, I.getDebugLoc(),
928 TII.get(TargetOpcode::IMPLICIT_DEF), ImpDefReg);
929
930 DefReg = MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI));
931 BuildMI(*I.getParent(), I, I.getDebugLoc(),
932 TII.get(TargetOpcode::INSERT_SUBREG), DefReg)
933 .addReg(ImpDefReg)
934 .addReg(SrcReg)
935 .addImm(X86::sub_8bit);
936 }
937
938 MachineInstr &AndInst =
939 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AndOpc), DstReg)
940 .addReg(DefReg)
941 .addImm(1);
942
944
945 I.eraseFromParent();
946 return true;
947}
948
949bool X86InstructionSelector::selectAnyext(MachineInstr &I,
950 MachineRegisterInfo &MRI,
951 MachineFunction &MF) const {
952 assert((I.getOpcode() == TargetOpcode::G_ANYEXT) && "unexpected instruction");
953
954 const Register DstReg = I.getOperand(0).getReg();
955 const Register SrcReg = I.getOperand(1).getReg();
956
957 const LLT DstTy = MRI.getType(DstReg);
958 const LLT SrcTy = MRI.getType(SrcReg);
959
960 const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
961 const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
962
963 assert(DstRB.getID() == SrcRB.getID() &&
964 "G_ANYEXT input/output on different banks\n");
965
966 assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() &&
967 "G_ANYEXT incorrect operand size");
968
969 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
970 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);
971
972 // If that's ANY_EXT of the value that lives on the floating class and goes
973 // into the vector class, just replace it with copy, as we are able to select
974 // it as a regular move.
975 if (canTurnIntoCOPY(SrcRC, DstRC))
976 return selectTurnIntoCOPY(I, MRI, SrcReg, SrcRC, DstReg, DstRC);
977
978 if (DstRB.getID() != X86::GPRRegBankID)
979 return false;
980
981 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
982 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
983 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
984 << " operand\n");
985 return false;
986 }
987
988 if (SrcRC == DstRC) {
989 I.setDesc(TII.get(X86::COPY));
990 return true;
991 }
992
993 BuildMI(*I.getParent(), I, I.getDebugLoc(),
994 TII.get(TargetOpcode::SUBREG_TO_REG))
995 .addDef(DstReg)
996 .addImm(0)
997 .addReg(SrcReg)
998 .addImm(getSubRegIndex(SrcRC));
999
1000 I.eraseFromParent();
1001 return true;
1002}
1003
1004bool X86InstructionSelector::selectCmp(MachineInstr &I,
1005 MachineRegisterInfo &MRI,
1006 MachineFunction &MF) const {
1007 assert((I.getOpcode() == TargetOpcode::G_ICMP) && "unexpected instruction");
1008
1009 X86::CondCode CC;
1010 bool SwapArgs;
1011 std::tie(CC, SwapArgs) = X86::getX86ConditionCode(
1012 (CmpInst::Predicate)I.getOperand(1).getPredicate());
1013
1014 Register LHS = I.getOperand(2).getReg();
1015 Register RHS = I.getOperand(3).getReg();
1016
1017 if (SwapArgs)
1018 std::swap(LHS, RHS);
1019
1020 unsigned OpCmp;
1021 LLT Ty = MRI.getType(LHS);
1022
1023 switch (Ty.getSizeInBits()) {
1024 default:
1025 return false;
1026 case 8:
1027 OpCmp = X86::CMP8rr;
1028 break;
1029 case 16:
1030 OpCmp = X86::CMP16rr;
1031 break;
1032 case 32:
1033 OpCmp = X86::CMP32rr;
1034 break;
1035 case 64:
1036 OpCmp = X86::CMP64rr;
1037 break;
1038 }
1039
1040 MachineInstr &CmpInst =
1041 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
1042 .addReg(LHS)
1043 .addReg(RHS);
1044
1045 MachineInstr &SetInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1046 TII.get(X86::SETCCr), I.getOperand(0).getReg()).addImm(CC);
1047
1050
1051 I.eraseFromParent();
1052 return true;
1053}
1054
1055bool X86InstructionSelector::selectFCmp(MachineInstr &I,
1056 MachineRegisterInfo &MRI,
1057 MachineFunction &MF) const {
1058 assert((I.getOpcode() == TargetOpcode::G_FCMP) && "unexpected instruction");
1059
1060 Register LhsReg = I.getOperand(2).getReg();
1061 Register RhsReg = I.getOperand(3).getReg();
1063 (CmpInst::Predicate)I.getOperand(1).getPredicate();
1064
1065 // FCMP_OEQ and FCMP_UNE cannot be checked with a single instruction.
1066 static const uint16_t SETFOpcTable[2][3] = {
1067 {X86::COND_E, X86::COND_NP, X86::AND8rr},
1068 {X86::COND_NE, X86::COND_P, X86::OR8rr}};
1069 const uint16_t *SETFOpc = nullptr;
1070 switch (Predicate) {
1071 default:
1072 break;
1073 case CmpInst::FCMP_OEQ:
1074 SETFOpc = &SETFOpcTable[0][0];
1075 break;
1076 case CmpInst::FCMP_UNE:
1077 SETFOpc = &SETFOpcTable[1][0];
1078 break;
1079 }
1080
1081 assert((LhsReg.isVirtual() && RhsReg.isVirtual()) &&
1082 "Both arguments of FCMP need to be virtual!");
1083 auto *LhsBank = RBI.getRegBank(LhsReg, MRI, TRI);
1084 [[maybe_unused]] auto *RhsBank = RBI.getRegBank(RhsReg, MRI, TRI);
1085 assert((LhsBank == RhsBank) &&
1086 "Both banks assigned to FCMP arguments need to be same!");
1087
1088 // Compute the opcode for the CMP instruction.
1089 unsigned OpCmp;
1090 LLT Ty = MRI.getType(LhsReg);
1091 switch (Ty.getSizeInBits()) {
1092 default:
1093 return false;
1094 case 32:
1095 OpCmp = LhsBank->getID() == X86::PSRRegBankID ? X86::UCOM_FpIr32
1096 : X86::UCOMISSrr;
1097 break;
1098 case 64:
1099 OpCmp = LhsBank->getID() == X86::PSRRegBankID ? X86::UCOM_FpIr64
1100 : X86::UCOMISDrr;
1101 break;
1102 case 80:
1103 OpCmp = X86::UCOM_FpIr80;
1104 break;
1105 }
1106
1107 Register ResultReg = I.getOperand(0).getReg();
1109 ResultReg,
1110 *getRegClass(LLT::scalar(8), *RBI.getRegBank(ResultReg, MRI, TRI)), MRI);
1111 if (SETFOpc) {
1112 MachineInstr &CmpInst =
1113 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
1114 .addReg(LhsReg)
1115 .addReg(RhsReg);
1116
1117 Register FlagReg1 = MRI.createVirtualRegister(&X86::GR8RegClass);
1118 Register FlagReg2 = MRI.createVirtualRegister(&X86::GR8RegClass);
1119 MachineInstr &Set1 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1120 TII.get(X86::SETCCr), FlagReg1).addImm(SETFOpc[0]);
1121 MachineInstr &Set2 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1122 TII.get(X86::SETCCr), FlagReg2).addImm(SETFOpc[1]);
1123 MachineInstr &Set3 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1124 TII.get(SETFOpc[2]), ResultReg)
1125 .addReg(FlagReg1)
1126 .addReg(FlagReg2);
1131
1132 I.eraseFromParent();
1133 return true;
1134 }
1135
1136 X86::CondCode CC;
1137 bool SwapArgs;
1138 std::tie(CC, SwapArgs) = X86::getX86ConditionCode(Predicate);
1139 assert(CC <= X86::LAST_VALID_COND && "Unexpected condition code.");
1140
1141 if (SwapArgs)
1142 std::swap(LhsReg, RhsReg);
1143
1144 // Emit a compare of LHS/RHS.
1145 MachineInstr &CmpInst =
1146 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
1147 .addReg(LhsReg)
1148 .addReg(RhsReg);
1149
1150 MachineInstr &Set =
1151 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::SETCCr), ResultReg).addImm(CC);
1154 I.eraseFromParent();
1155 return true;
1156}
1157
1158bool X86InstructionSelector::selectUAddSub(MachineInstr &I,
1159 MachineRegisterInfo &MRI,
1160 MachineFunction &MF) const {
1161 assert((I.getOpcode() == TargetOpcode::G_UADDE ||
1162 I.getOpcode() == TargetOpcode::G_UADDO ||
1163 I.getOpcode() == TargetOpcode::G_USUBE ||
1164 I.getOpcode() == TargetOpcode::G_USUBO) &&
1165 "unexpected instruction");
1166
1167 auto &CarryMI = cast<GAddSubCarryOut>(I);
1168
1169 const Register DstReg = CarryMI.getDstReg();
1170 const Register CarryOutReg = CarryMI.getCarryOutReg();
1171 const Register Op0Reg = CarryMI.getLHSReg();
1172 const Register Op1Reg = CarryMI.getRHSReg();
1173 bool IsSub = CarryMI.isSub();
1174
1175 const LLT DstTy = MRI.getType(DstReg);
1176 assert(DstTy.isScalar() && "selectUAddSub only supported for scalar types");
1177
1178 // TODO: Handle immediate argument variants?
1179 unsigned OpADC, OpADD, OpSBB, OpSUB;
1180 switch (DstTy.getSizeInBits()) {
1181 case 8:
1182 OpADC = X86::ADC8rr;
1183 OpADD = X86::ADD8rr;
1184 OpSBB = X86::SBB8rr;
1185 OpSUB = X86::SUB8rr;
1186 break;
1187 case 16:
1188 OpADC = X86::ADC16rr;
1189 OpADD = X86::ADD16rr;
1190 OpSBB = X86::SBB16rr;
1191 OpSUB = X86::SUB16rr;
1192 break;
1193 case 32:
1194 OpADC = X86::ADC32rr;
1195 OpADD = X86::ADD32rr;
1196 OpSBB = X86::SBB32rr;
1197 OpSUB = X86::SUB32rr;
1198 break;
1199 case 64:
1200 OpADC = X86::ADC64rr;
1201 OpADD = X86::ADD64rr;
1202 OpSBB = X86::SBB64rr;
1203 OpSUB = X86::SUB64rr;
1204 break;
1205 default:
1206 llvm_unreachable("selectUAddSub unsupported type.");
1207 }
1208
1209 const RegisterBank &CarryRB = *RBI.getRegBank(CarryOutReg, MRI, TRI);
1210 const TargetRegisterClass *CarryRC =
1211 getRegClass(MRI.getType(CarryOutReg), CarryRB);
1212
1213 unsigned Opcode = IsSub ? OpSUB : OpADD;
1214
1215 // G_UADDE/G_USUBE - find CarryIn def instruction.
1216 if (auto CarryInMI = dyn_cast<GAddSubCarryInOut>(&I)) {
1217 Register CarryInReg = CarryInMI->getCarryInReg();
1218 MachineInstr *Def = MRI.getVRegDef(CarryInReg);
1219 while (Def->getOpcode() == TargetOpcode::G_TRUNC) {
1220 CarryInReg = Def->getOperand(1).getReg();
1221 Def = MRI.getVRegDef(CarryInReg);
1222 }
1223
1224 // TODO - handle more CF generating instructions
1225 if (Def->getOpcode() == TargetOpcode::G_UADDE ||
1226 Def->getOpcode() == TargetOpcode::G_UADDO ||
1227 Def->getOpcode() == TargetOpcode::G_USUBE ||
1228 Def->getOpcode() == TargetOpcode::G_USUBO) {
1229 // carry set by prev ADD/SUB.
1230
1231 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::CMP8ri))
1232 .addReg(CarryInReg)
1233 .addImm(1);
1234
1235 if (!RBI.constrainGenericRegister(CarryInReg, *CarryRC, MRI))
1236 return false;
1237
1238 Opcode = IsSub ? OpSBB : OpADC;
1239 } else if (auto val = getIConstantVRegVal(CarryInReg, MRI)) {
1240 // carry is constant, support only 0.
1241 if (*val != 0)
1242 return false;
1243
1244 Opcode = IsSub ? OpSUB : OpADD;
1245 } else
1246 return false;
1247 }
1248
1249 MachineInstr &Inst =
1250 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)
1251 .addReg(Op0Reg)
1252 .addReg(Op1Reg);
1253
1254 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::SETCCr), CarryOutReg)
1256
1257 if (!constrainSelectedInstRegOperands(Inst, TII, TRI, RBI) ||
1258 !RBI.constrainGenericRegister(CarryOutReg, *CarryRC, MRI))
1259 return false;
1260
1261 I.eraseFromParent();
1262 return true;
1263}
1264
1265bool X86InstructionSelector::selectExtract(MachineInstr &I,
1266 MachineRegisterInfo &MRI,
1267 MachineFunction &MF) const {
1268 assert((I.getOpcode() == TargetOpcode::G_EXTRACT) &&
1269 "unexpected instruction");
1270
1271 const Register DstReg = I.getOperand(0).getReg();
1272 const Register SrcReg = I.getOperand(1).getReg();
1273 int64_t Index = I.getOperand(2).getImm();
1274
1275 const LLT DstTy = MRI.getType(DstReg);
1276 const LLT SrcTy = MRI.getType(SrcReg);
1277
1278 // Meanwile handle vector type only.
1279 if (!DstTy.isVector())
1280 return false;
1281
1282 if (Index % DstTy.getSizeInBits() != 0)
1283 return false; // Not extract subvector.
1284
1285 if (Index == 0) {
1286 // Replace by extract subreg copy.
1287 if (!emitExtractSubreg(DstReg, SrcReg, I, MRI, MF))
1288 return false;
1289
1290 I.eraseFromParent();
1291 return true;
1292 }
1293
1294 bool HasAVX = STI.hasAVX();
1295 bool HasAVX512 = STI.hasAVX512();
1296 bool HasVLX = STI.hasVLX();
1297
1298 if (SrcTy.getSizeInBits() == 256 && DstTy.getSizeInBits() == 128) {
1299 if (HasVLX)
1300 I.setDesc(TII.get(X86::VEXTRACTF32X4Z256rri));
1301 else if (HasAVX)
1302 I.setDesc(TII.get(X86::VEXTRACTF128rri));
1303 else
1304 return false;
1305 } else if (SrcTy.getSizeInBits() == 512 && HasAVX512) {
1306 if (DstTy.getSizeInBits() == 128)
1307 I.setDesc(TII.get(X86::VEXTRACTF32X4Zrri));
1308 else if (DstTy.getSizeInBits() == 256)
1309 I.setDesc(TII.get(X86::VEXTRACTF64X4Zrri));
1310 else
1311 return false;
1312 } else
1313 return false;
1314
1315 // Convert to X86 VEXTRACT immediate.
1316 Index = Index / DstTy.getSizeInBits();
1317 I.getOperand(2).setImm(Index);
1318
1320}
1321
1322bool X86InstructionSelector::emitExtractSubreg(Register DstReg, Register SrcReg,
1323 MachineInstr &I,
1324 MachineRegisterInfo &MRI,
1325 MachineFunction &MF) const {
1326 const LLT DstTy = MRI.getType(DstReg);
1327 const LLT SrcTy = MRI.getType(SrcReg);
1328 unsigned SubIdx = X86::NoSubRegister;
1329
1330 if (!DstTy.isVector() || !SrcTy.isVector())
1331 return false;
1332
1333 assert(SrcTy.getSizeInBits() > DstTy.getSizeInBits() &&
1334 "Incorrect Src/Dst register size");
1335
1336 if (DstTy.getSizeInBits() == 128)
1337 SubIdx = X86::sub_xmm;
1338 else if (DstTy.getSizeInBits() == 256)
1339 SubIdx = X86::sub_ymm;
1340 else
1341 return false;
1342
1343 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);
1344 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);
1345
1346 SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
1347
1348 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
1349 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
1350 LLVM_DEBUG(dbgs() << "Failed to constrain EXTRACT_SUBREG\n");
1351 return false;
1352 }
1353
1354 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), DstReg)
1355 .addReg(SrcReg, 0, SubIdx);
1356
1357 return true;
1358}
1359
1360bool X86InstructionSelector::emitInsertSubreg(Register DstReg, Register SrcReg,
1361 MachineInstr &I,
1362 MachineRegisterInfo &MRI,
1363 MachineFunction &MF) const {
1364 const LLT DstTy = MRI.getType(DstReg);
1365 const LLT SrcTy = MRI.getType(SrcReg);
1366 unsigned SubIdx = X86::NoSubRegister;
1367
1368 // TODO: support scalar types
1369 if (!DstTy.isVector() || !SrcTy.isVector())
1370 return false;
1371
1372 assert(SrcTy.getSizeInBits() < DstTy.getSizeInBits() &&
1373 "Incorrect Src/Dst register size");
1374
1375 if (SrcTy.getSizeInBits() == 128)
1376 SubIdx = X86::sub_xmm;
1377 else if (SrcTy.getSizeInBits() == 256)
1378 SubIdx = X86::sub_ymm;
1379 else
1380 return false;
1381
1382 const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);
1383 const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);
1384
1385 if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
1386 !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
1387 LLVM_DEBUG(dbgs() << "Failed to constrain INSERT_SUBREG\n");
1388 return false;
1389 }
1390
1391 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY))
1392 .addReg(DstReg, RegState::DefineNoRead, SubIdx)
1393 .addReg(SrcReg);
1394
1395 return true;
1396}
1397
1398bool X86InstructionSelector::selectInsert(MachineInstr &I,
1399 MachineRegisterInfo &MRI,
1400 MachineFunction &MF) const {
1401 assert((I.getOpcode() == TargetOpcode::G_INSERT) && "unexpected instruction");
1402
1403 const Register DstReg = I.getOperand(0).getReg();
1404 const Register SrcReg = I.getOperand(1).getReg();
1405 const Register InsertReg = I.getOperand(2).getReg();
1406 int64_t Index = I.getOperand(3).getImm();
1407
1408 const LLT DstTy = MRI.getType(DstReg);
1409 const LLT InsertRegTy = MRI.getType(InsertReg);
1410
1411 // Meanwile handle vector type only.
1412 if (!DstTy.isVector())
1413 return false;
1414
1415 if (Index % InsertRegTy.getSizeInBits() != 0)
1416 return false; // Not insert subvector.
1417
1418 if (Index == 0 && MRI.getVRegDef(SrcReg)->isImplicitDef()) {
1419 // Replace by subreg copy.
1420 if (!emitInsertSubreg(DstReg, InsertReg, I, MRI, MF))
1421 return false;
1422
1423 I.eraseFromParent();
1424 return true;
1425 }
1426
1427 bool HasAVX = STI.hasAVX();
1428 bool HasAVX512 = STI.hasAVX512();
1429 bool HasVLX = STI.hasVLX();
1430
1431 if (DstTy.getSizeInBits() == 256 && InsertRegTy.getSizeInBits() == 128) {
1432 if (HasVLX)
1433 I.setDesc(TII.get(X86::VINSERTF32X4Z256rri));
1434 else if (HasAVX)
1435 I.setDesc(TII.get(X86::VINSERTF128rri));
1436 else
1437 return false;
1438 } else if (DstTy.getSizeInBits() == 512 && HasAVX512) {
1439 if (InsertRegTy.getSizeInBits() == 128)
1440 I.setDesc(TII.get(X86::VINSERTF32X4Zrri));
1441 else if (InsertRegTy.getSizeInBits() == 256)
1442 I.setDesc(TII.get(X86::VINSERTF64X4Zrri));
1443 else
1444 return false;
1445 } else
1446 return false;
1447
1448 // Convert to X86 VINSERT immediate.
1449 Index = Index / InsertRegTy.getSizeInBits();
1450
1451 I.getOperand(3).setImm(Index);
1452
1454}
1455
1456bool X86InstructionSelector::selectUnmergeValues(
1457 MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) {
1458 assert((I.getOpcode() == TargetOpcode::G_UNMERGE_VALUES) &&
1459 "unexpected instruction");
1460
1461 // Split to extracts.
1462 unsigned NumDefs = I.getNumOperands() - 1;
1463 Register SrcReg = I.getOperand(NumDefs).getReg();
1464 unsigned DefSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
1465
1466 for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
1467 MachineInstr &ExtrInst =
1468 *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1469 TII.get(TargetOpcode::G_EXTRACT), I.getOperand(Idx).getReg())
1470 .addReg(SrcReg)
1471 .addImm(Idx * DefSize);
1472
1473 if (!select(ExtrInst))
1474 return false;
1475 }
1476
1477 I.eraseFromParent();
1478 return true;
1479}
1480
1481bool X86InstructionSelector::selectMergeValues(
1482 MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) {
1483 assert((I.getOpcode() == TargetOpcode::G_MERGE_VALUES ||
1484 I.getOpcode() == TargetOpcode::G_CONCAT_VECTORS) &&
1485 "unexpected instruction");
1486
1487 // Split to inserts.
1488 Register DstReg = I.getOperand(0).getReg();
1489 Register SrcReg0 = I.getOperand(1).getReg();
1490
1491 const LLT DstTy = MRI.getType(DstReg);
1492 const LLT SrcTy = MRI.getType(SrcReg0);
1493 unsigned SrcSize = SrcTy.getSizeInBits();
1494
1495 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
1496
1497 // For the first src use insertSubReg.
1498 Register DefReg = MRI.createGenericVirtualRegister(DstTy);
1499 MRI.setRegBank(DefReg, RegBank);
1500 if (!emitInsertSubreg(DefReg, I.getOperand(1).getReg(), I, MRI, MF))
1501 return false;
1502
1503 for (unsigned Idx = 2; Idx < I.getNumOperands(); ++Idx) {
1504 Register Tmp = MRI.createGenericVirtualRegister(DstTy);
1505 MRI.setRegBank(Tmp, RegBank);
1506
1507 MachineInstr &InsertInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1508 TII.get(TargetOpcode::G_INSERT), Tmp)
1509 .addReg(DefReg)
1510 .addReg(I.getOperand(Idx).getReg())
1511 .addImm((Idx - 1) * SrcSize);
1512
1513 DefReg = Tmp;
1514
1515 if (!select(InsertInst))
1516 return false;
1517 }
1518
1519 MachineInstr &CopyInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
1520 TII.get(TargetOpcode::COPY), DstReg)
1521 .addReg(DefReg);
1522
1523 if (!select(CopyInst))
1524 return false;
1525
1526 I.eraseFromParent();
1527 return true;
1528}
1529
1530bool X86InstructionSelector::selectCondBranch(MachineInstr &I,
1531 MachineRegisterInfo &MRI,
1532 MachineFunction &MF) const {
1533 assert((I.getOpcode() == TargetOpcode::G_BRCOND) && "unexpected instruction");
1534
1535 const Register CondReg = I.getOperand(0).getReg();
1536 MachineBasicBlock *DestMBB = I.getOperand(1).getMBB();
1537
1538 MachineInstr &TestInst =
1539 *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::TEST8ri))
1540 .addReg(CondReg)
1541 .addImm(1);
1542 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::JCC_1))
1543 .addMBB(DestMBB).addImm(X86::COND_NE);
1544
1545 constrainSelectedInstRegOperands(TestInst, TII, TRI, RBI);
1546
1547 I.eraseFromParent();
1548 return true;
1549}
1550
1551bool X86InstructionSelector::materializeFP(MachineInstr &I,
1552 MachineRegisterInfo &MRI,
1553 MachineFunction &MF) const {
1554 assert((I.getOpcode() == TargetOpcode::G_FCONSTANT) &&
1555 "unexpected instruction");
1556
1557 // Can't handle alternate code models yet.
1559 if (CM != CodeModel::Small && CM != CodeModel::Large)
1560 return false;
1561
1562 const Register DstReg = I.getOperand(0).getReg();
1563 const LLT DstTy = MRI.getType(DstReg);
1564 const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
1565 // Create the load from the constant pool.
1566 const ConstantFP *CFP = I.getOperand(1).getFPImm();
1567 const auto &DL = MF.getDataLayout();
1568 Align Alignment = DL.getPrefTypeAlign(CFP->getType());
1569 const DebugLoc &DbgLoc = I.getDebugLoc();
1570
1571 unsigned Opc =
1572 getLoadStoreOp(DstTy, RegBank, TargetOpcode::G_LOAD, Alignment);
1573
1574 unsigned CPI = MF.getConstantPool()->getConstantPoolIndex(CFP, Alignment);
1575 MachineInstr *LoadInst = nullptr;
1576 unsigned char OpFlag = STI.classifyLocalReference(nullptr);
1577
1578 if (CM == CodeModel::Large && STI.is64Bit()) {
1579 // Under X86-64 non-small code model, GV (and friends) are 64-bits, so
1580 // they cannot be folded into immediate fields.
1581
1582 Register AddrReg = MRI.createVirtualRegister(&X86::GR64RegClass);
1583 BuildMI(*I.getParent(), I, DbgLoc, TII.get(X86::MOV64ri), AddrReg)
1584 .addConstantPoolIndex(CPI, 0, OpFlag);
1585
1586 MachineMemOperand *MMO = MF.getMachineMemOperand(
1588 LLT::pointer(0, DL.getPointerSizeInBits()), Alignment);
1589
1590 LoadInst =
1591 addDirectMem(BuildMI(*I.getParent(), I, DbgLoc, TII.get(Opc), DstReg),
1592 AddrReg)
1593 .addMemOperand(MMO);
1594
1595 } else if (CM == CodeModel::Small || !STI.is64Bit()) {
1596 // Handle the case when globals fit in our immediate field.
1597 // This is true for X86-32 always and X86-64 when in -mcmodel=small mode.
1598
1599 // x86-32 PIC requires a PIC base register for constant pools.
1600 unsigned PICBase = 0;
1601 if (OpFlag == X86II::MO_PIC_BASE_OFFSET || OpFlag == X86II::MO_GOTOFF) {
1602 // PICBase can be allocated by TII.getGlobalBaseReg(&MF).
1603 // In DAGISEL the code that initialize it generated by the CGBR pass.
1604 return false; // TODO support the mode.
1605 } else if (STI.is64Bit() && TM.getCodeModel() == CodeModel::Small)
1606 PICBase = X86::RIP;
1607
1608 LoadInst = addConstantPoolReference(
1609 BuildMI(*I.getParent(), I, DbgLoc, TII.get(Opc), DstReg), CPI, PICBase,
1610 OpFlag);
1611 } else
1612 return false;
1613
1614 constrainSelectedInstRegOperands(*LoadInst, TII, TRI, RBI);
1615 I.eraseFromParent();
1616 return true;
1617}
1618
1619bool X86InstructionSelector::selectImplicitDefOrPHI(
1620 MachineInstr &I, MachineRegisterInfo &MRI) const {
1621 assert((I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF ||
1622 I.getOpcode() == TargetOpcode::G_PHI) &&
1623 "unexpected instruction");
1624
1625 Register DstReg = I.getOperand(0).getReg();
1626
1627 if (!MRI.getRegClassOrNull(DstReg)) {
1628 const LLT DstTy = MRI.getType(DstReg);
1629 const TargetRegisterClass *RC = getRegClass(DstTy, DstReg, MRI);
1630
1631 if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
1632 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
1633 << " operand\n");
1634 return false;
1635 }
1636 }
1637
1638 if (I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
1639 I.setDesc(TII.get(X86::IMPLICIT_DEF));
1640 else
1641 I.setDesc(TII.get(X86::PHI));
1642
1643 return true;
1644}
1645
1646bool X86InstructionSelector::selectMulDivRem(MachineInstr &I,
1647 MachineRegisterInfo &MRI,
1648 MachineFunction &MF) const {
1649 // The implementation of this function is adapted from X86FastISel.
1650 assert((I.getOpcode() == TargetOpcode::G_MUL ||
1651 I.getOpcode() == TargetOpcode::G_SMULH ||
1652 I.getOpcode() == TargetOpcode::G_UMULH ||
1653 I.getOpcode() == TargetOpcode::G_SDIV ||
1654 I.getOpcode() == TargetOpcode::G_SREM ||
1655 I.getOpcode() == TargetOpcode::G_UDIV ||
1656 I.getOpcode() == TargetOpcode::G_UREM) &&
1657 "unexpected instruction");
1658
1659 const Register DstReg = I.getOperand(0).getReg();
1660 const Register Op1Reg = I.getOperand(1).getReg();
1661 const Register Op2Reg = I.getOperand(2).getReg();
1662
1663 const LLT RegTy = MRI.getType(DstReg);
1664 assert(RegTy == MRI.getType(Op1Reg) && RegTy == MRI.getType(Op2Reg) &&
1665 "Arguments and return value types must match");
1666
1667 const RegisterBank *RegRB = RBI.getRegBank(DstReg, MRI, TRI);
1668 if (!RegRB || RegRB->getID() != X86::GPRRegBankID)
1669 return false;
1670
1671 const static unsigned NumTypes = 4; // i8, i16, i32, i64
1672 const static unsigned NumOps = 7; // SDiv/SRem/UDiv/URem/Mul/SMulH/UMulh
1673 const static bool S = true; // IsSigned
1674 const static bool U = false; // !IsSigned
1675 const static unsigned Copy = TargetOpcode::COPY;
1676
1677 // For the X86 IDIV instruction, in most cases the dividend
1678 // (numerator) must be in a specific register pair highreg:lowreg,
1679 // producing the quotient in lowreg and the remainder in highreg.
1680 // For most data types, to set up the instruction, the dividend is
1681 // copied into lowreg, and lowreg is sign-extended into highreg. The
1682 // exception is i8, where the dividend is defined as a single register rather
1683 // than a register pair, and we therefore directly sign-extend the dividend
1684 // into lowreg, instead of copying, and ignore the highreg.
1685 const static struct MulDivRemEntry {
1686 // The following portion depends only on the data type.
1687 unsigned SizeInBits;
1688 unsigned LowInReg; // low part of the register pair
1689 unsigned HighInReg; // high part of the register pair
1690 // The following portion depends on both the data type and the operation.
1691 struct MulDivRemResult {
1692 unsigned OpMulDivRem; // The specific MUL/DIV opcode to use.
1693 unsigned OpSignExtend; // Opcode for sign-extending lowreg into
1694 // highreg, or copying a zero into highreg.
1695 unsigned OpCopy; // Opcode for copying dividend into lowreg, or
1696 // zero/sign-extending into lowreg for i8.
1697 unsigned ResultReg; // Register containing the desired result.
1698 bool IsOpSigned; // Whether to use signed or unsigned form.
1699 } ResultTable[NumOps];
1700 } OpTable[NumTypes] = {
1701 {8,
1702 X86::AX,
1703 0,
1704 {
1705 {X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AL, S}, // SDiv
1706 {X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AH, S}, // SRem
1707 {X86::DIV8r, 0, X86::MOVZX16rr8, X86::AL, U}, // UDiv
1708 {X86::DIV8r, 0, X86::MOVZX16rr8, X86::AH, U}, // URem
1709 {X86::IMUL8r, 0, X86::MOVSX16rr8, X86::AL, S}, // Mul
1710 {X86::IMUL8r, 0, X86::MOVSX16rr8, X86::AH, S}, // SMulH
1711 {X86::MUL8r, 0, X86::MOVZX16rr8, X86::AH, U}, // UMulH
1712 }}, // i8
1713 {16,
1714 X86::AX,
1715 X86::DX,
1716 {
1717 {X86::IDIV16r, X86::CWD, Copy, X86::AX, S}, // SDiv
1718 {X86::IDIV16r, X86::CWD, Copy, X86::DX, S}, // SRem
1719 {X86::DIV16r, X86::MOV32r0, Copy, X86::AX, U}, // UDiv
1720 {X86::DIV16r, X86::MOV32r0, Copy, X86::DX, U}, // URem
1721 {X86::IMUL16r, X86::MOV32r0, Copy, X86::AX, S}, // Mul
1722 {X86::IMUL16r, X86::MOV32r0, Copy, X86::DX, S}, // SMulH
1723 {X86::MUL16r, X86::MOV32r0, Copy, X86::DX, U}, // UMulH
1724 }}, // i16
1725 {32,
1726 X86::EAX,
1727 X86::EDX,
1728 {
1729 {X86::IDIV32r, X86::CDQ, Copy, X86::EAX, S}, // SDiv
1730 {X86::IDIV32r, X86::CDQ, Copy, X86::EDX, S}, // SRem
1731 {X86::DIV32r, X86::MOV32r0, Copy, X86::EAX, U}, // UDiv
1732 {X86::DIV32r, X86::MOV32r0, Copy, X86::EDX, U}, // URem
1733 {X86::IMUL32r, X86::MOV32r0, Copy, X86::EAX, S}, // Mul
1734 {X86::IMUL32r, X86::MOV32r0, Copy, X86::EDX, S}, // SMulH
1735 {X86::MUL32r, X86::MOV32r0, Copy, X86::EDX, U}, // UMulH
1736 }}, // i32
1737 {64,
1738 X86::RAX,
1739 X86::RDX,
1740 {
1741 {X86::IDIV64r, X86::CQO, Copy, X86::RAX, S}, // SDiv
1742 {X86::IDIV64r, X86::CQO, Copy, X86::RDX, S}, // SRem
1743 {X86::DIV64r, X86::MOV32r0, Copy, X86::RAX, U}, // UDiv
1744 {X86::DIV64r, X86::MOV32r0, Copy, X86::RDX, U}, // URem
1745 {X86::IMUL64r, X86::MOV32r0, Copy, X86::RAX, S}, // Mul
1746 {X86::IMUL64r, X86::MOV32r0, Copy, X86::RDX, S}, // SMulH
1747 {X86::MUL64r, X86::MOV32r0, Copy, X86::RDX, U}, // UMulH
1748 }}, // i64
1749 };
1750
1751 auto OpEntryIt = llvm::find_if(OpTable, [RegTy](const MulDivRemEntry &El) {
1752 return El.SizeInBits == RegTy.getSizeInBits();
1753 });
1754 if (OpEntryIt == std::end(OpTable))
1755 return false;
1756
1757 unsigned OpIndex;
1758 switch (I.getOpcode()) {
1759 default:
1760 llvm_unreachable("Unexpected mul/div/rem opcode");
1761 case TargetOpcode::G_SDIV:
1762 OpIndex = 0;
1763 break;
1764 case TargetOpcode::G_SREM:
1765 OpIndex = 1;
1766 break;
1767 case TargetOpcode::G_UDIV:
1768 OpIndex = 2;
1769 break;
1770 case TargetOpcode::G_UREM:
1771 OpIndex = 3;
1772 break;
1773 case TargetOpcode::G_MUL:
1774 OpIndex = 4;
1775 break;
1776 case TargetOpcode::G_SMULH:
1777 OpIndex = 5;
1778 break;
1779 case TargetOpcode::G_UMULH:
1780 OpIndex = 6;
1781 break;
1782 }
1783
1784 const MulDivRemEntry &TypeEntry = *OpEntryIt;
1785 const MulDivRemEntry::MulDivRemResult &OpEntry =
1786 TypeEntry.ResultTable[OpIndex];
1787
1788 const TargetRegisterClass *RegRC = getRegClass(RegTy, *RegRB);
1789 if (!RBI.constrainGenericRegister(Op1Reg, *RegRC, MRI) ||
1790 !RBI.constrainGenericRegister(Op2Reg, *RegRC, MRI) ||
1791 !RBI.constrainGenericRegister(DstReg, *RegRC, MRI)) {
1792 LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
1793 << " operand\n");
1794 return false;
1795 }
1796
1797 // Move op1 into low-order input register.
1798 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpEntry.OpCopy),
1799 TypeEntry.LowInReg)
1800 .addReg(Op1Reg);
1801
1802 // Zero-extend or sign-extend into high-order input register.
1803 if (OpEntry.OpSignExtend) {
1804 if (OpEntry.IsOpSigned)
1805 BuildMI(*I.getParent(), I, I.getDebugLoc(),
1806 TII.get(OpEntry.OpSignExtend));
1807 else {
1808 Register Zero32 = MRI.createVirtualRegister(&X86::GR32RegClass);
1809 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::MOV32r0),
1810 Zero32);
1811
1812 // Copy the zero into the appropriate sub/super/identical physical
1813 // register. Unfortunately the operations needed are not uniform enough
1814 // to fit neatly into the table above.
1815 if (RegTy.getSizeInBits() == 16) {
1816 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Copy),
1817 TypeEntry.HighInReg)
1818 .addReg(Zero32, 0, X86::sub_16bit);
1819 } else if (RegTy.getSizeInBits() == 32) {
1820 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Copy),
1821 TypeEntry.HighInReg)
1822 .addReg(Zero32);
1823 } else if (RegTy.getSizeInBits() == 64) {
1824 BuildMI(*I.getParent(), I, I.getDebugLoc(),
1825 TII.get(TargetOpcode::SUBREG_TO_REG), TypeEntry.HighInReg)
1826 .addImm(0)
1827 .addReg(Zero32)
1828 .addImm(X86::sub_32bit);
1829 }
1830 }
1831 }
1832
1833 // Generate the DIV/IDIV/MUL/IMUL instruction.
1834 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpEntry.OpMulDivRem))
1835 .addReg(Op2Reg);
1836
1837 // For i8 remainder, we can't reference ah directly, as we'll end
1838 // up with bogus copies like %r9b = COPY %ah. Reference ax
1839 // instead to prevent ah references in a rex instruction.
1840 //
1841 // The current assumption of the fast register allocator is that isel
1842 // won't generate explicit references to the GR8_NOREX registers. If
1843 // the allocator and/or the backend get enhanced to be more robust in
1844 // that regard, this can be, and should be, removed.
1845 if (OpEntry.ResultReg == X86::AH && STI.is64Bit()) {
1846 Register SourceSuperReg = MRI.createVirtualRegister(&X86::GR16RegClass);
1847 Register ResultSuperReg = MRI.createVirtualRegister(&X86::GR16RegClass);
1848 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Copy), SourceSuperReg)
1849 .addReg(X86::AX);
1850
1851 // Shift AX right by 8 bits instead of using AH.
1852 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::SHR16ri),
1853 ResultSuperReg)
1854 .addReg(SourceSuperReg)
1855 .addImm(8);
1856
1857 // Now reference the 8-bit subreg of the result.
1858 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(TargetOpcode::COPY),
1859 DstReg)
1860 .addReg(ResultSuperReg, 0, X86::sub_8bit);
1861 } else {
1862 BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(TargetOpcode::COPY),
1863 DstReg)
1864 .addReg(OpEntry.ResultReg);
1865 }
1866 I.eraseFromParent();
1867
1868 return true;
1869}
1870
1871bool X86InstructionSelector::selectSelect(MachineInstr &I,
1872 MachineRegisterInfo &MRI,
1873 MachineFunction &MF) const {
1874 GSelect &Sel = cast<GSelect>(I);
1875 Register DstReg = Sel.getReg(0);
1876 BuildMI(*Sel.getParent(), Sel, Sel.getDebugLoc(), TII.get(X86::TEST32rr))
1877 .addReg(Sel.getCondReg())
1878 .addReg(Sel.getCondReg());
1879
1880 unsigned OpCmp;
1881 LLT Ty = MRI.getType(DstReg);
1882 if (Ty.getSizeInBits() == 80) {
1883 BuildMI(*Sel.getParent(), Sel, Sel.getDebugLoc(), TII.get(X86::CMOVE_Fp80),
1884 DstReg)
1885 .addReg(Sel.getTrueReg())
1886 .addReg(Sel.getFalseReg());
1887 } else {
1888 switch (Ty.getSizeInBits()) {
1889 default:
1890 return false;
1891 case 8:
1892 OpCmp = X86::CMOV_GR8;
1893 break;
1894 case 16:
1895 OpCmp = STI.canUseCMOV() ? X86::CMOV16rr : X86::CMOV_GR16;
1896 break;
1897 case 32:
1898 OpCmp = STI.canUseCMOV() ? X86::CMOV32rr : X86::CMOV_GR32;
1899 break;
1900 case 64:
1901 assert(STI.is64Bit() && STI.canUseCMOV());
1902 OpCmp = X86::CMOV64rr;
1903 break;
1904 }
1905 BuildMI(*Sel.getParent(), Sel, Sel.getDebugLoc(), TII.get(OpCmp), DstReg)
1906 .addReg(Sel.getTrueReg())
1907 .addReg(Sel.getFalseReg())
1909 }
1910 const TargetRegisterClass *DstRC = getRegClass(Ty, DstReg, MRI);
1911 if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
1912 LLVM_DEBUG(dbgs() << "Failed to constrain CMOV\n");
1913 return false;
1914 }
1915
1916 Sel.eraseFromParent();
1917 return true;
1918}
1919
1920InstructionSelector::ComplexRendererFns
1921X86InstructionSelector::selectAddr(MachineOperand &Root) const {
1922 MachineInstr *MI = Root.getParent();
1923 MachineIRBuilder MIRBuilder(*MI);
1924
1925 MachineRegisterInfo &MRI = MI->getMF()->getRegInfo();
1926 MachineInstr *Ptr = MRI.getVRegDef(Root.getReg());
1927 X86AddressMode AM;
1928 X86SelectAddress(*Ptr, TM, MRI, STI, AM);
1929
1930 if (AM.IndexReg)
1931 return std::nullopt;
1932
1933 return {// Base
1934 {[=](MachineInstrBuilder &MIB) {
1936 MIB.addUse(AM.Base.Reg);
1937 else {
1939 "Unknown type of address base");
1940 MIB.addFrameIndex(AM.Base.FrameIndex);
1941 }
1942 },
1943 // Scale
1944 [=](MachineInstrBuilder &MIB) { MIB.addImm(AM.Scale); },
1945 // Index
1946 [=](MachineInstrBuilder &MIB) { MIB.addUse(0); },
1947 // Disp
1948 [=](MachineInstrBuilder &MIB) {
1949 if (AM.GV)
1950 MIB.addGlobalAddress(AM.GV, AM.Disp, AM.GVOpFlags);
1951 else if (AM.CP)
1952 MIB.addConstantPoolIndex(AM.Disp, 0, AM.GVOpFlags);
1953 else
1954 MIB.addImm(AM.Disp);
1955 },
1956 // Segment
1957 [=](MachineInstrBuilder &MIB) { MIB.addUse(0); }}};
1958}
1959
1960InstructionSelector *
1962 const X86Subtarget &Subtarget,
1963 const X86RegisterBankInfo &RBI) {
1964 return new X86InstructionSelector(TM, Subtarget, RBI);
1965}
unsigned const MachineRegisterInfo * MRI
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
#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)
static bool selectDebugInstr(MachineInstr &I, MachineRegisterInfo &MRI, const RegisterBankInfo &RBI)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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)
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define DEBUG_TYPE
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
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 ...
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static unsigned selectLoadStoreOp(unsigned GenericOpc, unsigned RegBankID, unsigned OpSize)
static StringRef getName(Value *V)
unsigned OpIndex
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:480
#define LLVM_DEBUG(...)
Definition Debug.h:114
static bool X86SelectAddress(MachineInstr &I, const X86TargetMachine &TM, const MachineRegisterInfo &MRI, const X86Subtarget &STI, X86AddressMode &AM)
static bool canTurnIntoCOPY(const TargetRegisterClass *DstRC, const TargetRegisterClass *SrcRC)
static unsigned getLeaOP(LLT Ty, const X86Subtarget &STI)
static const TargetRegisterClass * getRegClassFromGRPhysReg(Register Reg)
Value * RHS
Value * LHS
This file declares the targeting of the RegisterBankInfo class for X86.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:676
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
Definition InstrTypes.h:679
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
Definition InstrTypes.h:692
Register getCondReg() const
Register getFalseReg() const
Register getTrueReg() const
Register getReg(unsigned Idx) const
Access the Idx'th operand as a register and return it.
constexpr bool isScalar() const
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 bool isPointer() const
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, LLT MemTy, 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.
const MachineBasicBlock * getParent() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
@ MOLoad
The memory access reads data.
MachineOperand class - Representation of each machine instruction operand.
LLVM_ABI void ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags=0)
ChangeToImmediate - Replace this operand with a new immediate operand of the specified value.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
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.
TypeSize getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
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:19
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:74
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:78
CodeModel::Model getCodeModel() const
Returns the code model.
bool hasSubClassEq(const TargetRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:256
Register getGlobalBaseReg(MachineFunction *MF) const
getGlobalBaseReg - Return a virtual register initialized with the the global base register value.
This class provides the information for the target register banks.
bool canUseCMOV() const
bool isTarget64BitILP32() const
Is this x86_64 with the ILP32 programming model (x32 ABI)?
const X86InstrInfo * getInstrInfo() const override
bool hasAVX512() const
unsigned char classifyGlobalReference(const GlobalValue *GV, const Module &M) const
bool isPICStyleRIPRel() const
unsigned char classifyLocalReference(const GlobalValue *GV) const
Classify a global variable reference for the current subtarget according to how we should reference i...
bool hasAVX() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
@ X86
Windows x64, Windows Itanium (IA-64)
Definition MCAsmInfo.h:50
@ MO_GOTOFF
MO_GOTOFF - On a symbol operand this indicates that the immediate is the offset to the location of th...
@ MO_PIC_BASE_OFFSET
MO_PIC_BASE_OFFSET - On a symbol operand this indicates that the immediate should get the value of th...
@ LAST_VALID_COND
Definition X86BaseInfo.h:94
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...
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
Definition TypePool.h:27
NodeAddr< DefNode * > Def
Definition RDFGraph.h:384
This is an optimization pass for GlobalISel generic memory operations.
static bool isGlobalStubReference(unsigned char TargetFlag)
isGlobalStubReference - Return true if the specified TargetFlag operand is a reference to a stub for ...
static bool isGlobalRelativeToPICBase(unsigned char TargetFlag)
isGlobalRelativeToPICBase - Return true if the specified global value reference is relative to a 32-b...
PointerUnion< const TargetRegisterClass *, const RegisterBank * > RegClassOrRegBank
Convenient type to represent either a register class or a register bank.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI std::optional< APInt > getIConstantVRegVal(Register VReg, const MachineRegisterInfo &MRI)
If VReg is defined by a G_CONSTANT, return the corresponding value.
Definition Utils.cpp:294
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
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 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:155
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.
static const MachineInstrBuilder & addConstantPoolReference(const MachineInstrBuilder &MIB, unsigned CPI, Register GlobalBaseReg, unsigned char OpFlags)
addConstantPoolReference - This function is used to add a reference to the base of a constant value s...
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:732
static const MachineInstrBuilder & addFullAddress(const MachineInstrBuilder &MIB, const X86AddressMode &AM)
LLVM_ABI 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:314
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
static const MachineInstrBuilder & addOffset(const MachineInstrBuilder &MIB, int Offset)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
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:1758
static const MachineInstrBuilder & addDirectMem(const MachineInstrBuilder &MIB, Register Reg)
addDirectMem - This function is used to add a direct memory reference to the current instruction – th...
InstructionSelector * createX86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &, const X86RegisterBankInfo &)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:869
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
static LLVM_ABI 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::BaseUnion Base
enum llvm::X86AddressMode::@202116273335065351270200035056227005202106004277 BaseType