106f32e7eSjoerg //===- X86InstructionSelector.cpp -----------------------------------------===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg /// \file
906f32e7eSjoerg /// This file implements the targeting of the InstructionSelector class for
1006f32e7eSjoerg /// X86.
1106f32e7eSjoerg /// \todo This should be generated by TableGen.
1206f32e7eSjoerg //===----------------------------------------------------------------------===//
1306f32e7eSjoerg 
1406f32e7eSjoerg #include "MCTargetDesc/X86BaseInfo.h"
15*da58b97aSjoerg #include "X86.h"
1606f32e7eSjoerg #include "X86InstrBuilder.h"
1706f32e7eSjoerg #include "X86InstrInfo.h"
1806f32e7eSjoerg #include "X86RegisterBankInfo.h"
1906f32e7eSjoerg #include "X86RegisterInfo.h"
2006f32e7eSjoerg #include "X86Subtarget.h"
2106f32e7eSjoerg #include "X86TargetMachine.h"
2206f32e7eSjoerg #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
2306f32e7eSjoerg #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h"
2406f32e7eSjoerg #include "llvm/CodeGen/GlobalISel/RegisterBank.h"
2506f32e7eSjoerg #include "llvm/CodeGen/GlobalISel/Utils.h"
2606f32e7eSjoerg #include "llvm/CodeGen/MachineBasicBlock.h"
2706f32e7eSjoerg #include "llvm/CodeGen/MachineConstantPool.h"
2806f32e7eSjoerg #include "llvm/CodeGen/MachineFunction.h"
2906f32e7eSjoerg #include "llvm/CodeGen/MachineInstr.h"
3006f32e7eSjoerg #include "llvm/CodeGen/MachineInstrBuilder.h"
3106f32e7eSjoerg #include "llvm/CodeGen/MachineMemOperand.h"
3206f32e7eSjoerg #include "llvm/CodeGen/MachineOperand.h"
3306f32e7eSjoerg #include "llvm/CodeGen/MachineRegisterInfo.h"
3406f32e7eSjoerg #include "llvm/CodeGen/TargetOpcodes.h"
3506f32e7eSjoerg #include "llvm/CodeGen/TargetRegisterInfo.h"
3606f32e7eSjoerg #include "llvm/IR/DataLayout.h"
3706f32e7eSjoerg #include "llvm/IR/InstrTypes.h"
38*da58b97aSjoerg #include "llvm/IR/IntrinsicsX86.h"
3906f32e7eSjoerg #include "llvm/Support/AtomicOrdering.h"
4006f32e7eSjoerg #include "llvm/Support/CodeGen.h"
4106f32e7eSjoerg #include "llvm/Support/Debug.h"
4206f32e7eSjoerg #include "llvm/Support/ErrorHandling.h"
4306f32e7eSjoerg #include "llvm/Support/LowLevelTypeImpl.h"
4406f32e7eSjoerg #include "llvm/Support/MathExtras.h"
4506f32e7eSjoerg #include "llvm/Support/raw_ostream.h"
4606f32e7eSjoerg #include <cassert>
4706f32e7eSjoerg #include <cstdint>
4806f32e7eSjoerg #include <tuple>
4906f32e7eSjoerg 
5006f32e7eSjoerg #define DEBUG_TYPE "X86-isel"
5106f32e7eSjoerg 
5206f32e7eSjoerg using namespace llvm;
5306f32e7eSjoerg 
5406f32e7eSjoerg namespace {
5506f32e7eSjoerg 
5606f32e7eSjoerg #define GET_GLOBALISEL_PREDICATE_BITSET
5706f32e7eSjoerg #include "X86GenGlobalISel.inc"
5806f32e7eSjoerg #undef GET_GLOBALISEL_PREDICATE_BITSET
5906f32e7eSjoerg 
6006f32e7eSjoerg class X86InstructionSelector : public InstructionSelector {
6106f32e7eSjoerg public:
6206f32e7eSjoerg   X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,
6306f32e7eSjoerg                          const X86RegisterBankInfo &RBI);
6406f32e7eSjoerg 
6506f32e7eSjoerg   bool select(MachineInstr &I) override;
getName()6606f32e7eSjoerg   static const char *getName() { return DEBUG_TYPE; }
6706f32e7eSjoerg 
6806f32e7eSjoerg private:
6906f32e7eSjoerg   /// tblgen-erated 'select' implementation, used as the initial selector for
7006f32e7eSjoerg   /// the patterns that don't require complex C++.
7106f32e7eSjoerg   bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
7206f32e7eSjoerg 
7306f32e7eSjoerg   // TODO: remove after supported by Tablegen-erated instruction selection.
7406f32e7eSjoerg   unsigned getLoadStoreOp(const LLT &Ty, const RegisterBank &RB, unsigned Opc,
75*da58b97aSjoerg                           Align Alignment) const;
7606f32e7eSjoerg 
7706f32e7eSjoerg   bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,
7806f32e7eSjoerg                          MachineFunction &MF) const;
7906f32e7eSjoerg   bool selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI,
8006f32e7eSjoerg                              MachineFunction &MF) const;
8106f32e7eSjoerg   bool selectGlobalValue(MachineInstr &I, MachineRegisterInfo &MRI,
8206f32e7eSjoerg                          MachineFunction &MF) const;
8306f32e7eSjoerg   bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,
8406f32e7eSjoerg                       MachineFunction &MF) const;
8506f32e7eSjoerg   bool selectTruncOrPtrToInt(MachineInstr &I, MachineRegisterInfo &MRI,
8606f32e7eSjoerg                              MachineFunction &MF) const;
8706f32e7eSjoerg   bool selectZext(MachineInstr &I, MachineRegisterInfo &MRI,
8806f32e7eSjoerg                   MachineFunction &MF) const;
8906f32e7eSjoerg   bool selectAnyext(MachineInstr &I, MachineRegisterInfo &MRI,
9006f32e7eSjoerg                     MachineFunction &MF) const;
9106f32e7eSjoerg   bool selectCmp(MachineInstr &I, MachineRegisterInfo &MRI,
9206f32e7eSjoerg                  MachineFunction &MF) const;
9306f32e7eSjoerg   bool selectFCmp(MachineInstr &I, MachineRegisterInfo &MRI,
9406f32e7eSjoerg                   MachineFunction &MF) const;
9506f32e7eSjoerg   bool selectUadde(MachineInstr &I, MachineRegisterInfo &MRI,
9606f32e7eSjoerg                    MachineFunction &MF) const;
9706f32e7eSjoerg   bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
9806f32e7eSjoerg   bool selectUnmergeValues(MachineInstr &I, MachineRegisterInfo &MRI,
9906f32e7eSjoerg                            MachineFunction &MF);
10006f32e7eSjoerg   bool selectMergeValues(MachineInstr &I, MachineRegisterInfo &MRI,
10106f32e7eSjoerg                          MachineFunction &MF);
10206f32e7eSjoerg   bool selectInsert(MachineInstr &I, MachineRegisterInfo &MRI,
10306f32e7eSjoerg                     MachineFunction &MF) const;
10406f32e7eSjoerg   bool selectExtract(MachineInstr &I, MachineRegisterInfo &MRI,
10506f32e7eSjoerg                      MachineFunction &MF) const;
10606f32e7eSjoerg   bool selectCondBranch(MachineInstr &I, MachineRegisterInfo &MRI,
10706f32e7eSjoerg                         MachineFunction &MF) const;
10806f32e7eSjoerg   bool selectTurnIntoCOPY(MachineInstr &I, MachineRegisterInfo &MRI,
10906f32e7eSjoerg                           const unsigned DstReg,
11006f32e7eSjoerg                           const TargetRegisterClass *DstRC,
11106f32e7eSjoerg                           const unsigned SrcReg,
11206f32e7eSjoerg                           const TargetRegisterClass *SrcRC) const;
11306f32e7eSjoerg   bool materializeFP(MachineInstr &I, MachineRegisterInfo &MRI,
11406f32e7eSjoerg                      MachineFunction &MF) const;
11506f32e7eSjoerg   bool selectImplicitDefOrPHI(MachineInstr &I, MachineRegisterInfo &MRI) const;
11606f32e7eSjoerg   bool selectDivRem(MachineInstr &I, MachineRegisterInfo &MRI,
11706f32e7eSjoerg                     MachineFunction &MF) const;
11806f32e7eSjoerg   bool selectIntrinsicWSideEffects(MachineInstr &I, MachineRegisterInfo &MRI,
11906f32e7eSjoerg                                    MachineFunction &MF) const;
12006f32e7eSjoerg 
12106f32e7eSjoerg   // emit insert subreg instruction and insert it before MachineInstr &I
12206f32e7eSjoerg   bool emitInsertSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
12306f32e7eSjoerg                         MachineRegisterInfo &MRI, MachineFunction &MF) const;
12406f32e7eSjoerg   // emit extract subreg instruction and insert it before MachineInstr &I
12506f32e7eSjoerg   bool emitExtractSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,
12606f32e7eSjoerg                          MachineRegisterInfo &MRI, MachineFunction &MF) const;
12706f32e7eSjoerg 
12806f32e7eSjoerg   const TargetRegisterClass *getRegClass(LLT Ty, const RegisterBank &RB) const;
12906f32e7eSjoerg   const TargetRegisterClass *getRegClass(LLT Ty, unsigned Reg,
13006f32e7eSjoerg                                          MachineRegisterInfo &MRI) const;
13106f32e7eSjoerg 
13206f32e7eSjoerg   const X86TargetMachine &TM;
13306f32e7eSjoerg   const X86Subtarget &STI;
13406f32e7eSjoerg   const X86InstrInfo &TII;
13506f32e7eSjoerg   const X86RegisterInfo &TRI;
13606f32e7eSjoerg   const X86RegisterBankInfo &RBI;
13706f32e7eSjoerg 
13806f32e7eSjoerg #define GET_GLOBALISEL_PREDICATES_DECL
13906f32e7eSjoerg #include "X86GenGlobalISel.inc"
14006f32e7eSjoerg #undef GET_GLOBALISEL_PREDICATES_DECL
14106f32e7eSjoerg 
14206f32e7eSjoerg #define GET_GLOBALISEL_TEMPORARIES_DECL
14306f32e7eSjoerg #include "X86GenGlobalISel.inc"
14406f32e7eSjoerg #undef GET_GLOBALISEL_TEMPORARIES_DECL
14506f32e7eSjoerg };
14606f32e7eSjoerg 
14706f32e7eSjoerg } // end anonymous namespace
14806f32e7eSjoerg 
14906f32e7eSjoerg #define GET_GLOBALISEL_IMPL
15006f32e7eSjoerg #include "X86GenGlobalISel.inc"
15106f32e7eSjoerg #undef GET_GLOBALISEL_IMPL
15206f32e7eSjoerg 
X86InstructionSelector(const X86TargetMachine & TM,const X86Subtarget & STI,const X86RegisterBankInfo & RBI)15306f32e7eSjoerg X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,
15406f32e7eSjoerg                                                const X86Subtarget &STI,
15506f32e7eSjoerg                                                const X86RegisterBankInfo &RBI)
15606f32e7eSjoerg     : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()),
15706f32e7eSjoerg       TRI(*STI.getRegisterInfo()), RBI(RBI),
15806f32e7eSjoerg #define GET_GLOBALISEL_PREDICATES_INIT
15906f32e7eSjoerg #include "X86GenGlobalISel.inc"
16006f32e7eSjoerg #undef GET_GLOBALISEL_PREDICATES_INIT
16106f32e7eSjoerg #define GET_GLOBALISEL_TEMPORARIES_INIT
16206f32e7eSjoerg #include "X86GenGlobalISel.inc"
16306f32e7eSjoerg #undef GET_GLOBALISEL_TEMPORARIES_INIT
16406f32e7eSjoerg {
16506f32e7eSjoerg }
16606f32e7eSjoerg 
16706f32e7eSjoerg // FIXME: This should be target-independent, inferred from the types declared
16806f32e7eSjoerg // for each class in the bank.
16906f32e7eSjoerg const TargetRegisterClass *
getRegClass(LLT Ty,const RegisterBank & RB) const17006f32e7eSjoerg X86InstructionSelector::getRegClass(LLT Ty, const RegisterBank &RB) const {
17106f32e7eSjoerg   if (RB.getID() == X86::GPRRegBankID) {
17206f32e7eSjoerg     if (Ty.getSizeInBits() <= 8)
17306f32e7eSjoerg       return &X86::GR8RegClass;
17406f32e7eSjoerg     if (Ty.getSizeInBits() == 16)
17506f32e7eSjoerg       return &X86::GR16RegClass;
17606f32e7eSjoerg     if (Ty.getSizeInBits() == 32)
17706f32e7eSjoerg       return &X86::GR32RegClass;
17806f32e7eSjoerg     if (Ty.getSizeInBits() == 64)
17906f32e7eSjoerg       return &X86::GR64RegClass;
18006f32e7eSjoerg   }
18106f32e7eSjoerg   if (RB.getID() == X86::VECRRegBankID) {
18206f32e7eSjoerg     if (Ty.getSizeInBits() == 32)
18306f32e7eSjoerg       return STI.hasAVX512() ? &X86::FR32XRegClass : &X86::FR32RegClass;
18406f32e7eSjoerg     if (Ty.getSizeInBits() == 64)
18506f32e7eSjoerg       return STI.hasAVX512() ? &X86::FR64XRegClass : &X86::FR64RegClass;
18606f32e7eSjoerg     if (Ty.getSizeInBits() == 128)
18706f32e7eSjoerg       return STI.hasAVX512() ? &X86::VR128XRegClass : &X86::VR128RegClass;
18806f32e7eSjoerg     if (Ty.getSizeInBits() == 256)
18906f32e7eSjoerg       return STI.hasAVX512() ? &X86::VR256XRegClass : &X86::VR256RegClass;
19006f32e7eSjoerg     if (Ty.getSizeInBits() == 512)
19106f32e7eSjoerg       return &X86::VR512RegClass;
19206f32e7eSjoerg   }
19306f32e7eSjoerg 
19406f32e7eSjoerg   llvm_unreachable("Unknown RegBank!");
19506f32e7eSjoerg }
19606f32e7eSjoerg 
19706f32e7eSjoerg const TargetRegisterClass *
getRegClass(LLT Ty,unsigned Reg,MachineRegisterInfo & MRI) const19806f32e7eSjoerg X86InstructionSelector::getRegClass(LLT Ty, unsigned Reg,
19906f32e7eSjoerg                                     MachineRegisterInfo &MRI) const {
20006f32e7eSjoerg   const RegisterBank &RegBank = *RBI.getRegBank(Reg, MRI, TRI);
20106f32e7eSjoerg   return getRegClass(Ty, RegBank);
20206f32e7eSjoerg }
20306f32e7eSjoerg 
getSubRegIndex(const TargetRegisterClass * RC)20406f32e7eSjoerg static unsigned getSubRegIndex(const TargetRegisterClass *RC) {
20506f32e7eSjoerg   unsigned SubIdx = X86::NoSubRegister;
20606f32e7eSjoerg   if (RC == &X86::GR32RegClass) {
20706f32e7eSjoerg     SubIdx = X86::sub_32bit;
20806f32e7eSjoerg   } else if (RC == &X86::GR16RegClass) {
20906f32e7eSjoerg     SubIdx = X86::sub_16bit;
21006f32e7eSjoerg   } else if (RC == &X86::GR8RegClass) {
21106f32e7eSjoerg     SubIdx = X86::sub_8bit;
21206f32e7eSjoerg   }
21306f32e7eSjoerg 
21406f32e7eSjoerg   return SubIdx;
21506f32e7eSjoerg }
21606f32e7eSjoerg 
getRegClassFromGRPhysReg(Register Reg)217*da58b97aSjoerg static const TargetRegisterClass *getRegClassFromGRPhysReg(Register Reg) {
218*da58b97aSjoerg   assert(Reg.isPhysical());
21906f32e7eSjoerg   if (X86::GR64RegClass.contains(Reg))
22006f32e7eSjoerg     return &X86::GR64RegClass;
22106f32e7eSjoerg   if (X86::GR32RegClass.contains(Reg))
22206f32e7eSjoerg     return &X86::GR32RegClass;
22306f32e7eSjoerg   if (X86::GR16RegClass.contains(Reg))
22406f32e7eSjoerg     return &X86::GR16RegClass;
22506f32e7eSjoerg   if (X86::GR8RegClass.contains(Reg))
22606f32e7eSjoerg     return &X86::GR8RegClass;
22706f32e7eSjoerg 
22806f32e7eSjoerg   llvm_unreachable("Unknown RegClass for PhysReg!");
22906f32e7eSjoerg }
23006f32e7eSjoerg 
23106f32e7eSjoerg // Set X86 Opcode and constrain DestReg.
selectCopy(MachineInstr & I,MachineRegisterInfo & MRI) const23206f32e7eSjoerg bool X86InstructionSelector::selectCopy(MachineInstr &I,
23306f32e7eSjoerg                                         MachineRegisterInfo &MRI) const {
23406f32e7eSjoerg   Register DstReg = I.getOperand(0).getReg();
23506f32e7eSjoerg   const unsigned DstSize = RBI.getSizeInBits(DstReg, MRI, TRI);
23606f32e7eSjoerg   const RegisterBank &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);
23706f32e7eSjoerg 
23806f32e7eSjoerg   Register SrcReg = I.getOperand(1).getReg();
23906f32e7eSjoerg   const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);
24006f32e7eSjoerg   const RegisterBank &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);
24106f32e7eSjoerg 
242*da58b97aSjoerg   if (DstReg.isPhysical()) {
24306f32e7eSjoerg     assert(I.isCopy() && "Generic operators do not allow physical registers");
24406f32e7eSjoerg 
24506f32e7eSjoerg     if (DstSize > SrcSize && SrcRegBank.getID() == X86::GPRRegBankID &&
24606f32e7eSjoerg         DstRegBank.getID() == X86::GPRRegBankID) {
24706f32e7eSjoerg 
24806f32e7eSjoerg       const TargetRegisterClass *SrcRC =
24906f32e7eSjoerg           getRegClass(MRI.getType(SrcReg), SrcRegBank);
25006f32e7eSjoerg       const TargetRegisterClass *DstRC = getRegClassFromGRPhysReg(DstReg);
25106f32e7eSjoerg 
25206f32e7eSjoerg       if (SrcRC != DstRC) {
25306f32e7eSjoerg         // This case can be generated by ABI lowering, performe anyext
25406f32e7eSjoerg         Register ExtSrc = MRI.createVirtualRegister(DstRC);
25506f32e7eSjoerg         BuildMI(*I.getParent(), I, I.getDebugLoc(),
25606f32e7eSjoerg                 TII.get(TargetOpcode::SUBREG_TO_REG))
25706f32e7eSjoerg             .addDef(ExtSrc)
25806f32e7eSjoerg             .addImm(0)
25906f32e7eSjoerg             .addReg(SrcReg)
26006f32e7eSjoerg             .addImm(getSubRegIndex(SrcRC));
26106f32e7eSjoerg 
26206f32e7eSjoerg         I.getOperand(1).setReg(ExtSrc);
26306f32e7eSjoerg       }
26406f32e7eSjoerg     }
26506f32e7eSjoerg 
26606f32e7eSjoerg     return true;
26706f32e7eSjoerg   }
26806f32e7eSjoerg 
269*da58b97aSjoerg   assert((!SrcReg.isPhysical() || I.isCopy()) &&
27006f32e7eSjoerg          "No phys reg on generic operators");
27106f32e7eSjoerg   assert((DstSize == SrcSize ||
27206f32e7eSjoerg           // Copies are a mean to setup initial types, the number of
27306f32e7eSjoerg           // bits may not exactly match.
274*da58b97aSjoerg           (SrcReg.isPhysical() &&
27506f32e7eSjoerg            DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&
27606f32e7eSjoerg          "Copy with different width?!");
27706f32e7eSjoerg 
27806f32e7eSjoerg   const TargetRegisterClass *DstRC =
27906f32e7eSjoerg       getRegClass(MRI.getType(DstReg), DstRegBank);
28006f32e7eSjoerg 
28106f32e7eSjoerg   if (SrcRegBank.getID() == X86::GPRRegBankID &&
28206f32e7eSjoerg       DstRegBank.getID() == X86::GPRRegBankID && SrcSize > DstSize &&
283*da58b97aSjoerg       SrcReg.isPhysical()) {
28406f32e7eSjoerg     // Change the physical register to performe truncate.
28506f32e7eSjoerg 
28606f32e7eSjoerg     const TargetRegisterClass *SrcRC = getRegClassFromGRPhysReg(SrcReg);
28706f32e7eSjoerg 
28806f32e7eSjoerg     if (DstRC != SrcRC) {
28906f32e7eSjoerg       I.getOperand(1).setSubReg(getSubRegIndex(DstRC));
29006f32e7eSjoerg       I.getOperand(1).substPhysReg(SrcReg, TRI);
29106f32e7eSjoerg     }
29206f32e7eSjoerg   }
29306f32e7eSjoerg 
29406f32e7eSjoerg   // No need to constrain SrcReg. It will get constrained when
29506f32e7eSjoerg   // we hit another of its use or its defs.
29606f32e7eSjoerg   // Copies do not have constraints.
29706f32e7eSjoerg   const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);
29806f32e7eSjoerg   if (!OldRC || !DstRC->hasSubClassEq(OldRC)) {
29906f32e7eSjoerg     if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
30006f32e7eSjoerg       LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
30106f32e7eSjoerg                         << " operand\n");
30206f32e7eSjoerg       return false;
30306f32e7eSjoerg     }
30406f32e7eSjoerg   }
30506f32e7eSjoerg   I.setDesc(TII.get(X86::COPY));
30606f32e7eSjoerg   return true;
30706f32e7eSjoerg }
30806f32e7eSjoerg 
select(MachineInstr & I)30906f32e7eSjoerg bool X86InstructionSelector::select(MachineInstr &I) {
31006f32e7eSjoerg   assert(I.getParent() && "Instruction should be in a basic block!");
31106f32e7eSjoerg   assert(I.getParent()->getParent() && "Instruction should be in a function!");
31206f32e7eSjoerg 
31306f32e7eSjoerg   MachineBasicBlock &MBB = *I.getParent();
31406f32e7eSjoerg   MachineFunction &MF = *MBB.getParent();
31506f32e7eSjoerg   MachineRegisterInfo &MRI = MF.getRegInfo();
31606f32e7eSjoerg 
31706f32e7eSjoerg   unsigned Opcode = I.getOpcode();
31806f32e7eSjoerg   if (!isPreISelGenericOpcode(Opcode)) {
31906f32e7eSjoerg     // Certain non-generic instructions also need some special handling.
32006f32e7eSjoerg 
32106f32e7eSjoerg     if (Opcode == TargetOpcode::LOAD_STACK_GUARD)
32206f32e7eSjoerg       return false;
32306f32e7eSjoerg 
32406f32e7eSjoerg     if (I.isCopy())
32506f32e7eSjoerg       return selectCopy(I, MRI);
32606f32e7eSjoerg 
32706f32e7eSjoerg     return true;
32806f32e7eSjoerg   }
32906f32e7eSjoerg 
33006f32e7eSjoerg   assert(I.getNumOperands() == I.getNumExplicitOperands() &&
33106f32e7eSjoerg          "Generic instruction has unexpected implicit operands\n");
33206f32e7eSjoerg 
33306f32e7eSjoerg   if (selectImpl(I, *CoverageInfo))
33406f32e7eSjoerg     return true;
33506f32e7eSjoerg 
33606f32e7eSjoerg   LLVM_DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));
33706f32e7eSjoerg 
33806f32e7eSjoerg   // TODO: This should be implemented by tblgen.
33906f32e7eSjoerg   switch (I.getOpcode()) {
34006f32e7eSjoerg   default:
34106f32e7eSjoerg     return false;
34206f32e7eSjoerg   case TargetOpcode::G_STORE:
34306f32e7eSjoerg   case TargetOpcode::G_LOAD:
34406f32e7eSjoerg     return selectLoadStoreOp(I, MRI, MF);
345*da58b97aSjoerg   case TargetOpcode::G_PTR_ADD:
34606f32e7eSjoerg   case TargetOpcode::G_FRAME_INDEX:
34706f32e7eSjoerg     return selectFrameIndexOrGep(I, MRI, MF);
34806f32e7eSjoerg   case TargetOpcode::G_GLOBAL_VALUE:
34906f32e7eSjoerg     return selectGlobalValue(I, MRI, MF);
35006f32e7eSjoerg   case TargetOpcode::G_CONSTANT:
35106f32e7eSjoerg     return selectConstant(I, MRI, MF);
35206f32e7eSjoerg   case TargetOpcode::G_FCONSTANT:
35306f32e7eSjoerg     return materializeFP(I, MRI, MF);
35406f32e7eSjoerg   case TargetOpcode::G_PTRTOINT:
35506f32e7eSjoerg   case TargetOpcode::G_TRUNC:
35606f32e7eSjoerg     return selectTruncOrPtrToInt(I, MRI, MF);
35706f32e7eSjoerg   case TargetOpcode::G_INTTOPTR:
35806f32e7eSjoerg     return selectCopy(I, MRI);
35906f32e7eSjoerg   case TargetOpcode::G_ZEXT:
36006f32e7eSjoerg     return selectZext(I, MRI, MF);
36106f32e7eSjoerg   case TargetOpcode::G_ANYEXT:
36206f32e7eSjoerg     return selectAnyext(I, MRI, MF);
36306f32e7eSjoerg   case TargetOpcode::G_ICMP:
36406f32e7eSjoerg     return selectCmp(I, MRI, MF);
36506f32e7eSjoerg   case TargetOpcode::G_FCMP:
36606f32e7eSjoerg     return selectFCmp(I, MRI, MF);
36706f32e7eSjoerg   case TargetOpcode::G_UADDE:
36806f32e7eSjoerg     return selectUadde(I, MRI, MF);
36906f32e7eSjoerg   case TargetOpcode::G_UNMERGE_VALUES:
37006f32e7eSjoerg     return selectUnmergeValues(I, MRI, MF);
37106f32e7eSjoerg   case TargetOpcode::G_MERGE_VALUES:
37206f32e7eSjoerg   case TargetOpcode::G_CONCAT_VECTORS:
37306f32e7eSjoerg     return selectMergeValues(I, MRI, MF);
37406f32e7eSjoerg   case TargetOpcode::G_EXTRACT:
37506f32e7eSjoerg     return selectExtract(I, MRI, MF);
37606f32e7eSjoerg   case TargetOpcode::G_INSERT:
37706f32e7eSjoerg     return selectInsert(I, MRI, MF);
37806f32e7eSjoerg   case TargetOpcode::G_BRCOND:
37906f32e7eSjoerg     return selectCondBranch(I, MRI, MF);
38006f32e7eSjoerg   case TargetOpcode::G_IMPLICIT_DEF:
38106f32e7eSjoerg   case TargetOpcode::G_PHI:
38206f32e7eSjoerg     return selectImplicitDefOrPHI(I, MRI);
38306f32e7eSjoerg   case TargetOpcode::G_SDIV:
38406f32e7eSjoerg   case TargetOpcode::G_UDIV:
38506f32e7eSjoerg   case TargetOpcode::G_SREM:
38606f32e7eSjoerg   case TargetOpcode::G_UREM:
38706f32e7eSjoerg     return selectDivRem(I, MRI, MF);
38806f32e7eSjoerg   case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
38906f32e7eSjoerg     return selectIntrinsicWSideEffects(I, MRI, MF);
39006f32e7eSjoerg   }
39106f32e7eSjoerg 
39206f32e7eSjoerg   return false;
39306f32e7eSjoerg }
39406f32e7eSjoerg 
getLoadStoreOp(const LLT & Ty,const RegisterBank & RB,unsigned Opc,Align Alignment) const39506f32e7eSjoerg unsigned X86InstructionSelector::getLoadStoreOp(const LLT &Ty,
39606f32e7eSjoerg                                                 const RegisterBank &RB,
39706f32e7eSjoerg                                                 unsigned Opc,
398*da58b97aSjoerg                                                 Align Alignment) const {
39906f32e7eSjoerg   bool Isload = (Opc == TargetOpcode::G_LOAD);
40006f32e7eSjoerg   bool HasAVX = STI.hasAVX();
40106f32e7eSjoerg   bool HasAVX512 = STI.hasAVX512();
40206f32e7eSjoerg   bool HasVLX = STI.hasVLX();
40306f32e7eSjoerg 
40406f32e7eSjoerg   if (Ty == LLT::scalar(8)) {
40506f32e7eSjoerg     if (X86::GPRRegBankID == RB.getID())
40606f32e7eSjoerg       return Isload ? X86::MOV8rm : X86::MOV8mr;
40706f32e7eSjoerg   } else if (Ty == LLT::scalar(16)) {
40806f32e7eSjoerg     if (X86::GPRRegBankID == RB.getID())
40906f32e7eSjoerg       return Isload ? X86::MOV16rm : X86::MOV16mr;
41006f32e7eSjoerg   } else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {
41106f32e7eSjoerg     if (X86::GPRRegBankID == RB.getID())
41206f32e7eSjoerg       return Isload ? X86::MOV32rm : X86::MOV32mr;
41306f32e7eSjoerg     if (X86::VECRRegBankID == RB.getID())
41406f32e7eSjoerg       return Isload ? (HasAVX512 ? X86::VMOVSSZrm_alt :
41506f32e7eSjoerg                        HasAVX    ? X86::VMOVSSrm_alt :
41606f32e7eSjoerg                                    X86::MOVSSrm_alt)
41706f32e7eSjoerg                     : (HasAVX512 ? X86::VMOVSSZmr :
41806f32e7eSjoerg                        HasAVX    ? X86::VMOVSSmr :
41906f32e7eSjoerg                                    X86::MOVSSmr);
42006f32e7eSjoerg   } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
42106f32e7eSjoerg     if (X86::GPRRegBankID == RB.getID())
42206f32e7eSjoerg       return Isload ? X86::MOV64rm : X86::MOV64mr;
42306f32e7eSjoerg     if (X86::VECRRegBankID == RB.getID())
42406f32e7eSjoerg       return Isload ? (HasAVX512 ? X86::VMOVSDZrm_alt :
42506f32e7eSjoerg                        HasAVX    ? X86::VMOVSDrm_alt :
42606f32e7eSjoerg                                    X86::MOVSDrm_alt)
42706f32e7eSjoerg                     : (HasAVX512 ? X86::VMOVSDZmr :
42806f32e7eSjoerg                        HasAVX    ? X86::VMOVSDmr :
42906f32e7eSjoerg                                    X86::MOVSDmr);
43006f32e7eSjoerg   } else if (Ty.isVector() && Ty.getSizeInBits() == 128) {
431*da58b97aSjoerg     if (Alignment >= Align(16))
43206f32e7eSjoerg       return Isload ? (HasVLX ? X86::VMOVAPSZ128rm
43306f32e7eSjoerg                               : HasAVX512
43406f32e7eSjoerg                                     ? X86::VMOVAPSZ128rm_NOVLX
43506f32e7eSjoerg                                     : HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)
43606f32e7eSjoerg                     : (HasVLX ? X86::VMOVAPSZ128mr
43706f32e7eSjoerg                               : HasAVX512
43806f32e7eSjoerg                                     ? X86::VMOVAPSZ128mr_NOVLX
43906f32e7eSjoerg                                     : HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);
44006f32e7eSjoerg     else
44106f32e7eSjoerg       return Isload ? (HasVLX ? X86::VMOVUPSZ128rm
44206f32e7eSjoerg                               : HasAVX512
44306f32e7eSjoerg                                     ? X86::VMOVUPSZ128rm_NOVLX
44406f32e7eSjoerg                                     : HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)
44506f32e7eSjoerg                     : (HasVLX ? X86::VMOVUPSZ128mr
44606f32e7eSjoerg                               : HasAVX512
44706f32e7eSjoerg                                     ? X86::VMOVUPSZ128mr_NOVLX
44806f32e7eSjoerg                                     : HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);
44906f32e7eSjoerg   } else if (Ty.isVector() && Ty.getSizeInBits() == 256) {
450*da58b97aSjoerg     if (Alignment >= Align(32))
45106f32e7eSjoerg       return Isload ? (HasVLX ? X86::VMOVAPSZ256rm
45206f32e7eSjoerg                               : HasAVX512 ? X86::VMOVAPSZ256rm_NOVLX
45306f32e7eSjoerg                                           : X86::VMOVAPSYrm)
45406f32e7eSjoerg                     : (HasVLX ? X86::VMOVAPSZ256mr
45506f32e7eSjoerg                               : HasAVX512 ? X86::VMOVAPSZ256mr_NOVLX
45606f32e7eSjoerg                                           : X86::VMOVAPSYmr);
45706f32e7eSjoerg     else
45806f32e7eSjoerg       return Isload ? (HasVLX ? X86::VMOVUPSZ256rm
45906f32e7eSjoerg                               : HasAVX512 ? X86::VMOVUPSZ256rm_NOVLX
46006f32e7eSjoerg                                           : X86::VMOVUPSYrm)
46106f32e7eSjoerg                     : (HasVLX ? X86::VMOVUPSZ256mr
46206f32e7eSjoerg                               : HasAVX512 ? X86::VMOVUPSZ256mr_NOVLX
46306f32e7eSjoerg                                           : X86::VMOVUPSYmr);
46406f32e7eSjoerg   } else if (Ty.isVector() && Ty.getSizeInBits() == 512) {
465*da58b97aSjoerg     if (Alignment >= Align(64))
46606f32e7eSjoerg       return Isload ? X86::VMOVAPSZrm : X86::VMOVAPSZmr;
46706f32e7eSjoerg     else
46806f32e7eSjoerg       return Isload ? X86::VMOVUPSZrm : X86::VMOVUPSZmr;
46906f32e7eSjoerg   }
47006f32e7eSjoerg   return Opc;
47106f32e7eSjoerg }
47206f32e7eSjoerg 
47306f32e7eSjoerg // Fill in an address from the given instruction.
X86SelectAddress(const MachineInstr & I,const MachineRegisterInfo & MRI,X86AddressMode & AM)47406f32e7eSjoerg static void X86SelectAddress(const MachineInstr &I,
47506f32e7eSjoerg                              const MachineRegisterInfo &MRI,
47606f32e7eSjoerg                              X86AddressMode &AM) {
47706f32e7eSjoerg   assert(I.getOperand(0).isReg() && "unsupported opperand.");
47806f32e7eSjoerg   assert(MRI.getType(I.getOperand(0).getReg()).isPointer() &&
47906f32e7eSjoerg          "unsupported type.");
48006f32e7eSjoerg 
481*da58b97aSjoerg   if (I.getOpcode() == TargetOpcode::G_PTR_ADD) {
482*da58b97aSjoerg     if (auto COff = getConstantVRegSExtVal(I.getOperand(2).getReg(), MRI)) {
48306f32e7eSjoerg       int64_t Imm = *COff;
48406f32e7eSjoerg       if (isInt<32>(Imm)) { // Check for displacement overflow.
48506f32e7eSjoerg         AM.Disp = static_cast<int32_t>(Imm);
48606f32e7eSjoerg         AM.Base.Reg = I.getOperand(1).getReg();
48706f32e7eSjoerg         return;
48806f32e7eSjoerg       }
48906f32e7eSjoerg     }
49006f32e7eSjoerg   } else if (I.getOpcode() == TargetOpcode::G_FRAME_INDEX) {
49106f32e7eSjoerg     AM.Base.FrameIndex = I.getOperand(1).getIndex();
49206f32e7eSjoerg     AM.BaseType = X86AddressMode::FrameIndexBase;
49306f32e7eSjoerg     return;
49406f32e7eSjoerg   }
49506f32e7eSjoerg 
49606f32e7eSjoerg   // Default behavior.
49706f32e7eSjoerg   AM.Base.Reg = I.getOperand(0).getReg();
49806f32e7eSjoerg }
49906f32e7eSjoerg 
selectLoadStoreOp(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const50006f32e7eSjoerg bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,
50106f32e7eSjoerg                                                MachineRegisterInfo &MRI,
50206f32e7eSjoerg                                                MachineFunction &MF) const {
50306f32e7eSjoerg   unsigned Opc = I.getOpcode();
50406f32e7eSjoerg 
50506f32e7eSjoerg   assert((Opc == TargetOpcode::G_STORE || Opc == TargetOpcode::G_LOAD) &&
50606f32e7eSjoerg          "unexpected instruction");
50706f32e7eSjoerg 
50806f32e7eSjoerg   const Register DefReg = I.getOperand(0).getReg();
50906f32e7eSjoerg   LLT Ty = MRI.getType(DefReg);
51006f32e7eSjoerg   const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);
51106f32e7eSjoerg 
51206f32e7eSjoerg   assert(I.hasOneMemOperand());
51306f32e7eSjoerg   auto &MemOp = **I.memoperands_begin();
51406f32e7eSjoerg   if (MemOp.isAtomic()) {
51506f32e7eSjoerg     // Note: for unordered operations, we rely on the fact the appropriate MMO
51606f32e7eSjoerg     // is already on the instruction we're mutating, and thus we don't need to
51706f32e7eSjoerg     // make any changes.  So long as we select an opcode which is capable of
51806f32e7eSjoerg     // loading or storing the appropriate size atomically, the rest of the
51906f32e7eSjoerg     // backend is required to respect the MMO state.
52006f32e7eSjoerg     if (!MemOp.isUnordered()) {
52106f32e7eSjoerg       LLVM_DEBUG(dbgs() << "Atomic ordering not supported yet\n");
52206f32e7eSjoerg       return false;
52306f32e7eSjoerg     }
524*da58b97aSjoerg     if (MemOp.getAlign() < Ty.getSizeInBits() / 8) {
52506f32e7eSjoerg       LLVM_DEBUG(dbgs() << "Unaligned atomics not supported yet\n");
52606f32e7eSjoerg       return false;
52706f32e7eSjoerg     }
52806f32e7eSjoerg   }
52906f32e7eSjoerg 
530*da58b97aSjoerg   unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlign());
53106f32e7eSjoerg   if (NewOpc == Opc)
53206f32e7eSjoerg     return false;
53306f32e7eSjoerg 
53406f32e7eSjoerg   X86AddressMode AM;
53506f32e7eSjoerg   X86SelectAddress(*MRI.getVRegDef(I.getOperand(1).getReg()), MRI, AM);
53606f32e7eSjoerg 
53706f32e7eSjoerg   I.setDesc(TII.get(NewOpc));
53806f32e7eSjoerg   MachineInstrBuilder MIB(MF, I);
53906f32e7eSjoerg   if (Opc == TargetOpcode::G_LOAD) {
54006f32e7eSjoerg     I.RemoveOperand(1);
54106f32e7eSjoerg     addFullAddress(MIB, AM);
54206f32e7eSjoerg   } else {
54306f32e7eSjoerg     // G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)
54406f32e7eSjoerg     I.RemoveOperand(1);
54506f32e7eSjoerg     I.RemoveOperand(0);
54606f32e7eSjoerg     addFullAddress(MIB, AM).addUse(DefReg);
54706f32e7eSjoerg   }
54806f32e7eSjoerg   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
54906f32e7eSjoerg }
55006f32e7eSjoerg 
getLeaOP(LLT Ty,const X86Subtarget & STI)55106f32e7eSjoerg static unsigned getLeaOP(LLT Ty, const X86Subtarget &STI) {
55206f32e7eSjoerg   if (Ty == LLT::pointer(0, 64))
55306f32e7eSjoerg     return X86::LEA64r;
55406f32e7eSjoerg   else if (Ty == LLT::pointer(0, 32))
55506f32e7eSjoerg     return STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;
55606f32e7eSjoerg   else
55706f32e7eSjoerg     llvm_unreachable("Can't get LEA opcode. Unsupported type.");
55806f32e7eSjoerg }
55906f32e7eSjoerg 
selectFrameIndexOrGep(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const56006f32e7eSjoerg bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I,
56106f32e7eSjoerg                                                    MachineRegisterInfo &MRI,
56206f32e7eSjoerg                                                    MachineFunction &MF) const {
56306f32e7eSjoerg   unsigned Opc = I.getOpcode();
56406f32e7eSjoerg 
565*da58b97aSjoerg   assert((Opc == TargetOpcode::G_FRAME_INDEX || Opc == TargetOpcode::G_PTR_ADD) &&
56606f32e7eSjoerg          "unexpected instruction");
56706f32e7eSjoerg 
56806f32e7eSjoerg   const Register DefReg = I.getOperand(0).getReg();
56906f32e7eSjoerg   LLT Ty = MRI.getType(DefReg);
57006f32e7eSjoerg 
57106f32e7eSjoerg   // Use LEA to calculate frame index and GEP
57206f32e7eSjoerg   unsigned NewOpc = getLeaOP(Ty, STI);
57306f32e7eSjoerg   I.setDesc(TII.get(NewOpc));
57406f32e7eSjoerg   MachineInstrBuilder MIB(MF, I);
57506f32e7eSjoerg 
57606f32e7eSjoerg   if (Opc == TargetOpcode::G_FRAME_INDEX) {
57706f32e7eSjoerg     addOffset(MIB, 0);
57806f32e7eSjoerg   } else {
57906f32e7eSjoerg     MachineOperand &InxOp = I.getOperand(2);
58006f32e7eSjoerg     I.addOperand(InxOp);        // set IndexReg
58106f32e7eSjoerg     InxOp.ChangeToImmediate(1); // set Scale
58206f32e7eSjoerg     MIB.addImm(0).addReg(0);
58306f32e7eSjoerg   }
58406f32e7eSjoerg 
58506f32e7eSjoerg   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
58606f32e7eSjoerg }
58706f32e7eSjoerg 
selectGlobalValue(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const58806f32e7eSjoerg bool X86InstructionSelector::selectGlobalValue(MachineInstr &I,
58906f32e7eSjoerg                                                MachineRegisterInfo &MRI,
59006f32e7eSjoerg                                                MachineFunction &MF) const {
59106f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE) &&
59206f32e7eSjoerg          "unexpected instruction");
59306f32e7eSjoerg 
59406f32e7eSjoerg   auto GV = I.getOperand(1).getGlobal();
59506f32e7eSjoerg   if (GV->isThreadLocal()) {
59606f32e7eSjoerg     return false; // TODO: we don't support TLS yet.
59706f32e7eSjoerg   }
59806f32e7eSjoerg 
59906f32e7eSjoerg   // Can't handle alternate code models yet.
60006f32e7eSjoerg   if (TM.getCodeModel() != CodeModel::Small)
60106f32e7eSjoerg     return false;
60206f32e7eSjoerg 
60306f32e7eSjoerg   X86AddressMode AM;
60406f32e7eSjoerg   AM.GV = GV;
60506f32e7eSjoerg   AM.GVOpFlags = STI.classifyGlobalReference(GV);
60606f32e7eSjoerg 
60706f32e7eSjoerg   // TODO: The ABI requires an extra load. not supported yet.
60806f32e7eSjoerg   if (isGlobalStubReference(AM.GVOpFlags))
60906f32e7eSjoerg     return false;
61006f32e7eSjoerg 
61106f32e7eSjoerg   // TODO: This reference is relative to the pic base. not supported yet.
61206f32e7eSjoerg   if (isGlobalRelativeToPICBase(AM.GVOpFlags))
61306f32e7eSjoerg     return false;
61406f32e7eSjoerg 
61506f32e7eSjoerg   if (STI.isPICStyleRIPRel()) {
61606f32e7eSjoerg     // Use rip-relative addressing.
61706f32e7eSjoerg     assert(AM.Base.Reg == 0 && AM.IndexReg == 0);
61806f32e7eSjoerg     AM.Base.Reg = X86::RIP;
61906f32e7eSjoerg   }
62006f32e7eSjoerg 
62106f32e7eSjoerg   const Register DefReg = I.getOperand(0).getReg();
62206f32e7eSjoerg   LLT Ty = MRI.getType(DefReg);
62306f32e7eSjoerg   unsigned NewOpc = getLeaOP(Ty, STI);
62406f32e7eSjoerg 
62506f32e7eSjoerg   I.setDesc(TII.get(NewOpc));
62606f32e7eSjoerg   MachineInstrBuilder MIB(MF, I);
62706f32e7eSjoerg 
62806f32e7eSjoerg   I.RemoveOperand(1);
62906f32e7eSjoerg   addFullAddress(MIB, AM);
63006f32e7eSjoerg 
63106f32e7eSjoerg   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
63206f32e7eSjoerg }
63306f32e7eSjoerg 
selectConstant(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const63406f32e7eSjoerg bool X86InstructionSelector::selectConstant(MachineInstr &I,
63506f32e7eSjoerg                                             MachineRegisterInfo &MRI,
63606f32e7eSjoerg                                             MachineFunction &MF) const {
63706f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_CONSTANT) &&
63806f32e7eSjoerg          "unexpected instruction");
63906f32e7eSjoerg 
64006f32e7eSjoerg   const Register DefReg = I.getOperand(0).getReg();
64106f32e7eSjoerg   LLT Ty = MRI.getType(DefReg);
64206f32e7eSjoerg 
64306f32e7eSjoerg   if (RBI.getRegBank(DefReg, MRI, TRI)->getID() != X86::GPRRegBankID)
64406f32e7eSjoerg     return false;
64506f32e7eSjoerg 
64606f32e7eSjoerg   uint64_t Val = 0;
64706f32e7eSjoerg   if (I.getOperand(1).isCImm()) {
64806f32e7eSjoerg     Val = I.getOperand(1).getCImm()->getZExtValue();
64906f32e7eSjoerg     I.getOperand(1).ChangeToImmediate(Val);
65006f32e7eSjoerg   } else if (I.getOperand(1).isImm()) {
65106f32e7eSjoerg     Val = I.getOperand(1).getImm();
65206f32e7eSjoerg   } else
65306f32e7eSjoerg     llvm_unreachable("Unsupported operand type.");
65406f32e7eSjoerg 
65506f32e7eSjoerg   unsigned NewOpc;
65606f32e7eSjoerg   switch (Ty.getSizeInBits()) {
65706f32e7eSjoerg   case 8:
65806f32e7eSjoerg     NewOpc = X86::MOV8ri;
65906f32e7eSjoerg     break;
66006f32e7eSjoerg   case 16:
66106f32e7eSjoerg     NewOpc = X86::MOV16ri;
66206f32e7eSjoerg     break;
66306f32e7eSjoerg   case 32:
66406f32e7eSjoerg     NewOpc = X86::MOV32ri;
66506f32e7eSjoerg     break;
66606f32e7eSjoerg   case 64:
66706f32e7eSjoerg     // TODO: in case isUInt<32>(Val), X86::MOV32ri can be used
66806f32e7eSjoerg     if (isInt<32>(Val))
66906f32e7eSjoerg       NewOpc = X86::MOV64ri32;
67006f32e7eSjoerg     else
67106f32e7eSjoerg       NewOpc = X86::MOV64ri;
67206f32e7eSjoerg     break;
67306f32e7eSjoerg   default:
67406f32e7eSjoerg     llvm_unreachable("Can't select G_CONSTANT, unsupported type.");
67506f32e7eSjoerg   }
67606f32e7eSjoerg 
67706f32e7eSjoerg   I.setDesc(TII.get(NewOpc));
67806f32e7eSjoerg   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
67906f32e7eSjoerg }
68006f32e7eSjoerg 
68106f32e7eSjoerg // Helper function for selectTruncOrPtrToInt and selectAnyext.
68206f32e7eSjoerg // Returns true if DstRC lives on a floating register class and
68306f32e7eSjoerg // SrcRC lives on a 128-bit vector class.
canTurnIntoCOPY(const TargetRegisterClass * DstRC,const TargetRegisterClass * SrcRC)68406f32e7eSjoerg static bool canTurnIntoCOPY(const TargetRegisterClass *DstRC,
68506f32e7eSjoerg                             const TargetRegisterClass *SrcRC) {
68606f32e7eSjoerg   return (DstRC == &X86::FR32RegClass || DstRC == &X86::FR32XRegClass ||
68706f32e7eSjoerg           DstRC == &X86::FR64RegClass || DstRC == &X86::FR64XRegClass) &&
68806f32e7eSjoerg          (SrcRC == &X86::VR128RegClass || SrcRC == &X86::VR128XRegClass);
68906f32e7eSjoerg }
69006f32e7eSjoerg 
selectTurnIntoCOPY(MachineInstr & I,MachineRegisterInfo & MRI,const unsigned DstReg,const TargetRegisterClass * DstRC,const unsigned SrcReg,const TargetRegisterClass * SrcRC) const69106f32e7eSjoerg bool X86InstructionSelector::selectTurnIntoCOPY(
69206f32e7eSjoerg     MachineInstr &I, MachineRegisterInfo &MRI, const unsigned DstReg,
69306f32e7eSjoerg     const TargetRegisterClass *DstRC, const unsigned SrcReg,
69406f32e7eSjoerg     const TargetRegisterClass *SrcRC) const {
69506f32e7eSjoerg 
69606f32e7eSjoerg   if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
69706f32e7eSjoerg       !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
69806f32e7eSjoerg     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
69906f32e7eSjoerg                       << " operand\n");
70006f32e7eSjoerg     return false;
70106f32e7eSjoerg   }
70206f32e7eSjoerg   I.setDesc(TII.get(X86::COPY));
70306f32e7eSjoerg   return true;
70406f32e7eSjoerg }
70506f32e7eSjoerg 
selectTruncOrPtrToInt(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const70606f32e7eSjoerg bool X86InstructionSelector::selectTruncOrPtrToInt(MachineInstr &I,
70706f32e7eSjoerg                                                    MachineRegisterInfo &MRI,
70806f32e7eSjoerg                                                    MachineFunction &MF) const {
70906f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_TRUNC ||
71006f32e7eSjoerg           I.getOpcode() == TargetOpcode::G_PTRTOINT) &&
71106f32e7eSjoerg          "unexpected instruction");
71206f32e7eSjoerg 
71306f32e7eSjoerg   const Register DstReg = I.getOperand(0).getReg();
71406f32e7eSjoerg   const Register SrcReg = I.getOperand(1).getReg();
71506f32e7eSjoerg 
71606f32e7eSjoerg   const LLT DstTy = MRI.getType(DstReg);
71706f32e7eSjoerg   const LLT SrcTy = MRI.getType(SrcReg);
71806f32e7eSjoerg 
71906f32e7eSjoerg   const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
72006f32e7eSjoerg   const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
72106f32e7eSjoerg 
72206f32e7eSjoerg   if (DstRB.getID() != SrcRB.getID()) {
72306f32e7eSjoerg     LLVM_DEBUG(dbgs() << TII.getName(I.getOpcode())
72406f32e7eSjoerg                       << " input/output on different banks\n");
72506f32e7eSjoerg     return false;
72606f32e7eSjoerg   }
72706f32e7eSjoerg 
72806f32e7eSjoerg   const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
72906f32e7eSjoerg   const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);
73006f32e7eSjoerg 
73106f32e7eSjoerg   if (!DstRC || !SrcRC)
73206f32e7eSjoerg     return false;
73306f32e7eSjoerg 
73406f32e7eSjoerg   // If that's truncation of the value that lives on the vector class and goes
73506f32e7eSjoerg   // into the floating class, just replace it with copy, as we are able to
73606f32e7eSjoerg   // select it as a regular move.
73706f32e7eSjoerg   if (canTurnIntoCOPY(DstRC, SrcRC))
73806f32e7eSjoerg     return selectTurnIntoCOPY(I, MRI, DstReg, DstRC, SrcReg, SrcRC);
73906f32e7eSjoerg 
74006f32e7eSjoerg   if (DstRB.getID() != X86::GPRRegBankID)
74106f32e7eSjoerg     return false;
74206f32e7eSjoerg 
74306f32e7eSjoerg   unsigned SubIdx;
74406f32e7eSjoerg   if (DstRC == SrcRC) {
74506f32e7eSjoerg     // Nothing to be done
74606f32e7eSjoerg     SubIdx = X86::NoSubRegister;
74706f32e7eSjoerg   } else if (DstRC == &X86::GR32RegClass) {
74806f32e7eSjoerg     SubIdx = X86::sub_32bit;
74906f32e7eSjoerg   } else if (DstRC == &X86::GR16RegClass) {
75006f32e7eSjoerg     SubIdx = X86::sub_16bit;
75106f32e7eSjoerg   } else if (DstRC == &X86::GR8RegClass) {
75206f32e7eSjoerg     SubIdx = X86::sub_8bit;
75306f32e7eSjoerg   } else {
75406f32e7eSjoerg     return false;
75506f32e7eSjoerg   }
75606f32e7eSjoerg 
75706f32e7eSjoerg   SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
75806f32e7eSjoerg 
75906f32e7eSjoerg   if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
76006f32e7eSjoerg       !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
76106f32e7eSjoerg     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
76206f32e7eSjoerg                       << "\n");
76306f32e7eSjoerg     return false;
76406f32e7eSjoerg   }
76506f32e7eSjoerg 
76606f32e7eSjoerg   I.getOperand(1).setSubReg(SubIdx);
76706f32e7eSjoerg 
76806f32e7eSjoerg   I.setDesc(TII.get(X86::COPY));
76906f32e7eSjoerg   return true;
77006f32e7eSjoerg }
77106f32e7eSjoerg 
selectZext(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const77206f32e7eSjoerg bool X86InstructionSelector::selectZext(MachineInstr &I,
77306f32e7eSjoerg                                         MachineRegisterInfo &MRI,
77406f32e7eSjoerg                                         MachineFunction &MF) const {
77506f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_ZEXT) && "unexpected instruction");
77606f32e7eSjoerg 
77706f32e7eSjoerg   const Register DstReg = I.getOperand(0).getReg();
77806f32e7eSjoerg   const Register SrcReg = I.getOperand(1).getReg();
77906f32e7eSjoerg 
78006f32e7eSjoerg   const LLT DstTy = MRI.getType(DstReg);
78106f32e7eSjoerg   const LLT SrcTy = MRI.getType(SrcReg);
78206f32e7eSjoerg 
783*da58b97aSjoerg   assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(16)) &&
784*da58b97aSjoerg          "8=>16 Zext is handled by tablegen");
78506f32e7eSjoerg   assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(32)) &&
78606f32e7eSjoerg          "8=>32 Zext is handled by tablegen");
78706f32e7eSjoerg   assert(!(SrcTy == LLT::scalar(16) && DstTy == LLT::scalar(32)) &&
78806f32e7eSjoerg          "16=>32 Zext is handled by tablegen");
789*da58b97aSjoerg   assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(64)) &&
790*da58b97aSjoerg          "8=>64 Zext is handled by tablegen");
791*da58b97aSjoerg   assert(!(SrcTy == LLT::scalar(16) && DstTy == LLT::scalar(64)) &&
792*da58b97aSjoerg          "16=>64 Zext is handled by tablegen");
793*da58b97aSjoerg   assert(!(SrcTy == LLT::scalar(32) && DstTy == LLT::scalar(64)) &&
794*da58b97aSjoerg          "32=>64 Zext is handled by tablegen");
79506f32e7eSjoerg 
79606f32e7eSjoerg   if (SrcTy != LLT::scalar(1))
79706f32e7eSjoerg     return false;
79806f32e7eSjoerg 
79906f32e7eSjoerg   unsigned AndOpc;
80006f32e7eSjoerg   if (DstTy == LLT::scalar(8))
80106f32e7eSjoerg     AndOpc = X86::AND8ri;
80206f32e7eSjoerg   else if (DstTy == LLT::scalar(16))
80306f32e7eSjoerg     AndOpc = X86::AND16ri8;
80406f32e7eSjoerg   else if (DstTy == LLT::scalar(32))
80506f32e7eSjoerg     AndOpc = X86::AND32ri8;
80606f32e7eSjoerg   else if (DstTy == LLT::scalar(64))
80706f32e7eSjoerg     AndOpc = X86::AND64ri8;
80806f32e7eSjoerg   else
80906f32e7eSjoerg     return false;
81006f32e7eSjoerg 
811*da58b97aSjoerg   Register DefReg = SrcReg;
81206f32e7eSjoerg   if (DstTy != LLT::scalar(8)) {
813*da58b97aSjoerg     Register ImpDefReg =
814*da58b97aSjoerg         MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI));
815*da58b97aSjoerg     BuildMI(*I.getParent(), I, I.getDebugLoc(),
816*da58b97aSjoerg             TII.get(TargetOpcode::IMPLICIT_DEF), ImpDefReg);
817*da58b97aSjoerg 
81806f32e7eSjoerg     DefReg = MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI));
81906f32e7eSjoerg     BuildMI(*I.getParent(), I, I.getDebugLoc(),
820*da58b97aSjoerg             TII.get(TargetOpcode::INSERT_SUBREG), DefReg)
821*da58b97aSjoerg         .addReg(ImpDefReg)
82206f32e7eSjoerg         .addReg(SrcReg)
82306f32e7eSjoerg         .addImm(X86::sub_8bit);
82406f32e7eSjoerg   }
82506f32e7eSjoerg 
82606f32e7eSjoerg   MachineInstr &AndInst =
82706f32e7eSjoerg       *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AndOpc), DstReg)
82806f32e7eSjoerg            .addReg(DefReg)
82906f32e7eSjoerg            .addImm(1);
83006f32e7eSjoerg 
83106f32e7eSjoerg   constrainSelectedInstRegOperands(AndInst, TII, TRI, RBI);
83206f32e7eSjoerg 
83306f32e7eSjoerg   I.eraseFromParent();
83406f32e7eSjoerg   return true;
83506f32e7eSjoerg }
83606f32e7eSjoerg 
selectAnyext(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const83706f32e7eSjoerg bool X86InstructionSelector::selectAnyext(MachineInstr &I,
83806f32e7eSjoerg                                           MachineRegisterInfo &MRI,
83906f32e7eSjoerg                                           MachineFunction &MF) const {
84006f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_ANYEXT) && "unexpected instruction");
84106f32e7eSjoerg 
84206f32e7eSjoerg   const Register DstReg = I.getOperand(0).getReg();
84306f32e7eSjoerg   const Register SrcReg = I.getOperand(1).getReg();
84406f32e7eSjoerg 
84506f32e7eSjoerg   const LLT DstTy = MRI.getType(DstReg);
84606f32e7eSjoerg   const LLT SrcTy = MRI.getType(SrcReg);
84706f32e7eSjoerg 
84806f32e7eSjoerg   const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);
84906f32e7eSjoerg   const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);
85006f32e7eSjoerg 
85106f32e7eSjoerg   assert(DstRB.getID() == SrcRB.getID() &&
85206f32e7eSjoerg          "G_ANYEXT input/output on different banks\n");
85306f32e7eSjoerg 
85406f32e7eSjoerg   assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() &&
85506f32e7eSjoerg          "G_ANYEXT incorrect operand size");
85606f32e7eSjoerg 
85706f32e7eSjoerg   const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);
85806f32e7eSjoerg   const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);
85906f32e7eSjoerg 
86006f32e7eSjoerg   // If that's ANY_EXT of the value that lives on the floating class and goes
86106f32e7eSjoerg   // into the vector class, just replace it with copy, as we are able to select
86206f32e7eSjoerg   // it as a regular move.
86306f32e7eSjoerg   if (canTurnIntoCOPY(SrcRC, DstRC))
86406f32e7eSjoerg     return selectTurnIntoCOPY(I, MRI, SrcReg, SrcRC, DstReg, DstRC);
86506f32e7eSjoerg 
86606f32e7eSjoerg   if (DstRB.getID() != X86::GPRRegBankID)
86706f32e7eSjoerg     return false;
86806f32e7eSjoerg 
86906f32e7eSjoerg   if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
87006f32e7eSjoerg       !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
87106f32e7eSjoerg     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
87206f32e7eSjoerg                       << " operand\n");
87306f32e7eSjoerg     return false;
87406f32e7eSjoerg   }
87506f32e7eSjoerg 
87606f32e7eSjoerg   if (SrcRC == DstRC) {
87706f32e7eSjoerg     I.setDesc(TII.get(X86::COPY));
87806f32e7eSjoerg     return true;
87906f32e7eSjoerg   }
88006f32e7eSjoerg 
88106f32e7eSjoerg   BuildMI(*I.getParent(), I, I.getDebugLoc(),
88206f32e7eSjoerg           TII.get(TargetOpcode::SUBREG_TO_REG))
88306f32e7eSjoerg       .addDef(DstReg)
88406f32e7eSjoerg       .addImm(0)
88506f32e7eSjoerg       .addReg(SrcReg)
88606f32e7eSjoerg       .addImm(getSubRegIndex(SrcRC));
88706f32e7eSjoerg 
88806f32e7eSjoerg   I.eraseFromParent();
88906f32e7eSjoerg   return true;
89006f32e7eSjoerg }
89106f32e7eSjoerg 
selectCmp(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const89206f32e7eSjoerg bool X86InstructionSelector::selectCmp(MachineInstr &I,
89306f32e7eSjoerg                                        MachineRegisterInfo &MRI,
89406f32e7eSjoerg                                        MachineFunction &MF) const {
89506f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_ICMP) && "unexpected instruction");
89606f32e7eSjoerg 
89706f32e7eSjoerg   X86::CondCode CC;
89806f32e7eSjoerg   bool SwapArgs;
89906f32e7eSjoerg   std::tie(CC, SwapArgs) = X86::getX86ConditionCode(
90006f32e7eSjoerg       (CmpInst::Predicate)I.getOperand(1).getPredicate());
90106f32e7eSjoerg 
90206f32e7eSjoerg   Register LHS = I.getOperand(2).getReg();
90306f32e7eSjoerg   Register RHS = I.getOperand(3).getReg();
90406f32e7eSjoerg 
90506f32e7eSjoerg   if (SwapArgs)
90606f32e7eSjoerg     std::swap(LHS, RHS);
90706f32e7eSjoerg 
90806f32e7eSjoerg   unsigned OpCmp;
90906f32e7eSjoerg   LLT Ty = MRI.getType(LHS);
91006f32e7eSjoerg 
91106f32e7eSjoerg   switch (Ty.getSizeInBits()) {
91206f32e7eSjoerg   default:
91306f32e7eSjoerg     return false;
91406f32e7eSjoerg   case 8:
91506f32e7eSjoerg     OpCmp = X86::CMP8rr;
91606f32e7eSjoerg     break;
91706f32e7eSjoerg   case 16:
91806f32e7eSjoerg     OpCmp = X86::CMP16rr;
91906f32e7eSjoerg     break;
92006f32e7eSjoerg   case 32:
92106f32e7eSjoerg     OpCmp = X86::CMP32rr;
92206f32e7eSjoerg     break;
92306f32e7eSjoerg   case 64:
92406f32e7eSjoerg     OpCmp = X86::CMP64rr;
92506f32e7eSjoerg     break;
92606f32e7eSjoerg   }
92706f32e7eSjoerg 
92806f32e7eSjoerg   MachineInstr &CmpInst =
92906f32e7eSjoerg       *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
93006f32e7eSjoerg            .addReg(LHS)
93106f32e7eSjoerg            .addReg(RHS);
93206f32e7eSjoerg 
93306f32e7eSjoerg   MachineInstr &SetInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
93406f32e7eSjoerg                                    TII.get(X86::SETCCr), I.getOperand(0).getReg()).addImm(CC);
93506f32e7eSjoerg 
93606f32e7eSjoerg   constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);
93706f32e7eSjoerg   constrainSelectedInstRegOperands(SetInst, TII, TRI, RBI);
93806f32e7eSjoerg 
93906f32e7eSjoerg   I.eraseFromParent();
94006f32e7eSjoerg   return true;
94106f32e7eSjoerg }
94206f32e7eSjoerg 
selectFCmp(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const94306f32e7eSjoerg bool X86InstructionSelector::selectFCmp(MachineInstr &I,
94406f32e7eSjoerg                                         MachineRegisterInfo &MRI,
94506f32e7eSjoerg                                         MachineFunction &MF) const {
94606f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_FCMP) && "unexpected instruction");
94706f32e7eSjoerg 
94806f32e7eSjoerg   Register LhsReg = I.getOperand(2).getReg();
94906f32e7eSjoerg   Register RhsReg = I.getOperand(3).getReg();
95006f32e7eSjoerg   CmpInst::Predicate Predicate =
95106f32e7eSjoerg       (CmpInst::Predicate)I.getOperand(1).getPredicate();
95206f32e7eSjoerg 
95306f32e7eSjoerg   // FCMP_OEQ and FCMP_UNE cannot be checked with a single instruction.
95406f32e7eSjoerg   static const uint16_t SETFOpcTable[2][3] = {
95506f32e7eSjoerg       {X86::COND_E, X86::COND_NP, X86::AND8rr},
95606f32e7eSjoerg       {X86::COND_NE, X86::COND_P, X86::OR8rr}};
95706f32e7eSjoerg   const uint16_t *SETFOpc = nullptr;
95806f32e7eSjoerg   switch (Predicate) {
95906f32e7eSjoerg   default:
96006f32e7eSjoerg     break;
96106f32e7eSjoerg   case CmpInst::FCMP_OEQ:
96206f32e7eSjoerg     SETFOpc = &SETFOpcTable[0][0];
96306f32e7eSjoerg     break;
96406f32e7eSjoerg   case CmpInst::FCMP_UNE:
96506f32e7eSjoerg     SETFOpc = &SETFOpcTable[1][0];
96606f32e7eSjoerg     break;
96706f32e7eSjoerg   }
96806f32e7eSjoerg 
96906f32e7eSjoerg   // Compute the opcode for the CMP instruction.
97006f32e7eSjoerg   unsigned OpCmp;
97106f32e7eSjoerg   LLT Ty = MRI.getType(LhsReg);
97206f32e7eSjoerg   switch (Ty.getSizeInBits()) {
97306f32e7eSjoerg   default:
97406f32e7eSjoerg     return false;
97506f32e7eSjoerg   case 32:
97606f32e7eSjoerg     OpCmp = X86::UCOMISSrr;
97706f32e7eSjoerg     break;
97806f32e7eSjoerg   case 64:
97906f32e7eSjoerg     OpCmp = X86::UCOMISDrr;
98006f32e7eSjoerg     break;
98106f32e7eSjoerg   }
98206f32e7eSjoerg 
98306f32e7eSjoerg   Register ResultReg = I.getOperand(0).getReg();
98406f32e7eSjoerg   RBI.constrainGenericRegister(
98506f32e7eSjoerg       ResultReg,
98606f32e7eSjoerg       *getRegClass(LLT::scalar(8), *RBI.getRegBank(ResultReg, MRI, TRI)), MRI);
98706f32e7eSjoerg   if (SETFOpc) {
98806f32e7eSjoerg     MachineInstr &CmpInst =
98906f32e7eSjoerg         *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
99006f32e7eSjoerg              .addReg(LhsReg)
99106f32e7eSjoerg              .addReg(RhsReg);
99206f32e7eSjoerg 
99306f32e7eSjoerg     Register FlagReg1 = MRI.createVirtualRegister(&X86::GR8RegClass);
99406f32e7eSjoerg     Register FlagReg2 = MRI.createVirtualRegister(&X86::GR8RegClass);
99506f32e7eSjoerg     MachineInstr &Set1 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
99606f32e7eSjoerg                                   TII.get(X86::SETCCr), FlagReg1).addImm(SETFOpc[0]);
99706f32e7eSjoerg     MachineInstr &Set2 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
99806f32e7eSjoerg                                   TII.get(X86::SETCCr), FlagReg2).addImm(SETFOpc[1]);
99906f32e7eSjoerg     MachineInstr &Set3 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
100006f32e7eSjoerg                                   TII.get(SETFOpc[2]), ResultReg)
100106f32e7eSjoerg                               .addReg(FlagReg1)
100206f32e7eSjoerg                               .addReg(FlagReg2);
100306f32e7eSjoerg     constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);
100406f32e7eSjoerg     constrainSelectedInstRegOperands(Set1, TII, TRI, RBI);
100506f32e7eSjoerg     constrainSelectedInstRegOperands(Set2, TII, TRI, RBI);
100606f32e7eSjoerg     constrainSelectedInstRegOperands(Set3, TII, TRI, RBI);
100706f32e7eSjoerg 
100806f32e7eSjoerg     I.eraseFromParent();
100906f32e7eSjoerg     return true;
101006f32e7eSjoerg   }
101106f32e7eSjoerg 
101206f32e7eSjoerg   X86::CondCode CC;
101306f32e7eSjoerg   bool SwapArgs;
101406f32e7eSjoerg   std::tie(CC, SwapArgs) = X86::getX86ConditionCode(Predicate);
101506f32e7eSjoerg   assert(CC <= X86::LAST_VALID_COND && "Unexpected condition code.");
101606f32e7eSjoerg 
101706f32e7eSjoerg   if (SwapArgs)
101806f32e7eSjoerg     std::swap(LhsReg, RhsReg);
101906f32e7eSjoerg 
102006f32e7eSjoerg   // Emit a compare of LHS/RHS.
102106f32e7eSjoerg   MachineInstr &CmpInst =
102206f32e7eSjoerg       *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))
102306f32e7eSjoerg            .addReg(LhsReg)
102406f32e7eSjoerg            .addReg(RhsReg);
102506f32e7eSjoerg 
102606f32e7eSjoerg   MachineInstr &Set =
102706f32e7eSjoerg       *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::SETCCr), ResultReg).addImm(CC);
102806f32e7eSjoerg   constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);
102906f32e7eSjoerg   constrainSelectedInstRegOperands(Set, TII, TRI, RBI);
103006f32e7eSjoerg   I.eraseFromParent();
103106f32e7eSjoerg   return true;
103206f32e7eSjoerg }
103306f32e7eSjoerg 
selectUadde(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const103406f32e7eSjoerg bool X86InstructionSelector::selectUadde(MachineInstr &I,
103506f32e7eSjoerg                                          MachineRegisterInfo &MRI,
103606f32e7eSjoerg                                          MachineFunction &MF) const {
103706f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_UADDE) && "unexpected instruction");
103806f32e7eSjoerg 
103906f32e7eSjoerg   const Register DstReg = I.getOperand(0).getReg();
104006f32e7eSjoerg   const Register CarryOutReg = I.getOperand(1).getReg();
104106f32e7eSjoerg   const Register Op0Reg = I.getOperand(2).getReg();
104206f32e7eSjoerg   const Register Op1Reg = I.getOperand(3).getReg();
104306f32e7eSjoerg   Register CarryInReg = I.getOperand(4).getReg();
104406f32e7eSjoerg 
104506f32e7eSjoerg   const LLT DstTy = MRI.getType(DstReg);
104606f32e7eSjoerg 
104706f32e7eSjoerg   if (DstTy != LLT::scalar(32))
104806f32e7eSjoerg     return false;
104906f32e7eSjoerg 
105006f32e7eSjoerg   // find CarryIn def instruction.
105106f32e7eSjoerg   MachineInstr *Def = MRI.getVRegDef(CarryInReg);
105206f32e7eSjoerg   while (Def->getOpcode() == TargetOpcode::G_TRUNC) {
105306f32e7eSjoerg     CarryInReg = Def->getOperand(1).getReg();
105406f32e7eSjoerg     Def = MRI.getVRegDef(CarryInReg);
105506f32e7eSjoerg   }
105606f32e7eSjoerg 
105706f32e7eSjoerg   unsigned Opcode;
105806f32e7eSjoerg   if (Def->getOpcode() == TargetOpcode::G_UADDE) {
105906f32e7eSjoerg     // carry set by prev ADD.
106006f32e7eSjoerg 
106106f32e7eSjoerg     BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), X86::EFLAGS)
106206f32e7eSjoerg         .addReg(CarryInReg);
106306f32e7eSjoerg 
106406f32e7eSjoerg     if (!RBI.constrainGenericRegister(CarryInReg, X86::GR32RegClass, MRI))
106506f32e7eSjoerg       return false;
106606f32e7eSjoerg 
106706f32e7eSjoerg     Opcode = X86::ADC32rr;
106806f32e7eSjoerg   } else if (auto val = getConstantVRegVal(CarryInReg, MRI)) {
106906f32e7eSjoerg     // carry is constant, support only 0.
107006f32e7eSjoerg     if (*val != 0)
107106f32e7eSjoerg       return false;
107206f32e7eSjoerg 
107306f32e7eSjoerg     Opcode = X86::ADD32rr;
107406f32e7eSjoerg   } else
107506f32e7eSjoerg     return false;
107606f32e7eSjoerg 
107706f32e7eSjoerg   MachineInstr &AddInst =
107806f32e7eSjoerg       *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)
107906f32e7eSjoerg            .addReg(Op0Reg)
108006f32e7eSjoerg            .addReg(Op1Reg);
108106f32e7eSjoerg 
108206f32e7eSjoerg   BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), CarryOutReg)
108306f32e7eSjoerg       .addReg(X86::EFLAGS);
108406f32e7eSjoerg 
108506f32e7eSjoerg   if (!constrainSelectedInstRegOperands(AddInst, TII, TRI, RBI) ||
108606f32e7eSjoerg       !RBI.constrainGenericRegister(CarryOutReg, X86::GR32RegClass, MRI))
108706f32e7eSjoerg     return false;
108806f32e7eSjoerg 
108906f32e7eSjoerg   I.eraseFromParent();
109006f32e7eSjoerg   return true;
109106f32e7eSjoerg }
109206f32e7eSjoerg 
selectExtract(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const109306f32e7eSjoerg bool X86InstructionSelector::selectExtract(MachineInstr &I,
109406f32e7eSjoerg                                            MachineRegisterInfo &MRI,
109506f32e7eSjoerg                                            MachineFunction &MF) const {
109606f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_EXTRACT) &&
109706f32e7eSjoerg          "unexpected instruction");
109806f32e7eSjoerg 
109906f32e7eSjoerg   const Register DstReg = I.getOperand(0).getReg();
110006f32e7eSjoerg   const Register SrcReg = I.getOperand(1).getReg();
110106f32e7eSjoerg   int64_t Index = I.getOperand(2).getImm();
110206f32e7eSjoerg 
110306f32e7eSjoerg   const LLT DstTy = MRI.getType(DstReg);
110406f32e7eSjoerg   const LLT SrcTy = MRI.getType(SrcReg);
110506f32e7eSjoerg 
110606f32e7eSjoerg   // Meanwile handle vector type only.
110706f32e7eSjoerg   if (!DstTy.isVector())
110806f32e7eSjoerg     return false;
110906f32e7eSjoerg 
111006f32e7eSjoerg   if (Index % DstTy.getSizeInBits() != 0)
111106f32e7eSjoerg     return false; // Not extract subvector.
111206f32e7eSjoerg 
111306f32e7eSjoerg   if (Index == 0) {
111406f32e7eSjoerg     // Replace by extract subreg copy.
111506f32e7eSjoerg     if (!emitExtractSubreg(DstReg, SrcReg, I, MRI, MF))
111606f32e7eSjoerg       return false;
111706f32e7eSjoerg 
111806f32e7eSjoerg     I.eraseFromParent();
111906f32e7eSjoerg     return true;
112006f32e7eSjoerg   }
112106f32e7eSjoerg 
112206f32e7eSjoerg   bool HasAVX = STI.hasAVX();
112306f32e7eSjoerg   bool HasAVX512 = STI.hasAVX512();
112406f32e7eSjoerg   bool HasVLX = STI.hasVLX();
112506f32e7eSjoerg 
112606f32e7eSjoerg   if (SrcTy.getSizeInBits() == 256 && DstTy.getSizeInBits() == 128) {
112706f32e7eSjoerg     if (HasVLX)
112806f32e7eSjoerg       I.setDesc(TII.get(X86::VEXTRACTF32x4Z256rr));
112906f32e7eSjoerg     else if (HasAVX)
113006f32e7eSjoerg       I.setDesc(TII.get(X86::VEXTRACTF128rr));
113106f32e7eSjoerg     else
113206f32e7eSjoerg       return false;
113306f32e7eSjoerg   } else if (SrcTy.getSizeInBits() == 512 && HasAVX512) {
113406f32e7eSjoerg     if (DstTy.getSizeInBits() == 128)
113506f32e7eSjoerg       I.setDesc(TII.get(X86::VEXTRACTF32x4Zrr));
113606f32e7eSjoerg     else if (DstTy.getSizeInBits() == 256)
113706f32e7eSjoerg       I.setDesc(TII.get(X86::VEXTRACTF64x4Zrr));
113806f32e7eSjoerg     else
113906f32e7eSjoerg       return false;
114006f32e7eSjoerg   } else
114106f32e7eSjoerg     return false;
114206f32e7eSjoerg 
114306f32e7eSjoerg   // Convert to X86 VEXTRACT immediate.
114406f32e7eSjoerg   Index = Index / DstTy.getSizeInBits();
114506f32e7eSjoerg   I.getOperand(2).setImm(Index);
114606f32e7eSjoerg 
114706f32e7eSjoerg   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
114806f32e7eSjoerg }
114906f32e7eSjoerg 
emitExtractSubreg(unsigned DstReg,unsigned SrcReg,MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const115006f32e7eSjoerg bool X86InstructionSelector::emitExtractSubreg(unsigned DstReg, unsigned SrcReg,
115106f32e7eSjoerg                                                MachineInstr &I,
115206f32e7eSjoerg                                                MachineRegisterInfo &MRI,
115306f32e7eSjoerg                                                MachineFunction &MF) const {
115406f32e7eSjoerg   const LLT DstTy = MRI.getType(DstReg);
115506f32e7eSjoerg   const LLT SrcTy = MRI.getType(SrcReg);
115606f32e7eSjoerg   unsigned SubIdx = X86::NoSubRegister;
115706f32e7eSjoerg 
115806f32e7eSjoerg   if (!DstTy.isVector() || !SrcTy.isVector())
115906f32e7eSjoerg     return false;
116006f32e7eSjoerg 
116106f32e7eSjoerg   assert(SrcTy.getSizeInBits() > DstTy.getSizeInBits() &&
116206f32e7eSjoerg          "Incorrect Src/Dst register size");
116306f32e7eSjoerg 
116406f32e7eSjoerg   if (DstTy.getSizeInBits() == 128)
116506f32e7eSjoerg     SubIdx = X86::sub_xmm;
116606f32e7eSjoerg   else if (DstTy.getSizeInBits() == 256)
116706f32e7eSjoerg     SubIdx = X86::sub_ymm;
116806f32e7eSjoerg   else
116906f32e7eSjoerg     return false;
117006f32e7eSjoerg 
117106f32e7eSjoerg   const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);
117206f32e7eSjoerg   const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);
117306f32e7eSjoerg 
117406f32e7eSjoerg   SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);
117506f32e7eSjoerg 
117606f32e7eSjoerg   if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
117706f32e7eSjoerg       !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
117806f32e7eSjoerg     LLVM_DEBUG(dbgs() << "Failed to constrain EXTRACT_SUBREG\n");
117906f32e7eSjoerg     return false;
118006f32e7eSjoerg   }
118106f32e7eSjoerg 
118206f32e7eSjoerg   BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), DstReg)
118306f32e7eSjoerg       .addReg(SrcReg, 0, SubIdx);
118406f32e7eSjoerg 
118506f32e7eSjoerg   return true;
118606f32e7eSjoerg }
118706f32e7eSjoerg 
emitInsertSubreg(unsigned DstReg,unsigned SrcReg,MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const118806f32e7eSjoerg bool X86InstructionSelector::emitInsertSubreg(unsigned DstReg, unsigned SrcReg,
118906f32e7eSjoerg                                               MachineInstr &I,
119006f32e7eSjoerg                                               MachineRegisterInfo &MRI,
119106f32e7eSjoerg                                               MachineFunction &MF) const {
119206f32e7eSjoerg   const LLT DstTy = MRI.getType(DstReg);
119306f32e7eSjoerg   const LLT SrcTy = MRI.getType(SrcReg);
119406f32e7eSjoerg   unsigned SubIdx = X86::NoSubRegister;
119506f32e7eSjoerg 
119606f32e7eSjoerg   // TODO: support scalar types
119706f32e7eSjoerg   if (!DstTy.isVector() || !SrcTy.isVector())
119806f32e7eSjoerg     return false;
119906f32e7eSjoerg 
120006f32e7eSjoerg   assert(SrcTy.getSizeInBits() < DstTy.getSizeInBits() &&
120106f32e7eSjoerg          "Incorrect Src/Dst register size");
120206f32e7eSjoerg 
120306f32e7eSjoerg   if (SrcTy.getSizeInBits() == 128)
120406f32e7eSjoerg     SubIdx = X86::sub_xmm;
120506f32e7eSjoerg   else if (SrcTy.getSizeInBits() == 256)
120606f32e7eSjoerg     SubIdx = X86::sub_ymm;
120706f32e7eSjoerg   else
120806f32e7eSjoerg     return false;
120906f32e7eSjoerg 
121006f32e7eSjoerg   const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);
121106f32e7eSjoerg   const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);
121206f32e7eSjoerg 
121306f32e7eSjoerg   if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||
121406f32e7eSjoerg       !RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {
121506f32e7eSjoerg     LLVM_DEBUG(dbgs() << "Failed to constrain INSERT_SUBREG\n");
121606f32e7eSjoerg     return false;
121706f32e7eSjoerg   }
121806f32e7eSjoerg 
121906f32e7eSjoerg   BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY))
122006f32e7eSjoerg       .addReg(DstReg, RegState::DefineNoRead, SubIdx)
122106f32e7eSjoerg       .addReg(SrcReg);
122206f32e7eSjoerg 
122306f32e7eSjoerg   return true;
122406f32e7eSjoerg }
122506f32e7eSjoerg 
selectInsert(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const122606f32e7eSjoerg bool X86InstructionSelector::selectInsert(MachineInstr &I,
122706f32e7eSjoerg                                           MachineRegisterInfo &MRI,
122806f32e7eSjoerg                                           MachineFunction &MF) const {
122906f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_INSERT) && "unexpected instruction");
123006f32e7eSjoerg 
123106f32e7eSjoerg   const Register DstReg = I.getOperand(0).getReg();
123206f32e7eSjoerg   const Register SrcReg = I.getOperand(1).getReg();
123306f32e7eSjoerg   const Register InsertReg = I.getOperand(2).getReg();
123406f32e7eSjoerg   int64_t Index = I.getOperand(3).getImm();
123506f32e7eSjoerg 
123606f32e7eSjoerg   const LLT DstTy = MRI.getType(DstReg);
123706f32e7eSjoerg   const LLT InsertRegTy = MRI.getType(InsertReg);
123806f32e7eSjoerg 
123906f32e7eSjoerg   // Meanwile handle vector type only.
124006f32e7eSjoerg   if (!DstTy.isVector())
124106f32e7eSjoerg     return false;
124206f32e7eSjoerg 
124306f32e7eSjoerg   if (Index % InsertRegTy.getSizeInBits() != 0)
124406f32e7eSjoerg     return false; // Not insert subvector.
124506f32e7eSjoerg 
124606f32e7eSjoerg   if (Index == 0 && MRI.getVRegDef(SrcReg)->isImplicitDef()) {
124706f32e7eSjoerg     // Replace by subreg copy.
124806f32e7eSjoerg     if (!emitInsertSubreg(DstReg, InsertReg, I, MRI, MF))
124906f32e7eSjoerg       return false;
125006f32e7eSjoerg 
125106f32e7eSjoerg     I.eraseFromParent();
125206f32e7eSjoerg     return true;
125306f32e7eSjoerg   }
125406f32e7eSjoerg 
125506f32e7eSjoerg   bool HasAVX = STI.hasAVX();
125606f32e7eSjoerg   bool HasAVX512 = STI.hasAVX512();
125706f32e7eSjoerg   bool HasVLX = STI.hasVLX();
125806f32e7eSjoerg 
125906f32e7eSjoerg   if (DstTy.getSizeInBits() == 256 && InsertRegTy.getSizeInBits() == 128) {
126006f32e7eSjoerg     if (HasVLX)
126106f32e7eSjoerg       I.setDesc(TII.get(X86::VINSERTF32x4Z256rr));
126206f32e7eSjoerg     else if (HasAVX)
126306f32e7eSjoerg       I.setDesc(TII.get(X86::VINSERTF128rr));
126406f32e7eSjoerg     else
126506f32e7eSjoerg       return false;
126606f32e7eSjoerg   } else if (DstTy.getSizeInBits() == 512 && HasAVX512) {
126706f32e7eSjoerg     if (InsertRegTy.getSizeInBits() == 128)
126806f32e7eSjoerg       I.setDesc(TII.get(X86::VINSERTF32x4Zrr));
126906f32e7eSjoerg     else if (InsertRegTy.getSizeInBits() == 256)
127006f32e7eSjoerg       I.setDesc(TII.get(X86::VINSERTF64x4Zrr));
127106f32e7eSjoerg     else
127206f32e7eSjoerg       return false;
127306f32e7eSjoerg   } else
127406f32e7eSjoerg     return false;
127506f32e7eSjoerg 
127606f32e7eSjoerg   // Convert to X86 VINSERT immediate.
127706f32e7eSjoerg   Index = Index / InsertRegTy.getSizeInBits();
127806f32e7eSjoerg 
127906f32e7eSjoerg   I.getOperand(3).setImm(Index);
128006f32e7eSjoerg 
128106f32e7eSjoerg   return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
128206f32e7eSjoerg }
128306f32e7eSjoerg 
selectUnmergeValues(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF)128406f32e7eSjoerg bool X86InstructionSelector::selectUnmergeValues(
128506f32e7eSjoerg     MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) {
128606f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_UNMERGE_VALUES) &&
128706f32e7eSjoerg          "unexpected instruction");
128806f32e7eSjoerg 
128906f32e7eSjoerg   // Split to extracts.
129006f32e7eSjoerg   unsigned NumDefs = I.getNumOperands() - 1;
129106f32e7eSjoerg   Register SrcReg = I.getOperand(NumDefs).getReg();
129206f32e7eSjoerg   unsigned DefSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();
129306f32e7eSjoerg 
129406f32e7eSjoerg   for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {
129506f32e7eSjoerg     MachineInstr &ExtrInst =
129606f32e7eSjoerg         *BuildMI(*I.getParent(), I, I.getDebugLoc(),
129706f32e7eSjoerg                  TII.get(TargetOpcode::G_EXTRACT), I.getOperand(Idx).getReg())
129806f32e7eSjoerg              .addReg(SrcReg)
129906f32e7eSjoerg              .addImm(Idx * DefSize);
130006f32e7eSjoerg 
130106f32e7eSjoerg     if (!select(ExtrInst))
130206f32e7eSjoerg       return false;
130306f32e7eSjoerg   }
130406f32e7eSjoerg 
130506f32e7eSjoerg   I.eraseFromParent();
130606f32e7eSjoerg   return true;
130706f32e7eSjoerg }
130806f32e7eSjoerg 
selectMergeValues(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF)130906f32e7eSjoerg bool X86InstructionSelector::selectMergeValues(
131006f32e7eSjoerg     MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) {
131106f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_MERGE_VALUES ||
131206f32e7eSjoerg           I.getOpcode() == TargetOpcode::G_CONCAT_VECTORS) &&
131306f32e7eSjoerg          "unexpected instruction");
131406f32e7eSjoerg 
131506f32e7eSjoerg   // Split to inserts.
131606f32e7eSjoerg   Register DstReg = I.getOperand(0).getReg();
131706f32e7eSjoerg   Register SrcReg0 = I.getOperand(1).getReg();
131806f32e7eSjoerg 
131906f32e7eSjoerg   const LLT DstTy = MRI.getType(DstReg);
132006f32e7eSjoerg   const LLT SrcTy = MRI.getType(SrcReg0);
132106f32e7eSjoerg   unsigned SrcSize = SrcTy.getSizeInBits();
132206f32e7eSjoerg 
132306f32e7eSjoerg   const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
132406f32e7eSjoerg 
132506f32e7eSjoerg   // For the first src use insertSubReg.
132606f32e7eSjoerg   Register DefReg = MRI.createGenericVirtualRegister(DstTy);
132706f32e7eSjoerg   MRI.setRegBank(DefReg, RegBank);
132806f32e7eSjoerg   if (!emitInsertSubreg(DefReg, I.getOperand(1).getReg(), I, MRI, MF))
132906f32e7eSjoerg     return false;
133006f32e7eSjoerg 
133106f32e7eSjoerg   for (unsigned Idx = 2; Idx < I.getNumOperands(); ++Idx) {
133206f32e7eSjoerg     Register Tmp = MRI.createGenericVirtualRegister(DstTy);
133306f32e7eSjoerg     MRI.setRegBank(Tmp, RegBank);
133406f32e7eSjoerg 
133506f32e7eSjoerg     MachineInstr &InsertInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
133606f32e7eSjoerg                                         TII.get(TargetOpcode::G_INSERT), Tmp)
133706f32e7eSjoerg                                     .addReg(DefReg)
133806f32e7eSjoerg                                     .addReg(I.getOperand(Idx).getReg())
133906f32e7eSjoerg                                     .addImm((Idx - 1) * SrcSize);
134006f32e7eSjoerg 
134106f32e7eSjoerg     DefReg = Tmp;
134206f32e7eSjoerg 
134306f32e7eSjoerg     if (!select(InsertInst))
134406f32e7eSjoerg       return false;
134506f32e7eSjoerg   }
134606f32e7eSjoerg 
134706f32e7eSjoerg   MachineInstr &CopyInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),
134806f32e7eSjoerg                                     TII.get(TargetOpcode::COPY), DstReg)
134906f32e7eSjoerg                                 .addReg(DefReg);
135006f32e7eSjoerg 
135106f32e7eSjoerg   if (!select(CopyInst))
135206f32e7eSjoerg     return false;
135306f32e7eSjoerg 
135406f32e7eSjoerg   I.eraseFromParent();
135506f32e7eSjoerg   return true;
135606f32e7eSjoerg }
135706f32e7eSjoerg 
selectCondBranch(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const135806f32e7eSjoerg bool X86InstructionSelector::selectCondBranch(MachineInstr &I,
135906f32e7eSjoerg                                               MachineRegisterInfo &MRI,
136006f32e7eSjoerg                                               MachineFunction &MF) const {
136106f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_BRCOND) && "unexpected instruction");
136206f32e7eSjoerg 
136306f32e7eSjoerg   const Register CondReg = I.getOperand(0).getReg();
136406f32e7eSjoerg   MachineBasicBlock *DestMBB = I.getOperand(1).getMBB();
136506f32e7eSjoerg 
136606f32e7eSjoerg   MachineInstr &TestInst =
136706f32e7eSjoerg       *BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::TEST8ri))
136806f32e7eSjoerg            .addReg(CondReg)
136906f32e7eSjoerg            .addImm(1);
137006f32e7eSjoerg   BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::JCC_1))
137106f32e7eSjoerg       .addMBB(DestMBB).addImm(X86::COND_NE);
137206f32e7eSjoerg 
137306f32e7eSjoerg   constrainSelectedInstRegOperands(TestInst, TII, TRI, RBI);
137406f32e7eSjoerg 
137506f32e7eSjoerg   I.eraseFromParent();
137606f32e7eSjoerg   return true;
137706f32e7eSjoerg }
137806f32e7eSjoerg 
materializeFP(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const137906f32e7eSjoerg bool X86InstructionSelector::materializeFP(MachineInstr &I,
138006f32e7eSjoerg                                            MachineRegisterInfo &MRI,
138106f32e7eSjoerg                                            MachineFunction &MF) const {
138206f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_FCONSTANT) &&
138306f32e7eSjoerg          "unexpected instruction");
138406f32e7eSjoerg 
138506f32e7eSjoerg   // Can't handle alternate code models yet.
138606f32e7eSjoerg   CodeModel::Model CM = TM.getCodeModel();
138706f32e7eSjoerg   if (CM != CodeModel::Small && CM != CodeModel::Large)
138806f32e7eSjoerg     return false;
138906f32e7eSjoerg 
139006f32e7eSjoerg   const Register DstReg = I.getOperand(0).getReg();
139106f32e7eSjoerg   const LLT DstTy = MRI.getType(DstReg);
139206f32e7eSjoerg   const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);
1393*da58b97aSjoerg   Align Alignment = Align(DstTy.getSizeInBytes());
139406f32e7eSjoerg   const DebugLoc &DbgLoc = I.getDebugLoc();
139506f32e7eSjoerg 
1396*da58b97aSjoerg   unsigned Opc =
1397*da58b97aSjoerg       getLoadStoreOp(DstTy, RegBank, TargetOpcode::G_LOAD, Alignment);
139806f32e7eSjoerg 
139906f32e7eSjoerg   // Create the load from the constant pool.
140006f32e7eSjoerg   const ConstantFP *CFP = I.getOperand(1).getFPImm();
1401*da58b97aSjoerg   unsigned CPI = MF.getConstantPool()->getConstantPoolIndex(CFP, Alignment);
140206f32e7eSjoerg   MachineInstr *LoadInst = nullptr;
140306f32e7eSjoerg   unsigned char OpFlag = STI.classifyLocalReference(nullptr);
140406f32e7eSjoerg 
140506f32e7eSjoerg   if (CM == CodeModel::Large && STI.is64Bit()) {
140606f32e7eSjoerg     // Under X86-64 non-small code model, GV (and friends) are 64-bits, so
140706f32e7eSjoerg     // they cannot be folded into immediate fields.
140806f32e7eSjoerg 
140906f32e7eSjoerg     Register AddrReg = MRI.createVirtualRegister(&X86::GR64RegClass);
141006f32e7eSjoerg     BuildMI(*I.getParent(), I, DbgLoc, TII.get(X86::MOV64ri), AddrReg)
141106f32e7eSjoerg         .addConstantPoolIndex(CPI, 0, OpFlag);
141206f32e7eSjoerg 
141306f32e7eSjoerg     MachineMemOperand *MMO = MF.getMachineMemOperand(
141406f32e7eSjoerg         MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad,
1415*da58b97aSjoerg         MF.getDataLayout().getPointerSize(), Alignment);
141606f32e7eSjoerg 
141706f32e7eSjoerg     LoadInst =
141806f32e7eSjoerg         addDirectMem(BuildMI(*I.getParent(), I, DbgLoc, TII.get(Opc), DstReg),
141906f32e7eSjoerg                      AddrReg)
142006f32e7eSjoerg             .addMemOperand(MMO);
142106f32e7eSjoerg 
142206f32e7eSjoerg   } else if (CM == CodeModel::Small || !STI.is64Bit()) {
142306f32e7eSjoerg     // Handle the case when globals fit in our immediate field.
142406f32e7eSjoerg     // This is true for X86-32 always and X86-64 when in -mcmodel=small mode.
142506f32e7eSjoerg 
142606f32e7eSjoerg     // x86-32 PIC requires a PIC base register for constant pools.
142706f32e7eSjoerg     unsigned PICBase = 0;
142806f32e7eSjoerg     if (OpFlag == X86II::MO_PIC_BASE_OFFSET || OpFlag == X86II::MO_GOTOFF) {
142906f32e7eSjoerg       // PICBase can be allocated by TII.getGlobalBaseReg(&MF).
143006f32e7eSjoerg       // In DAGISEL the code that initialize it generated by the CGBR pass.
143106f32e7eSjoerg       return false; // TODO support the mode.
143206f32e7eSjoerg     } else if (STI.is64Bit() && TM.getCodeModel() == CodeModel::Small)
143306f32e7eSjoerg       PICBase = X86::RIP;
143406f32e7eSjoerg 
143506f32e7eSjoerg     LoadInst = addConstantPoolReference(
143606f32e7eSjoerg         BuildMI(*I.getParent(), I, DbgLoc, TII.get(Opc), DstReg), CPI, PICBase,
143706f32e7eSjoerg         OpFlag);
143806f32e7eSjoerg   } else
143906f32e7eSjoerg     return false;
144006f32e7eSjoerg 
144106f32e7eSjoerg   constrainSelectedInstRegOperands(*LoadInst, TII, TRI, RBI);
144206f32e7eSjoerg   I.eraseFromParent();
144306f32e7eSjoerg   return true;
144406f32e7eSjoerg }
144506f32e7eSjoerg 
selectImplicitDefOrPHI(MachineInstr & I,MachineRegisterInfo & MRI) const144606f32e7eSjoerg bool X86InstructionSelector::selectImplicitDefOrPHI(
144706f32e7eSjoerg     MachineInstr &I, MachineRegisterInfo &MRI) const {
144806f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF ||
144906f32e7eSjoerg           I.getOpcode() == TargetOpcode::G_PHI) &&
145006f32e7eSjoerg          "unexpected instruction");
145106f32e7eSjoerg 
145206f32e7eSjoerg   Register DstReg = I.getOperand(0).getReg();
145306f32e7eSjoerg 
145406f32e7eSjoerg   if (!MRI.getRegClassOrNull(DstReg)) {
145506f32e7eSjoerg     const LLT DstTy = MRI.getType(DstReg);
145606f32e7eSjoerg     const TargetRegisterClass *RC = getRegClass(DstTy, DstReg, MRI);
145706f32e7eSjoerg 
145806f32e7eSjoerg     if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {
145906f32e7eSjoerg       LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
146006f32e7eSjoerg                         << " operand\n");
146106f32e7eSjoerg       return false;
146206f32e7eSjoerg     }
146306f32e7eSjoerg   }
146406f32e7eSjoerg 
146506f32e7eSjoerg   if (I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
146606f32e7eSjoerg     I.setDesc(TII.get(X86::IMPLICIT_DEF));
146706f32e7eSjoerg   else
146806f32e7eSjoerg     I.setDesc(TII.get(X86::PHI));
146906f32e7eSjoerg 
147006f32e7eSjoerg   return true;
147106f32e7eSjoerg }
147206f32e7eSjoerg 
selectDivRem(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const147306f32e7eSjoerg bool X86InstructionSelector::selectDivRem(MachineInstr &I,
147406f32e7eSjoerg                                           MachineRegisterInfo &MRI,
147506f32e7eSjoerg                                           MachineFunction &MF) const {
147606f32e7eSjoerg   // The implementation of this function is taken from X86FastISel.
147706f32e7eSjoerg   assert((I.getOpcode() == TargetOpcode::G_SDIV ||
147806f32e7eSjoerg           I.getOpcode() == TargetOpcode::G_SREM ||
147906f32e7eSjoerg           I.getOpcode() == TargetOpcode::G_UDIV ||
148006f32e7eSjoerg           I.getOpcode() == TargetOpcode::G_UREM) &&
148106f32e7eSjoerg          "unexpected instruction");
148206f32e7eSjoerg 
148306f32e7eSjoerg   const Register DstReg = I.getOperand(0).getReg();
148406f32e7eSjoerg   const Register Op1Reg = I.getOperand(1).getReg();
148506f32e7eSjoerg   const Register Op2Reg = I.getOperand(2).getReg();
148606f32e7eSjoerg 
148706f32e7eSjoerg   const LLT RegTy = MRI.getType(DstReg);
148806f32e7eSjoerg   assert(RegTy == MRI.getType(Op1Reg) && RegTy == MRI.getType(Op2Reg) &&
148906f32e7eSjoerg          "Arguments and return value types must match");
149006f32e7eSjoerg 
149106f32e7eSjoerg   const RegisterBank *RegRB = RBI.getRegBank(DstReg, MRI, TRI);
149206f32e7eSjoerg   if (!RegRB || RegRB->getID() != X86::GPRRegBankID)
149306f32e7eSjoerg     return false;
149406f32e7eSjoerg 
149506f32e7eSjoerg   const static unsigned NumTypes = 4; // i8, i16, i32, i64
149606f32e7eSjoerg   const static unsigned NumOps = 4;   // SDiv, SRem, UDiv, URem
149706f32e7eSjoerg   const static bool S = true;         // IsSigned
149806f32e7eSjoerg   const static bool U = false;        // !IsSigned
149906f32e7eSjoerg   const static unsigned Copy = TargetOpcode::COPY;
150006f32e7eSjoerg   // For the X86 IDIV instruction, in most cases the dividend
150106f32e7eSjoerg   // (numerator) must be in a specific register pair highreg:lowreg,
150206f32e7eSjoerg   // producing the quotient in lowreg and the remainder in highreg.
150306f32e7eSjoerg   // For most data types, to set up the instruction, the dividend is
150406f32e7eSjoerg   // copied into lowreg, and lowreg is sign-extended into highreg.  The
150506f32e7eSjoerg   // exception is i8, where the dividend is defined as a single register rather
150606f32e7eSjoerg   // than a register pair, and we therefore directly sign-extend the dividend
150706f32e7eSjoerg   // into lowreg, instead of copying, and ignore the highreg.
150806f32e7eSjoerg   const static struct DivRemEntry {
150906f32e7eSjoerg     // The following portion depends only on the data type.
151006f32e7eSjoerg     unsigned SizeInBits;
151106f32e7eSjoerg     unsigned LowInReg;  // low part of the register pair
151206f32e7eSjoerg     unsigned HighInReg; // high part of the register pair
151306f32e7eSjoerg     // The following portion depends on both the data type and the operation.
151406f32e7eSjoerg     struct DivRemResult {
151506f32e7eSjoerg       unsigned OpDivRem;        // The specific DIV/IDIV opcode to use.
151606f32e7eSjoerg       unsigned OpSignExtend;    // Opcode for sign-extending lowreg into
151706f32e7eSjoerg                                 // highreg, or copying a zero into highreg.
151806f32e7eSjoerg       unsigned OpCopy;          // Opcode for copying dividend into lowreg, or
151906f32e7eSjoerg                                 // zero/sign-extending into lowreg for i8.
152006f32e7eSjoerg       unsigned DivRemResultReg; // Register containing the desired result.
152106f32e7eSjoerg       bool IsOpSigned;          // Whether to use signed or unsigned form.
152206f32e7eSjoerg     } ResultTable[NumOps];
152306f32e7eSjoerg   } OpTable[NumTypes] = {
152406f32e7eSjoerg       {8,
152506f32e7eSjoerg        X86::AX,
152606f32e7eSjoerg        0,
152706f32e7eSjoerg        {
152806f32e7eSjoerg            {X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AL, S}, // SDiv
152906f32e7eSjoerg            {X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AH, S}, // SRem
153006f32e7eSjoerg            {X86::DIV8r, 0, X86::MOVZX16rr8, X86::AL, U},  // UDiv
153106f32e7eSjoerg            {X86::DIV8r, 0, X86::MOVZX16rr8, X86::AH, U},  // URem
153206f32e7eSjoerg        }},                                                // i8
153306f32e7eSjoerg       {16,
153406f32e7eSjoerg        X86::AX,
153506f32e7eSjoerg        X86::DX,
153606f32e7eSjoerg        {
153706f32e7eSjoerg            {X86::IDIV16r, X86::CWD, Copy, X86::AX, S},    // SDiv
153806f32e7eSjoerg            {X86::IDIV16r, X86::CWD, Copy, X86::DX, S},    // SRem
153906f32e7eSjoerg            {X86::DIV16r, X86::MOV32r0, Copy, X86::AX, U}, // UDiv
154006f32e7eSjoerg            {X86::DIV16r, X86::MOV32r0, Copy, X86::DX, U}, // URem
154106f32e7eSjoerg        }},                                                // i16
154206f32e7eSjoerg       {32,
154306f32e7eSjoerg        X86::EAX,
154406f32e7eSjoerg        X86::EDX,
154506f32e7eSjoerg        {
154606f32e7eSjoerg            {X86::IDIV32r, X86::CDQ, Copy, X86::EAX, S},    // SDiv
154706f32e7eSjoerg            {X86::IDIV32r, X86::CDQ, Copy, X86::EDX, S},    // SRem
154806f32e7eSjoerg            {X86::DIV32r, X86::MOV32r0, Copy, X86::EAX, U}, // UDiv
154906f32e7eSjoerg            {X86::DIV32r, X86::MOV32r0, Copy, X86::EDX, U}, // URem
155006f32e7eSjoerg        }},                                                 // i32
155106f32e7eSjoerg       {64,
155206f32e7eSjoerg        X86::RAX,
155306f32e7eSjoerg        X86::RDX,
155406f32e7eSjoerg        {
155506f32e7eSjoerg            {X86::IDIV64r, X86::CQO, Copy, X86::RAX, S},    // SDiv
155606f32e7eSjoerg            {X86::IDIV64r, X86::CQO, Copy, X86::RDX, S},    // SRem
155706f32e7eSjoerg            {X86::DIV64r, X86::MOV32r0, Copy, X86::RAX, U}, // UDiv
155806f32e7eSjoerg            {X86::DIV64r, X86::MOV32r0, Copy, X86::RDX, U}, // URem
155906f32e7eSjoerg        }},                                                 // i64
156006f32e7eSjoerg   };
156106f32e7eSjoerg 
1562*da58b97aSjoerg   auto OpEntryIt = llvm::find_if(OpTable, [RegTy](const DivRemEntry &El) {
156306f32e7eSjoerg     return El.SizeInBits == RegTy.getSizeInBits();
156406f32e7eSjoerg   });
156506f32e7eSjoerg   if (OpEntryIt == std::end(OpTable))
156606f32e7eSjoerg     return false;
156706f32e7eSjoerg 
156806f32e7eSjoerg   unsigned OpIndex;
156906f32e7eSjoerg   switch (I.getOpcode()) {
157006f32e7eSjoerg   default:
157106f32e7eSjoerg     llvm_unreachable("Unexpected div/rem opcode");
157206f32e7eSjoerg   case TargetOpcode::G_SDIV:
157306f32e7eSjoerg     OpIndex = 0;
157406f32e7eSjoerg     break;
157506f32e7eSjoerg   case TargetOpcode::G_SREM:
157606f32e7eSjoerg     OpIndex = 1;
157706f32e7eSjoerg     break;
157806f32e7eSjoerg   case TargetOpcode::G_UDIV:
157906f32e7eSjoerg     OpIndex = 2;
158006f32e7eSjoerg     break;
158106f32e7eSjoerg   case TargetOpcode::G_UREM:
158206f32e7eSjoerg     OpIndex = 3;
158306f32e7eSjoerg     break;
158406f32e7eSjoerg   }
158506f32e7eSjoerg 
158606f32e7eSjoerg   const DivRemEntry &TypeEntry = *OpEntryIt;
158706f32e7eSjoerg   const DivRemEntry::DivRemResult &OpEntry = TypeEntry.ResultTable[OpIndex];
158806f32e7eSjoerg 
158906f32e7eSjoerg   const TargetRegisterClass *RegRC = getRegClass(RegTy, *RegRB);
159006f32e7eSjoerg   if (!RBI.constrainGenericRegister(Op1Reg, *RegRC, MRI) ||
159106f32e7eSjoerg       !RBI.constrainGenericRegister(Op2Reg, *RegRC, MRI) ||
159206f32e7eSjoerg       !RBI.constrainGenericRegister(DstReg, *RegRC, MRI)) {
159306f32e7eSjoerg     LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())
159406f32e7eSjoerg                       << " operand\n");
159506f32e7eSjoerg     return false;
159606f32e7eSjoerg   }
159706f32e7eSjoerg 
159806f32e7eSjoerg   // Move op1 into low-order input register.
159906f32e7eSjoerg   BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpEntry.OpCopy),
160006f32e7eSjoerg           TypeEntry.LowInReg)
160106f32e7eSjoerg       .addReg(Op1Reg);
160206f32e7eSjoerg   // Zero-extend or sign-extend into high-order input register.
160306f32e7eSjoerg   if (OpEntry.OpSignExtend) {
160406f32e7eSjoerg     if (OpEntry.IsOpSigned)
160506f32e7eSjoerg       BuildMI(*I.getParent(), I, I.getDebugLoc(),
160606f32e7eSjoerg               TII.get(OpEntry.OpSignExtend));
160706f32e7eSjoerg     else {
160806f32e7eSjoerg       Register Zero32 = MRI.createVirtualRegister(&X86::GR32RegClass);
160906f32e7eSjoerg       BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::MOV32r0),
161006f32e7eSjoerg               Zero32);
161106f32e7eSjoerg 
161206f32e7eSjoerg       // Copy the zero into the appropriate sub/super/identical physical
161306f32e7eSjoerg       // register. Unfortunately the operations needed are not uniform enough
161406f32e7eSjoerg       // to fit neatly into the table above.
161506f32e7eSjoerg       if (RegTy.getSizeInBits() == 16) {
161606f32e7eSjoerg         BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Copy),
161706f32e7eSjoerg                 TypeEntry.HighInReg)
161806f32e7eSjoerg             .addReg(Zero32, 0, X86::sub_16bit);
161906f32e7eSjoerg       } else if (RegTy.getSizeInBits() == 32) {
162006f32e7eSjoerg         BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Copy),
162106f32e7eSjoerg                 TypeEntry.HighInReg)
162206f32e7eSjoerg             .addReg(Zero32);
162306f32e7eSjoerg       } else if (RegTy.getSizeInBits() == 64) {
162406f32e7eSjoerg         BuildMI(*I.getParent(), I, I.getDebugLoc(),
162506f32e7eSjoerg                 TII.get(TargetOpcode::SUBREG_TO_REG), TypeEntry.HighInReg)
162606f32e7eSjoerg             .addImm(0)
162706f32e7eSjoerg             .addReg(Zero32)
162806f32e7eSjoerg             .addImm(X86::sub_32bit);
162906f32e7eSjoerg       }
163006f32e7eSjoerg     }
163106f32e7eSjoerg   }
163206f32e7eSjoerg   // Generate the DIV/IDIV instruction.
163306f32e7eSjoerg   BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpEntry.OpDivRem))
163406f32e7eSjoerg       .addReg(Op2Reg);
163506f32e7eSjoerg   // For i8 remainder, we can't reference ah directly, as we'll end
163606f32e7eSjoerg   // up with bogus copies like %r9b = COPY %ah. Reference ax
163706f32e7eSjoerg   // instead to prevent ah references in a rex instruction.
163806f32e7eSjoerg   //
163906f32e7eSjoerg   // The current assumption of the fast register allocator is that isel
164006f32e7eSjoerg   // won't generate explicit references to the GR8_NOREX registers. If
164106f32e7eSjoerg   // the allocator and/or the backend get enhanced to be more robust in
164206f32e7eSjoerg   // that regard, this can be, and should be, removed.
164306f32e7eSjoerg   if ((I.getOpcode() == Instruction::SRem ||
164406f32e7eSjoerg        I.getOpcode() == Instruction::URem) &&
164506f32e7eSjoerg       OpEntry.DivRemResultReg == X86::AH && STI.is64Bit()) {
164606f32e7eSjoerg     Register SourceSuperReg = MRI.createVirtualRegister(&X86::GR16RegClass);
164706f32e7eSjoerg     Register ResultSuperReg = MRI.createVirtualRegister(&X86::GR16RegClass);
164806f32e7eSjoerg     BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Copy), SourceSuperReg)
164906f32e7eSjoerg         .addReg(X86::AX);
165006f32e7eSjoerg 
165106f32e7eSjoerg     // Shift AX right by 8 bits instead of using AH.
165206f32e7eSjoerg     BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::SHR16ri),
165306f32e7eSjoerg             ResultSuperReg)
165406f32e7eSjoerg         .addReg(SourceSuperReg)
165506f32e7eSjoerg         .addImm(8);
165606f32e7eSjoerg 
165706f32e7eSjoerg     // Now reference the 8-bit subreg of the result.
165806f32e7eSjoerg     BuildMI(*I.getParent(), I, I.getDebugLoc(),
165906f32e7eSjoerg             TII.get(TargetOpcode::SUBREG_TO_REG))
166006f32e7eSjoerg         .addDef(DstReg)
166106f32e7eSjoerg         .addImm(0)
166206f32e7eSjoerg         .addReg(ResultSuperReg)
166306f32e7eSjoerg         .addImm(X86::sub_8bit);
166406f32e7eSjoerg   } else {
166506f32e7eSjoerg     BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(TargetOpcode::COPY),
166606f32e7eSjoerg             DstReg)
166706f32e7eSjoerg         .addReg(OpEntry.DivRemResultReg);
166806f32e7eSjoerg   }
166906f32e7eSjoerg   I.eraseFromParent();
167006f32e7eSjoerg   return true;
167106f32e7eSjoerg }
167206f32e7eSjoerg 
selectIntrinsicWSideEffects(MachineInstr & I,MachineRegisterInfo & MRI,MachineFunction & MF) const167306f32e7eSjoerg bool X86InstructionSelector::selectIntrinsicWSideEffects(
167406f32e7eSjoerg     MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) const {
167506f32e7eSjoerg 
167606f32e7eSjoerg   assert(I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS &&
167706f32e7eSjoerg          "unexpected instruction");
167806f32e7eSjoerg 
167906f32e7eSjoerg   if (I.getOperand(0).getIntrinsicID() != Intrinsic::trap)
168006f32e7eSjoerg     return false;
168106f32e7eSjoerg 
168206f32e7eSjoerg   BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::TRAP));
168306f32e7eSjoerg 
168406f32e7eSjoerg   I.eraseFromParent();
168506f32e7eSjoerg   return true;
168606f32e7eSjoerg }
168706f32e7eSjoerg 
168806f32e7eSjoerg InstructionSelector *
createX86InstructionSelector(const X86TargetMachine & TM,X86Subtarget & Subtarget,X86RegisterBankInfo & RBI)168906f32e7eSjoerg llvm::createX86InstructionSelector(const X86TargetMachine &TM,
169006f32e7eSjoerg                                    X86Subtarget &Subtarget,
169106f32e7eSjoerg                                    X86RegisterBankInfo &RBI) {
169206f32e7eSjoerg   return new X86InstructionSelector(TM, Subtarget, RBI);
169306f32e7eSjoerg }
1694