xref: /llvm-project/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp (revision 3a5cf6d99b9988a013da3a87ab8f117e5c541f4b)
11c3f7f17SFangrui Song //===- X86InstructionSelector.cpp -----------------------------------------===//
21c3f7f17SFangrui Song //
31c3f7f17SFangrui Song // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41c3f7f17SFangrui Song // See https://llvm.org/LICENSE.txt for license information.
51c3f7f17SFangrui Song // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61c3f7f17SFangrui Song //
71c3f7f17SFangrui Song //===----------------------------------------------------------------------===//
81c3f7f17SFangrui Song /// \file
91c3f7f17SFangrui Song /// This file implements the targeting of the InstructionSelector class for
101c3f7f17SFangrui Song /// X86.
111c3f7f17SFangrui Song /// \todo This should be generated by TableGen.
121c3f7f17SFangrui Song //===----------------------------------------------------------------------===//
131c3f7f17SFangrui Song 
141c3f7f17SFangrui Song #include "MCTargetDesc/X86BaseInfo.h"
151c3f7f17SFangrui Song #include "X86.h"
161c3f7f17SFangrui Song #include "X86InstrBuilder.h"
171c3f7f17SFangrui Song #include "X86InstrInfo.h"
181c3f7f17SFangrui Song #include "X86RegisterBankInfo.h"
191c3f7f17SFangrui Song #include "X86RegisterInfo.h"
201c3f7f17SFangrui Song #include "X86Subtarget.h"
211c3f7f17SFangrui Song #include "X86TargetMachine.h"
221c3f7f17SFangrui Song #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
23ef35da82SEvgenii Kudriashov #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
241c3f7f17SFangrui Song #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
251c3f7f17SFangrui Song #include "llvm/CodeGen/GlobalISel/Utils.h"
261c3f7f17SFangrui Song #include "llvm/CodeGen/MachineBasicBlock.h"
271c3f7f17SFangrui Song #include "llvm/CodeGen/MachineConstantPool.h"
281c3f7f17SFangrui Song #include "llvm/CodeGen/MachineFunction.h"
291c3f7f17SFangrui Song #include "llvm/CodeGen/MachineInstr.h"
301c3f7f17SFangrui Song #include "llvm/CodeGen/MachineInstrBuilder.h"
311c3f7f17SFangrui Song #include "llvm/CodeGen/MachineMemOperand.h"
321c3f7f17SFangrui Song #include "llvm/CodeGen/MachineOperand.h"
331c3f7f17SFangrui Song #include "llvm/CodeGen/MachineRegisterInfo.h"
341c3f7f17SFangrui Song #include "llvm/CodeGen/RegisterBank.h"
351c3f7f17SFangrui Song #include "llvm/CodeGen/TargetOpcodes.h"
361c3f7f17SFangrui Song #include "llvm/CodeGen/TargetRegisterInfo.h"
37184ca395SNico Weber #include "llvm/CodeGenTypes/LowLevelType.h"
381c3f7f17SFangrui Song #include "llvm/IR/DataLayout.h"
391c3f7f17SFangrui Song #include "llvm/IR/InstrTypes.h"
401c3f7f17SFangrui Song #include "llvm/IR/IntrinsicsX86.h"
411c3f7f17SFangrui Song #include "llvm/Support/CodeGen.h"
421c3f7f17SFangrui Song #include "llvm/Support/Debug.h"
431c3f7f17SFangrui Song #include "llvm/Support/ErrorHandling.h"
441c3f7f17SFangrui Song #include "llvm/Support/MathExtras.h"
451c3f7f17SFangrui Song #include "llvm/Support/raw_ostream.h"
461c3f7f17SFangrui Song #include <cassert>
471c3f7f17SFangrui Song #include <cstdint>
481c3f7f17SFangrui Song #include <tuple>
491c3f7f17SFangrui Song 
501c3f7f17SFangrui Song #define DEBUG_TYPE "X86-isel"
511c3f7f17SFangrui Song 
521c3f7f17SFangrui Song using namespace llvm;
531c3f7f17SFangrui Song 
541c3f7f17SFangrui Song namespace {
551c3f7f17SFangrui Song 
561c3f7f17SFangrui Song #define GET_GLOBALISEL_PREDICATE_BITSET
571c3f7f17SFangrui Song #include "X86GenGlobalISel.inc"
581c3f7f17SFangrui Song #undef GET_GLOBALISEL_PREDICATE_BITSET
591c3f7f17SFangrui Song 
601c3f7f17SFangrui Song class X86InstructionSelector : public InstructionSelector {
611c3f7f17SFangrui Song public:
621c3f7f17SFangrui Song   X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
631c3f7f17SFangrui Song                          const X86RegisterBankInfo &RBI);
641c3f7f17SFangrui Song 
651c3f7f17SFangrui Song   bool select(MachineInstr &I) override;
661c3f7f17SFangrui Song   static const char *getName() { return DEBUG_TYPE; }
671c3f7f17SFangrui Song 
681c3f7f17SFangrui Song private:
691c3f7f17SFangrui Song   /// tblgen-erated 'select' implementation, used as the initial selector for
701c3f7f17SFangrui Song   /// the patterns that don't require complex C++.
711c3f7f17SFangrui Song   bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
721c3f7f17SFangrui Song 
731c3f7f17SFangrui Song   // TODO: remove after supported by Tablegen-erated instruction selection.
741c3f7f17SFangrui Song   unsigned getLoadStoreOp(const LLT &Ty, const RegisterBank &RB, unsigned Opc,
751c3f7f17SFangrui Song                           Align Alignment) const;
761c3f7f17SFangrui Song 
771c3f7f17SFangrui Song   bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
781c3f7f17SFangrui Song                          MachineFunction &MF) const;
791c3f7f17SFangrui Song   bool selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI,
801c3f7f17SFangrui Song                              MachineFunction &MF) const;
811c3f7f17SFangrui Song   bool selectGlobalValue(MachineInstr &I, MachineRegisterInfo &MRI,
821c3f7f17SFangrui Song                          MachineFunction &MF) const;
831c3f7f17SFangrui Song   bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
841c3f7f17SFangrui Song                       MachineFunction &MF) const;
851c3f7f17SFangrui Song   bool selectTruncOrPtrToInt(MachineInstr &I, MachineRegisterInfo &MRI,
861c3f7f17SFangrui Song                              MachineFunction &MF) const;
871c3f7f17SFangrui Song   bool selectZext(MachineInstr &I, MachineRegisterInfo &MRI,
881c3f7f17SFangrui Song                   MachineFunction &MF) const;
891c3f7f17SFangrui Song   bool selectAnyext(MachineInstr &I, MachineRegisterInfo &MRI,
901c3f7f17SFangrui Song                     MachineFunction &MF) const;
911c3f7f17SFangrui Song   bool selectCmp(MachineInstr &I, MachineRegisterInfo &MRI,
921c3f7f17SFangrui Song                  MachineFunction &MF) const;
931c3f7f17SFangrui Song   bool selectFCmp(MachineInstr &I, MachineRegisterInfo &MRI,
941c3f7f17SFangrui Song                   MachineFunction &MF) const;
951c3f7f17SFangrui Song   bool selectUAddSub(MachineInstr &I, MachineRegisterInfo &MRI,
961c3f7f17SFangrui Song                      MachineFunction &MF) const;
971c3f7f17SFangrui Song   bool selectDebugInstr(MachineInstr &I, MachineRegisterInfo &MRI) const;
981c3f7f17SFangrui Song   bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
991c3f7f17SFangrui Song   bool selectUnmergeValues(MachineInstr &I, MachineRegisterInfo &MRI,
1001c3f7f17SFangrui Song                            MachineFunction &MF);
1011c3f7f17SFangrui Song   bool selectMergeValues(MachineInstr &I, MachineRegisterInfo &MRI,
1021c3f7f17SFangrui Song                          MachineFunction &MF);
1031c3f7f17SFangrui Song   bool selectInsert(MachineInstr &I, MachineRegisterInfo &MRI,
1041c3f7f17SFangrui Song                     MachineFunction &MF) const;
1051c3f7f17SFangrui Song   bool selectExtract(MachineInstr &I, MachineRegisterInfo &MRI,
1061c3f7f17SFangrui Song                      MachineFunction &MF) const;
1071c3f7f17SFangrui Song   bool selectCondBranch(MachineInstr &I, MachineRegisterInfo &MRI,
1081c3f7f17SFangrui Song                         MachineFunction &MF) const;
1091c3f7f17SFangrui Song   bool selectTurnIntoCOPY(MachineInstr &I, MachineRegisterInfo &MRI,
1101c3f7f17SFangrui Song                           const unsigned DstReg,
1111c3f7f17SFangrui Song                           const TargetRegisterClass *DstRC,
1121c3f7f17SFangrui Song                           const unsigned SrcReg,
1131c3f7f17SFangrui Song                           const TargetRegisterClass *SrcRC) const;
1141c3f7f17SFangrui Song   bool materializeFP(MachineInstr &I, MachineRegisterInfo &MRI,
1151c3f7f17SFangrui Song                      MachineFunction &MF) const;
1161c3f7f17SFangrui Song   bool selectImplicitDefOrPHI(MachineInstr &I, MachineRegisterInfo &MRI) const;
1171c3f7f17SFangrui Song   bool selectMulDivRem(MachineInstr &I, MachineRegisterInfo &MRI,
1181c3f7f17SFangrui Song                        MachineFunction &MF) const;
119ef35da82SEvgenii Kudriashov   bool selectSelect(MachineInstr &I, MachineRegisterInfo &MRI,
120ef35da82SEvgenii Kudriashov                     MachineFunction &MF) const;
1211c3f7f17SFangrui Song 
1221c3f7f17SFangrui Song   // emit insert subreg instruction and insert it before MachineInstr &I
1231c3f7f17SFangrui Song   bool emitInsertSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
1241c3f7f17SFangrui Song                         MachineRegisterInfo &MRI, MachineFunction &MF) const;
1251c3f7f17SFangrui Song   // emit extract subreg instruction and insert it before MachineInstr &I
1261c3f7f17SFangrui Song   bool emitExtractSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
1271c3f7f17SFangrui Song                          MachineRegisterInfo &MRI, MachineFunction &MF) const;
1281c3f7f17SFangrui Song 
1291c3f7f17SFangrui Song   const TargetRegisterClass *getRegClass(LLT Ty, const RegisterBank &RB) const;
1301c3f7f17SFangrui Song   const TargetRegisterClass *getRegClass(LLT Ty, unsigned Reg,
1311c3f7f17SFangrui Song                                          MachineRegisterInfo &MRI) const;
1321c3f7f17SFangrui Song 
1331c3f7f17SFangrui Song   const X86TargetMachine &TM;
1341c3f7f17SFangrui Song   const X86Subtarget &STI;
1351c3f7f17SFangrui Song   const X86InstrInfo &TII;
1361c3f7f17SFangrui Song   const X86RegisterInfo &TRI;
1371c3f7f17SFangrui Song   const X86RegisterBankInfo &RBI;
1381c3f7f17SFangrui Song 
1391c3f7f17SFangrui Song #define GET_GLOBALISEL_PREDICATES_DECL
1401c3f7f17SFangrui Song #include "X86GenGlobalISel.inc"
1411c3f7f17SFangrui Song #undef GET_GLOBALISEL_PREDICATES_DECL
1421c3f7f17SFangrui Song 
1431c3f7f17SFangrui Song #define GET_GLOBALISEL_TEMPORARIES_DECL
1441c3f7f17SFangrui Song #include "X86GenGlobalISel.inc"
1451c3f7f17SFangrui Song #undef GET_GLOBALISEL_TEMPORARIES_DECL
1461c3f7f17SFangrui Song };
1471c3f7f17SFangrui Song 
1481c3f7f17SFangrui Song } // end anonymous namespace
1491c3f7f17SFangrui Song 
1501c3f7f17SFangrui Song #define GET_GLOBALISEL_IMPL
1511c3f7f17SFangrui Song #include "X86GenGlobalISel.inc"
1521c3f7f17SFangrui Song #undef GET_GLOBALISEL_IMPL
1531c3f7f17SFangrui Song 
1541c3f7f17SFangrui Song X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
1551c3f7f17SFangrui Song                                                const X86Subtarget &STI,
1561c3f7f17SFangrui Song                                                const X86RegisterBankInfo &RBI)
1571c3f7f17SFangrui Song     : TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()),
1581c3f7f17SFangrui Song       RBI(RBI),
1591c3f7f17SFangrui Song #define GET_GLOBALISEL_PREDICATES_INIT
1601c3f7f17SFangrui Song #include "X86GenGlobalISel.inc"
1611c3f7f17SFangrui Song #undef GET_GLOBALISEL_PREDICATES_INIT
1621c3f7f17SFangrui Song #define GET_GLOBALISEL_TEMPORARIES_INIT
1631c3f7f17SFangrui Song #include "X86GenGlobalISel.inc"
1641c3f7f17SFangrui Song #undef GET_GLOBALISEL_TEMPORARIES_INIT
1651c3f7f17SFangrui Song {
1661c3f7f17SFangrui Song }
1671c3f7f17SFangrui Song 
1681c3f7f17SFangrui Song // FIXME: This should be target-independent, inferred from the types declared
1691c3f7f17SFangrui Song // for each class in the bank.
1701c3f7f17SFangrui Song const TargetRegisterClass *
1711c3f7f17SFangrui Song X86InstructionSelector::getRegClass(LLT Ty, const RegisterBank &RB) const {
1721c3f7f17SFangrui Song   if (RB.getID() == X86::GPRRegBankID) {
1731c3f7f17SFangrui Song     if (Ty.getSizeInBits() <= 8)
1741c3f7f17SFangrui Song       return &X86::GR8RegClass;
1751c3f7f17SFangrui Song     if (Ty.getSizeInBits() == 16)
1761c3f7f17SFangrui Song       return &X86::GR16RegClass;
1771c3f7f17SFangrui Song     if (Ty.getSizeInBits() == 32)
1781c3f7f17SFangrui Song       return &X86::GR32RegClass;
1791c3f7f17SFangrui Song     if (Ty.getSizeInBits() == 64)
1801c3f7f17SFangrui Song       return &X86::GR64RegClass;
1811c3f7f17SFangrui Song   }
1821c3f7f17SFangrui Song   if (RB.getID() == X86::VECRRegBankID) {
1831c3f7f17SFangrui Song     if (Ty.getSizeInBits() == 16)
1841c3f7f17SFangrui Song       return STI.hasAVX512() ? &X86::FR16XRegClass : &X86::FR16RegClass;
1851c3f7f17SFangrui Song     if (Ty.getSizeInBits() == 32)
1861c3f7f17SFangrui Song       return STI.hasAVX512() ? &X86::FR32XRegClass : &X86::FR32RegClass;
1871c3f7f17SFangrui Song     if (Ty.getSizeInBits() == 64)
1881c3f7f17SFangrui Song       return STI.hasAVX512() ? &X86::FR64XRegClass : &X86::FR64RegClass;
1891c3f7f17SFangrui Song     if (Ty.getSizeInBits() == 128)
1901c3f7f17SFangrui Song       return STI.hasAVX512() ? &X86::VR128XRegClass : &X86::VR128RegClass;
1911c3f7f17SFangrui Song     if (Ty.getSizeInBits() == 256)
1921c3f7f17SFangrui Song       return STI.hasAVX512() ? &X86::VR256XRegClass : &X86::VR256RegClass;
1931c3f7f17SFangrui Song     if (Ty.getSizeInBits() == 512)
1941c3f7f17SFangrui Song       return &X86::VR512RegClass;
1951c3f7f17SFangrui Song   }
1961c3f7f17SFangrui Song 
197a77d3ea3SMalay Sanghi   if (RB.getID() == X86::PSRRegBankID) {
198a77d3ea3SMalay Sanghi     if (Ty.getSizeInBits() == 80)
199a77d3ea3SMalay Sanghi       return &X86::RFP80RegClass;
200a77d3ea3SMalay Sanghi     if (Ty.getSizeInBits() == 64)
201a77d3ea3SMalay Sanghi       return &X86::RFP64RegClass;
202a77d3ea3SMalay Sanghi     if (Ty.getSizeInBits() == 32)
203a77d3ea3SMalay Sanghi       return &X86::RFP32RegClass;
204a77d3ea3SMalay Sanghi   }
205a77d3ea3SMalay Sanghi 
2061c3f7f17SFangrui Song   llvm_unreachable("Unknown RegBank!");
2071c3f7f17SFangrui Song }
2081c3f7f17SFangrui Song 
2091c3f7f17SFangrui Song const TargetRegisterClass *
2101c3f7f17SFangrui Song X86InstructionSelector::getRegClass(LLT Ty, unsigned Reg,
2111c3f7f17SFangrui Song                                     MachineRegisterInfo &MRI) const {
2121c3f7f17SFangrui Song   const RegisterBank &RegBank = *RBI.getRegBank(Reg, MRI, TRI);
2131c3f7f17SFangrui Song   return getRegClass(Ty, RegBank);
2141c3f7f17SFangrui Song }
2151c3f7f17SFangrui Song 
2161c3f7f17SFangrui Song static unsigned getSubRegIndex(const TargetRegisterClass *RC) {
2171c3f7f17SFangrui Song   unsigned SubIdx = X86::NoSubRegister;
2181c3f7f17SFangrui Song   if (RC == &X86::GR32RegClass) {
2191c3f7f17SFangrui Song     SubIdx = X86::sub_32bit;
2201c3f7f17SFangrui Song   } else if (RC == &X86::GR16RegClass) {
2211c3f7f17SFangrui Song     SubIdx = X86::sub_16bit;
2221c3f7f17SFangrui Song   } else if (RC == &X86::GR8RegClass) {
2231c3f7f17SFangrui Song     SubIdx = X86::sub_8bit;
2241c3f7f17SFangrui Song   }
2251c3f7f17SFangrui Song 
2261c3f7f17SFangrui Song   return SubIdx;
2271c3f7f17SFangrui Song }
2281c3f7f17SFangrui Song 
2291c3f7f17SFangrui Song static const TargetRegisterClass *getRegClassFromGRPhysReg(Register Reg) {
2301c3f7f17SFangrui Song   assert(Reg.isPhysical());
2311c3f7f17SFangrui Song   if (X86::GR64RegClass.contains(Reg))
2321c3f7f17SFangrui Song     return &X86::GR64RegClass;
2331c3f7f17SFangrui Song   if (X86::GR32RegClass.contains(Reg))
2341c3f7f17SFangrui Song     return &X86::GR32RegClass;
2351c3f7f17SFangrui Song   if (X86::GR16RegClass.contains(Reg))
2361c3f7f17SFangrui Song     return &X86::GR16RegClass;
2371c3f7f17SFangrui Song   if (X86::GR8RegClass.contains(Reg))
2381c3f7f17SFangrui Song     return &X86::GR8RegClass;
2391c3f7f17SFangrui Song 
2401c3f7f17SFangrui Song   llvm_unreachable("Unknown RegClass for PhysReg!");
2411c3f7f17SFangrui Song }
2421c3f7f17SFangrui Song 
2431c3f7f17SFangrui Song // FIXME: We need some sort of API in RBI/TRI to allow generic code to
2441c3f7f17SFangrui Song // constrain operands of simple instructions given a TargetRegisterClass
2451c3f7f17SFangrui Song // and LLT
2461c3f7f17SFangrui Song bool X86InstructionSelector::selectDebugInstr(MachineInstr &I,
2471c3f7f17SFangrui Song                                               MachineRegisterInfo &MRI) const {
2481c3f7f17SFangrui Song   for (MachineOperand &MO : I.operands()) {
2491c3f7f17SFangrui Song     if (!MO.isReg())
2501c3f7f17SFangrui Song       continue;
2511c3f7f17SFangrui Song     Register Reg = MO.getReg();
2521c3f7f17SFangrui Song     if (!Reg)
2531c3f7f17SFangrui Song       continue;
2541c3f7f17SFangrui Song     if (Reg.isPhysical())
2551c3f7f17SFangrui Song       continue;
2561c3f7f17SFangrui Song     LLT Ty = MRI.getType(Reg);
2571c3f7f17SFangrui Song     const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(Reg);
2581c3f7f17SFangrui Song     const TargetRegisterClass *RC =
2591c3f7f17SFangrui Song         dyn_cast_if_present<const TargetRegisterClass *>(RegClassOrBank);
2601c3f7f17SFangrui Song     if (!RC) {
2611c3f7f17SFangrui Song       const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
2621c3f7f17SFangrui Song       RC = getRegClass(Ty, RB);
2631c3f7f17SFangrui Song       if (!RC) {
2641c3f7f17SFangrui Song         LLVM_DEBUG(
2651c3f7f17SFangrui Song             dbgs() << "Warning: DBG_VALUE operand has unexpected size/bank\n");
2661c3f7f17SFangrui Song         break;
2671c3f7f17SFangrui Song       }
2681c3f7f17SFangrui Song     }
2691c3f7f17SFangrui Song     RBI.constrainGenericRegister(Reg, *RC, MRI);
2701c3f7f17SFangrui Song   }
2711c3f7f17SFangrui Song 
2721c3f7f17SFangrui Song   return true;
2731c3f7f17SFangrui Song }
2741c3f7f17SFangrui Song 
2751c3f7f17SFangrui Song // Set X86 Opcode and constrain DestReg.
2761c3f7f17SFangrui Song bool X86InstructionSelector::selectCopy(MachineInstr &I,
2771c3f7f17SFangrui Song                                         MachineRegisterInfo &MRI) const {
2781c3f7f17SFangrui Song   Register DstReg = I.getOperand(0).getReg();
2791c3f7f17SFangrui Song   const unsigned DstSize = RBI.getSizeInBits(DstReg, MRI, TRI);
2801c3f7f17SFangrui Song   const RegisterBank &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
2811c3f7f17SFangrui Song 
2821c3f7f17SFangrui Song   Register SrcReg = I.getOperand(1).getReg();
2831c3f7f17SFangrui Song   const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
2841c3f7f17SFangrui Song   const RegisterBank &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
2851c3f7f17SFangrui Song 
2861c3f7f17SFangrui Song   if (DstReg.isPhysical()) {
2871c3f7f17SFangrui Song     assert(I.isCopy() && "Generic operators do not allow physical registers");
2881c3f7f17SFangrui Song 
2891c3f7f17SFangrui Song     if (DstSize > SrcSize && SrcRegBank.getID() == X86::GPRRegBankID &&
2901c3f7f17SFangrui Song         DstRegBank.getID() == X86::GPRRegBankID) {
2911c3f7f17SFangrui Song 
2921c3f7f17SFangrui Song       const TargetRegisterClass *SrcRC =
2931c3f7f17SFangrui Song           getRegClass(MRI.getType(SrcReg), SrcRegBank);
2941c3f7f17SFangrui Song       const TargetRegisterClass *DstRC = getRegClassFromGRPhysReg(DstReg);
2951c3f7f17SFangrui Song 
2961c3f7f17SFangrui Song       if (SrcRC != DstRC) {
2971c3f7f17SFangrui Song         // This case can be generated by ABI lowering, performe anyext
2981c3f7f17SFangrui Song         Register ExtSrc = MRI.createVirtualRegister(DstRC);
2991c3f7f17SFangrui Song         BuildMI(*I.getParent(), I, I.getDebugLoc(),
3001c3f7f17SFangrui Song                 TII.get(TargetOpcode::SUBREG_TO_REG))
3011c3f7f17SFangrui Song             .addDef(ExtSrc)
3021c3f7f17SFangrui Song             .addImm(0)
3031c3f7f17SFangrui Song             .addReg(SrcReg)
3041c3f7f17SFangrui Song             .addImm(getSubRegIndex(SrcRC));
3051c3f7f17SFangrui Song 
3061c3f7f17SFangrui Song         I.getOperand(1).setReg(ExtSrc);
3071c3f7f17SFangrui Song       }
3081c3f7f17SFangrui Song     }
3091c3f7f17SFangrui Song 
3101c3f7f17SFangrui Song     return true;
3111c3f7f17SFangrui Song   }
3121c3f7f17SFangrui Song 
3131c3f7f17SFangrui Song   assert((!SrcReg.isPhysical() || I.isCopy()) &&
3141c3f7f17SFangrui Song          "No phys reg on generic operators");
3151c3f7f17SFangrui Song   assert((DstSize == SrcSize ||
3161c3f7f17SFangrui Song           // Copies are a mean to setup initial types, the number of
3171c3f7f17SFangrui Song           // bits may not exactly match.
3181c3f7f17SFangrui Song           (SrcReg.isPhysical() &&
3191c3f7f17SFangrui Song            DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
3201c3f7f17SFangrui Song          "Copy with different width?!");
3211c3f7f17SFangrui Song 
3221c3f7f17SFangrui Song   const TargetRegisterClass *DstRC =
3231c3f7f17SFangrui Song       getRegClass(MRI.getType(DstReg), DstRegBank);
3241c3f7f17SFangrui Song 
3251c3f7f17SFangrui Song   if (SrcRegBank.getID() == X86::GPRRegBankID &&
3261c3f7f17SFangrui Song       DstRegBank.getID() == X86::GPRRegBankID && SrcSize > DstSize &&
3271c3f7f17SFangrui Song       SrcReg.isPhysical()) {
3281c3f7f17SFangrui Song     // Change the physical register to performe truncate.
3291c3f7f17SFangrui Song 
3301c3f7f17SFangrui Song     const TargetRegisterClass *SrcRC = getRegClassFromGRPhysReg(SrcReg);
3311c3f7f17SFangrui Song 
3321c3f7f17SFangrui Song     if (DstRC != SrcRC) {
3331c3f7f17SFangrui Song       I.getOperand(1).setSubReg(getSubRegIndex(DstRC));
3341c3f7f17SFangrui Song       I.getOperand(1).substPhysReg(SrcReg, TRI);
3351c3f7f17SFangrui Song     }
3361c3f7f17SFangrui Song   }
3371c3f7f17SFangrui Song 
3381c3f7f17SFangrui Song   // No need to constrain SrcReg. It will get constrained when
3391c3f7f17SFangrui Song   // we hit another of its use or its defs.
3401c3f7f17SFangrui Song   // Copies do not have constraints.
3411c3f7f17SFangrui Song   const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
3421c3f7f17SFangrui Song   if (!OldRC || !DstRC->hasSubClassEq(OldRC)) {
3431c3f7f17SFangrui Song     if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
3441c3f7f17SFangrui Song       LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
3451c3f7f17SFangrui Song                         << " operand\n");
3461c3f7f17SFangrui Song       return false;
3471c3f7f17SFangrui Song     }
3481c3f7f17SFangrui Song   }
3491c3f7f17SFangrui Song   I.setDesc(TII.get(X86::COPY));
3501c3f7f17SFangrui Song   return true;
3511c3f7f17SFangrui Song }
3521c3f7f17SFangrui Song 
3531c3f7f17SFangrui Song bool X86InstructionSelector::select(MachineInstr &I) {
3541c3f7f17SFangrui Song   assert(I.getParent() && "Instruction should be in a basic block!");
3551c3f7f17SFangrui Song   assert(I.getParent()->getParent() && "Instruction should be in a function!");
3561c3f7f17SFangrui Song 
3571c3f7f17SFangrui Song   MachineBasicBlock &MBB = *I.getParent();
3581c3f7f17SFangrui Song   MachineFunction &MF = *MBB.getParent();
3591c3f7f17SFangrui Song   MachineRegisterInfo &MRI = MF.getRegInfo();
3601c3f7f17SFangrui Song 
3611c3f7f17SFangrui Song   unsigned Opcode = I.getOpcode();
3621c3f7f17SFangrui Song   if (!isPreISelGenericOpcode(Opcode)) {
3631c3f7f17SFangrui Song     // Certain non-generic instructions also need some special handling.
3641c3f7f17SFangrui Song 
3651c3f7f17SFangrui Song     if (Opcode == TargetOpcode::LOAD_STACK_GUARD)
3661c3f7f17SFangrui Song       return false;
3671c3f7f17SFangrui Song 
3681c3f7f17SFangrui Song     if (I.isCopy())
3691c3f7f17SFangrui Song       return selectCopy(I, MRI);
3701c3f7f17SFangrui Song 
3711c3f7f17SFangrui Song     if (I.isDebugInstr())
3721c3f7f17SFangrui Song       return selectDebugInstr(I, MRI);
3731c3f7f17SFangrui Song 
3741c3f7f17SFangrui Song     return true;
3751c3f7f17SFangrui Song   }
3761c3f7f17SFangrui Song 
3771c3f7f17SFangrui Song   assert(I.getNumOperands() == I.getNumExplicitOperands() &&
3781c3f7f17SFangrui Song          "Generic instruction has unexpected implicit operands\n");
3791c3f7f17SFangrui Song 
3801c3f7f17SFangrui Song   if (selectImpl(I, *CoverageInfo))
3811c3f7f17SFangrui Song     return true;
3821c3f7f17SFangrui Song 
3831c3f7f17SFangrui Song   LLVM_DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));
3841c3f7f17SFangrui Song 
3851c3f7f17SFangrui Song   // TODO: This should be implemented by tblgen.
3861c3f7f17SFangrui Song   switch (I.getOpcode()) {
3871c3f7f17SFangrui Song   default:
3881c3f7f17SFangrui Song     return false;
3891c3f7f17SFangrui Song   case TargetOpcode::G_STORE:
3901c3f7f17SFangrui Song   case TargetOpcode::G_LOAD:
3911c3f7f17SFangrui Song     return selectLoadStoreOp(I, MRI, MF);
3921c3f7f17SFangrui Song   case TargetOpcode::G_PTR_ADD:
3931c3f7f17SFangrui Song   case TargetOpcode::G_FRAME_INDEX:
3941c3f7f17SFangrui Song     return selectFrameIndexOrGep(I, MRI, MF);
3951c3f7f17SFangrui Song   case TargetOpcode::G_GLOBAL_VALUE:
3961c3f7f17SFangrui Song     return selectGlobalValue(I, MRI, MF);
3971c3f7f17SFangrui Song   case TargetOpcode::G_CONSTANT:
3981c3f7f17SFangrui Song     return selectConstant(I, MRI, MF);
3991c3f7f17SFangrui Song   case TargetOpcode::G_FCONSTANT:
4001c3f7f17SFangrui Song     return materializeFP(I, MRI, MF);
4011c3f7f17SFangrui Song   case TargetOpcode::G_PTRTOINT:
4021c3f7f17SFangrui Song   case TargetOpcode::G_TRUNC:
4031c3f7f17SFangrui Song     return selectTruncOrPtrToInt(I, MRI, MF);
4041c3f7f17SFangrui Song   case TargetOpcode::G_INTTOPTR:
4051c3f7f17SFangrui Song     return selectCopy(I, MRI);
4061c3f7f17SFangrui Song   case TargetOpcode::G_ZEXT:
4071c3f7f17SFangrui Song     return selectZext(I, MRI, MF);
4081c3f7f17SFangrui Song   case TargetOpcode::G_ANYEXT:
4091c3f7f17SFangrui Song     return selectAnyext(I, MRI, MF);
4101c3f7f17SFangrui Song   case TargetOpcode::G_ICMP:
4111c3f7f17SFangrui Song     return selectCmp(I, MRI, MF);
4121c3f7f17SFangrui Song   case TargetOpcode::G_FCMP:
4131c3f7f17SFangrui Song     return selectFCmp(I, MRI, MF);
4141c3f7f17SFangrui Song   case TargetOpcode::G_UADDE:
4151c3f7f17SFangrui Song   case TargetOpcode::G_UADDO:
4161c3f7f17SFangrui Song   case TargetOpcode::G_USUBE:
4171c3f7f17SFangrui Song   case TargetOpcode::G_USUBO:
4181c3f7f17SFangrui Song     return selectUAddSub(I, MRI, MF);
4191c3f7f17SFangrui Song   case TargetOpcode::G_UNMERGE_VALUES:
4201c3f7f17SFangrui Song     return selectUnmergeValues(I, MRI, MF);
4211c3f7f17SFangrui Song   case TargetOpcode::G_MERGE_VALUES:
4221c3f7f17SFangrui Song   case TargetOpcode::G_CONCAT_VECTORS:
4231c3f7f17SFangrui Song     return selectMergeValues(I, MRI, MF);
4241c3f7f17SFangrui Song   case TargetOpcode::G_EXTRACT:
4251c3f7f17SFangrui Song     return selectExtract(I, MRI, MF);
4261c3f7f17SFangrui Song   case TargetOpcode::G_INSERT:
4271c3f7f17SFangrui Song     return selectInsert(I, MRI, MF);
4281c3f7f17SFangrui Song   case TargetOpcode::G_BRCOND:
4291c3f7f17SFangrui Song     return selectCondBranch(I, MRI, MF);
4301c3f7f17SFangrui Song   case TargetOpcode::G_IMPLICIT_DEF:
4311c3f7f17SFangrui Song   case TargetOpcode::G_PHI:
4321c3f7f17SFangrui Song     return selectImplicitDefOrPHI(I, MRI);
4331c3f7f17SFangrui Song   case TargetOpcode::G_MUL:
4341c3f7f17SFangrui Song   case TargetOpcode::G_SMULH:
4351c3f7f17SFangrui Song   case TargetOpcode::G_UMULH:
4361c3f7f17SFangrui Song   case TargetOpcode::G_SDIV:
4371c3f7f17SFangrui Song   case TargetOpcode::G_UDIV:
4381c3f7f17SFangrui Song   case TargetOpcode::G_SREM:
4391c3f7f17SFangrui Song   case TargetOpcode::G_UREM:
4401c3f7f17SFangrui Song     return selectMulDivRem(I, MRI, MF);
441ef35da82SEvgenii Kudriashov   case TargetOpcode::G_SELECT:
442ef35da82SEvgenii Kudriashov     return selectSelect(I, MRI, MF);
4431c3f7f17SFangrui Song   }
4441c3f7f17SFangrui Song 
4451c3f7f17SFangrui Song   return false;
4461c3f7f17SFangrui Song }
4471c3f7f17SFangrui Song 
4481c3f7f17SFangrui Song unsigned X86InstructionSelector::getLoadStoreOp(const LLT &Ty,
4491c3f7f17SFangrui Song                                                 const RegisterBank &RB,
4501c3f7f17SFangrui Song                                                 unsigned Opc,
4511c3f7f17SFangrui Song                                                 Align Alignment) const {
4521c3f7f17SFangrui Song   bool Isload = (Opc == TargetOpcode::G_LOAD);
4531c3f7f17SFangrui Song   bool HasAVX = STI.hasAVX();
4541c3f7f17SFangrui Song   bool HasAVX512 = STI.hasAVX512();
4551c3f7f17SFangrui Song   bool HasVLX = STI.hasVLX();
4561c3f7f17SFangrui Song 
4571c3f7f17SFangrui Song   if (Ty == LLT::scalar(8)) {
4581c3f7f17SFangrui Song     if (X86::GPRRegBankID == RB.getID())
4591c3f7f17SFangrui Song       return Isload ? X86::MOV8rm : X86::MOV8mr;
4601c3f7f17SFangrui Song   } else if (Ty == LLT::scalar(16)) {
4611c3f7f17SFangrui Song     if (X86::GPRRegBankID == RB.getID())
4621c3f7f17SFangrui Song       return Isload ? X86::MOV16rm : X86::MOV16mr;
4631c3f7f17SFangrui Song   } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {
4641c3f7f17SFangrui Song     if (X86::GPRRegBankID == RB.getID())
4651c3f7f17SFangrui Song       return Isload ? X86::MOV32rm : X86::MOV32mr;
4661c3f7f17SFangrui Song     if (X86::VECRRegBankID == RB.getID())
4671c3f7f17SFangrui Song       return Isload ? (HasAVX512 ? X86::VMOVSSZrm_alt :
4681c3f7f17SFangrui Song                        HasAVX    ? X86::VMOVSSrm_alt :
4691c3f7f17SFangrui Song                                    X86::MOVSSrm_alt)
4701c3f7f17SFangrui Song                     : (HasAVX512 ? X86::VMOVSSZmr :
4711c3f7f17SFangrui Song                        HasAVX    ? X86::VMOVSSmr :
4721c3f7f17SFangrui Song                                    X86::MOVSSmr);
473a77d3ea3SMalay Sanghi     if (X86::PSRRegBankID == RB.getID())
474a77d3ea3SMalay Sanghi       return Isload ? X86::LD_Fp32m : X86::ST_Fp32m;
4751c3f7f17SFangrui Song   } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
4761c3f7f17SFangrui Song     if (X86::GPRRegBankID == RB.getID())
4771c3f7f17SFangrui Song       return Isload ? X86::MOV64rm : X86::MOV64mr;
4781c3f7f17SFangrui Song     if (X86::VECRRegBankID == RB.getID())
4791c3f7f17SFangrui Song       return Isload ? (HasAVX512 ? X86::VMOVSDZrm_alt :
4801c3f7f17SFangrui Song                        HasAVX    ? X86::VMOVSDrm_alt :
4811c3f7f17SFangrui Song                                    X86::MOVSDrm_alt)
4821c3f7f17SFangrui Song                     : (HasAVX512 ? X86::VMOVSDZmr :
4831c3f7f17SFangrui Song                        HasAVX    ? X86::VMOVSDmr :
4841c3f7f17SFangrui Song                                    X86::MOVSDmr);
485a77d3ea3SMalay Sanghi     if (X86::PSRRegBankID == RB.getID())
486a77d3ea3SMalay Sanghi       return Isload ? X86::LD_Fp64m : X86::ST_Fp64m;
487a77d3ea3SMalay Sanghi   } else if (Ty == LLT::scalar(80)) {
488a77d3ea3SMalay Sanghi     return Isload ? X86::LD_Fp80m : X86::ST_FpP80m;
4891c3f7f17SFangrui Song   } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
4901c3f7f17SFangrui Song     if (Alignment >= Align(16))
4911c3f7f17SFangrui Song       return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
4921c3f7f17SFangrui Song                               : HasAVX512
4931c3f7f17SFangrui Song                                     ? X86::VMOVAPSZ128rm_NOVLX
4941c3f7f17SFangrui Song                                     : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
4951c3f7f17SFangrui Song                     : (HasVLX ? X86::VMOVAPSZ128mr
4961c3f7f17SFangrui Song                               : HasAVX512
4971c3f7f17SFangrui Song                                     ? X86::VMOVAPSZ128mr_NOVLX
4981c3f7f17SFangrui Song                                     : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
4991c3f7f17SFangrui Song     else
5001c3f7f17SFangrui Song       return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
5011c3f7f17SFangrui Song                               : HasAVX512
5021c3f7f17SFangrui Song                                     ? X86::VMOVUPSZ128rm_NOVLX
5031c3f7f17SFangrui Song                                     : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
5041c3f7f17SFangrui Song                     : (HasVLX ? X86::VMOVUPSZ128mr
5051c3f7f17SFangrui Song                               : HasAVX512
5061c3f7f17SFangrui Song                                     ? X86::VMOVUPSZ128mr_NOVLX
5071c3f7f17SFangrui Song                                     : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
5081c3f7f17SFangrui Song   } else if (Ty.isVector() && Ty.getSizeInBits() == 256) {
5091c3f7f17SFangrui Song     if (Alignment >= Align(32))
5101c3f7f17SFangrui Song       return Isload ? (HasVLX ? X86::VMOVAPSZ256rm
5111c3f7f17SFangrui Song                               : HasAVX512 ? X86::VMOVAPSZ256rm_NOVLX
5121c3f7f17SFangrui Song                                           : X86::VMOVAPSYrm)
5131c3f7f17SFangrui Song                     : (HasVLX ? X86::VMOVAPSZ256mr
5141c3f7f17SFangrui Song                               : HasAVX512 ? X86::VMOVAPSZ256mr_NOVLX
5151c3f7f17SFangrui Song                                           : X86::VMOVAPSYmr);
5161c3f7f17SFangrui Song     else
5171c3f7f17SFangrui Song       return Isload ? (HasVLX ? X86::VMOVUPSZ256rm
5181c3f7f17SFangrui Song                               : HasAVX512 ? X86::VMOVUPSZ256rm_NOVLX
5191c3f7f17SFangrui Song                                           : X86::VMOVUPSYrm)
5201c3f7f17SFangrui Song                     : (HasVLX ? X86::VMOVUPSZ256mr
5211c3f7f17SFangrui Song                               : HasAVX512 ? X86::VMOVUPSZ256mr_NOVLX
5221c3f7f17SFangrui Song                                           : X86::VMOVUPSYmr);
5231c3f7f17SFangrui Song   } else if (Ty.isVector() && Ty.getSizeInBits() == 512) {
5241c3f7f17SFangrui Song     if (Alignment >= Align(64))
5251c3f7f17SFangrui Song       return Isload ? X86::VMOVAPSZrm : X86::VMOVAPSZmr;
5261c3f7f17SFangrui Song     else
5271c3f7f17SFangrui Song       return Isload ? X86::VMOVUPSZrm : X86::VMOVUPSZmr;
5281c3f7f17SFangrui Song   }
5291c3f7f17SFangrui Song   return Opc;
5301c3f7f17SFangrui Song }
5311c3f7f17SFangrui Song 
5321c3f7f17SFangrui Song // Fill in an address from the given instruction.
5331c3f7f17SFangrui Song static void X86SelectAddress(const MachineInstr &I,
5341c3f7f17SFangrui Song                              const MachineRegisterInfo &MRI,
5351c3f7f17SFangrui Song                              X86AddressMode &AM) {
5361c3f7f17SFangrui Song   assert(I.getOperand(0).isReg() && "unsupported opperand.");
5371c3f7f17SFangrui Song   assert(MRI.getType(I.getOperand(0).getReg()).isPointer() &&
5381c3f7f17SFangrui Song          "unsupported type.");
5391c3f7f17SFangrui Song 
5401c3f7f17SFangrui Song   if (I.getOpcode() == TargetOpcode::G_PTR_ADD) {
5411c3f7f17SFangrui Song     if (auto COff = getIConstantVRegSExtVal(I.getOperand(2).getReg(), MRI)) {
5421c3f7f17SFangrui Song       int64_t Imm = *COff;
5431c3f7f17SFangrui Song       if (isInt<32>(Imm)) { // Check for displacement overflow.
5441c3f7f17SFangrui Song         AM.Disp = static_cast<int32_t>(Imm);
5451c3f7f17SFangrui Song         AM.Base.Reg = I.getOperand(1).getReg();
5461c3f7f17SFangrui Song         return;
5471c3f7f17SFangrui Song       }
5481c3f7f17SFangrui Song     }
5491c3f7f17SFangrui Song   } else if (I.getOpcode() == TargetOpcode::G_FRAME_INDEX) {
5501c3f7f17SFangrui Song     AM.Base.FrameIndex = I.getOperand(1).getIndex();
5511c3f7f17SFangrui Song     AM.BaseType = X86AddressMode::FrameIndexBase;
5521c3f7f17SFangrui Song     return;
5531c3f7f17SFangrui Song   }
5541c3f7f17SFangrui Song 
5551c3f7f17SFangrui Song   // Default behavior.
5561c3f7f17SFangrui Song   AM.Base.Reg = I.getOperand(0).getReg();
5571c3f7f17SFangrui Song }
5581c3f7f17SFangrui Song 
5591c3f7f17SFangrui Song bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
5601c3f7f17SFangrui Song                                                MachineRegisterInfo &MRI,
5611c3f7f17SFangrui Song                                                MachineFunction &MF) const {
5621c3f7f17SFangrui Song   unsigned Opc = I.getOpcode();
5631c3f7f17SFangrui Song 
5641c3f7f17SFangrui Song   assert((Opc == TargetOpcode::G_STORE || Opc == TargetOpcode::G_LOAD) &&
56511d7203cSEvgenii Kudriashov          "Only G_STORE and G_LOAD are expected for selection");
5661c3f7f17SFangrui Song 
5671c3f7f17SFangrui Song   const Register DefReg = I.getOperand(0).getReg();
5681c3f7f17SFangrui Song   LLT Ty = MRI.getType(DefReg);
5691c3f7f17SFangrui Song   const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
5701c3f7f17SFangrui Song 
5711c3f7f17SFangrui Song   assert(I.hasOneMemOperand());
5721c3f7f17SFangrui Song   auto &MemOp = **I.memoperands_begin();
5731c3f7f17SFangrui Song   if (MemOp.isAtomic()) {
5741c3f7f17SFangrui Song     // Note: for unordered operations, we rely on the fact the appropriate MMO
5751c3f7f17SFangrui Song     // is already on the instruction we're mutating, and thus we don't need to
5761c3f7f17SFangrui Song     // make any changes.  So long as we select an opcode which is capable of
5771c3f7f17SFangrui Song     // loading or storing the appropriate size atomically, the rest of the
5781c3f7f17SFangrui Song     // backend is required to respect the MMO state.
5791c3f7f17SFangrui Song     if (!MemOp.isUnordered()) {
5801c3f7f17SFangrui Song       LLVM_DEBUG(dbgs() << "Atomic ordering not supported yet\n");
5811c3f7f17SFangrui Song       return false;
5821c3f7f17SFangrui Song     }
5831c3f7f17SFangrui Song     if (MemOp.getAlign() < Ty.getSizeInBits() / 8) {
5841c3f7f17SFangrui Song       LLVM_DEBUG(dbgs() << "Unaligned atomics not supported yet\n");
5851c3f7f17SFangrui Song       return false;
5861c3f7f17SFangrui Song     }
5871c3f7f17SFangrui Song   }
5881c3f7f17SFangrui Song 
5891c3f7f17SFangrui Song   unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlign());
5901c3f7f17SFangrui Song   if (NewOpc == Opc)
5911c3f7f17SFangrui Song     return false;
5921c3f7f17SFangrui Song 
5931c3f7f17SFangrui Song   I.setDesc(TII.get(NewOpc));
5941c3f7f17SFangrui Song   MachineInstrBuilder MIB(MF, I);
59511d7203cSEvgenii Kudriashov   const MachineInstr *Ptr = MRI.getVRegDef(I.getOperand(1).getReg());
59611d7203cSEvgenii Kudriashov 
59711d7203cSEvgenii Kudriashov   if (Ptr->getOpcode() == TargetOpcode::G_CONSTANT_POOL) {
59811d7203cSEvgenii Kudriashov     assert(Opc == TargetOpcode::G_LOAD &&
59911d7203cSEvgenii Kudriashov            "Only G_LOAD from constant pool is expected");
60011d7203cSEvgenii Kudriashov     // TODO: Need a separate move for Large model
60111d7203cSEvgenii Kudriashov     if (TM.getCodeModel() == CodeModel::Large)
60211d7203cSEvgenii Kudriashov       return false;
60311d7203cSEvgenii Kudriashov 
60411d7203cSEvgenii Kudriashov     unsigned char OpFlag = STI.classifyLocalReference(nullptr);
60511d7203cSEvgenii Kudriashov     unsigned PICBase = 0;
60611d7203cSEvgenii Kudriashov     if (OpFlag == X86II::MO_GOTOFF)
60711d7203cSEvgenii Kudriashov       PICBase = TII.getGlobalBaseReg(&MF);
60811d7203cSEvgenii Kudriashov     else if (STI.is64Bit())
60911d7203cSEvgenii Kudriashov       PICBase = X86::RIP;
61011d7203cSEvgenii Kudriashov 
61111d7203cSEvgenii Kudriashov     I.removeOperand(1);
61211d7203cSEvgenii Kudriashov     addConstantPoolReference(MIB, Ptr->getOperand(1).getIndex(), PICBase,
61311d7203cSEvgenii Kudriashov                              OpFlag);
61411d7203cSEvgenii Kudriashov     return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
61511d7203cSEvgenii Kudriashov   }
61611d7203cSEvgenii Kudriashov 
61711d7203cSEvgenii Kudriashov   X86AddressMode AM;
61811d7203cSEvgenii Kudriashov   X86SelectAddress(*Ptr, MRI, AM);
6191c3f7f17SFangrui Song   if (Opc == TargetOpcode::G_LOAD) {
6201c3f7f17SFangrui Song     I.removeOperand(1);
6211c3f7f17SFangrui Song     addFullAddress(MIB, AM);
6221c3f7f17SFangrui Song   } else {
6231c3f7f17SFangrui Song     // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
6241c3f7f17SFangrui Song     I.removeOperand(1);
6251c3f7f17SFangrui Song     I.removeOperand(0);
6261c3f7f17SFangrui Song     addFullAddress(MIB, AM).addUse(DefReg);
6271c3f7f17SFangrui Song   }
628a77d3ea3SMalay Sanghi   bool Constrained = constrainSelectedInstRegOperands(I, TII, TRI, RBI);
629a77d3ea3SMalay Sanghi   I.addImplicitDefUseOperands(MF);
630a77d3ea3SMalay Sanghi   return Constrained;
6311c3f7f17SFangrui Song }
6321c3f7f17SFangrui Song 
6331c3f7f17SFangrui Song static unsigned getLeaOP(LLT Ty, const X86Subtarget &STI) {
6341c3f7f17SFangrui Song   if (Ty == LLT::pointer(0, 64))
6351c3f7f17SFangrui Song     return X86::LEA64r;
6361c3f7f17SFangrui Song   else if (Ty == LLT::pointer(0, 32))
6371c3f7f17SFangrui Song     return STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
6381c3f7f17SFangrui Song   else
6391c3f7f17SFangrui Song     llvm_unreachable("Can't get LEA opcode. Unsupported type.");
6401c3f7f17SFangrui Song }
6411c3f7f17SFangrui Song 
6421c3f7f17SFangrui Song bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I,
6431c3f7f17SFangrui Song                                                    MachineRegisterInfo &MRI,
6441c3f7f17SFangrui Song                                                    MachineFunction &MF) const {
6451c3f7f17SFangrui Song   unsigned Opc = I.getOpcode();
6461c3f7f17SFangrui Song 
6471c3f7f17SFangrui Song   assert((Opc == TargetOpcode::G_FRAME_INDEX || Opc == TargetOpcode::G_PTR_ADD) &&
6481c3f7f17SFangrui Song          "unexpected instruction");
6491c3f7f17SFangrui Song 
6501c3f7f17SFangrui Song   const Register DefReg = I.getOperand(0).getReg();
6511c3f7f17SFangrui Song   LLT Ty = MRI.getType(DefReg);
6521c3f7f17SFangrui Song 
6531c3f7f17SFangrui Song   // Use LEA to calculate frame index and GEP
6541c3f7f17SFangrui Song   unsigned NewOpc = getLeaOP(Ty, STI);
6551c3f7f17SFangrui Song   I.setDesc(TII.get(NewOpc));
6561c3f7f17SFangrui Song   MachineInstrBuilder MIB(MF, I);
6571c3f7f17SFangrui Song 
6581c3f7f17SFangrui Song   if (Opc == TargetOpcode::G_FRAME_INDEX) {
6591c3f7f17SFangrui Song     addOffset(MIB, 0);
6601c3f7f17SFangrui Song   } else {
6611c3f7f17SFangrui Song     MachineOperand &InxOp = I.getOperand(2);
6621c3f7f17SFangrui Song     I.addOperand(InxOp);        // set IndexReg
6631c3f7f17SFangrui Song     InxOp.ChangeToImmediate(1); // set Scale
6641c3f7f17SFangrui Song     MIB.addImm(0).addReg(0);
6651c3f7f17SFangrui Song   }
6661c3f7f17SFangrui Song 
6671c3f7f17SFangrui Song   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
6681c3f7f17SFangrui Song }
6691c3f7f17SFangrui Song 
6701c3f7f17SFangrui Song bool X86InstructionSelector::selectGlobalValue(MachineInstr &I,
6711c3f7f17SFangrui Song                                                MachineRegisterInfo &MRI,
6721c3f7f17SFangrui Song                                                MachineFunction &MF) const {
6731c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE) &&
6741c3f7f17SFangrui Song          "unexpected instruction");
6751c3f7f17SFangrui Song 
6761c3f7f17SFangrui Song   auto GV = I.getOperand(1).getGlobal();
6771c3f7f17SFangrui Song   if (GV->isThreadLocal()) {
6781c3f7f17SFangrui Song     return false; // TODO: we don't support TLS yet.
6791c3f7f17SFangrui Song   }
6801c3f7f17SFangrui Song 
6811c3f7f17SFangrui Song   // Can't handle alternate code models yet.
6821c3f7f17SFangrui Song   if (TM.getCodeModel() != CodeModel::Small)
6831c3f7f17SFangrui Song     return false;
6841c3f7f17SFangrui Song 
6851c3f7f17SFangrui Song   X86AddressMode AM;
6861c3f7f17SFangrui Song   AM.GV = GV;
6871c3f7f17SFangrui Song   AM.GVOpFlags = STI.classifyGlobalReference(GV);
6881c3f7f17SFangrui Song 
6891c3f7f17SFangrui Song   // TODO: The ABI requires an extra load. not supported yet.
6901c3f7f17SFangrui Song   if (isGlobalStubReference(AM.GVOpFlags))
6911c3f7f17SFangrui Song     return false;
6921c3f7f17SFangrui Song 
6931c3f7f17SFangrui Song   // TODO: This reference is relative to the pic base. not supported yet.
6941c3f7f17SFangrui Song   if (isGlobalRelativeToPICBase(AM.GVOpFlags))
6951c3f7f17SFangrui Song     return false;
6961c3f7f17SFangrui Song 
6971c3f7f17SFangrui Song   if (STI.isPICStyleRIPRel()) {
6981c3f7f17SFangrui Song     // Use rip-relative addressing.
6991c3f7f17SFangrui Song     assert(AM.Base.Reg == 0 && AM.IndexReg == 0);
7001c3f7f17SFangrui Song     AM.Base.Reg = X86::RIP;
7011c3f7f17SFangrui Song   }
7021c3f7f17SFangrui Song 
7031c3f7f17SFangrui Song   const Register DefReg = I.getOperand(0).getReg();
7041c3f7f17SFangrui Song   LLT Ty = MRI.getType(DefReg);
7051c3f7f17SFangrui Song   unsigned NewOpc = getLeaOP(Ty, STI);
7061c3f7f17SFangrui Song 
7071c3f7f17SFangrui Song   I.setDesc(TII.get(NewOpc));
7081c3f7f17SFangrui Song   MachineInstrBuilder MIB(MF, I);
7091c3f7f17SFangrui Song 
7101c3f7f17SFangrui Song   I.removeOperand(1);
7111c3f7f17SFangrui Song   addFullAddress(MIB, AM);
7121c3f7f17SFangrui Song 
7131c3f7f17SFangrui Song   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
7141c3f7f17SFangrui Song }
7151c3f7f17SFangrui Song 
7161c3f7f17SFangrui Song bool X86InstructionSelector::selectConstant(MachineInstr &I,
7171c3f7f17SFangrui Song                                             MachineRegisterInfo &MRI,
7181c3f7f17SFangrui Song                                             MachineFunction &MF) const {
7191c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_CONSTANT) &&
7201c3f7f17SFangrui Song          "unexpected instruction");
7211c3f7f17SFangrui Song 
7221c3f7f17SFangrui Song   const Register DefReg = I.getOperand(0).getReg();
7231c3f7f17SFangrui Song   LLT Ty = MRI.getType(DefReg);
7241c3f7f17SFangrui Song 
7251c3f7f17SFangrui Song   if (RBI.getRegBank(DefReg, MRI, TRI)->getID() != X86::GPRRegBankID)
7261c3f7f17SFangrui Song     return false;
7271c3f7f17SFangrui Song 
7281c3f7f17SFangrui Song   uint64_t Val = 0;
7291c3f7f17SFangrui Song   if (I.getOperand(1).isCImm()) {
7301c3f7f17SFangrui Song     Val = I.getOperand(1).getCImm()->getZExtValue();
7311c3f7f17SFangrui Song     I.getOperand(1).ChangeToImmediate(Val);
7321c3f7f17SFangrui Song   } else if (I.getOperand(1).isImm()) {
7331c3f7f17SFangrui Song     Val = I.getOperand(1).getImm();
7341c3f7f17SFangrui Song   } else
7351c3f7f17SFangrui Song     llvm_unreachable("Unsupported operand type.");
7361c3f7f17SFangrui Song 
7371c3f7f17SFangrui Song   unsigned NewOpc;
7381c3f7f17SFangrui Song   switch (Ty.getSizeInBits()) {
7391c3f7f17SFangrui Song   case 8:
7401c3f7f17SFangrui Song     NewOpc = X86::MOV8ri;
7411c3f7f17SFangrui Song     break;
7421c3f7f17SFangrui Song   case 16:
7431c3f7f17SFangrui Song     NewOpc = X86::MOV16ri;
7441c3f7f17SFangrui Song     break;
7451c3f7f17SFangrui Song   case 32:
7461c3f7f17SFangrui Song     NewOpc = X86::MOV32ri;
7471c3f7f17SFangrui Song     break;
7481c3f7f17SFangrui Song   case 64:
7491c3f7f17SFangrui Song     // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
7501c3f7f17SFangrui Song     if (isInt<32>(Val))
7511c3f7f17SFangrui Song       NewOpc = X86::MOV64ri32;
7521c3f7f17SFangrui Song     else
7531c3f7f17SFangrui Song       NewOpc = X86::MOV64ri;
7541c3f7f17SFangrui Song     break;
7551c3f7f17SFangrui Song   default:
7561c3f7f17SFangrui Song     llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
7571c3f7f17SFangrui Song   }
7581c3f7f17SFangrui Song 
7591c3f7f17SFangrui Song   I.setDesc(TII.get(NewOpc));
7601c3f7f17SFangrui Song   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
7611c3f7f17SFangrui Song }
7621c3f7f17SFangrui Song 
7631c3f7f17SFangrui Song // Helper function for selectTruncOrPtrToInt and selectAnyext.
7641c3f7f17SFangrui Song // Returns true if DstRC lives on a floating register class and
7651c3f7f17SFangrui Song // SrcRC lives on a 128-bit vector class.
7661c3f7f17SFangrui Song static bool canTurnIntoCOPY(const TargetRegisterClass *DstRC,
7671c3f7f17SFangrui Song                             const TargetRegisterClass *SrcRC) {
7681c3f7f17SFangrui Song   return (DstRC == &X86::FR32RegClass || DstRC == &X86::FR32XRegClass ||
7691c3f7f17SFangrui Song           DstRC == &X86::FR64RegClass || DstRC == &X86::FR64XRegClass) &&
7701c3f7f17SFangrui Song          (SrcRC == &X86::VR128RegClass || SrcRC == &X86::VR128XRegClass);
7711c3f7f17SFangrui Song }
7721c3f7f17SFangrui Song 
7731c3f7f17SFangrui Song bool X86InstructionSelector::selectTurnIntoCOPY(
7741c3f7f17SFangrui Song     MachineInstr &I, MachineRegisterInfo &MRI, const unsigned DstReg,
7751c3f7f17SFangrui Song     const TargetRegisterClass *DstRC, const unsigned SrcReg,
7761c3f7f17SFangrui Song     const TargetRegisterClass *SrcRC) const {
7771c3f7f17SFangrui Song 
7781c3f7f17SFangrui Song   if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
7791c3f7f17SFangrui Song       !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
7801c3f7f17SFangrui Song     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
7811c3f7f17SFangrui Song                       << " operand\n");
7821c3f7f17SFangrui Song     return false;
7831c3f7f17SFangrui Song   }
7841c3f7f17SFangrui Song   I.setDesc(TII.get(X86::COPY));
7851c3f7f17SFangrui Song   return true;
7861c3f7f17SFangrui Song }
7871c3f7f17SFangrui Song 
7881c3f7f17SFangrui Song bool X86InstructionSelector::selectTruncOrPtrToInt(MachineInstr &I,
7891c3f7f17SFangrui Song                                                    MachineRegisterInfo &MRI,
7901c3f7f17SFangrui Song                                                    MachineFunction &MF) const {
7911c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_TRUNC ||
7921c3f7f17SFangrui Song           I.getOpcode() == TargetOpcode::G_PTRTOINT) &&
7931c3f7f17SFangrui Song          "unexpected instruction");
7941c3f7f17SFangrui Song 
7951c3f7f17SFangrui Song   const Register DstReg = I.getOperand(0).getReg();
7961c3f7f17SFangrui Song   const Register SrcReg = I.getOperand(1).getReg();
7971c3f7f17SFangrui Song 
7981c3f7f17SFangrui Song   const LLT DstTy = MRI.getType(DstReg);
7991c3f7f17SFangrui Song   const LLT SrcTy = MRI.getType(SrcReg);
8001c3f7f17SFangrui Song 
8011c3f7f17SFangrui Song   const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
8021c3f7f17SFangrui Song   const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
8031c3f7f17SFangrui Song 
8041c3f7f17SFangrui Song   if (DstRB.getID() != SrcRB.getID()) {
8051c3f7f17SFangrui Song     LLVM_DEBUG(dbgs() << TII.getName(I.getOpcode())
8061c3f7f17SFangrui Song                       << " input/output on different banks\n");
8071c3f7f17SFangrui Song     return false;
8081c3f7f17SFangrui Song   }
8091c3f7f17SFangrui Song 
8101c3f7f17SFangrui Song   const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
8111c3f7f17SFangrui Song   const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);
8121c3f7f17SFangrui Song 
8131c3f7f17SFangrui Song   if (!DstRC || !SrcRC)
8141c3f7f17SFangrui Song     return false;
8151c3f7f17SFangrui Song 
8161c3f7f17SFangrui Song   // If that's truncation of the value that lives on the vector class and goes
8171c3f7f17SFangrui Song   // into the floating class, just replace it with copy, as we are able to
8181c3f7f17SFangrui Song   // select it as a regular move.
8191c3f7f17SFangrui Song   if (canTurnIntoCOPY(DstRC, SrcRC))
8201c3f7f17SFangrui Song     return selectTurnIntoCOPY(I, MRI, DstReg, DstRC, SrcReg, SrcRC);
8211c3f7f17SFangrui Song 
8221c3f7f17SFangrui Song   if (DstRB.getID() != X86::GPRRegBankID)
8231c3f7f17SFangrui Song     return false;
8241c3f7f17SFangrui Song 
8251c3f7f17SFangrui Song   unsigned SubIdx;
8261c3f7f17SFangrui Song   if (DstRC == SrcRC) {
8271c3f7f17SFangrui Song     // Nothing to be done
8281c3f7f17SFangrui Song     SubIdx = X86::NoSubRegister;
8291c3f7f17SFangrui Song   } else if (DstRC == &X86::GR32RegClass) {
8301c3f7f17SFangrui Song     SubIdx = X86::sub_32bit;
8311c3f7f17SFangrui Song   } else if (DstRC == &X86::GR16RegClass) {
8321c3f7f17SFangrui Song     SubIdx = X86::sub_16bit;
8331c3f7f17SFangrui Song   } else if (DstRC == &X86::GR8RegClass) {
8341c3f7f17SFangrui Song     SubIdx = X86::sub_8bit;
8351c3f7f17SFangrui Song   } else {
8361c3f7f17SFangrui Song     return false;
8371c3f7f17SFangrui Song   }
8381c3f7f17SFangrui Song 
8391c3f7f17SFangrui Song   SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
8401c3f7f17SFangrui Song 
8411c3f7f17SFangrui Song   if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
8421c3f7f17SFangrui Song       !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
8431c3f7f17SFangrui Song     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
8441c3f7f17SFangrui Song                       << "\n");
8451c3f7f17SFangrui Song     return false;
8461c3f7f17SFangrui Song   }
8471c3f7f17SFangrui Song 
8481c3f7f17SFangrui Song   I.getOperand(1).setSubReg(SubIdx);
8491c3f7f17SFangrui Song 
8501c3f7f17SFangrui Song   I.setDesc(TII.get(X86::COPY));
8511c3f7f17SFangrui Song   return true;
8521c3f7f17SFangrui Song }
8531c3f7f17SFangrui Song 
8541c3f7f17SFangrui Song bool X86InstructionSelector::selectZext(MachineInstr &I,
8551c3f7f17SFangrui Song                                         MachineRegisterInfo &MRI,
8561c3f7f17SFangrui Song                                         MachineFunction &MF) const {
8571c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_ZEXT) && "unexpected instruction");
8581c3f7f17SFangrui Song 
8591c3f7f17SFangrui Song   const Register DstReg = I.getOperand(0).getReg();
8601c3f7f17SFangrui Song   const Register SrcReg = I.getOperand(1).getReg();
8611c3f7f17SFangrui Song 
8621c3f7f17SFangrui Song   const LLT DstTy = MRI.getType(DstReg);
8631c3f7f17SFangrui Song   const LLT SrcTy = MRI.getType(SrcReg);
8641c3f7f17SFangrui Song 
8651c3f7f17SFangrui Song   assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(16)) &&
8661c3f7f17SFangrui Song          "8=>16 Zext is handled by tablegen");
8671c3f7f17SFangrui Song   assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(32)) &&
8681c3f7f17SFangrui Song          "8=>32 Zext is handled by tablegen");
8691c3f7f17SFangrui Song   assert(!(SrcTy == LLT::scalar(16) && DstTy == LLT::scalar(32)) &&
8701c3f7f17SFangrui Song          "16=>32 Zext is handled by tablegen");
8711c3f7f17SFangrui Song   assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(64)) &&
8721c3f7f17SFangrui Song          "8=>64 Zext is handled by tablegen");
8731c3f7f17SFangrui Song   assert(!(SrcTy == LLT::scalar(16) && DstTy == LLT::scalar(64)) &&
8741c3f7f17SFangrui Song          "16=>64 Zext is handled by tablegen");
8751c3f7f17SFangrui Song   assert(!(SrcTy == LLT::scalar(32) && DstTy == LLT::scalar(64)) &&
8761c3f7f17SFangrui Song          "32=>64 Zext is handled by tablegen");
8771c3f7f17SFangrui Song 
8781c3f7f17SFangrui Song   if (SrcTy != LLT::scalar(1))
8791c3f7f17SFangrui Song     return false;
8801c3f7f17SFangrui Song 
8811c3f7f17SFangrui Song   unsigned AndOpc;
8821c3f7f17SFangrui Song   if (DstTy == LLT::scalar(8))
8831c3f7f17SFangrui Song     AndOpc = X86::AND8ri;
8841c3f7f17SFangrui Song   else if (DstTy == LLT::scalar(16))
8851c3f7f17SFangrui Song     AndOpc = X86::AND16ri;
8861c3f7f17SFangrui Song   else if (DstTy == LLT::scalar(32))
8871c3f7f17SFangrui Song     AndOpc = X86::AND32ri;
8881c3f7f17SFangrui Song   else if (DstTy == LLT::scalar(64))
8891c3f7f17SFangrui Song     AndOpc = X86::AND64ri32;
8901c3f7f17SFangrui Song   else
8911c3f7f17SFangrui Song     return false;
8921c3f7f17SFangrui Song 
8931c3f7f17SFangrui Song   Register DefReg = SrcReg;
8941c3f7f17SFangrui Song   if (DstTy != LLT::scalar(8)) {
8951c3f7f17SFangrui Song     Register ImpDefReg =
8961c3f7f17SFangrui Song         MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI));
8971c3f7f17SFangrui Song     BuildMI(*I.getParent(), I, I.getDebugLoc(),
8981c3f7f17SFangrui Song             TII.get(TargetOpcode::IMPLICIT_DEF), ImpDefReg);
8991c3f7f17SFangrui Song 
9001c3f7f17SFangrui Song     DefReg = MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI));
9011c3f7f17SFangrui Song     BuildMI(*I.getParent(), I, I.getDebugLoc(),
9021c3f7f17SFangrui Song             TII.get(TargetOpcode::INSERT_SUBREG), DefReg)
9031c3f7f17SFangrui Song         .addReg(ImpDefReg)
9041c3f7f17SFangrui Song         .addReg(SrcReg)
9051c3f7f17SFangrui Song         .addImm(X86::sub_8bit);
9061c3f7f17SFangrui Song   }
9071c3f7f17SFangrui Song 
9081c3f7f17SFangrui Song   MachineInstr &AndInst =
9091c3f7f17SFangrui Song       *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AndOpc), DstReg)
9101c3f7f17SFangrui Song            .addReg(DefReg)
9111c3f7f17SFangrui Song            .addImm(1);
9121c3f7f17SFangrui Song 
9131c3f7f17SFangrui Song   constrainSelectedInstRegOperands(AndInst, TII, TRI, RBI);
9141c3f7f17SFangrui Song 
9151c3f7f17SFangrui Song   I.eraseFromParent();
9161c3f7f17SFangrui Song   return true;
9171c3f7f17SFangrui Song }
9181c3f7f17SFangrui Song 
9191c3f7f17SFangrui Song bool X86InstructionSelector::selectAnyext(MachineInstr &I,
9201c3f7f17SFangrui Song                                           MachineRegisterInfo &MRI,
9211c3f7f17SFangrui Song                                           MachineFunction &MF) const {
9221c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_ANYEXT) && "unexpected instruction");
9231c3f7f17SFangrui Song 
9241c3f7f17SFangrui Song   const Register DstReg = I.getOperand(0).getReg();
9251c3f7f17SFangrui Song   const Register SrcReg = I.getOperand(1).getReg();
9261c3f7f17SFangrui Song 
9271c3f7f17SFangrui Song   const LLT DstTy = MRI.getType(DstReg);
9281c3f7f17SFangrui Song   const LLT SrcTy = MRI.getType(SrcReg);
9291c3f7f17SFangrui Song 
9301c3f7f17SFangrui Song   const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
9311c3f7f17SFangrui Song   const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
9321c3f7f17SFangrui Song 
9331c3f7f17SFangrui Song   assert(DstRB.getID() == SrcRB.getID() &&
9341c3f7f17SFangrui Song          "G_ANYEXT input/output on different banks\n");
9351c3f7f17SFangrui Song 
9361c3f7f17SFangrui Song   assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() &&
9371c3f7f17SFangrui Song          "G_ANYEXT incorrect operand size");
9381c3f7f17SFangrui Song 
9391c3f7f17SFangrui Song   const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
9401c3f7f17SFangrui Song   const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);
9411c3f7f17SFangrui Song 
9421c3f7f17SFangrui Song   // If that's ANY_EXT of the value that lives on the floating class and goes
9431c3f7f17SFangrui Song   // into the vector class, just replace it with copy, as we are able to select
9441c3f7f17SFangrui Song   // it as a regular move.
9451c3f7f17SFangrui Song   if (canTurnIntoCOPY(SrcRC, DstRC))
9461c3f7f17SFangrui Song     return selectTurnIntoCOPY(I, MRI, SrcReg, SrcRC, DstReg, DstRC);
9471c3f7f17SFangrui Song 
9481c3f7f17SFangrui Song   if (DstRB.getID() != X86::GPRRegBankID)
9491c3f7f17SFangrui Song     return false;
9501c3f7f17SFangrui Song 
9511c3f7f17SFangrui Song   if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
9521c3f7f17SFangrui Song       !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
9531c3f7f17SFangrui Song     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
9541c3f7f17SFangrui Song                       << " operand\n");
9551c3f7f17SFangrui Song     return false;
9561c3f7f17SFangrui Song   }
9571c3f7f17SFangrui Song 
9581c3f7f17SFangrui Song   if (SrcRC == DstRC) {
9591c3f7f17SFangrui Song     I.setDesc(TII.get(X86::COPY));
9601c3f7f17SFangrui Song     return true;
9611c3f7f17SFangrui Song   }
9621c3f7f17SFangrui Song 
9631c3f7f17SFangrui Song   BuildMI(*I.getParent(), I, I.getDebugLoc(),
9641c3f7f17SFangrui Song           TII.get(TargetOpcode::SUBREG_TO_REG))
9651c3f7f17SFangrui Song       .addDef(DstReg)
9661c3f7f17SFangrui Song       .addImm(0)
9671c3f7f17SFangrui Song       .addReg(SrcReg)
9681c3f7f17SFangrui Song       .addImm(getSubRegIndex(SrcRC));
9691c3f7f17SFangrui Song 
9701c3f7f17SFangrui Song   I.eraseFromParent();
9711c3f7f17SFangrui Song   return true;
9721c3f7f17SFangrui Song }
9731c3f7f17SFangrui Song 
9741c3f7f17SFangrui Song bool X86InstructionSelector::selectCmp(MachineInstr &I,
9751c3f7f17SFangrui Song                                        MachineRegisterInfo &MRI,
9761c3f7f17SFangrui Song                                        MachineFunction &MF) const {
9771c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_ICMP) && "unexpected instruction");
9781c3f7f17SFangrui Song 
9791c3f7f17SFangrui Song   X86::CondCode CC;
9801c3f7f17SFangrui Song   bool SwapArgs;
9811c3f7f17SFangrui Song   std::tie(CC, SwapArgs) = X86::getX86ConditionCode(
9821c3f7f17SFangrui Song       (CmpInst::Predicate)I.getOperand(1).getPredicate());
9831c3f7f17SFangrui Song 
9841c3f7f17SFangrui Song   Register LHS = I.getOperand(2).getReg();
9851c3f7f17SFangrui Song   Register RHS = I.getOperand(3).getReg();
9861c3f7f17SFangrui Song 
9871c3f7f17SFangrui Song   if (SwapArgs)
9881c3f7f17SFangrui Song     std::swap(LHS, RHS);
9891c3f7f17SFangrui Song 
9901c3f7f17SFangrui Song   unsigned OpCmp;
9911c3f7f17SFangrui Song   LLT Ty = MRI.getType(LHS);
9921c3f7f17SFangrui Song 
9931c3f7f17SFangrui Song   switch (Ty.getSizeInBits()) {
9941c3f7f17SFangrui Song   default:
9951c3f7f17SFangrui Song     return false;
9961c3f7f17SFangrui Song   case 8:
9971c3f7f17SFangrui Song     OpCmp = X86::CMP8rr;
9981c3f7f17SFangrui Song     break;
9991c3f7f17SFangrui Song   case 16:
10001c3f7f17SFangrui Song     OpCmp = X86::CMP16rr;
10011c3f7f17SFangrui Song     break;
10021c3f7f17SFangrui Song   case 32:
10031c3f7f17SFangrui Song     OpCmp = X86::CMP32rr;
10041c3f7f17SFangrui Song     break;
10051c3f7f17SFangrui Song   case 64:
10061c3f7f17SFangrui Song     OpCmp = X86::CMP64rr;
10071c3f7f17SFangrui Song     break;
10081c3f7f17SFangrui Song   }
10091c3f7f17SFangrui Song 
10101c3f7f17SFangrui Song   MachineInstr &CmpInst =
10111c3f7f17SFangrui Song       *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
10121c3f7f17SFangrui Song            .addReg(LHS)
10131c3f7f17SFangrui Song            .addReg(RHS);
10141c3f7f17SFangrui Song 
10151c3f7f17SFangrui Song   MachineInstr &SetInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
10161c3f7f17SFangrui Song                                    TII.get(X86::SETCCr), I.getOperand(0).getReg()).addImm(CC);
10171c3f7f17SFangrui Song 
10181c3f7f17SFangrui Song   constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);
10191c3f7f17SFangrui Song   constrainSelectedInstRegOperands(SetInst, TII, TRI, RBI);
10201c3f7f17SFangrui Song 
10211c3f7f17SFangrui Song   I.eraseFromParent();
10221c3f7f17SFangrui Song   return true;
10231c3f7f17SFangrui Song }
10241c3f7f17SFangrui Song 
10251c3f7f17SFangrui Song bool X86InstructionSelector::selectFCmp(MachineInstr &I,
10261c3f7f17SFangrui Song                                         MachineRegisterInfo &MRI,
10271c3f7f17SFangrui Song                                         MachineFunction &MF) const {
10281c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_FCMP) && "unexpected instruction");
10291c3f7f17SFangrui Song 
10301c3f7f17SFangrui Song   Register LhsReg = I.getOperand(2).getReg();
10311c3f7f17SFangrui Song   Register RhsReg = I.getOperand(3).getReg();
10321c3f7f17SFangrui Song   CmpInst::Predicate Predicate =
10331c3f7f17SFangrui Song       (CmpInst::Predicate)I.getOperand(1).getPredicate();
10341c3f7f17SFangrui Song 
10351c3f7f17SFangrui Song   // FCMP_OEQ and FCMP_UNE cannot be checked with a single instruction.
10361c3f7f17SFangrui Song   static const uint16_t SETFOpcTable[2][3] = {
10371c3f7f17SFangrui Song       {X86::COND_E, X86::COND_NP, X86::AND8rr},
10381c3f7f17SFangrui Song       {X86::COND_NE, X86::COND_P, X86::OR8rr}};
10391c3f7f17SFangrui Song   const uint16_t *SETFOpc = nullptr;
10401c3f7f17SFangrui Song   switch (Predicate) {
10411c3f7f17SFangrui Song   default:
10421c3f7f17SFangrui Song     break;
10431c3f7f17SFangrui Song   case CmpInst::FCMP_OEQ:
10441c3f7f17SFangrui Song     SETFOpc = &SETFOpcTable[0][0];
10451c3f7f17SFangrui Song     break;
10461c3f7f17SFangrui Song   case CmpInst::FCMP_UNE:
10471c3f7f17SFangrui Song     SETFOpc = &SETFOpcTable[1][0];
10481c3f7f17SFangrui Song     break;
10491c3f7f17SFangrui Song   }
10501c3f7f17SFangrui Song 
10511c3f7f17SFangrui Song   // Compute the opcode for the CMP instruction.
10521c3f7f17SFangrui Song   unsigned OpCmp;
10531c3f7f17SFangrui Song   LLT Ty = MRI.getType(LhsReg);
10541c3f7f17SFangrui Song   switch (Ty.getSizeInBits()) {
10551c3f7f17SFangrui Song   default:
10561c3f7f17SFangrui Song     return false;
10571c3f7f17SFangrui Song   case 32:
10581c3f7f17SFangrui Song     OpCmp = X86::UCOMISSrr;
10591c3f7f17SFangrui Song     break;
10601c3f7f17SFangrui Song   case 64:
10611c3f7f17SFangrui Song     OpCmp = X86::UCOMISDrr;
10621c3f7f17SFangrui Song     break;
10631c3f7f17SFangrui Song   }
10641c3f7f17SFangrui Song 
10651c3f7f17SFangrui Song   Register ResultReg = I.getOperand(0).getReg();
10661c3f7f17SFangrui Song   RBI.constrainGenericRegister(
10671c3f7f17SFangrui Song       ResultReg,
10681c3f7f17SFangrui Song       *getRegClass(LLT::scalar(8), *RBI.getRegBank(ResultReg, MRI, TRI)), MRI);
10691c3f7f17SFangrui Song   if (SETFOpc) {
10701c3f7f17SFangrui Song     MachineInstr &CmpInst =
10711c3f7f17SFangrui Song         *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
10721c3f7f17SFangrui Song              .addReg(LhsReg)
10731c3f7f17SFangrui Song              .addReg(RhsReg);
10741c3f7f17SFangrui Song 
10751c3f7f17SFangrui Song     Register FlagReg1 = MRI.createVirtualRegister(&X86::GR8RegClass);
10761c3f7f17SFangrui Song     Register FlagReg2 = MRI.createVirtualRegister(&X86::GR8RegClass);
10771c3f7f17SFangrui Song     MachineInstr &Set1 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
10781c3f7f17SFangrui Song                                   TII.get(X86::SETCCr), FlagReg1).addImm(SETFOpc[0]);
10791c3f7f17SFangrui Song     MachineInstr &Set2 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
10801c3f7f17SFangrui Song                                   TII.get(X86::SETCCr), FlagReg2).addImm(SETFOpc[1]);
10811c3f7f17SFangrui Song     MachineInstr &Set3 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
10821c3f7f17SFangrui Song                                   TII.get(SETFOpc[2]), ResultReg)
10831c3f7f17SFangrui Song                               .addReg(FlagReg1)
10841c3f7f17SFangrui Song                               .addReg(FlagReg2);
10851c3f7f17SFangrui Song     constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);
10861c3f7f17SFangrui Song     constrainSelectedInstRegOperands(Set1, TII, TRI, RBI);
10871c3f7f17SFangrui Song     constrainSelectedInstRegOperands(Set2, TII, TRI, RBI);
10881c3f7f17SFangrui Song     constrainSelectedInstRegOperands(Set3, TII, TRI, RBI);
10891c3f7f17SFangrui Song 
10901c3f7f17SFangrui Song     I.eraseFromParent();
10911c3f7f17SFangrui Song     return true;
10921c3f7f17SFangrui Song   }
10931c3f7f17SFangrui Song 
10941c3f7f17SFangrui Song   X86::CondCode CC;
10951c3f7f17SFangrui Song   bool SwapArgs;
10961c3f7f17SFangrui Song   std::tie(CC, SwapArgs) = X86::getX86ConditionCode(Predicate);
10971c3f7f17SFangrui Song   assert(CC <= X86::LAST_VALID_COND && "Unexpected condition code.");
10981c3f7f17SFangrui Song 
10991c3f7f17SFangrui Song   if (SwapArgs)
11001c3f7f17SFangrui Song     std::swap(LhsReg, RhsReg);
11011c3f7f17SFangrui Song 
11021c3f7f17SFangrui Song   // Emit a compare of LHS/RHS.
11031c3f7f17SFangrui Song   MachineInstr &CmpInst =
11041c3f7f17SFangrui Song       *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
11051c3f7f17SFangrui Song            .addReg(LhsReg)
11061c3f7f17SFangrui Song            .addReg(RhsReg);
11071c3f7f17SFangrui Song 
11081c3f7f17SFangrui Song   MachineInstr &Set =
11091c3f7f17SFangrui Song       *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::SETCCr), ResultReg).addImm(CC);
11101c3f7f17SFangrui Song   constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);
11111c3f7f17SFangrui Song   constrainSelectedInstRegOperands(Set, TII, TRI, RBI);
11121c3f7f17SFangrui Song   I.eraseFromParent();
11131c3f7f17SFangrui Song   return true;
11141c3f7f17SFangrui Song }
11151c3f7f17SFangrui Song 
11161c3f7f17SFangrui Song bool X86InstructionSelector::selectUAddSub(MachineInstr &I,
11171c3f7f17SFangrui Song                                            MachineRegisterInfo &MRI,
11181c3f7f17SFangrui Song                                            MachineFunction &MF) const {
11191c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_UADDE ||
11201c3f7f17SFangrui Song           I.getOpcode() == TargetOpcode::G_UADDO ||
11211c3f7f17SFangrui Song           I.getOpcode() == TargetOpcode::G_USUBE ||
11221c3f7f17SFangrui Song           I.getOpcode() == TargetOpcode::G_USUBO) &&
11231c3f7f17SFangrui Song          "unexpected instruction");
11241c3f7f17SFangrui Song 
11251c3f7f17SFangrui Song   const Register DstReg = I.getOperand(0).getReg();
11261c3f7f17SFangrui Song   const Register CarryOutReg = I.getOperand(1).getReg();
11271c3f7f17SFangrui Song   const Register Op0Reg = I.getOperand(2).getReg();
11281c3f7f17SFangrui Song   const Register Op1Reg = I.getOperand(3).getReg();
11291c3f7f17SFangrui Song   bool IsSub = I.getOpcode() == TargetOpcode::G_USUBE ||
11301c3f7f17SFangrui Song                I.getOpcode() == TargetOpcode::G_USUBO;
11311c3f7f17SFangrui Song   bool HasCarryIn = I.getOpcode() == TargetOpcode::G_UADDE ||
11321c3f7f17SFangrui Song                     I.getOpcode() == TargetOpcode::G_USUBE;
11331c3f7f17SFangrui Song 
11341c3f7f17SFangrui Song   const LLT DstTy = MRI.getType(DstReg);
11351c3f7f17SFangrui Song   assert(DstTy.isScalar() && "selectUAddSub only supported for scalar types");
11361c3f7f17SFangrui Song 
11371c3f7f17SFangrui Song   // TODO: Handle immediate argument variants?
11381c3f7f17SFangrui Song   unsigned OpADC, OpADD, OpSBB, OpSUB;
11391c3f7f17SFangrui Song   switch (DstTy.getSizeInBits()) {
11401c3f7f17SFangrui Song   case 8:
11411c3f7f17SFangrui Song     OpADC = X86::ADC8rr;
11421c3f7f17SFangrui Song     OpADD = X86::ADD8rr;
11431c3f7f17SFangrui Song     OpSBB = X86::SBB8rr;
11441c3f7f17SFangrui Song     OpSUB = X86::SUB8rr;
11451c3f7f17SFangrui Song     break;
11461c3f7f17SFangrui Song   case 16:
11471c3f7f17SFangrui Song     OpADC = X86::ADC16rr;
11481c3f7f17SFangrui Song     OpADD = X86::ADD16rr;
11491c3f7f17SFangrui Song     OpSBB = X86::SBB16rr;
11501c3f7f17SFangrui Song     OpSUB = X86::SUB16rr;
11511c3f7f17SFangrui Song     break;
11521c3f7f17SFangrui Song   case 32:
11531c3f7f17SFangrui Song     OpADC = X86::ADC32rr;
11541c3f7f17SFangrui Song     OpADD = X86::ADD32rr;
11551c3f7f17SFangrui Song     OpSBB = X86::SBB32rr;
11561c3f7f17SFangrui Song     OpSUB = X86::SUB32rr;
11571c3f7f17SFangrui Song     break;
11581c3f7f17SFangrui Song   case 64:
11591c3f7f17SFangrui Song     OpADC = X86::ADC64rr;
11601c3f7f17SFangrui Song     OpADD = X86::ADD64rr;
11611c3f7f17SFangrui Song     OpSBB = X86::SBB64rr;
11621c3f7f17SFangrui Song     OpSUB = X86::SUB64rr;
11631c3f7f17SFangrui Song     break;
11641c3f7f17SFangrui Song   default:
11651c3f7f17SFangrui Song     llvm_unreachable("selectUAddSub unsupported type.");
11661c3f7f17SFangrui Song   }
11671c3f7f17SFangrui Song 
11681c3f7f17SFangrui Song   const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
11691c3f7f17SFangrui Song   const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
11701c3f7f17SFangrui Song 
11711c3f7f17SFangrui Song   unsigned Opcode = IsSub ? OpSUB : OpADD;
11721c3f7f17SFangrui Song 
11731c3f7f17SFangrui Song   // G_UADDE/G_USUBE - find CarryIn def instruction.
11741c3f7f17SFangrui Song   if (HasCarryIn) {
11751c3f7f17SFangrui Song     Register CarryInReg = I.getOperand(4).getReg();
11761c3f7f17SFangrui Song     MachineInstr *Def = MRI.getVRegDef(CarryInReg);
11771c3f7f17SFangrui Song     while (Def->getOpcode() == TargetOpcode::G_TRUNC) {
11781c3f7f17SFangrui Song       CarryInReg = Def->getOperand(1).getReg();
11791c3f7f17SFangrui Song       Def = MRI.getVRegDef(CarryInReg);
11801c3f7f17SFangrui Song     }
11811c3f7f17SFangrui Song 
11821c3f7f17SFangrui Song     // TODO - handle more CF generating instructions
11831c3f7f17SFangrui Song     if (Def->getOpcode() == TargetOpcode::G_UADDE ||
11841c3f7f17SFangrui Song         Def->getOpcode() == TargetOpcode::G_UADDO ||
11851c3f7f17SFangrui Song         Def->getOpcode() == TargetOpcode::G_USUBE ||
11861c3f7f17SFangrui Song         Def->getOpcode() == TargetOpcode::G_USUBO) {
11871c3f7f17SFangrui Song       // carry set by prev ADD/SUB.
11881c3f7f17SFangrui Song       BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY),
11891c3f7f17SFangrui Song               X86::EFLAGS)
11901c3f7f17SFangrui Song           .addReg(CarryInReg);
11911c3f7f17SFangrui Song 
11921c3f7f17SFangrui Song       if (!RBI.constrainGenericRegister(CarryInReg, *DstRC, MRI))
11931c3f7f17SFangrui Song         return false;
11941c3f7f17SFangrui Song 
11951c3f7f17SFangrui Song       Opcode = IsSub ? OpSBB : OpADC;
11961c3f7f17SFangrui Song     } else if (auto val = getIConstantVRegVal(CarryInReg, MRI)) {
11971c3f7f17SFangrui Song       // carry is constant, support only 0.
11981c3f7f17SFangrui Song       if (*val != 0)
11991c3f7f17SFangrui Song         return false;
12001c3f7f17SFangrui Song 
12011c3f7f17SFangrui Song       Opcode = IsSub ? OpSUB : OpADD;
12021c3f7f17SFangrui Song     } else
12031c3f7f17SFangrui Song       return false;
12041c3f7f17SFangrui Song   }
12051c3f7f17SFangrui Song 
12061c3f7f17SFangrui Song   MachineInstr &Inst =
12071c3f7f17SFangrui Song       *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)
12081c3f7f17SFangrui Song            .addReg(Op0Reg)
12091c3f7f17SFangrui Song            .addReg(Op1Reg);
12101c3f7f17SFangrui Song 
12111c3f7f17SFangrui Song   BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), CarryOutReg)
12121c3f7f17SFangrui Song       .addReg(X86::EFLAGS);
12131c3f7f17SFangrui Song 
12141c3f7f17SFangrui Song   if (!constrainSelectedInstRegOperands(Inst, TII, TRI, RBI) ||
12151c3f7f17SFangrui Song       !RBI.constrainGenericRegister(CarryOutReg, *DstRC, MRI))
12161c3f7f17SFangrui Song     return false;
12171c3f7f17SFangrui Song 
12181c3f7f17SFangrui Song   I.eraseFromParent();
12191c3f7f17SFangrui Song   return true;
12201c3f7f17SFangrui Song }
12211c3f7f17SFangrui Song 
12221c3f7f17SFangrui Song bool X86InstructionSelector::selectExtract(MachineInstr &I,
12231c3f7f17SFangrui Song                                            MachineRegisterInfo &MRI,
12241c3f7f17SFangrui Song                                            MachineFunction &MF) const {
12251c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_EXTRACT) &&
12261c3f7f17SFangrui Song          "unexpected instruction");
12271c3f7f17SFangrui Song 
12281c3f7f17SFangrui Song   const Register DstReg = I.getOperand(0).getReg();
12291c3f7f17SFangrui Song   const Register SrcReg = I.getOperand(1).getReg();
12301c3f7f17SFangrui Song   int64_t Index = I.getOperand(2).getImm();
12311c3f7f17SFangrui Song 
12321c3f7f17SFangrui Song   const LLT DstTy = MRI.getType(DstReg);
12331c3f7f17SFangrui Song   const LLT SrcTy = MRI.getType(SrcReg);
12341c3f7f17SFangrui Song 
12351c3f7f17SFangrui Song   // Meanwile handle vector type only.
12361c3f7f17SFangrui Song   if (!DstTy.isVector())
12371c3f7f17SFangrui Song     return false;
12381c3f7f17SFangrui Song 
12391c3f7f17SFangrui Song   if (Index % DstTy.getSizeInBits() != 0)
12401c3f7f17SFangrui Song     return false; // Not extract subvector.
12411c3f7f17SFangrui Song 
12421c3f7f17SFangrui Song   if (Index == 0) {
12431c3f7f17SFangrui Song     // Replace by extract subreg copy.
12441c3f7f17SFangrui Song     if (!emitExtractSubreg(DstReg, SrcReg, I, MRI, MF))
12451c3f7f17SFangrui Song       return false;
12461c3f7f17SFangrui Song 
12471c3f7f17SFangrui Song     I.eraseFromParent();
12481c3f7f17SFangrui Song     return true;
12491c3f7f17SFangrui Song   }
12501c3f7f17SFangrui Song 
12511c3f7f17SFangrui Song   bool HasAVX = STI.hasAVX();
12521c3f7f17SFangrui Song   bool HasAVX512 = STI.hasAVX512();
12531c3f7f17SFangrui Song   bool HasVLX = STI.hasVLX();
12541c3f7f17SFangrui Song 
12551c3f7f17SFangrui Song   if (SrcTy.getSizeInBits() == 256 && DstTy.getSizeInBits() == 128) {
12561c3f7f17SFangrui Song     if (HasVLX)
1257*3a5cf6d9SSimon Pilgrim       I.setDesc(TII.get(X86::VEXTRACTF32X4Z256rri));
12581c3f7f17SFangrui Song     else if (HasAVX)
1259614a064cSSimon Pilgrim       I.setDesc(TII.get(X86::VEXTRACTF128rri));
12601c3f7f17SFangrui Song     else
12611c3f7f17SFangrui Song       return false;
12621c3f7f17SFangrui Song   } else if (SrcTy.getSizeInBits() == 512 && HasAVX512) {
12631c3f7f17SFangrui Song     if (DstTy.getSizeInBits() == 128)
1264*3a5cf6d9SSimon Pilgrim       I.setDesc(TII.get(X86::VEXTRACTF32X4Zrri));
12651c3f7f17SFangrui Song     else if (DstTy.getSizeInBits() == 256)
1266*3a5cf6d9SSimon Pilgrim       I.setDesc(TII.get(X86::VEXTRACTF64X4Zrri));
12671c3f7f17SFangrui Song     else
12681c3f7f17SFangrui Song       return false;
12691c3f7f17SFangrui Song   } else
12701c3f7f17SFangrui Song     return false;
12711c3f7f17SFangrui Song 
12721c3f7f17SFangrui Song   // Convert to X86 VEXTRACT immediate.
12731c3f7f17SFangrui Song   Index = Index / DstTy.getSizeInBits();
12741c3f7f17SFangrui Song   I.getOperand(2).setImm(Index);
12751c3f7f17SFangrui Song 
12761c3f7f17SFangrui Song   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
12771c3f7f17SFangrui Song }
12781c3f7f17SFangrui Song 
12791c3f7f17SFangrui Song bool X86InstructionSelector::emitExtractSubreg(unsigned DstReg, unsigned SrcReg,
12801c3f7f17SFangrui Song                                                MachineInstr &I,
12811c3f7f17SFangrui Song                                                MachineRegisterInfo &MRI,
12821c3f7f17SFangrui Song                                                MachineFunction &MF) const {
12831c3f7f17SFangrui Song   const LLT DstTy = MRI.getType(DstReg);
12841c3f7f17SFangrui Song   const LLT SrcTy = MRI.getType(SrcReg);
12851c3f7f17SFangrui Song   unsigned SubIdx = X86::NoSubRegister;
12861c3f7f17SFangrui Song 
12871c3f7f17SFangrui Song   if (!DstTy.isVector() || !SrcTy.isVector())
12881c3f7f17SFangrui Song     return false;
12891c3f7f17SFangrui Song 
12901c3f7f17SFangrui Song   assert(SrcTy.getSizeInBits() > DstTy.getSizeInBits() &&
12911c3f7f17SFangrui Song          "Incorrect Src/Dst register size");
12921c3f7f17SFangrui Song 
12931c3f7f17SFangrui Song   if (DstTy.getSizeInBits() == 128)
12941c3f7f17SFangrui Song     SubIdx = X86::sub_xmm;
12951c3f7f17SFangrui Song   else if (DstTy.getSizeInBits() == 256)
12961c3f7f17SFangrui Song     SubIdx = X86::sub_ymm;
12971c3f7f17SFangrui Song   else
12981c3f7f17SFangrui Song     return false;
12991c3f7f17SFangrui Song 
13001c3f7f17SFangrui Song   const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);
13011c3f7f17SFangrui Song   const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);
13021c3f7f17SFangrui Song 
13031c3f7f17SFangrui Song   SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
13041c3f7f17SFangrui Song 
13051c3f7f17SFangrui Song   if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
13061c3f7f17SFangrui Song       !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
13071c3f7f17SFangrui Song     LLVM_DEBUG(dbgs() << "Failed to constrain EXTRACT_SUBREG\n");
13081c3f7f17SFangrui Song     return false;
13091c3f7f17SFangrui Song   }
13101c3f7f17SFangrui Song 
13111c3f7f17SFangrui Song   BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), DstReg)
13121c3f7f17SFangrui Song       .addReg(SrcReg, 0, SubIdx);
13131c3f7f17SFangrui Song 
13141c3f7f17SFangrui Song   return true;
13151c3f7f17SFangrui Song }
13161c3f7f17SFangrui Song 
13171c3f7f17SFangrui Song bool X86InstructionSelector::emitInsertSubreg(unsigned DstReg, unsigned SrcReg,
13181c3f7f17SFangrui Song                                               MachineInstr &I,
13191c3f7f17SFangrui Song                                               MachineRegisterInfo &MRI,
13201c3f7f17SFangrui Song                                               MachineFunction &MF) const {
13211c3f7f17SFangrui Song   const LLT DstTy = MRI.getType(DstReg);
13221c3f7f17SFangrui Song   const LLT SrcTy = MRI.getType(SrcReg);
13231c3f7f17SFangrui Song   unsigned SubIdx = X86::NoSubRegister;
13241c3f7f17SFangrui Song 
13251c3f7f17SFangrui Song   // TODO: support scalar types
13261c3f7f17SFangrui Song   if (!DstTy.isVector() || !SrcTy.isVector())
13271c3f7f17SFangrui Song     return false;
13281c3f7f17SFangrui Song 
13291c3f7f17SFangrui Song   assert(SrcTy.getSizeInBits() < DstTy.getSizeInBits() &&
13301c3f7f17SFangrui Song          "Incorrect Src/Dst register size");
13311c3f7f17SFangrui Song 
13321c3f7f17SFangrui Song   if (SrcTy.getSizeInBits() == 128)
13331c3f7f17SFangrui Song     SubIdx = X86::sub_xmm;
13341c3f7f17SFangrui Song   else if (SrcTy.getSizeInBits() == 256)
13351c3f7f17SFangrui Song     SubIdx = X86::sub_ymm;
13361c3f7f17SFangrui Song   else
13371c3f7f17SFangrui Song     return false;
13381c3f7f17SFangrui Song 
13391c3f7f17SFangrui Song   const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);
13401c3f7f17SFangrui Song   const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);
13411c3f7f17SFangrui Song 
13421c3f7f17SFangrui Song   if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
13431c3f7f17SFangrui Song       !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
13441c3f7f17SFangrui Song     LLVM_DEBUG(dbgs() << "Failed to constrain INSERT_SUBREG\n");
13451c3f7f17SFangrui Song     return false;
13461c3f7f17SFangrui Song   }
13471c3f7f17SFangrui Song 
13481c3f7f17SFangrui Song   BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY))
13491c3f7f17SFangrui Song       .addReg(DstReg, RegState::DefineNoRead, SubIdx)
13501c3f7f17SFangrui Song       .addReg(SrcReg);
13511c3f7f17SFangrui Song 
13521c3f7f17SFangrui Song   return true;
13531c3f7f17SFangrui Song }
13541c3f7f17SFangrui Song 
13551c3f7f17SFangrui Song bool X86InstructionSelector::selectInsert(MachineInstr &I,
13561c3f7f17SFangrui Song                                           MachineRegisterInfo &MRI,
13571c3f7f17SFangrui Song                                           MachineFunction &MF) const {
13581c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_INSERT) && "unexpected instruction");
13591c3f7f17SFangrui Song 
13601c3f7f17SFangrui Song   const Register DstReg = I.getOperand(0).getReg();
13611c3f7f17SFangrui Song   const Register SrcReg = I.getOperand(1).getReg();
13621c3f7f17SFangrui Song   const Register InsertReg = I.getOperand(2).getReg();
13631c3f7f17SFangrui Song   int64_t Index = I.getOperand(3).getImm();
13641c3f7f17SFangrui Song 
13651c3f7f17SFangrui Song   const LLT DstTy = MRI.getType(DstReg);
13661c3f7f17SFangrui Song   const LLT InsertRegTy = MRI.getType(InsertReg);
13671c3f7f17SFangrui Song 
13681c3f7f17SFangrui Song   // Meanwile handle vector type only.
13691c3f7f17SFangrui Song   if (!DstTy.isVector())
13701c3f7f17SFangrui Song     return false;
13711c3f7f17SFangrui Song 
13721c3f7f17SFangrui Song   if (Index % InsertRegTy.getSizeInBits() != 0)
13731c3f7f17SFangrui Song     return false; // Not insert subvector.
13741c3f7f17SFangrui Song 
13751c3f7f17SFangrui Song   if (Index == 0 && MRI.getVRegDef(SrcReg)->isImplicitDef()) {
13761c3f7f17SFangrui Song     // Replace by subreg copy.
13771c3f7f17SFangrui Song     if (!emitInsertSubreg(DstReg, InsertReg, I, MRI, MF))
13781c3f7f17SFangrui Song       return false;
13791c3f7f17SFangrui Song 
13801c3f7f17SFangrui Song     I.eraseFromParent();
13811c3f7f17SFangrui Song     return true;
13821c3f7f17SFangrui Song   }
13831c3f7f17SFangrui Song 
13841c3f7f17SFangrui Song   bool HasAVX = STI.hasAVX();
13851c3f7f17SFangrui Song   bool HasAVX512 = STI.hasAVX512();
13861c3f7f17SFangrui Song   bool HasVLX = STI.hasVLX();
13871c3f7f17SFangrui Song 
13881c3f7f17SFangrui Song   if (DstTy.getSizeInBits() == 256 && InsertRegTy.getSizeInBits() == 128) {
13891c3f7f17SFangrui Song     if (HasVLX)
1390*3a5cf6d9SSimon Pilgrim       I.setDesc(TII.get(X86::VINSERTF32X4Z256rri));
13911c3f7f17SFangrui Song     else if (HasAVX)
1392614a064cSSimon Pilgrim       I.setDesc(TII.get(X86::VINSERTF128rri));
13931c3f7f17SFangrui Song     else
13941c3f7f17SFangrui Song       return false;
13951c3f7f17SFangrui Song   } else if (DstTy.getSizeInBits() == 512 && HasAVX512) {
13961c3f7f17SFangrui Song     if (InsertRegTy.getSizeInBits() == 128)
1397*3a5cf6d9SSimon Pilgrim       I.setDesc(TII.get(X86::VINSERTF32X4Zrri));
13981c3f7f17SFangrui Song     else if (InsertRegTy.getSizeInBits() == 256)
1399*3a5cf6d9SSimon Pilgrim       I.setDesc(TII.get(X86::VINSERTF64X4Zrri));
14001c3f7f17SFangrui Song     else
14011c3f7f17SFangrui Song       return false;
14021c3f7f17SFangrui Song   } else
14031c3f7f17SFangrui Song     return false;
14041c3f7f17SFangrui Song 
14051c3f7f17SFangrui Song   // Convert to X86 VINSERT immediate.
14061c3f7f17SFangrui Song   Index = Index / InsertRegTy.getSizeInBits();
14071c3f7f17SFangrui Song 
14081c3f7f17SFangrui Song   I.getOperand(3).setImm(Index);
14091c3f7f17SFangrui Song 
14101c3f7f17SFangrui Song   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
14111c3f7f17SFangrui Song }
14121c3f7f17SFangrui Song 
14131c3f7f17SFangrui Song bool X86InstructionSelector::selectUnmergeValues(
14141c3f7f17SFangrui Song     MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) {
14151c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_UNMERGE_VALUES) &&
14161c3f7f17SFangrui Song          "unexpected instruction");
14171c3f7f17SFangrui Song 
14181c3f7f17SFangrui Song   // Split to extracts.
14191c3f7f17SFangrui Song   unsigned NumDefs = I.getNumOperands() - 1;
14201c3f7f17SFangrui Song   Register SrcReg = I.getOperand(NumDefs).getReg();
14211c3f7f17SFangrui Song   unsigned DefSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
14221c3f7f17SFangrui Song 
14231c3f7f17SFangrui Song   for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
14241c3f7f17SFangrui Song     MachineInstr &ExtrInst =
14251c3f7f17SFangrui Song         *BuildMI(*I.getParent(), I, I.getDebugLoc(),
14261c3f7f17SFangrui Song                  TII.get(TargetOpcode::G_EXTRACT), I.getOperand(Idx).getReg())
14271c3f7f17SFangrui Song              .addReg(SrcReg)
14281c3f7f17SFangrui Song              .addImm(Idx * DefSize);
14291c3f7f17SFangrui Song 
14301c3f7f17SFangrui Song     if (!select(ExtrInst))
14311c3f7f17SFangrui Song       return false;
14321c3f7f17SFangrui Song   }
14331c3f7f17SFangrui Song 
14341c3f7f17SFangrui Song   I.eraseFromParent();
14351c3f7f17SFangrui Song   return true;
14361c3f7f17SFangrui Song }
14371c3f7f17SFangrui Song 
14381c3f7f17SFangrui Song bool X86InstructionSelector::selectMergeValues(
14391c3f7f17SFangrui Song     MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) {
14401c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_MERGE_VALUES ||
14411c3f7f17SFangrui Song           I.getOpcode() == TargetOpcode::G_CONCAT_VECTORS) &&
14421c3f7f17SFangrui Song          "unexpected instruction");
14431c3f7f17SFangrui Song 
14441c3f7f17SFangrui Song   // Split to inserts.
14451c3f7f17SFangrui Song   Register DstReg = I.getOperand(0).getReg();
14461c3f7f17SFangrui Song   Register SrcReg0 = I.getOperand(1).getReg();
14471c3f7f17SFangrui Song 
14481c3f7f17SFangrui Song   const LLT DstTy = MRI.getType(DstReg);
14491c3f7f17SFangrui Song   const LLT SrcTy = MRI.getType(SrcReg0);
14501c3f7f17SFangrui Song   unsigned SrcSize = SrcTy.getSizeInBits();
14511c3f7f17SFangrui Song 
14521c3f7f17SFangrui Song   const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
14531c3f7f17SFangrui Song 
14541c3f7f17SFangrui Song   // For the first src use insertSubReg.
14551c3f7f17SFangrui Song   Register DefReg = MRI.createGenericVirtualRegister(DstTy);
14561c3f7f17SFangrui Song   MRI.setRegBank(DefReg, RegBank);
14571c3f7f17SFangrui Song   if (!emitInsertSubreg(DefReg, I.getOperand(1).getReg(), I, MRI, MF))
14581c3f7f17SFangrui Song     return false;
14591c3f7f17SFangrui Song 
14601c3f7f17SFangrui Song   for (unsigned Idx = 2; Idx < I.getNumOperands(); ++Idx) {
14611c3f7f17SFangrui Song     Register Tmp = MRI.createGenericVirtualRegister(DstTy);
14621c3f7f17SFangrui Song     MRI.setRegBank(Tmp, RegBank);
14631c3f7f17SFangrui Song 
14641c3f7f17SFangrui Song     MachineInstr &InsertInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
14651c3f7f17SFangrui Song                                         TII.get(TargetOpcode::G_INSERT), Tmp)
14661c3f7f17SFangrui Song                                     .addReg(DefReg)
14671c3f7f17SFangrui Song                                     .addReg(I.getOperand(Idx).getReg())
14681c3f7f17SFangrui Song                                     .addImm((Idx - 1) * SrcSize);
14691c3f7f17SFangrui Song 
14701c3f7f17SFangrui Song     DefReg = Tmp;
14711c3f7f17SFangrui Song 
14721c3f7f17SFangrui Song     if (!select(InsertInst))
14731c3f7f17SFangrui Song       return false;
14741c3f7f17SFangrui Song   }
14751c3f7f17SFangrui Song 
14761c3f7f17SFangrui Song   MachineInstr &CopyInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
14771c3f7f17SFangrui Song                                     TII.get(TargetOpcode::COPY), DstReg)
14781c3f7f17SFangrui Song                                 .addReg(DefReg);
14791c3f7f17SFangrui Song 
14801c3f7f17SFangrui Song   if (!select(CopyInst))
14811c3f7f17SFangrui Song     return false;
14821c3f7f17SFangrui Song 
14831c3f7f17SFangrui Song   I.eraseFromParent();
14841c3f7f17SFangrui Song   return true;
14851c3f7f17SFangrui Song }
14861c3f7f17SFangrui Song 
14871c3f7f17SFangrui Song bool X86InstructionSelector::selectCondBranch(MachineInstr &I,
14881c3f7f17SFangrui Song                                               MachineRegisterInfo &MRI,
14891c3f7f17SFangrui Song                                               MachineFunction &MF) const {
14901c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_BRCOND) && "unexpected instruction");
14911c3f7f17SFangrui Song 
14921c3f7f17SFangrui Song   const Register CondReg = I.getOperand(0).getReg();
14931c3f7f17SFangrui Song   MachineBasicBlock *DestMBB = I.getOperand(1).getMBB();
14941c3f7f17SFangrui Song 
14951c3f7f17SFangrui Song   MachineInstr &TestInst =
14961c3f7f17SFangrui Song       *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::TEST8ri))
14971c3f7f17SFangrui Song            .addReg(CondReg)
14981c3f7f17SFangrui Song            .addImm(1);
14991c3f7f17SFangrui Song   BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::JCC_1))
15001c3f7f17SFangrui Song       .addMBB(DestMBB).addImm(X86::COND_NE);
15011c3f7f17SFangrui Song 
15021c3f7f17SFangrui Song   constrainSelectedInstRegOperands(TestInst, TII, TRI, RBI);
15031c3f7f17SFangrui Song 
15041c3f7f17SFangrui Song   I.eraseFromParent();
15051c3f7f17SFangrui Song   return true;
15061c3f7f17SFangrui Song }
15071c3f7f17SFangrui Song 
15081c3f7f17SFangrui Song bool X86InstructionSelector::materializeFP(MachineInstr &I,
15091c3f7f17SFangrui Song                                            MachineRegisterInfo &MRI,
15101c3f7f17SFangrui Song                                            MachineFunction &MF) const {
15111c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_FCONSTANT) &&
15121c3f7f17SFangrui Song          "unexpected instruction");
15131c3f7f17SFangrui Song 
15141c3f7f17SFangrui Song   // Can't handle alternate code models yet.
15151c3f7f17SFangrui Song   CodeModel::Model CM = TM.getCodeModel();
15161c3f7f17SFangrui Song   if (CM != CodeModel::Small && CM != CodeModel::Large)
15171c3f7f17SFangrui Song     return false;
15181c3f7f17SFangrui Song 
15191c3f7f17SFangrui Song   const Register DstReg = I.getOperand(0).getReg();
15201c3f7f17SFangrui Song   const LLT DstTy = MRI.getType(DstReg);
15211c3f7f17SFangrui Song   const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
1522a77d3ea3SMalay Sanghi   // Create the load from the constant pool.
1523a77d3ea3SMalay Sanghi   const ConstantFP *CFP = I.getOperand(1).getFPImm();
1524a77d3ea3SMalay Sanghi   const auto &DL = MF.getDataLayout();
1525a77d3ea3SMalay Sanghi   Align Alignment = DL.getPrefTypeAlign(CFP->getType());
15261c3f7f17SFangrui Song   const DebugLoc &DbgLoc = I.getDebugLoc();
15271c3f7f17SFangrui Song 
15281c3f7f17SFangrui Song   unsigned Opc =
15291c3f7f17SFangrui Song       getLoadStoreOp(DstTy, RegBank, TargetOpcode::G_LOAD, Alignment);
15301c3f7f17SFangrui Song 
15311c3f7f17SFangrui Song   unsigned CPI = MF.getConstantPool()->getConstantPoolIndex(CFP, Alignment);
15321c3f7f17SFangrui Song   MachineInstr *LoadInst = nullptr;
15331c3f7f17SFangrui Song   unsigned char OpFlag = STI.classifyLocalReference(nullptr);
15341c3f7f17SFangrui Song 
15351c3f7f17SFangrui Song   if (CM == CodeModel::Large && STI.is64Bit()) {
15361c3f7f17SFangrui Song     // Under X86-64 non-small code model, GV (and friends) are 64-bits, so
15371c3f7f17SFangrui Song     // they cannot be folded into immediate fields.
15381c3f7f17SFangrui Song 
15391c3f7f17SFangrui Song     Register AddrReg = MRI.createVirtualRegister(&X86::GR64RegClass);
15401c3f7f17SFangrui Song     BuildMI(*I.getParent(), I, DbgLoc, TII.get(X86::MOV64ri), AddrReg)
15411c3f7f17SFangrui Song         .addConstantPoolIndex(CPI, 0, OpFlag);
15421c3f7f17SFangrui Song 
15431c3f7f17SFangrui Song     MachineMemOperand *MMO = MF.getMachineMemOperand(
15441c3f7f17SFangrui Song         MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad,
1545a77d3ea3SMalay Sanghi         LLT::pointer(0, DL.getPointerSizeInBits()), Alignment);
15461c3f7f17SFangrui Song 
15471c3f7f17SFangrui Song     LoadInst =
15481c3f7f17SFangrui Song         addDirectMem(BuildMI(*I.getParent(), I, DbgLoc, TII.get(Opc), DstReg),
15491c3f7f17SFangrui Song                      AddrReg)
15501c3f7f17SFangrui Song             .addMemOperand(MMO);
15511c3f7f17SFangrui Song 
15521c3f7f17SFangrui Song   } else if (CM == CodeModel::Small || !STI.is64Bit()) {
15531c3f7f17SFangrui Song     // Handle the case when globals fit in our immediate field.
15541c3f7f17SFangrui Song     // This is true for X86-32 always and X86-64 when in -mcmodel=small mode.
15551c3f7f17SFangrui Song 
15561c3f7f17SFangrui Song     // x86-32 PIC requires a PIC base register for constant pools.
15571c3f7f17SFangrui Song     unsigned PICBase = 0;
15581c3f7f17SFangrui Song     if (OpFlag == X86II::MO_PIC_BASE_OFFSET || OpFlag == X86II::MO_GOTOFF) {
15591c3f7f17SFangrui Song       // PICBase can be allocated by TII.getGlobalBaseReg(&MF).
15601c3f7f17SFangrui Song       // In DAGISEL the code that initialize it generated by the CGBR pass.
15611c3f7f17SFangrui Song       return false; // TODO support the mode.
15621c3f7f17SFangrui Song     } else if (STI.is64Bit() && TM.getCodeModel() == CodeModel::Small)
15631c3f7f17SFangrui Song       PICBase = X86::RIP;
15641c3f7f17SFangrui Song 
15651c3f7f17SFangrui Song     LoadInst = addConstantPoolReference(
15661c3f7f17SFangrui Song         BuildMI(*I.getParent(), I, DbgLoc, TII.get(Opc), DstReg), CPI, PICBase,
15671c3f7f17SFangrui Song         OpFlag);
15681c3f7f17SFangrui Song   } else
15691c3f7f17SFangrui Song     return false;
15701c3f7f17SFangrui Song 
15711c3f7f17SFangrui Song   constrainSelectedInstRegOperands(*LoadInst, TII, TRI, RBI);
15721c3f7f17SFangrui Song   I.eraseFromParent();
15731c3f7f17SFangrui Song   return true;
15741c3f7f17SFangrui Song }
15751c3f7f17SFangrui Song 
15761c3f7f17SFangrui Song bool X86InstructionSelector::selectImplicitDefOrPHI(
15771c3f7f17SFangrui Song     MachineInstr &I, MachineRegisterInfo &MRI) const {
15781c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF ||
15791c3f7f17SFangrui Song           I.getOpcode() == TargetOpcode::G_PHI) &&
15801c3f7f17SFangrui Song          "unexpected instruction");
15811c3f7f17SFangrui Song 
15821c3f7f17SFangrui Song   Register DstReg = I.getOperand(0).getReg();
15831c3f7f17SFangrui Song 
15841c3f7f17SFangrui Song   if (!MRI.getRegClassOrNull(DstReg)) {
15851c3f7f17SFangrui Song     const LLT DstTy = MRI.getType(DstReg);
15861c3f7f17SFangrui Song     const TargetRegisterClass *RC = getRegClass(DstTy, DstReg, MRI);
15871c3f7f17SFangrui Song 
15881c3f7f17SFangrui Song     if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
15891c3f7f17SFangrui Song       LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
15901c3f7f17SFangrui Song                         << " operand\n");
15911c3f7f17SFangrui Song       return false;
15921c3f7f17SFangrui Song     }
15931c3f7f17SFangrui Song   }
15941c3f7f17SFangrui Song 
15951c3f7f17SFangrui Song   if (I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
15961c3f7f17SFangrui Song     I.setDesc(TII.get(X86::IMPLICIT_DEF));
15971c3f7f17SFangrui Song   else
15981c3f7f17SFangrui Song     I.setDesc(TII.get(X86::PHI));
15991c3f7f17SFangrui Song 
16001c3f7f17SFangrui Song   return true;
16011c3f7f17SFangrui Song }
16021c3f7f17SFangrui Song 
16031c3f7f17SFangrui Song bool X86InstructionSelector::selectMulDivRem(MachineInstr &I,
16041c3f7f17SFangrui Song                                              MachineRegisterInfo &MRI,
16051c3f7f17SFangrui Song                                              MachineFunction &MF) const {
16061c3f7f17SFangrui Song   // The implementation of this function is adapted from X86FastISel.
16071c3f7f17SFangrui Song   assert((I.getOpcode() == TargetOpcode::G_MUL ||
16081c3f7f17SFangrui Song           I.getOpcode() == TargetOpcode::G_SMULH ||
16091c3f7f17SFangrui Song           I.getOpcode() == TargetOpcode::G_UMULH ||
16101c3f7f17SFangrui Song           I.getOpcode() == TargetOpcode::G_SDIV ||
16111c3f7f17SFangrui Song           I.getOpcode() == TargetOpcode::G_SREM ||
16121c3f7f17SFangrui Song           I.getOpcode() == TargetOpcode::G_UDIV ||
16131c3f7f17SFangrui Song           I.getOpcode() == TargetOpcode::G_UREM) &&
16141c3f7f17SFangrui Song          "unexpected instruction");
16151c3f7f17SFangrui Song 
16161c3f7f17SFangrui Song   const Register DstReg = I.getOperand(0).getReg();
16171c3f7f17SFangrui Song   const Register Op1Reg = I.getOperand(1).getReg();
16181c3f7f17SFangrui Song   const Register Op2Reg = I.getOperand(2).getReg();
16191c3f7f17SFangrui Song 
16201c3f7f17SFangrui Song   const LLT RegTy = MRI.getType(DstReg);
16211c3f7f17SFangrui Song   assert(RegTy == MRI.getType(Op1Reg) && RegTy == MRI.getType(Op2Reg) &&
16221c3f7f17SFangrui Song          "Arguments and return value types must match");
16231c3f7f17SFangrui Song 
16241c3f7f17SFangrui Song   const RegisterBank *RegRB = RBI.getRegBank(DstReg, MRI, TRI);
16251c3f7f17SFangrui Song   if (!RegRB || RegRB->getID() != X86::GPRRegBankID)
16261c3f7f17SFangrui Song     return false;
16271c3f7f17SFangrui Song 
16281c3f7f17SFangrui Song   const static unsigned NumTypes = 4; // i8, i16, i32, i64
16291c3f7f17SFangrui Song   const static unsigned NumOps = 7;   // SDiv/SRem/UDiv/URem/Mul/SMulH/UMulh
16301c3f7f17SFangrui Song   const static bool S = true;         // IsSigned
16311c3f7f17SFangrui Song   const static bool U = false;        // !IsSigned
16321c3f7f17SFangrui Song   const static unsigned Copy = TargetOpcode::COPY;
16331c3f7f17SFangrui Song 
16341c3f7f17SFangrui Song   // For the X86 IDIV instruction, in most cases the dividend
16351c3f7f17SFangrui Song   // (numerator) must be in a specific register pair highreg:lowreg,
16361c3f7f17SFangrui Song   // producing the quotient in lowreg and the remainder in highreg.
16371c3f7f17SFangrui Song   // For most data types, to set up the instruction, the dividend is
16381c3f7f17SFangrui Song   // copied into lowreg, and lowreg is sign-extended into highreg.  The
16391c3f7f17SFangrui Song   // exception is i8, where the dividend is defined as a single register rather
16401c3f7f17SFangrui Song   // than a register pair, and we therefore directly sign-extend the dividend
16411c3f7f17SFangrui Song   // into lowreg, instead of copying, and ignore the highreg.
16421c3f7f17SFangrui Song   const static struct MulDivRemEntry {
16431c3f7f17SFangrui Song     // The following portion depends only on the data type.
16441c3f7f17SFangrui Song     unsigned SizeInBits;
16451c3f7f17SFangrui Song     unsigned LowInReg;  // low part of the register pair
16461c3f7f17SFangrui Song     unsigned HighInReg; // high part of the register pair
16471c3f7f17SFangrui Song     // The following portion depends on both the data type and the operation.
16481c3f7f17SFangrui Song     struct MulDivRemResult {
16491c3f7f17SFangrui Song       unsigned OpMulDivRem;     // The specific MUL/DIV opcode to use.
16501c3f7f17SFangrui Song       unsigned OpSignExtend;    // Opcode for sign-extending lowreg into
16511c3f7f17SFangrui Song                                 // highreg, or copying a zero into highreg.
16521c3f7f17SFangrui Song       unsigned OpCopy;          // Opcode for copying dividend into lowreg, or
16531c3f7f17SFangrui Song                                 // zero/sign-extending into lowreg for i8.
16541c3f7f17SFangrui Song       unsigned ResultReg;       // Register containing the desired result.
16551c3f7f17SFangrui Song       bool IsOpSigned;          // Whether to use signed or unsigned form.
16561c3f7f17SFangrui Song     } ResultTable[NumOps];
16571c3f7f17SFangrui Song   } OpTable[NumTypes] = {
16581c3f7f17SFangrui Song       {8,
16591c3f7f17SFangrui Song        X86::AX,
16601c3f7f17SFangrui Song        0,
16611c3f7f17SFangrui Song        {
16621c3f7f17SFangrui Song            {X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AL, S}, // SDiv
16631c3f7f17SFangrui Song            {X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AH, S}, // SRem
16641c3f7f17SFangrui Song            {X86::DIV8r, 0, X86::MOVZX16rr8, X86::AL, U},  // UDiv
16651c3f7f17SFangrui Song            {X86::DIV8r, 0, X86::MOVZX16rr8, X86::AH, U},  // URem
16661c3f7f17SFangrui Song            {X86::IMUL8r, 0, X86::MOVSX16rr8, X86::AL, S}, // Mul
16671c3f7f17SFangrui Song            {X86::IMUL8r, 0, X86::MOVSX16rr8, X86::AH, S}, // SMulH
16681c3f7f17SFangrui Song            {X86::MUL8r, 0, X86::MOVZX16rr8, X86::AH, U},  // UMulH
16691c3f7f17SFangrui Song        }},                                                // i8
16701c3f7f17SFangrui Song       {16,
16711c3f7f17SFangrui Song        X86::AX,
16721c3f7f17SFangrui Song        X86::DX,
16731c3f7f17SFangrui Song        {
16741c3f7f17SFangrui Song            {X86::IDIV16r, X86::CWD, Copy, X86::AX, S},     // SDiv
16751c3f7f17SFangrui Song            {X86::IDIV16r, X86::CWD, Copy, X86::DX, S},     // SRem
16761c3f7f17SFangrui Song            {X86::DIV16r, X86::MOV32r0, Copy, X86::AX, U},  // UDiv
16771c3f7f17SFangrui Song            {X86::DIV16r, X86::MOV32r0, Copy, X86::DX, U},  // URem
16781c3f7f17SFangrui Song            {X86::IMUL16r, X86::MOV32r0, Copy, X86::AX, S}, // Mul
16791c3f7f17SFangrui Song            {X86::IMUL16r, X86::MOV32r0, Copy, X86::DX, S}, // SMulH
16801c3f7f17SFangrui Song            {X86::MUL16r, X86::MOV32r0, Copy, X86::DX, U},  // UMulH
16811c3f7f17SFangrui Song        }},                                                 // i16
16821c3f7f17SFangrui Song       {32,
16831c3f7f17SFangrui Song        X86::EAX,
16841c3f7f17SFangrui Song        X86::EDX,
16851c3f7f17SFangrui Song        {
16861c3f7f17SFangrui Song            {X86::IDIV32r, X86::CDQ, Copy, X86::EAX, S},     // SDiv
16871c3f7f17SFangrui Song            {X86::IDIV32r, X86::CDQ, Copy, X86::EDX, S},     // SRem
16881c3f7f17SFangrui Song            {X86::DIV32r, X86::MOV32r0, Copy, X86::EAX, U},  // UDiv
16891c3f7f17SFangrui Song            {X86::DIV32r, X86::MOV32r0, Copy, X86::EDX, U},  // URem
16901c3f7f17SFangrui Song            {X86::IMUL32r, X86::MOV32r0, Copy, X86::EAX, S}, // Mul
16911c3f7f17SFangrui Song            {X86::IMUL32r, X86::MOV32r0, Copy, X86::EDX, S}, // SMulH
16921c3f7f17SFangrui Song            {X86::MUL32r, X86::MOV32r0, Copy, X86::EDX, U},  // UMulH
16931c3f7f17SFangrui Song        }},                                                  // i32
16941c3f7f17SFangrui Song       {64,
16951c3f7f17SFangrui Song        X86::RAX,
16961c3f7f17SFangrui Song        X86::RDX,
16971c3f7f17SFangrui Song        {
16981c3f7f17SFangrui Song            {X86::IDIV64r, X86::CQO, Copy, X86::RAX, S},    // SDiv
16991c3f7f17SFangrui Song            {X86::IDIV64r, X86::CQO, Copy, X86::RDX, S},    // SRem
17001c3f7f17SFangrui Song            {X86::DIV64r, X86::MOV32r0, Copy, X86::RAX, U}, // UDiv
17011c3f7f17SFangrui Song            {X86::DIV64r, X86::MOV32r0, Copy, X86::RDX, U}, // URem
17021c3f7f17SFangrui Song            {X86::IMUL64r, X86::MOV32r0, Copy, X86::RAX, S}, // Mul
17031c3f7f17SFangrui Song            {X86::IMUL64r, X86::MOV32r0, Copy, X86::RDX, S}, // SMulH
17041c3f7f17SFangrui Song            {X86::MUL64r, X86::MOV32r0, Copy, X86::RDX, U},  // UMulH
17051c3f7f17SFangrui Song        }},                                                  // i64
17061c3f7f17SFangrui Song   };
17071c3f7f17SFangrui Song 
17081c3f7f17SFangrui Song   auto OpEntryIt = llvm::find_if(OpTable, [RegTy](const MulDivRemEntry &El) {
17091c3f7f17SFangrui Song     return El.SizeInBits == RegTy.getSizeInBits();
17101c3f7f17SFangrui Song   });
17111c3f7f17SFangrui Song   if (OpEntryIt == std::end(OpTable))
17121c3f7f17SFangrui Song     return false;
17131c3f7f17SFangrui Song 
17141c3f7f17SFangrui Song   unsigned OpIndex;
17151c3f7f17SFangrui Song   switch (I.getOpcode()) {
17161c3f7f17SFangrui Song   default:
17171c3f7f17SFangrui Song     llvm_unreachable("Unexpected mul/div/rem opcode");
17181c3f7f17SFangrui Song   case TargetOpcode::G_SDIV:
17191c3f7f17SFangrui Song     OpIndex = 0;
17201c3f7f17SFangrui Song     break;
17211c3f7f17SFangrui Song   case TargetOpcode::G_SREM:
17221c3f7f17SFangrui Song     OpIndex = 1;
17231c3f7f17SFangrui Song     break;
17241c3f7f17SFangrui Song   case TargetOpcode::G_UDIV:
17251c3f7f17SFangrui Song     OpIndex = 2;
17261c3f7f17SFangrui Song     break;
17271c3f7f17SFangrui Song   case TargetOpcode::G_UREM:
17281c3f7f17SFangrui Song     OpIndex = 3;
17291c3f7f17SFangrui Song     break;
17301c3f7f17SFangrui Song   case TargetOpcode::G_MUL:
17311c3f7f17SFangrui Song     OpIndex = 4;
17321c3f7f17SFangrui Song     break;
17331c3f7f17SFangrui Song   case TargetOpcode::G_SMULH:
17341c3f7f17SFangrui Song     OpIndex = 5;
17351c3f7f17SFangrui Song     break;
17361c3f7f17SFangrui Song   case TargetOpcode::G_UMULH:
17371c3f7f17SFangrui Song     OpIndex = 6;
17381c3f7f17SFangrui Song     break;
17391c3f7f17SFangrui Song   }
17401c3f7f17SFangrui Song 
17411c3f7f17SFangrui Song   const MulDivRemEntry &TypeEntry = *OpEntryIt;
17421c3f7f17SFangrui Song   const MulDivRemEntry::MulDivRemResult &OpEntry =
17431c3f7f17SFangrui Song       TypeEntry.ResultTable[OpIndex];
17441c3f7f17SFangrui Song 
17451c3f7f17SFangrui Song   const TargetRegisterClass *RegRC = getRegClass(RegTy, *RegRB);
17461c3f7f17SFangrui Song   if (!RBI.constrainGenericRegister(Op1Reg, *RegRC, MRI) ||
17471c3f7f17SFangrui Song       !RBI.constrainGenericRegister(Op2Reg, *RegRC, MRI) ||
17481c3f7f17SFangrui Song       !RBI.constrainGenericRegister(DstReg, *RegRC, MRI)) {
17491c3f7f17SFangrui Song     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
17501c3f7f17SFangrui Song                       << " operand\n");
17511c3f7f17SFangrui Song     return false;
17521c3f7f17SFangrui Song   }
17531c3f7f17SFangrui Song 
17541c3f7f17SFangrui Song   // Move op1 into low-order input register.
17551c3f7f17SFangrui Song   BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpEntry.OpCopy),
17561c3f7f17SFangrui Song           TypeEntry.LowInReg)
17571c3f7f17SFangrui Song       .addReg(Op1Reg);
17581c3f7f17SFangrui Song 
17591c3f7f17SFangrui Song   // Zero-extend or sign-extend into high-order input register.
17601c3f7f17SFangrui Song   if (OpEntry.OpSignExtend) {
17611c3f7f17SFangrui Song     if (OpEntry.IsOpSigned)
17621c3f7f17SFangrui Song       BuildMI(*I.getParent(), I, I.getDebugLoc(),
17631c3f7f17SFangrui Song               TII.get(OpEntry.OpSignExtend));
17641c3f7f17SFangrui Song     else {
17651c3f7f17SFangrui Song       Register Zero32 = MRI.createVirtualRegister(&X86::GR32RegClass);
17661c3f7f17SFangrui Song       BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::MOV32r0),
17671c3f7f17SFangrui Song               Zero32);
17681c3f7f17SFangrui Song 
17691c3f7f17SFangrui Song       // Copy the zero into the appropriate sub/super/identical physical
17701c3f7f17SFangrui Song       // register. Unfortunately the operations needed are not uniform enough
17711c3f7f17SFangrui Song       // to fit neatly into the table above.
17721c3f7f17SFangrui Song       if (RegTy.getSizeInBits() == 16) {
17731c3f7f17SFangrui Song         BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Copy),
17741c3f7f17SFangrui Song                 TypeEntry.HighInReg)
17751c3f7f17SFangrui Song             .addReg(Zero32, 0, X86::sub_16bit);
17761c3f7f17SFangrui Song       } else if (RegTy.getSizeInBits() == 32) {
17771c3f7f17SFangrui Song         BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Copy),
17781c3f7f17SFangrui Song                 TypeEntry.HighInReg)
17791c3f7f17SFangrui Song             .addReg(Zero32);
17801c3f7f17SFangrui Song       } else if (RegTy.getSizeInBits() == 64) {
17811c3f7f17SFangrui Song         BuildMI(*I.getParent(), I, I.getDebugLoc(),
17821c3f7f17SFangrui Song                 TII.get(TargetOpcode::SUBREG_TO_REG), TypeEntry.HighInReg)
17831c3f7f17SFangrui Song             .addImm(0)
17841c3f7f17SFangrui Song             .addReg(Zero32)
17851c3f7f17SFangrui Song             .addImm(X86::sub_32bit);
17861c3f7f17SFangrui Song       }
17871c3f7f17SFangrui Song     }
17881c3f7f17SFangrui Song   }
17891c3f7f17SFangrui Song 
17901c3f7f17SFangrui Song   // Generate the DIV/IDIV/MUL/IMUL instruction.
17911c3f7f17SFangrui Song   BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpEntry.OpMulDivRem))
17921c3f7f17SFangrui Song       .addReg(Op2Reg);
17931c3f7f17SFangrui Song 
17941c3f7f17SFangrui Song   // For i8 remainder, we can't reference ah directly, as we'll end
17951c3f7f17SFangrui Song   // up with bogus copies like %r9b = COPY %ah. Reference ax
17961c3f7f17SFangrui Song   // instead to prevent ah references in a rex instruction.
17971c3f7f17SFangrui Song   //
17981c3f7f17SFangrui Song   // The current assumption of the fast register allocator is that isel
17991c3f7f17SFangrui Song   // won't generate explicit references to the GR8_NOREX registers. If
18001c3f7f17SFangrui Song   // the allocator and/or the backend get enhanced to be more robust in
18011c3f7f17SFangrui Song   // that regard, this can be, and should be, removed.
18021c3f7f17SFangrui Song   if (OpEntry.ResultReg == X86::AH && STI.is64Bit()) {
18031c3f7f17SFangrui Song     Register SourceSuperReg = MRI.createVirtualRegister(&X86::GR16RegClass);
18041c3f7f17SFangrui Song     Register ResultSuperReg = MRI.createVirtualRegister(&X86::GR16RegClass);
18051c3f7f17SFangrui Song     BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Copy), SourceSuperReg)
18061c3f7f17SFangrui Song         .addReg(X86::AX);
18071c3f7f17SFangrui Song 
18081c3f7f17SFangrui Song     // Shift AX right by 8 bits instead of using AH.
18091c3f7f17SFangrui Song     BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::SHR16ri),
18101c3f7f17SFangrui Song             ResultSuperReg)
18111c3f7f17SFangrui Song         .addReg(SourceSuperReg)
18121c3f7f17SFangrui Song         .addImm(8);
18131c3f7f17SFangrui Song 
18141c3f7f17SFangrui Song     // Now reference the 8-bit subreg of the result.
181510edabbcSEvgenii Kudriashov     BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(TargetOpcode::COPY),
181610edabbcSEvgenii Kudriashov             DstReg)
181710edabbcSEvgenii Kudriashov         .addReg(ResultSuperReg, 0, X86::sub_8bit);
18181c3f7f17SFangrui Song   } else {
18191c3f7f17SFangrui Song     BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(TargetOpcode::COPY),
18201c3f7f17SFangrui Song             DstReg)
18211c3f7f17SFangrui Song         .addReg(OpEntry.ResultReg);
18221c3f7f17SFangrui Song   }
18231c3f7f17SFangrui Song   I.eraseFromParent();
18241c3f7f17SFangrui Song 
18251c3f7f17SFangrui Song   return true;
18261c3f7f17SFangrui Song }
18271c3f7f17SFangrui Song 
1828ef35da82SEvgenii Kudriashov bool X86InstructionSelector::selectSelect(MachineInstr &I,
1829ef35da82SEvgenii Kudriashov                                           MachineRegisterInfo &MRI,
1830ef35da82SEvgenii Kudriashov                                           MachineFunction &MF) const {
1831ef35da82SEvgenii Kudriashov   GSelect &Sel = cast<GSelect>(I);
1832ef35da82SEvgenii Kudriashov   unsigned DstReg = Sel.getReg(0);
1833ef35da82SEvgenii Kudriashov   BuildMI(*Sel.getParent(), Sel, Sel.getDebugLoc(), TII.get(X86::TEST32rr))
1834ef35da82SEvgenii Kudriashov       .addReg(Sel.getCondReg())
1835ef35da82SEvgenii Kudriashov       .addReg(Sel.getCondReg());
1836ef35da82SEvgenii Kudriashov 
1837ef35da82SEvgenii Kudriashov   unsigned OpCmp;
1838ef35da82SEvgenii Kudriashov   LLT Ty = MRI.getType(DstReg);
1839ef35da82SEvgenii Kudriashov   switch (Ty.getSizeInBits()) {
1840ef35da82SEvgenii Kudriashov   default:
1841ef35da82SEvgenii Kudriashov     return false;
1842ef35da82SEvgenii Kudriashov   case 8:
1843ef35da82SEvgenii Kudriashov     OpCmp = X86::CMOV_GR8;
1844ef35da82SEvgenii Kudriashov     break;
1845ef35da82SEvgenii Kudriashov   case 16:
1846ef35da82SEvgenii Kudriashov     OpCmp = STI.canUseCMOV() ? X86::CMOV16rr : X86::CMOV_GR16;
1847ef35da82SEvgenii Kudriashov     break;
1848ef35da82SEvgenii Kudriashov   case 32:
1849ef35da82SEvgenii Kudriashov     OpCmp = STI.canUseCMOV() ? X86::CMOV32rr : X86::CMOV_GR32;
1850ef35da82SEvgenii Kudriashov     break;
1851ef35da82SEvgenii Kudriashov   case 64:
1852ef35da82SEvgenii Kudriashov     assert(STI.is64Bit() && STI.canUseCMOV());
1853ef35da82SEvgenii Kudriashov     OpCmp = X86::CMOV64rr;
1854ef35da82SEvgenii Kudriashov     break;
1855ef35da82SEvgenii Kudriashov   }
1856ef35da82SEvgenii Kudriashov   BuildMI(*Sel.getParent(), Sel, Sel.getDebugLoc(), TII.get(OpCmp), DstReg)
1857ef35da82SEvgenii Kudriashov       .addReg(Sel.getTrueReg())
1858ef35da82SEvgenii Kudriashov       .addReg(Sel.getFalseReg())
1859ef35da82SEvgenii Kudriashov       .addImm(X86::COND_E);
1860ef35da82SEvgenii Kudriashov 
1861ef35da82SEvgenii Kudriashov   const TargetRegisterClass *DstRC = getRegClass(Ty, DstReg, MRI);
1862ef35da82SEvgenii Kudriashov   if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
1863ef35da82SEvgenii Kudriashov     LLVM_DEBUG(dbgs() << "Failed to constrain CMOV\n");
1864ef35da82SEvgenii Kudriashov     return false;
1865ef35da82SEvgenii Kudriashov   }
1866ef35da82SEvgenii Kudriashov 
1867ef35da82SEvgenii Kudriashov   Sel.eraseFromParent();
1868ef35da82SEvgenii Kudriashov   return true;
1869ef35da82SEvgenii Kudriashov }
1870ef35da82SEvgenii Kudriashov 
18711c3f7f17SFangrui Song InstructionSelector *
18721c3f7f17SFangrui Song llvm::createX86InstructionSelector(const X86TargetMachine &TM,
18739b95d08eSMichael Maitland                                    const X86Subtarget &Subtarget,
18749b95d08eSMichael Maitland                                    const X86RegisterBankInfo &RBI) {
18751c3f7f17SFangrui Song   return new X86InstructionSelector(TM, Subtarget, RBI);
18761c3f7f17SFangrui Song }
1877