Path: blob/main/contrib/llvm-project/llvm/lib/Target/X86/GISel/X86InstructionSelector.cpp
35294 views
//===- X86InstructionSelector.cpp -----------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8/// This file implements the targeting of the InstructionSelector class for9/// X86.10/// \todo This should be generated by TableGen.11//===----------------------------------------------------------------------===//1213#include "MCTargetDesc/X86BaseInfo.h"14#include "X86.h"15#include "X86InstrBuilder.h"16#include "X86InstrInfo.h"17#include "X86RegisterBankInfo.h"18#include "X86RegisterInfo.h"19#include "X86Subtarget.h"20#include "X86TargetMachine.h"21#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"22#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"23#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"24#include "llvm/CodeGen/GlobalISel/Utils.h"25#include "llvm/CodeGen/MachineBasicBlock.h"26#include "llvm/CodeGen/MachineConstantPool.h"27#include "llvm/CodeGen/MachineFunction.h"28#include "llvm/CodeGen/MachineInstr.h"29#include "llvm/CodeGen/MachineInstrBuilder.h"30#include "llvm/CodeGen/MachineMemOperand.h"31#include "llvm/CodeGen/MachineOperand.h"32#include "llvm/CodeGen/MachineRegisterInfo.h"33#include "llvm/CodeGen/RegisterBank.h"34#include "llvm/CodeGen/TargetOpcodes.h"35#include "llvm/CodeGen/TargetRegisterInfo.h"36#include "llvm/CodeGenTypes/LowLevelType.h"37#include "llvm/IR/DataLayout.h"38#include "llvm/IR/InstrTypes.h"39#include "llvm/IR/IntrinsicsX86.h"40#include "llvm/Support/AtomicOrdering.h"41#include "llvm/Support/CodeGen.h"42#include "llvm/Support/Debug.h"43#include "llvm/Support/ErrorHandling.h"44#include "llvm/Support/MathExtras.h"45#include "llvm/Support/raw_ostream.h"46#include <cassert>47#include <cstdint>48#include <tuple>4950#define DEBUG_TYPE "X86-isel"5152using namespace llvm;5354namespace {5556#define GET_GLOBALISEL_PREDICATE_BITSET57#include "X86GenGlobalISel.inc"58#undef GET_GLOBALISEL_PREDICATE_BITSET5960class X86InstructionSelector : public InstructionSelector {61public:62X86InstructionSelector(const X86TargetMachine &TM, const X86Subtarget &STI,63const X86RegisterBankInfo &RBI);6465bool select(MachineInstr &I) override;66static const char *getName() { return DEBUG_TYPE; }6768private:69/// tblgen-erated 'select' implementation, used as the initial selector for70/// the patterns that don't require complex C++.71bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;7273// TODO: remove after supported by Tablegen-erated instruction selection.74unsigned getLoadStoreOp(const LLT &Ty, const RegisterBank &RB, unsigned Opc,75Align Alignment) const;7677bool selectLoadStoreOp(MachineInstr &I, MachineRegisterInfo &MRI,78MachineFunction &MF) const;79bool selectFrameIndexOrGep(MachineInstr &I, MachineRegisterInfo &MRI,80MachineFunction &MF) const;81bool selectGlobalValue(MachineInstr &I, MachineRegisterInfo &MRI,82MachineFunction &MF) const;83bool selectConstant(MachineInstr &I, MachineRegisterInfo &MRI,84MachineFunction &MF) const;85bool selectTruncOrPtrToInt(MachineInstr &I, MachineRegisterInfo &MRI,86MachineFunction &MF) const;87bool selectZext(MachineInstr &I, MachineRegisterInfo &MRI,88MachineFunction &MF) const;89bool selectAnyext(MachineInstr &I, MachineRegisterInfo &MRI,90MachineFunction &MF) const;91bool selectCmp(MachineInstr &I, MachineRegisterInfo &MRI,92MachineFunction &MF) const;93bool selectFCmp(MachineInstr &I, MachineRegisterInfo &MRI,94MachineFunction &MF) const;95bool selectUAddSub(MachineInstr &I, MachineRegisterInfo &MRI,96MachineFunction &MF) const;97bool selectDebugInstr(MachineInstr &I, MachineRegisterInfo &MRI) const;98bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;99bool selectUnmergeValues(MachineInstr &I, MachineRegisterInfo &MRI,100MachineFunction &MF);101bool selectMergeValues(MachineInstr &I, MachineRegisterInfo &MRI,102MachineFunction &MF);103bool selectInsert(MachineInstr &I, MachineRegisterInfo &MRI,104MachineFunction &MF) const;105bool selectExtract(MachineInstr &I, MachineRegisterInfo &MRI,106MachineFunction &MF) const;107bool selectCondBranch(MachineInstr &I, MachineRegisterInfo &MRI,108MachineFunction &MF) const;109bool selectTurnIntoCOPY(MachineInstr &I, MachineRegisterInfo &MRI,110const unsigned DstReg,111const TargetRegisterClass *DstRC,112const unsigned SrcReg,113const TargetRegisterClass *SrcRC) const;114bool materializeFP(MachineInstr &I, MachineRegisterInfo &MRI,115MachineFunction &MF) const;116bool selectImplicitDefOrPHI(MachineInstr &I, MachineRegisterInfo &MRI) const;117bool selectMulDivRem(MachineInstr &I, MachineRegisterInfo &MRI,118MachineFunction &MF) const;119bool selectSelect(MachineInstr &I, MachineRegisterInfo &MRI,120MachineFunction &MF) const;121122// emit insert subreg instruction and insert it before MachineInstr &I123bool emitInsertSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,124MachineRegisterInfo &MRI, MachineFunction &MF) const;125// emit extract subreg instruction and insert it before MachineInstr &I126bool emitExtractSubreg(unsigned DstReg, unsigned SrcReg, MachineInstr &I,127MachineRegisterInfo &MRI, MachineFunction &MF) const;128129const TargetRegisterClass *getRegClass(LLT Ty, const RegisterBank &RB) const;130const TargetRegisterClass *getRegClass(LLT Ty, unsigned Reg,131MachineRegisterInfo &MRI) const;132133const X86TargetMachine &TM;134const X86Subtarget &STI;135const X86InstrInfo &TII;136const X86RegisterInfo &TRI;137const X86RegisterBankInfo &RBI;138139#define GET_GLOBALISEL_PREDICATES_DECL140#include "X86GenGlobalISel.inc"141#undef GET_GLOBALISEL_PREDICATES_DECL142143#define GET_GLOBALISEL_TEMPORARIES_DECL144#include "X86GenGlobalISel.inc"145#undef GET_GLOBALISEL_TEMPORARIES_DECL146};147148} // end anonymous namespace149150#define GET_GLOBALISEL_IMPL151#include "X86GenGlobalISel.inc"152#undef GET_GLOBALISEL_IMPL153154X86InstructionSelector::X86InstructionSelector(const X86TargetMachine &TM,155const X86Subtarget &STI,156const X86RegisterBankInfo &RBI)157: TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()),158RBI(RBI),159#define GET_GLOBALISEL_PREDICATES_INIT160#include "X86GenGlobalISel.inc"161#undef GET_GLOBALISEL_PREDICATES_INIT162#define GET_GLOBALISEL_TEMPORARIES_INIT163#include "X86GenGlobalISel.inc"164#undef GET_GLOBALISEL_TEMPORARIES_INIT165{166}167168// FIXME: This should be target-independent, inferred from the types declared169// for each class in the bank.170const TargetRegisterClass *171X86InstructionSelector::getRegClass(LLT Ty, const RegisterBank &RB) const {172if (RB.getID() == X86::GPRRegBankID) {173if (Ty.getSizeInBits() <= 8)174return &X86::GR8RegClass;175if (Ty.getSizeInBits() == 16)176return &X86::GR16RegClass;177if (Ty.getSizeInBits() == 32)178return &X86::GR32RegClass;179if (Ty.getSizeInBits() == 64)180return &X86::GR64RegClass;181}182if (RB.getID() == X86::VECRRegBankID) {183if (Ty.getSizeInBits() == 16)184return STI.hasAVX512() ? &X86::FR16XRegClass : &X86::FR16RegClass;185if (Ty.getSizeInBits() == 32)186return STI.hasAVX512() ? &X86::FR32XRegClass : &X86::FR32RegClass;187if (Ty.getSizeInBits() == 64)188return STI.hasAVX512() ? &X86::FR64XRegClass : &X86::FR64RegClass;189if (Ty.getSizeInBits() == 128)190return STI.hasAVX512() ? &X86::VR128XRegClass : &X86::VR128RegClass;191if (Ty.getSizeInBits() == 256)192return STI.hasAVX512() ? &X86::VR256XRegClass : &X86::VR256RegClass;193if (Ty.getSizeInBits() == 512)194return &X86::VR512RegClass;195}196197if (RB.getID() == X86::PSRRegBankID) {198if (Ty.getSizeInBits() == 80)199return &X86::RFP80RegClass;200if (Ty.getSizeInBits() == 64)201return &X86::RFP64RegClass;202if (Ty.getSizeInBits() == 32)203return &X86::RFP32RegClass;204}205206llvm_unreachable("Unknown RegBank!");207}208209const TargetRegisterClass *210X86InstructionSelector::getRegClass(LLT Ty, unsigned Reg,211MachineRegisterInfo &MRI) const {212const RegisterBank &RegBank = *RBI.getRegBank(Reg, MRI, TRI);213return getRegClass(Ty, RegBank);214}215216static unsigned getSubRegIndex(const TargetRegisterClass *RC) {217unsigned SubIdx = X86::NoSubRegister;218if (RC == &X86::GR32RegClass) {219SubIdx = X86::sub_32bit;220} else if (RC == &X86::GR16RegClass) {221SubIdx = X86::sub_16bit;222} else if (RC == &X86::GR8RegClass) {223SubIdx = X86::sub_8bit;224}225226return SubIdx;227}228229static const TargetRegisterClass *getRegClassFromGRPhysReg(Register Reg) {230assert(Reg.isPhysical());231if (X86::GR64RegClass.contains(Reg))232return &X86::GR64RegClass;233if (X86::GR32RegClass.contains(Reg))234return &X86::GR32RegClass;235if (X86::GR16RegClass.contains(Reg))236return &X86::GR16RegClass;237if (X86::GR8RegClass.contains(Reg))238return &X86::GR8RegClass;239240llvm_unreachable("Unknown RegClass for PhysReg!");241}242243// FIXME: We need some sort of API in RBI/TRI to allow generic code to244// constrain operands of simple instructions given a TargetRegisterClass245// and LLT246bool X86InstructionSelector::selectDebugInstr(MachineInstr &I,247MachineRegisterInfo &MRI) const {248for (MachineOperand &MO : I.operands()) {249if (!MO.isReg())250continue;251Register Reg = MO.getReg();252if (!Reg)253continue;254if (Reg.isPhysical())255continue;256LLT Ty = MRI.getType(Reg);257const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(Reg);258const TargetRegisterClass *RC =259dyn_cast_if_present<const TargetRegisterClass *>(RegClassOrBank);260if (!RC) {261const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);262RC = getRegClass(Ty, RB);263if (!RC) {264LLVM_DEBUG(265dbgs() << "Warning: DBG_VALUE operand has unexpected size/bank\n");266break;267}268}269RBI.constrainGenericRegister(Reg, *RC, MRI);270}271272return true;273}274275// Set X86 Opcode and constrain DestReg.276bool X86InstructionSelector::selectCopy(MachineInstr &I,277MachineRegisterInfo &MRI) const {278Register DstReg = I.getOperand(0).getReg();279const unsigned DstSize = RBI.getSizeInBits(DstReg, MRI, TRI);280const RegisterBank &DstRegBank = *RBI.getRegBank(DstReg, MRI, TRI);281282Register SrcReg = I.getOperand(1).getReg();283const unsigned SrcSize = RBI.getSizeInBits(SrcReg, MRI, TRI);284const RegisterBank &SrcRegBank = *RBI.getRegBank(SrcReg, MRI, TRI);285286if (DstReg.isPhysical()) {287assert(I.isCopy() && "Generic operators do not allow physical registers");288289if (DstSize > SrcSize && SrcRegBank.getID() == X86::GPRRegBankID &&290DstRegBank.getID() == X86::GPRRegBankID) {291292const TargetRegisterClass *SrcRC =293getRegClass(MRI.getType(SrcReg), SrcRegBank);294const TargetRegisterClass *DstRC = getRegClassFromGRPhysReg(DstReg);295296if (SrcRC != DstRC) {297// This case can be generated by ABI lowering, performe anyext298Register ExtSrc = MRI.createVirtualRegister(DstRC);299BuildMI(*I.getParent(), I, I.getDebugLoc(),300TII.get(TargetOpcode::SUBREG_TO_REG))301.addDef(ExtSrc)302.addImm(0)303.addReg(SrcReg)304.addImm(getSubRegIndex(SrcRC));305306I.getOperand(1).setReg(ExtSrc);307}308}309310return true;311}312313assert((!SrcReg.isPhysical() || I.isCopy()) &&314"No phys reg on generic operators");315assert((DstSize == SrcSize ||316// Copies are a mean to setup initial types, the number of317// bits may not exactly match.318(SrcReg.isPhysical() &&319DstSize <= RBI.getSizeInBits(SrcReg, MRI, TRI))) &&320"Copy with different width?!");321322const TargetRegisterClass *DstRC =323getRegClass(MRI.getType(DstReg), DstRegBank);324325if (SrcRegBank.getID() == X86::GPRRegBankID &&326DstRegBank.getID() == X86::GPRRegBankID && SrcSize > DstSize &&327SrcReg.isPhysical()) {328// Change the physical register to performe truncate.329330const TargetRegisterClass *SrcRC = getRegClassFromGRPhysReg(SrcReg);331332if (DstRC != SrcRC) {333I.getOperand(1).setSubReg(getSubRegIndex(DstRC));334I.getOperand(1).substPhysReg(SrcReg, TRI);335}336}337338// No need to constrain SrcReg. It will get constrained when339// we hit another of its use or its defs.340// Copies do not have constraints.341const TargetRegisterClass *OldRC = MRI.getRegClassOrNull(DstReg);342if (!OldRC || !DstRC->hasSubClassEq(OldRC)) {343if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {344LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())345<< " operand\n");346return false;347}348}349I.setDesc(TII.get(X86::COPY));350return true;351}352353bool X86InstructionSelector::select(MachineInstr &I) {354assert(I.getParent() && "Instruction should be in a basic block!");355assert(I.getParent()->getParent() && "Instruction should be in a function!");356357MachineBasicBlock &MBB = *I.getParent();358MachineFunction &MF = *MBB.getParent();359MachineRegisterInfo &MRI = MF.getRegInfo();360361unsigned Opcode = I.getOpcode();362if (!isPreISelGenericOpcode(Opcode)) {363// Certain non-generic instructions also need some special handling.364365if (Opcode == TargetOpcode::LOAD_STACK_GUARD)366return false;367368if (I.isCopy())369return selectCopy(I, MRI);370371if (I.isDebugInstr())372return selectDebugInstr(I, MRI);373374return true;375}376377assert(I.getNumOperands() == I.getNumExplicitOperands() &&378"Generic instruction has unexpected implicit operands\n");379380if (selectImpl(I, *CoverageInfo))381return true;382383LLVM_DEBUG(dbgs() << " C++ instruction selection: "; I.print(dbgs()));384385// TODO: This should be implemented by tblgen.386switch (I.getOpcode()) {387default:388return false;389case TargetOpcode::G_STORE:390case TargetOpcode::G_LOAD:391return selectLoadStoreOp(I, MRI, MF);392case TargetOpcode::G_PTR_ADD:393case TargetOpcode::G_FRAME_INDEX:394return selectFrameIndexOrGep(I, MRI, MF);395case TargetOpcode::G_GLOBAL_VALUE:396return selectGlobalValue(I, MRI, MF);397case TargetOpcode::G_CONSTANT:398return selectConstant(I, MRI, MF);399case TargetOpcode::G_FCONSTANT:400return materializeFP(I, MRI, MF);401case TargetOpcode::G_PTRTOINT:402case TargetOpcode::G_TRUNC:403return selectTruncOrPtrToInt(I, MRI, MF);404case TargetOpcode::G_INTTOPTR:405return selectCopy(I, MRI);406case TargetOpcode::G_ZEXT:407return selectZext(I, MRI, MF);408case TargetOpcode::G_ANYEXT:409return selectAnyext(I, MRI, MF);410case TargetOpcode::G_ICMP:411return selectCmp(I, MRI, MF);412case TargetOpcode::G_FCMP:413return selectFCmp(I, MRI, MF);414case TargetOpcode::G_UADDE:415case TargetOpcode::G_UADDO:416case TargetOpcode::G_USUBE:417case TargetOpcode::G_USUBO:418return selectUAddSub(I, MRI, MF);419case TargetOpcode::G_UNMERGE_VALUES:420return selectUnmergeValues(I, MRI, MF);421case TargetOpcode::G_MERGE_VALUES:422case TargetOpcode::G_CONCAT_VECTORS:423return selectMergeValues(I, MRI, MF);424case TargetOpcode::G_EXTRACT:425return selectExtract(I, MRI, MF);426case TargetOpcode::G_INSERT:427return selectInsert(I, MRI, MF);428case TargetOpcode::G_BRCOND:429return selectCondBranch(I, MRI, MF);430case TargetOpcode::G_IMPLICIT_DEF:431case TargetOpcode::G_PHI:432return selectImplicitDefOrPHI(I, MRI);433case TargetOpcode::G_MUL:434case TargetOpcode::G_SMULH:435case TargetOpcode::G_UMULH:436case TargetOpcode::G_SDIV:437case TargetOpcode::G_UDIV:438case TargetOpcode::G_SREM:439case TargetOpcode::G_UREM:440return selectMulDivRem(I, MRI, MF);441case TargetOpcode::G_SELECT:442return selectSelect(I, MRI, MF);443}444445return false;446}447448unsigned X86InstructionSelector::getLoadStoreOp(const LLT &Ty,449const RegisterBank &RB,450unsigned Opc,451Align Alignment) const {452bool Isload = (Opc == TargetOpcode::G_LOAD);453bool HasAVX = STI.hasAVX();454bool HasAVX512 = STI.hasAVX512();455bool HasVLX = STI.hasVLX();456457if (Ty == LLT::scalar(8)) {458if (X86::GPRRegBankID == RB.getID())459return Isload ? X86::MOV8rm : X86::MOV8mr;460} else if (Ty == LLT::scalar(16)) {461if (X86::GPRRegBankID == RB.getID())462return Isload ? X86::MOV16rm : X86::MOV16mr;463} else if (Ty == LLT::scalar(32) || Ty == LLT::pointer(0, 32)) {464if (X86::GPRRegBankID == RB.getID())465return Isload ? X86::MOV32rm : X86::MOV32mr;466if (X86::VECRRegBankID == RB.getID())467return Isload ? (HasAVX512 ? X86::VMOVSSZrm_alt :468HasAVX ? X86::VMOVSSrm_alt :469X86::MOVSSrm_alt)470: (HasAVX512 ? X86::VMOVSSZmr :471HasAVX ? X86::VMOVSSmr :472X86::MOVSSmr);473if (X86::PSRRegBankID == RB.getID())474return Isload ? X86::LD_Fp32m : X86::ST_Fp32m;475} else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {476if (X86::GPRRegBankID == RB.getID())477return Isload ? X86::MOV64rm : X86::MOV64mr;478if (X86::VECRRegBankID == RB.getID())479return Isload ? (HasAVX512 ? X86::VMOVSDZrm_alt :480HasAVX ? X86::VMOVSDrm_alt :481X86::MOVSDrm_alt)482: (HasAVX512 ? X86::VMOVSDZmr :483HasAVX ? X86::VMOVSDmr :484X86::MOVSDmr);485if (X86::PSRRegBankID == RB.getID())486return Isload ? X86::LD_Fp64m : X86::ST_Fp64m;487} else if (Ty == LLT::scalar(80)) {488return Isload ? X86::LD_Fp80m : X86::ST_FpP80m;489} else if (Ty.isVector() && Ty.getSizeInBits() == 128) {490if (Alignment >= Align(16))491return Isload ? (HasVLX ? X86::VMOVAPSZ128rm492: HasAVX512493? X86::VMOVAPSZ128rm_NOVLX494: HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm)495: (HasVLX ? X86::VMOVAPSZ128mr496: HasAVX512497? X86::VMOVAPSZ128mr_NOVLX498: HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr);499else500return Isload ? (HasVLX ? X86::VMOVUPSZ128rm501: HasAVX512502? X86::VMOVUPSZ128rm_NOVLX503: HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm)504: (HasVLX ? X86::VMOVUPSZ128mr505: HasAVX512506? X86::VMOVUPSZ128mr_NOVLX507: HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr);508} else if (Ty.isVector() && Ty.getSizeInBits() == 256) {509if (Alignment >= Align(32))510return Isload ? (HasVLX ? X86::VMOVAPSZ256rm511: HasAVX512 ? X86::VMOVAPSZ256rm_NOVLX512: X86::VMOVAPSYrm)513: (HasVLX ? X86::VMOVAPSZ256mr514: HasAVX512 ? X86::VMOVAPSZ256mr_NOVLX515: X86::VMOVAPSYmr);516else517return Isload ? (HasVLX ? X86::VMOVUPSZ256rm518: HasAVX512 ? X86::VMOVUPSZ256rm_NOVLX519: X86::VMOVUPSYrm)520: (HasVLX ? X86::VMOVUPSZ256mr521: HasAVX512 ? X86::VMOVUPSZ256mr_NOVLX522: X86::VMOVUPSYmr);523} else if (Ty.isVector() && Ty.getSizeInBits() == 512) {524if (Alignment >= Align(64))525return Isload ? X86::VMOVAPSZrm : X86::VMOVAPSZmr;526else527return Isload ? X86::VMOVUPSZrm : X86::VMOVUPSZmr;528}529return Opc;530}531532// Fill in an address from the given instruction.533static void X86SelectAddress(const MachineInstr &I,534const MachineRegisterInfo &MRI,535X86AddressMode &AM) {536assert(I.getOperand(0).isReg() && "unsupported opperand.");537assert(MRI.getType(I.getOperand(0).getReg()).isPointer() &&538"unsupported type.");539540if (I.getOpcode() == TargetOpcode::G_PTR_ADD) {541if (auto COff = getIConstantVRegSExtVal(I.getOperand(2).getReg(), MRI)) {542int64_t Imm = *COff;543if (isInt<32>(Imm)) { // Check for displacement overflow.544AM.Disp = static_cast<int32_t>(Imm);545AM.Base.Reg = I.getOperand(1).getReg();546return;547}548}549} else if (I.getOpcode() == TargetOpcode::G_FRAME_INDEX) {550AM.Base.FrameIndex = I.getOperand(1).getIndex();551AM.BaseType = X86AddressMode::FrameIndexBase;552return;553}554555// Default behavior.556AM.Base.Reg = I.getOperand(0).getReg();557}558559bool X86InstructionSelector::selectLoadStoreOp(MachineInstr &I,560MachineRegisterInfo &MRI,561MachineFunction &MF) const {562unsigned Opc = I.getOpcode();563564assert((Opc == TargetOpcode::G_STORE || Opc == TargetOpcode::G_LOAD) &&565"Only G_STORE and G_LOAD are expected for selection");566567const Register DefReg = I.getOperand(0).getReg();568LLT Ty = MRI.getType(DefReg);569const RegisterBank &RB = *RBI.getRegBank(DefReg, MRI, TRI);570571assert(I.hasOneMemOperand());572auto &MemOp = **I.memoperands_begin();573if (MemOp.isAtomic()) {574// Note: for unordered operations, we rely on the fact the appropriate MMO575// is already on the instruction we're mutating, and thus we don't need to576// make any changes. So long as we select an opcode which is capable of577// loading or storing the appropriate size atomically, the rest of the578// backend is required to respect the MMO state.579if (!MemOp.isUnordered()) {580LLVM_DEBUG(dbgs() << "Atomic ordering not supported yet\n");581return false;582}583if (MemOp.getAlign() < Ty.getSizeInBits() / 8) {584LLVM_DEBUG(dbgs() << "Unaligned atomics not supported yet\n");585return false;586}587}588589unsigned NewOpc = getLoadStoreOp(Ty, RB, Opc, MemOp.getAlign());590if (NewOpc == Opc)591return false;592593I.setDesc(TII.get(NewOpc));594MachineInstrBuilder MIB(MF, I);595const MachineInstr *Ptr = MRI.getVRegDef(I.getOperand(1).getReg());596597if (Ptr->getOpcode() == TargetOpcode::G_CONSTANT_POOL) {598assert(Opc == TargetOpcode::G_LOAD &&599"Only G_LOAD from constant pool is expected");600// TODO: Need a separate move for Large model601if (TM.getCodeModel() == CodeModel::Large)602return false;603604unsigned char OpFlag = STI.classifyLocalReference(nullptr);605unsigned PICBase = 0;606if (OpFlag == X86II::MO_GOTOFF)607PICBase = TII.getGlobalBaseReg(&MF);608else if (STI.is64Bit())609PICBase = X86::RIP;610611I.removeOperand(1);612addConstantPoolReference(MIB, Ptr->getOperand(1).getIndex(), PICBase,613OpFlag);614return constrainSelectedInstRegOperands(I, TII, TRI, RBI);615}616617X86AddressMode AM;618X86SelectAddress(*Ptr, MRI, AM);619if (Opc == TargetOpcode::G_LOAD) {620I.removeOperand(1);621addFullAddress(MIB, AM);622} else {623// G_STORE (VAL, Addr), X86Store instruction (Addr, VAL)624I.removeOperand(1);625I.removeOperand(0);626addFullAddress(MIB, AM).addUse(DefReg);627}628bool Constrained = constrainSelectedInstRegOperands(I, TII, TRI, RBI);629I.addImplicitDefUseOperands(MF);630return Constrained;631}632633static unsigned getLeaOP(LLT Ty, const X86Subtarget &STI) {634if (Ty == LLT::pointer(0, 64))635return X86::LEA64r;636else if (Ty == LLT::pointer(0, 32))637return STI.isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r;638else639llvm_unreachable("Can't get LEA opcode. Unsupported type.");640}641642bool X86InstructionSelector::selectFrameIndexOrGep(MachineInstr &I,643MachineRegisterInfo &MRI,644MachineFunction &MF) const {645unsigned Opc = I.getOpcode();646647assert((Opc == TargetOpcode::G_FRAME_INDEX || Opc == TargetOpcode::G_PTR_ADD) &&648"unexpected instruction");649650const Register DefReg = I.getOperand(0).getReg();651LLT Ty = MRI.getType(DefReg);652653// Use LEA to calculate frame index and GEP654unsigned NewOpc = getLeaOP(Ty, STI);655I.setDesc(TII.get(NewOpc));656MachineInstrBuilder MIB(MF, I);657658if (Opc == TargetOpcode::G_FRAME_INDEX) {659addOffset(MIB, 0);660} else {661MachineOperand &InxOp = I.getOperand(2);662I.addOperand(InxOp); // set IndexReg663InxOp.ChangeToImmediate(1); // set Scale664MIB.addImm(0).addReg(0);665}666667return constrainSelectedInstRegOperands(I, TII, TRI, RBI);668}669670bool X86InstructionSelector::selectGlobalValue(MachineInstr &I,671MachineRegisterInfo &MRI,672MachineFunction &MF) const {673assert((I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE) &&674"unexpected instruction");675676auto GV = I.getOperand(1).getGlobal();677if (GV->isThreadLocal()) {678return false; // TODO: we don't support TLS yet.679}680681// Can't handle alternate code models yet.682if (TM.getCodeModel() != CodeModel::Small)683return false;684685X86AddressMode AM;686AM.GV = GV;687AM.GVOpFlags = STI.classifyGlobalReference(GV);688689// TODO: The ABI requires an extra load. not supported yet.690if (isGlobalStubReference(AM.GVOpFlags))691return false;692693// TODO: This reference is relative to the pic base. not supported yet.694if (isGlobalRelativeToPICBase(AM.GVOpFlags))695return false;696697if (STI.isPICStyleRIPRel()) {698// Use rip-relative addressing.699assert(AM.Base.Reg == 0 && AM.IndexReg == 0);700AM.Base.Reg = X86::RIP;701}702703const Register DefReg = I.getOperand(0).getReg();704LLT Ty = MRI.getType(DefReg);705unsigned NewOpc = getLeaOP(Ty, STI);706707I.setDesc(TII.get(NewOpc));708MachineInstrBuilder MIB(MF, I);709710I.removeOperand(1);711addFullAddress(MIB, AM);712713return constrainSelectedInstRegOperands(I, TII, TRI, RBI);714}715716bool X86InstructionSelector::selectConstant(MachineInstr &I,717MachineRegisterInfo &MRI,718MachineFunction &MF) const {719assert((I.getOpcode() == TargetOpcode::G_CONSTANT) &&720"unexpected instruction");721722const Register DefReg = I.getOperand(0).getReg();723LLT Ty = MRI.getType(DefReg);724725if (RBI.getRegBank(DefReg, MRI, TRI)->getID() != X86::GPRRegBankID)726return false;727728uint64_t Val = 0;729if (I.getOperand(1).isCImm()) {730Val = I.getOperand(1).getCImm()->getZExtValue();731I.getOperand(1).ChangeToImmediate(Val);732} else if (I.getOperand(1).isImm()) {733Val = I.getOperand(1).getImm();734} else735llvm_unreachable("Unsupported operand type.");736737unsigned NewOpc;738switch (Ty.getSizeInBits()) {739case 8:740NewOpc = X86::MOV8ri;741break;742case 16:743NewOpc = X86::MOV16ri;744break;745case 32:746NewOpc = X86::MOV32ri;747break;748case 64:749// TODO: in case isUInt<32>(Val), X86::MOV32ri can be used750if (isInt<32>(Val))751NewOpc = X86::MOV64ri32;752else753NewOpc = X86::MOV64ri;754break;755default:756llvm_unreachable("Can't select G_CONSTANT, unsupported type.");757}758759I.setDesc(TII.get(NewOpc));760return constrainSelectedInstRegOperands(I, TII, TRI, RBI);761}762763// Helper function for selectTruncOrPtrToInt and selectAnyext.764// Returns true if DstRC lives on a floating register class and765// SrcRC lives on a 128-bit vector class.766static bool canTurnIntoCOPY(const TargetRegisterClass *DstRC,767const TargetRegisterClass *SrcRC) {768return (DstRC == &X86::FR32RegClass || DstRC == &X86::FR32XRegClass ||769DstRC == &X86::FR64RegClass || DstRC == &X86::FR64XRegClass) &&770(SrcRC == &X86::VR128RegClass || SrcRC == &X86::VR128XRegClass);771}772773bool X86InstructionSelector::selectTurnIntoCOPY(774MachineInstr &I, MachineRegisterInfo &MRI, const unsigned DstReg,775const TargetRegisterClass *DstRC, const unsigned SrcReg,776const TargetRegisterClass *SrcRC) const {777778if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||779!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {780LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())781<< " operand\n");782return false;783}784I.setDesc(TII.get(X86::COPY));785return true;786}787788bool X86InstructionSelector::selectTruncOrPtrToInt(MachineInstr &I,789MachineRegisterInfo &MRI,790MachineFunction &MF) const {791assert((I.getOpcode() == TargetOpcode::G_TRUNC ||792I.getOpcode() == TargetOpcode::G_PTRTOINT) &&793"unexpected instruction");794795const Register DstReg = I.getOperand(0).getReg();796const Register SrcReg = I.getOperand(1).getReg();797798const LLT DstTy = MRI.getType(DstReg);799const LLT SrcTy = MRI.getType(SrcReg);800801const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);802const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);803804if (DstRB.getID() != SrcRB.getID()) {805LLVM_DEBUG(dbgs() << TII.getName(I.getOpcode())806<< " input/output on different banks\n");807return false;808}809810const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);811const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);812813if (!DstRC || !SrcRC)814return false;815816// If that's truncation of the value that lives on the vector class and goes817// into the floating class, just replace it with copy, as we are able to818// select it as a regular move.819if (canTurnIntoCOPY(DstRC, SrcRC))820return selectTurnIntoCOPY(I, MRI, DstReg, DstRC, SrcReg, SrcRC);821822if (DstRB.getID() != X86::GPRRegBankID)823return false;824825unsigned SubIdx;826if (DstRC == SrcRC) {827// Nothing to be done828SubIdx = X86::NoSubRegister;829} else if (DstRC == &X86::GR32RegClass) {830SubIdx = X86::sub_32bit;831} else if (DstRC == &X86::GR16RegClass) {832SubIdx = X86::sub_16bit;833} else if (DstRC == &X86::GR8RegClass) {834SubIdx = X86::sub_8bit;835} else {836return false;837}838839SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);840841if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||842!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {843LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())844<< "\n");845return false;846}847848I.getOperand(1).setSubReg(SubIdx);849850I.setDesc(TII.get(X86::COPY));851return true;852}853854bool X86InstructionSelector::selectZext(MachineInstr &I,855MachineRegisterInfo &MRI,856MachineFunction &MF) const {857assert((I.getOpcode() == TargetOpcode::G_ZEXT) && "unexpected instruction");858859const Register DstReg = I.getOperand(0).getReg();860const Register SrcReg = I.getOperand(1).getReg();861862const LLT DstTy = MRI.getType(DstReg);863const LLT SrcTy = MRI.getType(SrcReg);864865assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(16)) &&866"8=>16 Zext is handled by tablegen");867assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(32)) &&868"8=>32 Zext is handled by tablegen");869assert(!(SrcTy == LLT::scalar(16) && DstTy == LLT::scalar(32)) &&870"16=>32 Zext is handled by tablegen");871assert(!(SrcTy == LLT::scalar(8) && DstTy == LLT::scalar(64)) &&872"8=>64 Zext is handled by tablegen");873assert(!(SrcTy == LLT::scalar(16) && DstTy == LLT::scalar(64)) &&874"16=>64 Zext is handled by tablegen");875assert(!(SrcTy == LLT::scalar(32) && DstTy == LLT::scalar(64)) &&876"32=>64 Zext is handled by tablegen");877878if (SrcTy != LLT::scalar(1))879return false;880881unsigned AndOpc;882if (DstTy == LLT::scalar(8))883AndOpc = X86::AND8ri;884else if (DstTy == LLT::scalar(16))885AndOpc = X86::AND16ri;886else if (DstTy == LLT::scalar(32))887AndOpc = X86::AND32ri;888else if (DstTy == LLT::scalar(64))889AndOpc = X86::AND64ri32;890else891return false;892893Register DefReg = SrcReg;894if (DstTy != LLT::scalar(8)) {895Register ImpDefReg =896MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI));897BuildMI(*I.getParent(), I, I.getDebugLoc(),898TII.get(TargetOpcode::IMPLICIT_DEF), ImpDefReg);899900DefReg = MRI.createVirtualRegister(getRegClass(DstTy, DstReg, MRI));901BuildMI(*I.getParent(), I, I.getDebugLoc(),902TII.get(TargetOpcode::INSERT_SUBREG), DefReg)903.addReg(ImpDefReg)904.addReg(SrcReg)905.addImm(X86::sub_8bit);906}907908MachineInstr &AndInst =909*BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(AndOpc), DstReg)910.addReg(DefReg)911.addImm(1);912913constrainSelectedInstRegOperands(AndInst, TII, TRI, RBI);914915I.eraseFromParent();916return true;917}918919bool X86InstructionSelector::selectAnyext(MachineInstr &I,920MachineRegisterInfo &MRI,921MachineFunction &MF) const {922assert((I.getOpcode() == TargetOpcode::G_ANYEXT) && "unexpected instruction");923924const Register DstReg = I.getOperand(0).getReg();925const Register SrcReg = I.getOperand(1).getReg();926927const LLT DstTy = MRI.getType(DstReg);928const LLT SrcTy = MRI.getType(SrcReg);929930const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);931const RegisterBank &SrcRB = *RBI.getRegBank(SrcReg, MRI, TRI);932933assert(DstRB.getID() == SrcRB.getID() &&934"G_ANYEXT input/output on different banks\n");935936assert(DstTy.getSizeInBits() > SrcTy.getSizeInBits() &&937"G_ANYEXT incorrect operand size");938939const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);940const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcRB);941942// If that's ANY_EXT of the value that lives on the floating class and goes943// into the vector class, just replace it with copy, as we are able to select944// it as a regular move.945if (canTurnIntoCOPY(SrcRC, DstRC))946return selectTurnIntoCOPY(I, MRI, SrcReg, SrcRC, DstReg, DstRC);947948if (DstRB.getID() != X86::GPRRegBankID)949return false;950951if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||952!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {953LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())954<< " operand\n");955return false;956}957958if (SrcRC == DstRC) {959I.setDesc(TII.get(X86::COPY));960return true;961}962963BuildMI(*I.getParent(), I, I.getDebugLoc(),964TII.get(TargetOpcode::SUBREG_TO_REG))965.addDef(DstReg)966.addImm(0)967.addReg(SrcReg)968.addImm(getSubRegIndex(SrcRC));969970I.eraseFromParent();971return true;972}973974bool X86InstructionSelector::selectCmp(MachineInstr &I,975MachineRegisterInfo &MRI,976MachineFunction &MF) const {977assert((I.getOpcode() == TargetOpcode::G_ICMP) && "unexpected instruction");978979X86::CondCode CC;980bool SwapArgs;981std::tie(CC, SwapArgs) = X86::getX86ConditionCode(982(CmpInst::Predicate)I.getOperand(1).getPredicate());983984Register LHS = I.getOperand(2).getReg();985Register RHS = I.getOperand(3).getReg();986987if (SwapArgs)988std::swap(LHS, RHS);989990unsigned OpCmp;991LLT Ty = MRI.getType(LHS);992993switch (Ty.getSizeInBits()) {994default:995return false;996case 8:997OpCmp = X86::CMP8rr;998break;999case 16:1000OpCmp = X86::CMP16rr;1001break;1002case 32:1003OpCmp = X86::CMP32rr;1004break;1005case 64:1006OpCmp = X86::CMP64rr;1007break;1008}10091010MachineInstr &CmpInst =1011*BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))1012.addReg(LHS)1013.addReg(RHS);10141015MachineInstr &SetInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),1016TII.get(X86::SETCCr), I.getOperand(0).getReg()).addImm(CC);10171018constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);1019constrainSelectedInstRegOperands(SetInst, TII, TRI, RBI);10201021I.eraseFromParent();1022return true;1023}10241025bool X86InstructionSelector::selectFCmp(MachineInstr &I,1026MachineRegisterInfo &MRI,1027MachineFunction &MF) const {1028assert((I.getOpcode() == TargetOpcode::G_FCMP) && "unexpected instruction");10291030Register LhsReg = I.getOperand(2).getReg();1031Register RhsReg = I.getOperand(3).getReg();1032CmpInst::Predicate Predicate =1033(CmpInst::Predicate)I.getOperand(1).getPredicate();10341035// FCMP_OEQ and FCMP_UNE cannot be checked with a single instruction.1036static const uint16_t SETFOpcTable[2][3] = {1037{X86::COND_E, X86::COND_NP, X86::AND8rr},1038{X86::COND_NE, X86::COND_P, X86::OR8rr}};1039const uint16_t *SETFOpc = nullptr;1040switch (Predicate) {1041default:1042break;1043case CmpInst::FCMP_OEQ:1044SETFOpc = &SETFOpcTable[0][0];1045break;1046case CmpInst::FCMP_UNE:1047SETFOpc = &SETFOpcTable[1][0];1048break;1049}10501051// Compute the opcode for the CMP instruction.1052unsigned OpCmp;1053LLT Ty = MRI.getType(LhsReg);1054switch (Ty.getSizeInBits()) {1055default:1056return false;1057case 32:1058OpCmp = X86::UCOMISSrr;1059break;1060case 64:1061OpCmp = X86::UCOMISDrr;1062break;1063}10641065Register ResultReg = I.getOperand(0).getReg();1066RBI.constrainGenericRegister(1067ResultReg,1068*getRegClass(LLT::scalar(8), *RBI.getRegBank(ResultReg, MRI, TRI)), MRI);1069if (SETFOpc) {1070MachineInstr &CmpInst =1071*BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))1072.addReg(LhsReg)1073.addReg(RhsReg);10741075Register FlagReg1 = MRI.createVirtualRegister(&X86::GR8RegClass);1076Register FlagReg2 = MRI.createVirtualRegister(&X86::GR8RegClass);1077MachineInstr &Set1 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),1078TII.get(X86::SETCCr), FlagReg1).addImm(SETFOpc[0]);1079MachineInstr &Set2 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),1080TII.get(X86::SETCCr), FlagReg2).addImm(SETFOpc[1]);1081MachineInstr &Set3 = *BuildMI(*I.getParent(), I, I.getDebugLoc(),1082TII.get(SETFOpc[2]), ResultReg)1083.addReg(FlagReg1)1084.addReg(FlagReg2);1085constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);1086constrainSelectedInstRegOperands(Set1, TII, TRI, RBI);1087constrainSelectedInstRegOperands(Set2, TII, TRI, RBI);1088constrainSelectedInstRegOperands(Set3, TII, TRI, RBI);10891090I.eraseFromParent();1091return true;1092}10931094X86::CondCode CC;1095bool SwapArgs;1096std::tie(CC, SwapArgs) = X86::getX86ConditionCode(Predicate);1097assert(CC <= X86::LAST_VALID_COND && "Unexpected condition code.");10981099if (SwapArgs)1100std::swap(LhsReg, RhsReg);11011102// Emit a compare of LHS/RHS.1103MachineInstr &CmpInst =1104*BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpCmp))1105.addReg(LhsReg)1106.addReg(RhsReg);11071108MachineInstr &Set =1109*BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::SETCCr), ResultReg).addImm(CC);1110constrainSelectedInstRegOperands(CmpInst, TII, TRI, RBI);1111constrainSelectedInstRegOperands(Set, TII, TRI, RBI);1112I.eraseFromParent();1113return true;1114}11151116bool X86InstructionSelector::selectUAddSub(MachineInstr &I,1117MachineRegisterInfo &MRI,1118MachineFunction &MF) const {1119assert((I.getOpcode() == TargetOpcode::G_UADDE ||1120I.getOpcode() == TargetOpcode::G_UADDO ||1121I.getOpcode() == TargetOpcode::G_USUBE ||1122I.getOpcode() == TargetOpcode::G_USUBO) &&1123"unexpected instruction");11241125const Register DstReg = I.getOperand(0).getReg();1126const Register CarryOutReg = I.getOperand(1).getReg();1127const Register Op0Reg = I.getOperand(2).getReg();1128const Register Op1Reg = I.getOperand(3).getReg();1129bool IsSub = I.getOpcode() == TargetOpcode::G_USUBE ||1130I.getOpcode() == TargetOpcode::G_USUBO;1131bool HasCarryIn = I.getOpcode() == TargetOpcode::G_UADDE ||1132I.getOpcode() == TargetOpcode::G_USUBE;11331134const LLT DstTy = MRI.getType(DstReg);1135assert(DstTy.isScalar() && "selectUAddSub only supported for scalar types");11361137// TODO: Handle immediate argument variants?1138unsigned OpADC, OpADD, OpSBB, OpSUB;1139switch (DstTy.getSizeInBits()) {1140case 8:1141OpADC = X86::ADC8rr;1142OpADD = X86::ADD8rr;1143OpSBB = X86::SBB8rr;1144OpSUB = X86::SUB8rr;1145break;1146case 16:1147OpADC = X86::ADC16rr;1148OpADD = X86::ADD16rr;1149OpSBB = X86::SBB16rr;1150OpSUB = X86::SUB16rr;1151break;1152case 32:1153OpADC = X86::ADC32rr;1154OpADD = X86::ADD32rr;1155OpSBB = X86::SBB32rr;1156OpSUB = X86::SUB32rr;1157break;1158case 64:1159OpADC = X86::ADC64rr;1160OpADD = X86::ADD64rr;1161OpSBB = X86::SBB64rr;1162OpSUB = X86::SUB64rr;1163break;1164default:1165llvm_unreachable("selectUAddSub unsupported type.");1166}11671168const RegisterBank &DstRB = *RBI.getRegBank(DstReg, MRI, TRI);1169const TargetRegisterClass *DstRC = getRegClass(DstTy, DstRB);11701171unsigned Opcode = IsSub ? OpSUB : OpADD;11721173// G_UADDE/G_USUBE - find CarryIn def instruction.1174if (HasCarryIn) {1175Register CarryInReg = I.getOperand(4).getReg();1176MachineInstr *Def = MRI.getVRegDef(CarryInReg);1177while (Def->getOpcode() == TargetOpcode::G_TRUNC) {1178CarryInReg = Def->getOperand(1).getReg();1179Def = MRI.getVRegDef(CarryInReg);1180}11811182// TODO - handle more CF generating instructions1183if (Def->getOpcode() == TargetOpcode::G_UADDE ||1184Def->getOpcode() == TargetOpcode::G_UADDO ||1185Def->getOpcode() == TargetOpcode::G_USUBE ||1186Def->getOpcode() == TargetOpcode::G_USUBO) {1187// carry set by prev ADD/SUB.1188BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY),1189X86::EFLAGS)1190.addReg(CarryInReg);11911192if (!RBI.constrainGenericRegister(CarryInReg, *DstRC, MRI))1193return false;11941195Opcode = IsSub ? OpSBB : OpADC;1196} else if (auto val = getIConstantVRegVal(CarryInReg, MRI)) {1197// carry is constant, support only 0.1198if (*val != 0)1199return false;12001201Opcode = IsSub ? OpSUB : OpADD;1202} else1203return false;1204}12051206MachineInstr &Inst =1207*BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode), DstReg)1208.addReg(Op0Reg)1209.addReg(Op1Reg);12101211BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), CarryOutReg)1212.addReg(X86::EFLAGS);12131214if (!constrainSelectedInstRegOperands(Inst, TII, TRI, RBI) ||1215!RBI.constrainGenericRegister(CarryOutReg, *DstRC, MRI))1216return false;12171218I.eraseFromParent();1219return true;1220}12211222bool X86InstructionSelector::selectExtract(MachineInstr &I,1223MachineRegisterInfo &MRI,1224MachineFunction &MF) const {1225assert((I.getOpcode() == TargetOpcode::G_EXTRACT) &&1226"unexpected instruction");12271228const Register DstReg = I.getOperand(0).getReg();1229const Register SrcReg = I.getOperand(1).getReg();1230int64_t Index = I.getOperand(2).getImm();12311232const LLT DstTy = MRI.getType(DstReg);1233const LLT SrcTy = MRI.getType(SrcReg);12341235// Meanwile handle vector type only.1236if (!DstTy.isVector())1237return false;12381239if (Index % DstTy.getSizeInBits() != 0)1240return false; // Not extract subvector.12411242if (Index == 0) {1243// Replace by extract subreg copy.1244if (!emitExtractSubreg(DstReg, SrcReg, I, MRI, MF))1245return false;12461247I.eraseFromParent();1248return true;1249}12501251bool HasAVX = STI.hasAVX();1252bool HasAVX512 = STI.hasAVX512();1253bool HasVLX = STI.hasVLX();12541255if (SrcTy.getSizeInBits() == 256 && DstTy.getSizeInBits() == 128) {1256if (HasVLX)1257I.setDesc(TII.get(X86::VEXTRACTF32x4Z256rr));1258else if (HasAVX)1259I.setDesc(TII.get(X86::VEXTRACTF128rr));1260else1261return false;1262} else if (SrcTy.getSizeInBits() == 512 && HasAVX512) {1263if (DstTy.getSizeInBits() == 128)1264I.setDesc(TII.get(X86::VEXTRACTF32x4Zrr));1265else if (DstTy.getSizeInBits() == 256)1266I.setDesc(TII.get(X86::VEXTRACTF64x4Zrr));1267else1268return false;1269} else1270return false;12711272// Convert to X86 VEXTRACT immediate.1273Index = Index / DstTy.getSizeInBits();1274I.getOperand(2).setImm(Index);12751276return constrainSelectedInstRegOperands(I, TII, TRI, RBI);1277}12781279bool X86InstructionSelector::emitExtractSubreg(unsigned DstReg, unsigned SrcReg,1280MachineInstr &I,1281MachineRegisterInfo &MRI,1282MachineFunction &MF) const {1283const LLT DstTy = MRI.getType(DstReg);1284const LLT SrcTy = MRI.getType(SrcReg);1285unsigned SubIdx = X86::NoSubRegister;12861287if (!DstTy.isVector() || !SrcTy.isVector())1288return false;12891290assert(SrcTy.getSizeInBits() > DstTy.getSizeInBits() &&1291"Incorrect Src/Dst register size");12921293if (DstTy.getSizeInBits() == 128)1294SubIdx = X86::sub_xmm;1295else if (DstTy.getSizeInBits() == 256)1296SubIdx = X86::sub_ymm;1297else1298return false;12991300const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);1301const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);13021303SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubIdx);13041305if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||1306!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {1307LLVM_DEBUG(dbgs() << "Failed to constrain EXTRACT_SUBREG\n");1308return false;1309}13101311BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY), DstReg)1312.addReg(SrcReg, 0, SubIdx);13131314return true;1315}13161317bool X86InstructionSelector::emitInsertSubreg(unsigned DstReg, unsigned SrcReg,1318MachineInstr &I,1319MachineRegisterInfo &MRI,1320MachineFunction &MF) const {1321const LLT DstTy = MRI.getType(DstReg);1322const LLT SrcTy = MRI.getType(SrcReg);1323unsigned SubIdx = X86::NoSubRegister;13241325// TODO: support scalar types1326if (!DstTy.isVector() || !SrcTy.isVector())1327return false;13281329assert(SrcTy.getSizeInBits() < DstTy.getSizeInBits() &&1330"Incorrect Src/Dst register size");13311332if (SrcTy.getSizeInBits() == 128)1333SubIdx = X86::sub_xmm;1334else if (SrcTy.getSizeInBits() == 256)1335SubIdx = X86::sub_ymm;1336else1337return false;13381339const TargetRegisterClass *SrcRC = getRegClass(SrcTy, SrcReg, MRI);1340const TargetRegisterClass *DstRC = getRegClass(DstTy, DstReg, MRI);13411342if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI) ||1343!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {1344LLVM_DEBUG(dbgs() << "Failed to constrain INSERT_SUBREG\n");1345return false;1346}13471348BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::COPY))1349.addReg(DstReg, RegState::DefineNoRead, SubIdx)1350.addReg(SrcReg);13511352return true;1353}13541355bool X86InstructionSelector::selectInsert(MachineInstr &I,1356MachineRegisterInfo &MRI,1357MachineFunction &MF) const {1358assert((I.getOpcode() == TargetOpcode::G_INSERT) && "unexpected instruction");13591360const Register DstReg = I.getOperand(0).getReg();1361const Register SrcReg = I.getOperand(1).getReg();1362const Register InsertReg = I.getOperand(2).getReg();1363int64_t Index = I.getOperand(3).getImm();13641365const LLT DstTy = MRI.getType(DstReg);1366const LLT InsertRegTy = MRI.getType(InsertReg);13671368// Meanwile handle vector type only.1369if (!DstTy.isVector())1370return false;13711372if (Index % InsertRegTy.getSizeInBits() != 0)1373return false; // Not insert subvector.13741375if (Index == 0 && MRI.getVRegDef(SrcReg)->isImplicitDef()) {1376// Replace by subreg copy.1377if (!emitInsertSubreg(DstReg, InsertReg, I, MRI, MF))1378return false;13791380I.eraseFromParent();1381return true;1382}13831384bool HasAVX = STI.hasAVX();1385bool HasAVX512 = STI.hasAVX512();1386bool HasVLX = STI.hasVLX();13871388if (DstTy.getSizeInBits() == 256 && InsertRegTy.getSizeInBits() == 128) {1389if (HasVLX)1390I.setDesc(TII.get(X86::VINSERTF32x4Z256rr));1391else if (HasAVX)1392I.setDesc(TII.get(X86::VINSERTF128rr));1393else1394return false;1395} else if (DstTy.getSizeInBits() == 512 && HasAVX512) {1396if (InsertRegTy.getSizeInBits() == 128)1397I.setDesc(TII.get(X86::VINSERTF32x4Zrr));1398else if (InsertRegTy.getSizeInBits() == 256)1399I.setDesc(TII.get(X86::VINSERTF64x4Zrr));1400else1401return false;1402} else1403return false;14041405// Convert to X86 VINSERT immediate.1406Index = Index / InsertRegTy.getSizeInBits();14071408I.getOperand(3).setImm(Index);14091410return constrainSelectedInstRegOperands(I, TII, TRI, RBI);1411}14121413bool X86InstructionSelector::selectUnmergeValues(1414MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) {1415assert((I.getOpcode() == TargetOpcode::G_UNMERGE_VALUES) &&1416"unexpected instruction");14171418// Split to extracts.1419unsigned NumDefs = I.getNumOperands() - 1;1420Register SrcReg = I.getOperand(NumDefs).getReg();1421unsigned DefSize = MRI.getType(I.getOperand(0).getReg()).getSizeInBits();14221423for (unsigned Idx = 0; Idx < NumDefs; ++Idx) {1424MachineInstr &ExtrInst =1425*BuildMI(*I.getParent(), I, I.getDebugLoc(),1426TII.get(TargetOpcode::G_EXTRACT), I.getOperand(Idx).getReg())1427.addReg(SrcReg)1428.addImm(Idx * DefSize);14291430if (!select(ExtrInst))1431return false;1432}14331434I.eraseFromParent();1435return true;1436}14371438bool X86InstructionSelector::selectMergeValues(1439MachineInstr &I, MachineRegisterInfo &MRI, MachineFunction &MF) {1440assert((I.getOpcode() == TargetOpcode::G_MERGE_VALUES ||1441I.getOpcode() == TargetOpcode::G_CONCAT_VECTORS) &&1442"unexpected instruction");14431444// Split to inserts.1445Register DstReg = I.getOperand(0).getReg();1446Register SrcReg0 = I.getOperand(1).getReg();14471448const LLT DstTy = MRI.getType(DstReg);1449const LLT SrcTy = MRI.getType(SrcReg0);1450unsigned SrcSize = SrcTy.getSizeInBits();14511452const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);14531454// For the first src use insertSubReg.1455Register DefReg = MRI.createGenericVirtualRegister(DstTy);1456MRI.setRegBank(DefReg, RegBank);1457if (!emitInsertSubreg(DefReg, I.getOperand(1).getReg(), I, MRI, MF))1458return false;14591460for (unsigned Idx = 2; Idx < I.getNumOperands(); ++Idx) {1461Register Tmp = MRI.createGenericVirtualRegister(DstTy);1462MRI.setRegBank(Tmp, RegBank);14631464MachineInstr &InsertInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),1465TII.get(TargetOpcode::G_INSERT), Tmp)1466.addReg(DefReg)1467.addReg(I.getOperand(Idx).getReg())1468.addImm((Idx - 1) * SrcSize);14691470DefReg = Tmp;14711472if (!select(InsertInst))1473return false;1474}14751476MachineInstr &CopyInst = *BuildMI(*I.getParent(), I, I.getDebugLoc(),1477TII.get(TargetOpcode::COPY), DstReg)1478.addReg(DefReg);14791480if (!select(CopyInst))1481return false;14821483I.eraseFromParent();1484return true;1485}14861487bool X86InstructionSelector::selectCondBranch(MachineInstr &I,1488MachineRegisterInfo &MRI,1489MachineFunction &MF) const {1490assert((I.getOpcode() == TargetOpcode::G_BRCOND) && "unexpected instruction");14911492const Register CondReg = I.getOperand(0).getReg();1493MachineBasicBlock *DestMBB = I.getOperand(1).getMBB();14941495MachineInstr &TestInst =1496*BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::TEST8ri))1497.addReg(CondReg)1498.addImm(1);1499BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::JCC_1))1500.addMBB(DestMBB).addImm(X86::COND_NE);15011502constrainSelectedInstRegOperands(TestInst, TII, TRI, RBI);15031504I.eraseFromParent();1505return true;1506}15071508bool X86InstructionSelector::materializeFP(MachineInstr &I,1509MachineRegisterInfo &MRI,1510MachineFunction &MF) const {1511assert((I.getOpcode() == TargetOpcode::G_FCONSTANT) &&1512"unexpected instruction");15131514// Can't handle alternate code models yet.1515CodeModel::Model CM = TM.getCodeModel();1516if (CM != CodeModel::Small && CM != CodeModel::Large)1517return false;15181519const Register DstReg = I.getOperand(0).getReg();1520const LLT DstTy = MRI.getType(DstReg);1521const RegisterBank &RegBank = *RBI.getRegBank(DstReg, MRI, TRI);1522// Create the load from the constant pool.1523const ConstantFP *CFP = I.getOperand(1).getFPImm();1524const auto &DL = MF.getDataLayout();1525Align Alignment = DL.getPrefTypeAlign(CFP->getType());1526const DebugLoc &DbgLoc = I.getDebugLoc();15271528unsigned Opc =1529getLoadStoreOp(DstTy, RegBank, TargetOpcode::G_LOAD, Alignment);15301531unsigned CPI = MF.getConstantPool()->getConstantPoolIndex(CFP, Alignment);1532MachineInstr *LoadInst = nullptr;1533unsigned char OpFlag = STI.classifyLocalReference(nullptr);15341535if (CM == CodeModel::Large && STI.is64Bit()) {1536// Under X86-64 non-small code model, GV (and friends) are 64-bits, so1537// they cannot be folded into immediate fields.15381539Register AddrReg = MRI.createVirtualRegister(&X86::GR64RegClass);1540BuildMI(*I.getParent(), I, DbgLoc, TII.get(X86::MOV64ri), AddrReg)1541.addConstantPoolIndex(CPI, 0, OpFlag);15421543MachineMemOperand *MMO = MF.getMachineMemOperand(1544MachinePointerInfo::getConstantPool(MF), MachineMemOperand::MOLoad,1545LLT::pointer(0, DL.getPointerSizeInBits()), Alignment);15461547LoadInst =1548addDirectMem(BuildMI(*I.getParent(), I, DbgLoc, TII.get(Opc), DstReg),1549AddrReg)1550.addMemOperand(MMO);15511552} else if (CM == CodeModel::Small || !STI.is64Bit()) {1553// Handle the case when globals fit in our immediate field.1554// This is true for X86-32 always and X86-64 when in -mcmodel=small mode.15551556// x86-32 PIC requires a PIC base register for constant pools.1557unsigned PICBase = 0;1558if (OpFlag == X86II::MO_PIC_BASE_OFFSET || OpFlag == X86II::MO_GOTOFF) {1559// PICBase can be allocated by TII.getGlobalBaseReg(&MF).1560// In DAGISEL the code that initialize it generated by the CGBR pass.1561return false; // TODO support the mode.1562} else if (STI.is64Bit() && TM.getCodeModel() == CodeModel::Small)1563PICBase = X86::RIP;15641565LoadInst = addConstantPoolReference(1566BuildMI(*I.getParent(), I, DbgLoc, TII.get(Opc), DstReg), CPI, PICBase,1567OpFlag);1568} else1569return false;15701571constrainSelectedInstRegOperands(*LoadInst, TII, TRI, RBI);1572I.eraseFromParent();1573return true;1574}15751576bool X86InstructionSelector::selectImplicitDefOrPHI(1577MachineInstr &I, MachineRegisterInfo &MRI) const {1578assert((I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF ||1579I.getOpcode() == TargetOpcode::G_PHI) &&1580"unexpected instruction");15811582Register DstReg = I.getOperand(0).getReg();15831584if (!MRI.getRegClassOrNull(DstReg)) {1585const LLT DstTy = MRI.getType(DstReg);1586const TargetRegisterClass *RC = getRegClass(DstTy, DstReg, MRI);15871588if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) {1589LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())1590<< " operand\n");1591return false;1592}1593}15941595if (I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF)1596I.setDesc(TII.get(X86::IMPLICIT_DEF));1597else1598I.setDesc(TII.get(X86::PHI));15991600return true;1601}16021603bool X86InstructionSelector::selectMulDivRem(MachineInstr &I,1604MachineRegisterInfo &MRI,1605MachineFunction &MF) const {1606// The implementation of this function is adapted from X86FastISel.1607assert((I.getOpcode() == TargetOpcode::G_MUL ||1608I.getOpcode() == TargetOpcode::G_SMULH ||1609I.getOpcode() == TargetOpcode::G_UMULH ||1610I.getOpcode() == TargetOpcode::G_SDIV ||1611I.getOpcode() == TargetOpcode::G_SREM ||1612I.getOpcode() == TargetOpcode::G_UDIV ||1613I.getOpcode() == TargetOpcode::G_UREM) &&1614"unexpected instruction");16151616const Register DstReg = I.getOperand(0).getReg();1617const Register Op1Reg = I.getOperand(1).getReg();1618const Register Op2Reg = I.getOperand(2).getReg();16191620const LLT RegTy = MRI.getType(DstReg);1621assert(RegTy == MRI.getType(Op1Reg) && RegTy == MRI.getType(Op2Reg) &&1622"Arguments and return value types must match");16231624const RegisterBank *RegRB = RBI.getRegBank(DstReg, MRI, TRI);1625if (!RegRB || RegRB->getID() != X86::GPRRegBankID)1626return false;16271628const static unsigned NumTypes = 4; // i8, i16, i32, i641629const static unsigned NumOps = 7; // SDiv/SRem/UDiv/URem/Mul/SMulH/UMulh1630const static bool S = true; // IsSigned1631const static bool U = false; // !IsSigned1632const static unsigned Copy = TargetOpcode::COPY;16331634// For the X86 IDIV instruction, in most cases the dividend1635// (numerator) must be in a specific register pair highreg:lowreg,1636// producing the quotient in lowreg and the remainder in highreg.1637// For most data types, to set up the instruction, the dividend is1638// copied into lowreg, and lowreg is sign-extended into highreg. The1639// exception is i8, where the dividend is defined as a single register rather1640// than a register pair, and we therefore directly sign-extend the dividend1641// into lowreg, instead of copying, and ignore the highreg.1642const static struct MulDivRemEntry {1643// The following portion depends only on the data type.1644unsigned SizeInBits;1645unsigned LowInReg; // low part of the register pair1646unsigned HighInReg; // high part of the register pair1647// The following portion depends on both the data type and the operation.1648struct MulDivRemResult {1649unsigned OpMulDivRem; // The specific MUL/DIV opcode to use.1650unsigned OpSignExtend; // Opcode for sign-extending lowreg into1651// highreg, or copying a zero into highreg.1652unsigned OpCopy; // Opcode for copying dividend into lowreg, or1653// zero/sign-extending into lowreg for i8.1654unsigned ResultReg; // Register containing the desired result.1655bool IsOpSigned; // Whether to use signed or unsigned form.1656} ResultTable[NumOps];1657} OpTable[NumTypes] = {1658{8,1659X86::AX,16600,1661{1662{X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AL, S}, // SDiv1663{X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AH, S}, // SRem1664{X86::DIV8r, 0, X86::MOVZX16rr8, X86::AL, U}, // UDiv1665{X86::DIV8r, 0, X86::MOVZX16rr8, X86::AH, U}, // URem1666{X86::IMUL8r, 0, X86::MOVSX16rr8, X86::AL, S}, // Mul1667{X86::IMUL8r, 0, X86::MOVSX16rr8, X86::AH, S}, // SMulH1668{X86::MUL8r, 0, X86::MOVZX16rr8, X86::AH, U}, // UMulH1669}}, // i81670{16,1671X86::AX,1672X86::DX,1673{1674{X86::IDIV16r, X86::CWD, Copy, X86::AX, S}, // SDiv1675{X86::IDIV16r, X86::CWD, Copy, X86::DX, S}, // SRem1676{X86::DIV16r, X86::MOV32r0, Copy, X86::AX, U}, // UDiv1677{X86::DIV16r, X86::MOV32r0, Copy, X86::DX, U}, // URem1678{X86::IMUL16r, X86::MOV32r0, Copy, X86::AX, S}, // Mul1679{X86::IMUL16r, X86::MOV32r0, Copy, X86::DX, S}, // SMulH1680{X86::MUL16r, X86::MOV32r0, Copy, X86::DX, U}, // UMulH1681}}, // i161682{32,1683X86::EAX,1684X86::EDX,1685{1686{X86::IDIV32r, X86::CDQ, Copy, X86::EAX, S}, // SDiv1687{X86::IDIV32r, X86::CDQ, Copy, X86::EDX, S}, // SRem1688{X86::DIV32r, X86::MOV32r0, Copy, X86::EAX, U}, // UDiv1689{X86::DIV32r, X86::MOV32r0, Copy, X86::EDX, U}, // URem1690{X86::IMUL32r, X86::MOV32r0, Copy, X86::EAX, S}, // Mul1691{X86::IMUL32r, X86::MOV32r0, Copy, X86::EDX, S}, // SMulH1692{X86::MUL32r, X86::MOV32r0, Copy, X86::EDX, U}, // UMulH1693}}, // i321694{64,1695X86::RAX,1696X86::RDX,1697{1698{X86::IDIV64r, X86::CQO, Copy, X86::RAX, S}, // SDiv1699{X86::IDIV64r, X86::CQO, Copy, X86::RDX, S}, // SRem1700{X86::DIV64r, X86::MOV32r0, Copy, X86::RAX, U}, // UDiv1701{X86::DIV64r, X86::MOV32r0, Copy, X86::RDX, U}, // URem1702{X86::IMUL64r, X86::MOV32r0, Copy, X86::RAX, S}, // Mul1703{X86::IMUL64r, X86::MOV32r0, Copy, X86::RDX, S}, // SMulH1704{X86::MUL64r, X86::MOV32r0, Copy, X86::RDX, U}, // UMulH1705}}, // i641706};17071708auto OpEntryIt = llvm::find_if(OpTable, [RegTy](const MulDivRemEntry &El) {1709return El.SizeInBits == RegTy.getSizeInBits();1710});1711if (OpEntryIt == std::end(OpTable))1712return false;17131714unsigned OpIndex;1715switch (I.getOpcode()) {1716default:1717llvm_unreachable("Unexpected mul/div/rem opcode");1718case TargetOpcode::G_SDIV:1719OpIndex = 0;1720break;1721case TargetOpcode::G_SREM:1722OpIndex = 1;1723break;1724case TargetOpcode::G_UDIV:1725OpIndex = 2;1726break;1727case TargetOpcode::G_UREM:1728OpIndex = 3;1729break;1730case TargetOpcode::G_MUL:1731OpIndex = 4;1732break;1733case TargetOpcode::G_SMULH:1734OpIndex = 5;1735break;1736case TargetOpcode::G_UMULH:1737OpIndex = 6;1738break;1739}17401741const MulDivRemEntry &TypeEntry = *OpEntryIt;1742const MulDivRemEntry::MulDivRemResult &OpEntry =1743TypeEntry.ResultTable[OpIndex];17441745const TargetRegisterClass *RegRC = getRegClass(RegTy, *RegRB);1746if (!RBI.constrainGenericRegister(Op1Reg, *RegRC, MRI) ||1747!RBI.constrainGenericRegister(Op2Reg, *RegRC, MRI) ||1748!RBI.constrainGenericRegister(DstReg, *RegRC, MRI)) {1749LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode())1750<< " operand\n");1751return false;1752}17531754// Move op1 into low-order input register.1755BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpEntry.OpCopy),1756TypeEntry.LowInReg)1757.addReg(Op1Reg);17581759// Zero-extend or sign-extend into high-order input register.1760if (OpEntry.OpSignExtend) {1761if (OpEntry.IsOpSigned)1762BuildMI(*I.getParent(), I, I.getDebugLoc(),1763TII.get(OpEntry.OpSignExtend));1764else {1765Register Zero32 = MRI.createVirtualRegister(&X86::GR32RegClass);1766BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::MOV32r0),1767Zero32);17681769// Copy the zero into the appropriate sub/super/identical physical1770// register. Unfortunately the operations needed are not uniform enough1771// to fit neatly into the table above.1772if (RegTy.getSizeInBits() == 16) {1773BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Copy),1774TypeEntry.HighInReg)1775.addReg(Zero32, 0, X86::sub_16bit);1776} else if (RegTy.getSizeInBits() == 32) {1777BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Copy),1778TypeEntry.HighInReg)1779.addReg(Zero32);1780} else if (RegTy.getSizeInBits() == 64) {1781BuildMI(*I.getParent(), I, I.getDebugLoc(),1782TII.get(TargetOpcode::SUBREG_TO_REG), TypeEntry.HighInReg)1783.addImm(0)1784.addReg(Zero32)1785.addImm(X86::sub_32bit);1786}1787}1788}17891790// Generate the DIV/IDIV/MUL/IMUL instruction.1791BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(OpEntry.OpMulDivRem))1792.addReg(Op2Reg);17931794// For i8 remainder, we can't reference ah directly, as we'll end1795// up with bogus copies like %r9b = COPY %ah. Reference ax1796// instead to prevent ah references in a rex instruction.1797//1798// The current assumption of the fast register allocator is that isel1799// won't generate explicit references to the GR8_NOREX registers. If1800// the allocator and/or the backend get enhanced to be more robust in1801// that regard, this can be, and should be, removed.1802if (OpEntry.ResultReg == X86::AH && STI.is64Bit()) {1803Register SourceSuperReg = MRI.createVirtualRegister(&X86::GR16RegClass);1804Register ResultSuperReg = MRI.createVirtualRegister(&X86::GR16RegClass);1805BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Copy), SourceSuperReg)1806.addReg(X86::AX);18071808// Shift AX right by 8 bits instead of using AH.1809BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(X86::SHR16ri),1810ResultSuperReg)1811.addReg(SourceSuperReg)1812.addImm(8);18131814// Now reference the 8-bit subreg of the result.1815BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(TargetOpcode::COPY),1816DstReg)1817.addReg(ResultSuperReg, 0, X86::sub_8bit);1818} else {1819BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(TargetOpcode::COPY),1820DstReg)1821.addReg(OpEntry.ResultReg);1822}1823I.eraseFromParent();18241825return true;1826}18271828bool X86InstructionSelector::selectSelect(MachineInstr &I,1829MachineRegisterInfo &MRI,1830MachineFunction &MF) const {1831GSelect &Sel = cast<GSelect>(I);1832unsigned DstReg = Sel.getReg(0);1833BuildMI(*Sel.getParent(), Sel, Sel.getDebugLoc(), TII.get(X86::TEST32rr))1834.addReg(Sel.getCondReg())1835.addReg(Sel.getCondReg());18361837unsigned OpCmp;1838LLT Ty = MRI.getType(DstReg);1839switch (Ty.getSizeInBits()) {1840default:1841return false;1842case 8:1843OpCmp = X86::CMOV_GR8;1844break;1845case 16:1846OpCmp = STI.canUseCMOV() ? X86::CMOV16rr : X86::CMOV_GR16;1847break;1848case 32:1849OpCmp = STI.canUseCMOV() ? X86::CMOV32rr : X86::CMOV_GR32;1850break;1851case 64:1852assert(STI.is64Bit() && STI.canUseCMOV());1853OpCmp = X86::CMOV64rr;1854break;1855}1856BuildMI(*Sel.getParent(), Sel, Sel.getDebugLoc(), TII.get(OpCmp), DstReg)1857.addReg(Sel.getTrueReg())1858.addReg(Sel.getFalseReg())1859.addImm(X86::COND_E);18601861const TargetRegisterClass *DstRC = getRegClass(Ty, DstReg, MRI);1862if (!RBI.constrainGenericRegister(DstReg, *DstRC, MRI)) {1863LLVM_DEBUG(dbgs() << "Failed to constrain CMOV\n");1864return false;1865}18661867Sel.eraseFromParent();1868return true;1869}18701871InstructionSelector *1872llvm::createX86InstructionSelector(const X86TargetMachine &TM,1873const X86Subtarget &Subtarget,1874const X86RegisterBankInfo &RBI) {1875return new X86InstructionSelector(TM, Subtarget, RBI);1876}187718781879