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