10b57cec5SDimitry Andric //===-- X86RegisterInfo.cpp - X86 Register Information --------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains the X86 implementation of the TargetRegisterInfo class.
100b57cec5SDimitry Andric // This file is responsible for the frame pointer elimination optimization
110b57cec5SDimitry Andric // on X86.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric #include "X86RegisterInfo.h"
160b57cec5SDimitry Andric #include "X86FrameLowering.h"
170b57cec5SDimitry Andric #include "X86MachineFunctionInfo.h"
180b57cec5SDimitry Andric #include "X86Subtarget.h"
190b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
200b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
21e8d8bef9SDimitry Andric #include "llvm/ADT/SmallSet.h"
22e8d8bef9SDimitry Andric #include "llvm/CodeGen/LiveRegMatrix.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/TargetFrameLowering.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
2981ad6265SDimitry Andric #include "llvm/CodeGen/TileShapeInfo.h"
3081ad6265SDimitry Andric #include "llvm/CodeGen/VirtRegMap.h"
310b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
320b57cec5SDimitry Andric #include "llvm/IR/Function.h"
330b57cec5SDimitry Andric #include "llvm/IR/Type.h"
340b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
350b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
360b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
370b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h"
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric using namespace llvm;
400b57cec5SDimitry Andric
410b57cec5SDimitry Andric #define GET_REGINFO_TARGET_DESC
420b57cec5SDimitry Andric #include "X86GenRegisterInfo.inc"
430b57cec5SDimitry Andric
440b57cec5SDimitry Andric static cl::opt<bool>
450b57cec5SDimitry Andric EnableBasePointer("x86-use-base-pointer", cl::Hidden, cl::init(true),
460b57cec5SDimitry Andric cl::desc("Enable use of a base pointer for complex stack frames"));
470b57cec5SDimitry Andric
X86RegisterInfo(const Triple & TT)480b57cec5SDimitry Andric X86RegisterInfo::X86RegisterInfo(const Triple &TT)
490b57cec5SDimitry Andric : X86GenRegisterInfo((TT.isArch64Bit() ? X86::RIP : X86::EIP),
500b57cec5SDimitry Andric X86_MC::getDwarfRegFlavour(TT, false),
510b57cec5SDimitry Andric X86_MC::getDwarfRegFlavour(TT, true),
520b57cec5SDimitry Andric (TT.isArch64Bit() ? X86::RIP : X86::EIP)) {
530b57cec5SDimitry Andric X86_MC::initLLVMToSEHAndCVRegMapping(this);
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric // Cache some information.
560b57cec5SDimitry Andric Is64Bit = TT.isArch64Bit();
570b57cec5SDimitry Andric IsWin64 = Is64Bit && TT.isOSWindows();
580b57cec5SDimitry Andric
590b57cec5SDimitry Andric // Use a callee-saved register as the base pointer. These registers must
600b57cec5SDimitry Andric // not conflict with any ABI requirements. For example, in 32-bit mode PIC
610b57cec5SDimitry Andric // requires GOT in the EBX register before function calls via PLT GOT pointer.
620b57cec5SDimitry Andric if (Is64Bit) {
630b57cec5SDimitry Andric SlotSize = 8;
640b57cec5SDimitry Andric // This matches the simplified 32-bit pointer code in the data layout
650b57cec5SDimitry Andric // computation.
660b57cec5SDimitry Andric // FIXME: Should use the data layout?
67fe6060f1SDimitry Andric bool Use64BitReg = !TT.isX32();
680b57cec5SDimitry Andric StackPtr = Use64BitReg ? X86::RSP : X86::ESP;
690b57cec5SDimitry Andric FramePtr = Use64BitReg ? X86::RBP : X86::EBP;
700b57cec5SDimitry Andric BasePtr = Use64BitReg ? X86::RBX : X86::EBX;
710b57cec5SDimitry Andric } else {
720b57cec5SDimitry Andric SlotSize = 4;
730b57cec5SDimitry Andric StackPtr = X86::ESP;
740b57cec5SDimitry Andric FramePtr = X86::EBP;
750b57cec5SDimitry Andric BasePtr = X86::ESI;
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric int
getSEHRegNum(unsigned i) const800b57cec5SDimitry Andric X86RegisterInfo::getSEHRegNum(unsigned i) const {
810b57cec5SDimitry Andric return getEncodingValue(i);
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric
840b57cec5SDimitry Andric const TargetRegisterClass *
getSubClassWithSubReg(const TargetRegisterClass * RC,unsigned Idx) const850b57cec5SDimitry Andric X86RegisterInfo::getSubClassWithSubReg(const TargetRegisterClass *RC,
860b57cec5SDimitry Andric unsigned Idx) const {
870b57cec5SDimitry Andric // The sub_8bit sub-register index is more constrained in 32-bit mode.
880b57cec5SDimitry Andric // It behaves just like the sub_8bit_hi index.
890b57cec5SDimitry Andric if (!Is64Bit && Idx == X86::sub_8bit)
900b57cec5SDimitry Andric Idx = X86::sub_8bit_hi;
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric // Forward to TableGen's default version.
930b57cec5SDimitry Andric return X86GenRegisterInfo::getSubClassWithSubReg(RC, Idx);
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric
960b57cec5SDimitry Andric const TargetRegisterClass *
getMatchingSuperRegClass(const TargetRegisterClass * A,const TargetRegisterClass * B,unsigned SubIdx) const970b57cec5SDimitry Andric X86RegisterInfo::getMatchingSuperRegClass(const TargetRegisterClass *A,
980b57cec5SDimitry Andric const TargetRegisterClass *B,
990b57cec5SDimitry Andric unsigned SubIdx) const {
1000b57cec5SDimitry Andric // The sub_8bit sub-register index is more constrained in 32-bit mode.
1010b57cec5SDimitry Andric if (!Is64Bit && SubIdx == X86::sub_8bit) {
1020b57cec5SDimitry Andric A = X86GenRegisterInfo::getSubClassWithSubReg(A, X86::sub_8bit_hi);
1030b57cec5SDimitry Andric if (!A)
1040b57cec5SDimitry Andric return nullptr;
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric return X86GenRegisterInfo::getMatchingSuperRegClass(A, B, SubIdx);
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric
1090b57cec5SDimitry Andric const TargetRegisterClass *
getLargestLegalSuperClass(const TargetRegisterClass * RC,const MachineFunction & MF) const1100b57cec5SDimitry Andric X86RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC,
1110b57cec5SDimitry Andric const MachineFunction &MF) const {
1120b57cec5SDimitry Andric // Don't allow super-classes of GR8_NOREX. This class is only used after
1130b57cec5SDimitry Andric // extracting sub_8bit_hi sub-registers. The H sub-registers cannot be copied
1140b57cec5SDimitry Andric // to the full GR8 register class in 64-bit mode, so we cannot allow the
1150b57cec5SDimitry Andric // reigster class inflation.
1160b57cec5SDimitry Andric //
1170b57cec5SDimitry Andric // The GR8_NOREX class is always used in a way that won't be constrained to a
1180b57cec5SDimitry Andric // sub-class, so sub-classes like GR8_ABCD_L are allowed to expand to the
1190b57cec5SDimitry Andric // full GR8 class.
1200b57cec5SDimitry Andric if (RC == &X86::GR8_NOREXRegClass)
1210b57cec5SDimitry Andric return RC;
1220b57cec5SDimitry Andric
1230b57cec5SDimitry Andric const X86Subtarget &Subtarget = MF.getSubtarget<X86Subtarget>();
1240b57cec5SDimitry Andric
1250b57cec5SDimitry Andric const TargetRegisterClass *Super = RC;
1260b57cec5SDimitry Andric TargetRegisterClass::sc_iterator I = RC->getSuperClasses();
1270b57cec5SDimitry Andric do {
1280b57cec5SDimitry Andric switch (Super->getID()) {
1290b57cec5SDimitry Andric case X86::FR32RegClassID:
1300b57cec5SDimitry Andric case X86::FR64RegClassID:
1310b57cec5SDimitry Andric // If AVX-512 isn't supported we should only inflate to these classes.
1320b57cec5SDimitry Andric if (!Subtarget.hasAVX512() &&
1330b57cec5SDimitry Andric getRegSizeInBits(*Super) == getRegSizeInBits(*RC))
1340b57cec5SDimitry Andric return Super;
1350b57cec5SDimitry Andric break;
1360b57cec5SDimitry Andric case X86::VR128RegClassID:
1370b57cec5SDimitry Andric case X86::VR256RegClassID:
1380b57cec5SDimitry Andric // If VLX isn't supported we should only inflate to these classes.
1390b57cec5SDimitry Andric if (!Subtarget.hasVLX() &&
1400b57cec5SDimitry Andric getRegSizeInBits(*Super) == getRegSizeInBits(*RC))
1410b57cec5SDimitry Andric return Super;
1420b57cec5SDimitry Andric break;
1430b57cec5SDimitry Andric case X86::VR128XRegClassID:
1440b57cec5SDimitry Andric case X86::VR256XRegClassID:
1450b57cec5SDimitry Andric // If VLX isn't support we shouldn't inflate to these classes.
1460b57cec5SDimitry Andric if (Subtarget.hasVLX() &&
1470b57cec5SDimitry Andric getRegSizeInBits(*Super) == getRegSizeInBits(*RC))
1480b57cec5SDimitry Andric return Super;
1490b57cec5SDimitry Andric break;
1500b57cec5SDimitry Andric case X86::FR32XRegClassID:
1510b57cec5SDimitry Andric case X86::FR64XRegClassID:
1520b57cec5SDimitry Andric // If AVX-512 isn't support we shouldn't inflate to these classes.
1530b57cec5SDimitry Andric if (Subtarget.hasAVX512() &&
1540b57cec5SDimitry Andric getRegSizeInBits(*Super) == getRegSizeInBits(*RC))
1550b57cec5SDimitry Andric return Super;
1560b57cec5SDimitry Andric break;
1570b57cec5SDimitry Andric case X86::GR8RegClassID:
1580b57cec5SDimitry Andric case X86::GR16RegClassID:
1590b57cec5SDimitry Andric case X86::GR32RegClassID:
1600b57cec5SDimitry Andric case X86::GR64RegClassID:
1615f757f3fSDimitry Andric case X86::GR8_NOREX2RegClassID:
1625f757f3fSDimitry Andric case X86::GR16_NOREX2RegClassID:
1635f757f3fSDimitry Andric case X86::GR32_NOREX2RegClassID:
1645f757f3fSDimitry Andric case X86::GR64_NOREX2RegClassID:
1650b57cec5SDimitry Andric case X86::RFP32RegClassID:
1660b57cec5SDimitry Andric case X86::RFP64RegClassID:
1670b57cec5SDimitry Andric case X86::RFP80RegClassID:
1680b57cec5SDimitry Andric case X86::VR512_0_15RegClassID:
1690b57cec5SDimitry Andric case X86::VR512RegClassID:
1700b57cec5SDimitry Andric // Don't return a super-class that would shrink the spill size.
1710b57cec5SDimitry Andric // That can happen with the vector and float classes.
1720b57cec5SDimitry Andric if (getRegSizeInBits(*Super) == getRegSizeInBits(*RC))
1730b57cec5SDimitry Andric return Super;
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric Super = *I++;
1760b57cec5SDimitry Andric } while (Super);
1770b57cec5SDimitry Andric return RC;
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric
1800b57cec5SDimitry Andric const TargetRegisterClass *
getPointerRegClass(const MachineFunction & MF,unsigned Kind) const1810b57cec5SDimitry Andric X86RegisterInfo::getPointerRegClass(const MachineFunction &MF,
1820b57cec5SDimitry Andric unsigned Kind) const {
1830b57cec5SDimitry Andric const X86Subtarget &Subtarget = MF.getSubtarget<X86Subtarget>();
1840b57cec5SDimitry Andric switch (Kind) {
1850b57cec5SDimitry Andric default: llvm_unreachable("Unexpected Kind in getPointerRegClass!");
1860b57cec5SDimitry Andric case 0: // Normal GPRs.
1870b57cec5SDimitry Andric if (Subtarget.isTarget64BitLP64())
1880b57cec5SDimitry Andric return &X86::GR64RegClass;
1890b57cec5SDimitry Andric // If the target is 64bit but we have been told to use 32bit addresses,
1900b57cec5SDimitry Andric // we can still use 64-bit register as long as we know the high bits
1910b57cec5SDimitry Andric // are zeros.
1920b57cec5SDimitry Andric // Reflect that in the returned register class.
1930b57cec5SDimitry Andric if (Is64Bit) {
1940b57cec5SDimitry Andric // When the target also allows 64-bit frame pointer and we do have a
1950b57cec5SDimitry Andric // frame, this is fine to use it for the address accesses as well.
1960b57cec5SDimitry Andric const X86FrameLowering *TFI = getFrameLowering(MF);
1970b57cec5SDimitry Andric return TFI->hasFP(MF) && TFI->Uses64BitFramePtr
1980b57cec5SDimitry Andric ? &X86::LOW32_ADDR_ACCESS_RBPRegClass
1990b57cec5SDimitry Andric : &X86::LOW32_ADDR_ACCESSRegClass;
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric return &X86::GR32RegClass;
2020b57cec5SDimitry Andric case 1: // Normal GPRs except the stack pointer (for encoding reasons).
2030b57cec5SDimitry Andric if (Subtarget.isTarget64BitLP64())
2040b57cec5SDimitry Andric return &X86::GR64_NOSPRegClass;
2050b57cec5SDimitry Andric // NOSP does not contain RIP, so no special case here.
2060b57cec5SDimitry Andric return &X86::GR32_NOSPRegClass;
2070b57cec5SDimitry Andric case 2: // NOREX GPRs.
2080b57cec5SDimitry Andric if (Subtarget.isTarget64BitLP64())
2090b57cec5SDimitry Andric return &X86::GR64_NOREXRegClass;
2100b57cec5SDimitry Andric return &X86::GR32_NOREXRegClass;
2110b57cec5SDimitry Andric case 3: // NOREX GPRs except the stack pointer (for encoding reasons).
2120b57cec5SDimitry Andric if (Subtarget.isTarget64BitLP64())
2130b57cec5SDimitry Andric return &X86::GR64_NOREX_NOSPRegClass;
2140b57cec5SDimitry Andric // NOSP does not contain RIP, so no special case here.
2150b57cec5SDimitry Andric return &X86::GR32_NOREX_NOSPRegClass;
2160b57cec5SDimitry Andric case 4: // Available for tailcall (not callee-saved GPRs).
2170b57cec5SDimitry Andric return getGPRsForTailCall(MF);
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric
shouldRewriteCopySrc(const TargetRegisterClass * DefRC,unsigned DefSubReg,const TargetRegisterClass * SrcRC,unsigned SrcSubReg) const2210b57cec5SDimitry Andric bool X86RegisterInfo::shouldRewriteCopySrc(const TargetRegisterClass *DefRC,
2220b57cec5SDimitry Andric unsigned DefSubReg,
2230b57cec5SDimitry Andric const TargetRegisterClass *SrcRC,
2240b57cec5SDimitry Andric unsigned SrcSubReg) const {
2250b57cec5SDimitry Andric // Prevent rewriting a copy where the destination size is larger than the
2260b57cec5SDimitry Andric // input size. See PR41619.
2270b57cec5SDimitry Andric // FIXME: Should this be factored into the base implementation somehow.
2280b57cec5SDimitry Andric if (DefRC->hasSuperClassEq(&X86::GR64RegClass) && DefSubReg == 0 &&
2290b57cec5SDimitry Andric SrcRC->hasSuperClassEq(&X86::GR64RegClass) && SrcSubReg == X86::sub_32bit)
2300b57cec5SDimitry Andric return false;
2310b57cec5SDimitry Andric
2320b57cec5SDimitry Andric return TargetRegisterInfo::shouldRewriteCopySrc(DefRC, DefSubReg,
2330b57cec5SDimitry Andric SrcRC, SrcSubReg);
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric
2360b57cec5SDimitry Andric const TargetRegisterClass *
getGPRsForTailCall(const MachineFunction & MF) const2370b57cec5SDimitry Andric X86RegisterInfo::getGPRsForTailCall(const MachineFunction &MF) const {
2380b57cec5SDimitry Andric const Function &F = MF.getFunction();
2390b57cec5SDimitry Andric if (IsWin64 || (F.getCallingConv() == CallingConv::Win64))
2400b57cec5SDimitry Andric return &X86::GR64_TCW64RegClass;
2410b57cec5SDimitry Andric else if (Is64Bit)
2420b57cec5SDimitry Andric return &X86::GR64_TCRegClass;
2430b57cec5SDimitry Andric
2440b57cec5SDimitry Andric bool hasHipeCC = (F.getCallingConv() == CallingConv::HiPE);
2450b57cec5SDimitry Andric if (hasHipeCC)
2460b57cec5SDimitry Andric return &X86::GR32RegClass;
2470b57cec5SDimitry Andric return &X86::GR32_TCRegClass;
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric
2500b57cec5SDimitry Andric const TargetRegisterClass *
getCrossCopyRegClass(const TargetRegisterClass * RC) const2510b57cec5SDimitry Andric X86RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
2520b57cec5SDimitry Andric if (RC == &X86::CCRRegClass) {
2530b57cec5SDimitry Andric if (Is64Bit)
2540b57cec5SDimitry Andric return &X86::GR64RegClass;
2550b57cec5SDimitry Andric else
2560b57cec5SDimitry Andric return &X86::GR32RegClass;
2570b57cec5SDimitry Andric }
2580b57cec5SDimitry Andric return RC;
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric
2610b57cec5SDimitry Andric unsigned
getRegPressureLimit(const TargetRegisterClass * RC,MachineFunction & MF) const2620b57cec5SDimitry Andric X86RegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
2630b57cec5SDimitry Andric MachineFunction &MF) const {
2640b57cec5SDimitry Andric const X86FrameLowering *TFI = getFrameLowering(MF);
2650b57cec5SDimitry Andric
2660b57cec5SDimitry Andric unsigned FPDiff = TFI->hasFP(MF) ? 1 : 0;
2670b57cec5SDimitry Andric switch (RC->getID()) {
2680b57cec5SDimitry Andric default:
2690b57cec5SDimitry Andric return 0;
2700b57cec5SDimitry Andric case X86::GR32RegClassID:
2710b57cec5SDimitry Andric return 4 - FPDiff;
2720b57cec5SDimitry Andric case X86::GR64RegClassID:
2730b57cec5SDimitry Andric return 12 - FPDiff;
2740b57cec5SDimitry Andric case X86::VR128RegClassID:
2750b57cec5SDimitry Andric return Is64Bit ? 10 : 4;
2760b57cec5SDimitry Andric case X86::VR64RegClassID:
2770b57cec5SDimitry Andric return 4;
2780b57cec5SDimitry Andric }
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric
2810b57cec5SDimitry Andric const MCPhysReg *
getCalleeSavedRegs(const MachineFunction * MF) const2820b57cec5SDimitry Andric X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
2830b57cec5SDimitry Andric assert(MF && "MachineFunction required");
2840b57cec5SDimitry Andric
2850b57cec5SDimitry Andric const X86Subtarget &Subtarget = MF->getSubtarget<X86Subtarget>();
2860b57cec5SDimitry Andric const Function &F = MF->getFunction();
2870b57cec5SDimitry Andric bool HasSSE = Subtarget.hasSSE1();
2880b57cec5SDimitry Andric bool HasAVX = Subtarget.hasAVX();
2890b57cec5SDimitry Andric bool HasAVX512 = Subtarget.hasAVX512();
2900b57cec5SDimitry Andric bool CallsEHReturn = MF->callsEHReturn();
2910b57cec5SDimitry Andric
2920b57cec5SDimitry Andric CallingConv::ID CC = F.getCallingConv();
2930b57cec5SDimitry Andric
2940b57cec5SDimitry Andric // If attribute NoCallerSavedRegisters exists then we set X86_INTR calling
2950b57cec5SDimitry Andric // convention because it has the CSR list.
2960b57cec5SDimitry Andric if (MF->getFunction().hasFnAttribute("no_caller_saved_registers"))
2970b57cec5SDimitry Andric CC = CallingConv::X86_INTR;
2980b57cec5SDimitry Andric
299fe6060f1SDimitry Andric // If atribute specified, override the CSRs normally specified by the
300fe6060f1SDimitry Andric // calling convention and use the empty set instead.
301fe6060f1SDimitry Andric if (MF->getFunction().hasFnAttribute("no_callee_saved_registers"))
302fe6060f1SDimitry Andric return CSR_NoRegs_SaveList;
303fe6060f1SDimitry Andric
3040b57cec5SDimitry Andric switch (CC) {
3050b57cec5SDimitry Andric case CallingConv::GHC:
3060b57cec5SDimitry Andric case CallingConv::HiPE:
3070b57cec5SDimitry Andric return CSR_NoRegs_SaveList;
3080b57cec5SDimitry Andric case CallingConv::AnyReg:
3090b57cec5SDimitry Andric if (HasAVX)
3100b57cec5SDimitry Andric return CSR_64_AllRegs_AVX_SaveList;
3110b57cec5SDimitry Andric return CSR_64_AllRegs_SaveList;
3120b57cec5SDimitry Andric case CallingConv::PreserveMost:
3135f757f3fSDimitry Andric return IsWin64 ? CSR_Win64_RT_MostRegs_SaveList
3145f757f3fSDimitry Andric : CSR_64_RT_MostRegs_SaveList;
3150b57cec5SDimitry Andric case CallingConv::PreserveAll:
3160b57cec5SDimitry Andric if (HasAVX)
3170b57cec5SDimitry Andric return CSR_64_RT_AllRegs_AVX_SaveList;
3180b57cec5SDimitry Andric return CSR_64_RT_AllRegs_SaveList;
319*0fca6ea1SDimitry Andric case CallingConv::PreserveNone:
320*0fca6ea1SDimitry Andric return CSR_64_NoneRegs_SaveList;
3210b57cec5SDimitry Andric case CallingConv::CXX_FAST_TLS:
3220b57cec5SDimitry Andric if (Is64Bit)
3230b57cec5SDimitry Andric return MF->getInfo<X86MachineFunctionInfo>()->isSplitCSR() ?
3240b57cec5SDimitry Andric CSR_64_CXX_TLS_Darwin_PE_SaveList : CSR_64_TLS_Darwin_SaveList;
3250b57cec5SDimitry Andric break;
3260b57cec5SDimitry Andric case CallingConv::Intel_OCL_BI: {
3270b57cec5SDimitry Andric if (HasAVX512 && IsWin64)
3280b57cec5SDimitry Andric return CSR_Win64_Intel_OCL_BI_AVX512_SaveList;
3290b57cec5SDimitry Andric if (HasAVX512 && Is64Bit)
3300b57cec5SDimitry Andric return CSR_64_Intel_OCL_BI_AVX512_SaveList;
3310b57cec5SDimitry Andric if (HasAVX && IsWin64)
3320b57cec5SDimitry Andric return CSR_Win64_Intel_OCL_BI_AVX_SaveList;
3330b57cec5SDimitry Andric if (HasAVX && Is64Bit)
3340b57cec5SDimitry Andric return CSR_64_Intel_OCL_BI_AVX_SaveList;
3350b57cec5SDimitry Andric if (!HasAVX && !IsWin64 && Is64Bit)
3360b57cec5SDimitry Andric return CSR_64_Intel_OCL_BI_SaveList;
3370b57cec5SDimitry Andric break;
3380b57cec5SDimitry Andric }
3390b57cec5SDimitry Andric case CallingConv::X86_RegCall:
3400b57cec5SDimitry Andric if (Is64Bit) {
3410b57cec5SDimitry Andric if (IsWin64) {
3420b57cec5SDimitry Andric return (HasSSE ? CSR_Win64_RegCall_SaveList :
3430b57cec5SDimitry Andric CSR_Win64_RegCall_NoSSE_SaveList);
3440b57cec5SDimitry Andric } else {
3450b57cec5SDimitry Andric return (HasSSE ? CSR_SysV64_RegCall_SaveList :
3460b57cec5SDimitry Andric CSR_SysV64_RegCall_NoSSE_SaveList);
3470b57cec5SDimitry Andric }
3480b57cec5SDimitry Andric } else {
3490b57cec5SDimitry Andric return (HasSSE ? CSR_32_RegCall_SaveList :
3500b57cec5SDimitry Andric CSR_32_RegCall_NoSSE_SaveList);
3510b57cec5SDimitry Andric }
352480093f4SDimitry Andric case CallingConv::CFGuard_Check:
353480093f4SDimitry Andric assert(!Is64Bit && "CFGuard check mechanism only used on 32-bit X86");
354480093f4SDimitry Andric return (HasSSE ? CSR_Win32_CFGuard_Check_SaveList
355480093f4SDimitry Andric : CSR_Win32_CFGuard_Check_NoSSE_SaveList);
3560b57cec5SDimitry Andric case CallingConv::Cold:
3570b57cec5SDimitry Andric if (Is64Bit)
3580b57cec5SDimitry Andric return CSR_64_MostRegs_SaveList;
3590b57cec5SDimitry Andric break;
3600b57cec5SDimitry Andric case CallingConv::Win64:
3610b57cec5SDimitry Andric if (!HasSSE)
3620b57cec5SDimitry Andric return CSR_Win64_NoSSE_SaveList;
3630b57cec5SDimitry Andric return CSR_Win64_SaveList;
364fe6060f1SDimitry Andric case CallingConv::SwiftTail:
365fe6060f1SDimitry Andric if (!Is64Bit)
366fe6060f1SDimitry Andric return CSR_32_SaveList;
367fe6060f1SDimitry Andric return IsWin64 ? CSR_Win64_SwiftTail_SaveList : CSR_64_SwiftTail_SaveList;
3680b57cec5SDimitry Andric case CallingConv::X86_64_SysV:
3690b57cec5SDimitry Andric if (CallsEHReturn)
3700b57cec5SDimitry Andric return CSR_64EHRet_SaveList;
3710b57cec5SDimitry Andric return CSR_64_SaveList;
3720b57cec5SDimitry Andric case CallingConv::X86_INTR:
3730b57cec5SDimitry Andric if (Is64Bit) {
3740b57cec5SDimitry Andric if (HasAVX512)
3750b57cec5SDimitry Andric return CSR_64_AllRegs_AVX512_SaveList;
3760b57cec5SDimitry Andric if (HasAVX)
3770b57cec5SDimitry Andric return CSR_64_AllRegs_AVX_SaveList;
3780b57cec5SDimitry Andric if (HasSSE)
3790b57cec5SDimitry Andric return CSR_64_AllRegs_SaveList;
3800b57cec5SDimitry Andric return CSR_64_AllRegs_NoSSE_SaveList;
3810b57cec5SDimitry Andric } else {
3820b57cec5SDimitry Andric if (HasAVX512)
3830b57cec5SDimitry Andric return CSR_32_AllRegs_AVX512_SaveList;
3840b57cec5SDimitry Andric if (HasAVX)
3850b57cec5SDimitry Andric return CSR_32_AllRegs_AVX_SaveList;
3860b57cec5SDimitry Andric if (HasSSE)
3870b57cec5SDimitry Andric return CSR_32_AllRegs_SSE_SaveList;
3880b57cec5SDimitry Andric return CSR_32_AllRegs_SaveList;
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric default:
3910b57cec5SDimitry Andric break;
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric
3940b57cec5SDimitry Andric if (Is64Bit) {
3950b57cec5SDimitry Andric bool IsSwiftCC = Subtarget.getTargetLowering()->supportSwiftError() &&
3960b57cec5SDimitry Andric F.getAttributes().hasAttrSomewhere(Attribute::SwiftError);
3970b57cec5SDimitry Andric if (IsSwiftCC)
3980b57cec5SDimitry Andric return IsWin64 ? CSR_Win64_SwiftError_SaveList
3990b57cec5SDimitry Andric : CSR_64_SwiftError_SaveList;
4000b57cec5SDimitry Andric
4010b57cec5SDimitry Andric if (IsWin64)
4020b57cec5SDimitry Andric return HasSSE ? CSR_Win64_SaveList : CSR_Win64_NoSSE_SaveList;
4030b57cec5SDimitry Andric if (CallsEHReturn)
4040b57cec5SDimitry Andric return CSR_64EHRet_SaveList;
4050b57cec5SDimitry Andric return CSR_64_SaveList;
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric
4080b57cec5SDimitry Andric return CallsEHReturn ? CSR_32EHRet_SaveList : CSR_32_SaveList;
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric
getCalleeSavedRegsViaCopy(const MachineFunction * MF) const4110b57cec5SDimitry Andric const MCPhysReg *X86RegisterInfo::getCalleeSavedRegsViaCopy(
4120b57cec5SDimitry Andric const MachineFunction *MF) const {
4130b57cec5SDimitry Andric assert(MF && "Invalid MachineFunction pointer.");
4140b57cec5SDimitry Andric if (MF->getFunction().getCallingConv() == CallingConv::CXX_FAST_TLS &&
4150b57cec5SDimitry Andric MF->getInfo<X86MachineFunctionInfo>()->isSplitCSR())
4160b57cec5SDimitry Andric return CSR_64_CXX_TLS_Darwin_ViaCopy_SaveList;
4170b57cec5SDimitry Andric return nullptr;
4180b57cec5SDimitry Andric }
4190b57cec5SDimitry Andric
4200b57cec5SDimitry Andric const uint32_t *
getCallPreservedMask(const MachineFunction & MF,CallingConv::ID CC) const4210b57cec5SDimitry Andric X86RegisterInfo::getCallPreservedMask(const MachineFunction &MF,
4220b57cec5SDimitry Andric CallingConv::ID CC) const {
4230b57cec5SDimitry Andric const X86Subtarget &Subtarget = MF.getSubtarget<X86Subtarget>();
4240b57cec5SDimitry Andric bool HasSSE = Subtarget.hasSSE1();
4250b57cec5SDimitry Andric bool HasAVX = Subtarget.hasAVX();
4260b57cec5SDimitry Andric bool HasAVX512 = Subtarget.hasAVX512();
4270b57cec5SDimitry Andric
4280b57cec5SDimitry Andric switch (CC) {
4290b57cec5SDimitry Andric case CallingConv::GHC:
4300b57cec5SDimitry Andric case CallingConv::HiPE:
4310b57cec5SDimitry Andric return CSR_NoRegs_RegMask;
4320b57cec5SDimitry Andric case CallingConv::AnyReg:
4330b57cec5SDimitry Andric if (HasAVX)
4340b57cec5SDimitry Andric return CSR_64_AllRegs_AVX_RegMask;
4350b57cec5SDimitry Andric return CSR_64_AllRegs_RegMask;
4360b57cec5SDimitry Andric case CallingConv::PreserveMost:
4375f757f3fSDimitry Andric return IsWin64 ? CSR_Win64_RT_MostRegs_RegMask : CSR_64_RT_MostRegs_RegMask;
4380b57cec5SDimitry Andric case CallingConv::PreserveAll:
4390b57cec5SDimitry Andric if (HasAVX)
4400b57cec5SDimitry Andric return CSR_64_RT_AllRegs_AVX_RegMask;
4410b57cec5SDimitry Andric return CSR_64_RT_AllRegs_RegMask;
442*0fca6ea1SDimitry Andric case CallingConv::PreserveNone:
443*0fca6ea1SDimitry Andric return CSR_64_NoneRegs_RegMask;
4440b57cec5SDimitry Andric case CallingConv::CXX_FAST_TLS:
4450b57cec5SDimitry Andric if (Is64Bit)
4460b57cec5SDimitry Andric return CSR_64_TLS_Darwin_RegMask;
4470b57cec5SDimitry Andric break;
4480b57cec5SDimitry Andric case CallingConv::Intel_OCL_BI: {
4490b57cec5SDimitry Andric if (HasAVX512 && IsWin64)
4500b57cec5SDimitry Andric return CSR_Win64_Intel_OCL_BI_AVX512_RegMask;
4510b57cec5SDimitry Andric if (HasAVX512 && Is64Bit)
4520b57cec5SDimitry Andric return CSR_64_Intel_OCL_BI_AVX512_RegMask;
4530b57cec5SDimitry Andric if (HasAVX && IsWin64)
4540b57cec5SDimitry Andric return CSR_Win64_Intel_OCL_BI_AVX_RegMask;
4550b57cec5SDimitry Andric if (HasAVX && Is64Bit)
4560b57cec5SDimitry Andric return CSR_64_Intel_OCL_BI_AVX_RegMask;
4570b57cec5SDimitry Andric if (!HasAVX && !IsWin64 && Is64Bit)
4580b57cec5SDimitry Andric return CSR_64_Intel_OCL_BI_RegMask;
4590b57cec5SDimitry Andric break;
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric case CallingConv::X86_RegCall:
4620b57cec5SDimitry Andric if (Is64Bit) {
4630b57cec5SDimitry Andric if (IsWin64) {
4640b57cec5SDimitry Andric return (HasSSE ? CSR_Win64_RegCall_RegMask :
4650b57cec5SDimitry Andric CSR_Win64_RegCall_NoSSE_RegMask);
4660b57cec5SDimitry Andric } else {
4670b57cec5SDimitry Andric return (HasSSE ? CSR_SysV64_RegCall_RegMask :
4680b57cec5SDimitry Andric CSR_SysV64_RegCall_NoSSE_RegMask);
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric } else {
4710b57cec5SDimitry Andric return (HasSSE ? CSR_32_RegCall_RegMask :
4720b57cec5SDimitry Andric CSR_32_RegCall_NoSSE_RegMask);
4730b57cec5SDimitry Andric }
474480093f4SDimitry Andric case CallingConv::CFGuard_Check:
475480093f4SDimitry Andric assert(!Is64Bit && "CFGuard check mechanism only used on 32-bit X86");
476480093f4SDimitry Andric return (HasSSE ? CSR_Win32_CFGuard_Check_RegMask
477480093f4SDimitry Andric : CSR_Win32_CFGuard_Check_NoSSE_RegMask);
4780b57cec5SDimitry Andric case CallingConv::Cold:
4790b57cec5SDimitry Andric if (Is64Bit)
4800b57cec5SDimitry Andric return CSR_64_MostRegs_RegMask;
4810b57cec5SDimitry Andric break;
4820b57cec5SDimitry Andric case CallingConv::Win64:
4830b57cec5SDimitry Andric return CSR_Win64_RegMask;
484fe6060f1SDimitry Andric case CallingConv::SwiftTail:
485fe6060f1SDimitry Andric if (!Is64Bit)
486fe6060f1SDimitry Andric return CSR_32_RegMask;
487fe6060f1SDimitry Andric return IsWin64 ? CSR_Win64_SwiftTail_RegMask : CSR_64_SwiftTail_RegMask;
4880b57cec5SDimitry Andric case CallingConv::X86_64_SysV:
4890b57cec5SDimitry Andric return CSR_64_RegMask;
4900b57cec5SDimitry Andric case CallingConv::X86_INTR:
4910b57cec5SDimitry Andric if (Is64Bit) {
4920b57cec5SDimitry Andric if (HasAVX512)
4930b57cec5SDimitry Andric return CSR_64_AllRegs_AVX512_RegMask;
4940b57cec5SDimitry Andric if (HasAVX)
4950b57cec5SDimitry Andric return CSR_64_AllRegs_AVX_RegMask;
4960b57cec5SDimitry Andric if (HasSSE)
4970b57cec5SDimitry Andric return CSR_64_AllRegs_RegMask;
4980b57cec5SDimitry Andric return CSR_64_AllRegs_NoSSE_RegMask;
4990b57cec5SDimitry Andric } else {
5000b57cec5SDimitry Andric if (HasAVX512)
5010b57cec5SDimitry Andric return CSR_32_AllRegs_AVX512_RegMask;
5020b57cec5SDimitry Andric if (HasAVX)
5030b57cec5SDimitry Andric return CSR_32_AllRegs_AVX_RegMask;
5040b57cec5SDimitry Andric if (HasSSE)
5050b57cec5SDimitry Andric return CSR_32_AllRegs_SSE_RegMask;
5060b57cec5SDimitry Andric return CSR_32_AllRegs_RegMask;
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric default:
5090b57cec5SDimitry Andric break;
5100b57cec5SDimitry Andric }
5110b57cec5SDimitry Andric
5120b57cec5SDimitry Andric // Unlike getCalleeSavedRegs(), we don't have MMI so we can't check
5130b57cec5SDimitry Andric // callsEHReturn().
5140b57cec5SDimitry Andric if (Is64Bit) {
5150b57cec5SDimitry Andric const Function &F = MF.getFunction();
5160b57cec5SDimitry Andric bool IsSwiftCC = Subtarget.getTargetLowering()->supportSwiftError() &&
5170b57cec5SDimitry Andric F.getAttributes().hasAttrSomewhere(Attribute::SwiftError);
5180b57cec5SDimitry Andric if (IsSwiftCC)
5190b57cec5SDimitry Andric return IsWin64 ? CSR_Win64_SwiftError_RegMask : CSR_64_SwiftError_RegMask;
520fe6060f1SDimitry Andric
5210b57cec5SDimitry Andric return IsWin64 ? CSR_Win64_RegMask : CSR_64_RegMask;
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric
5240b57cec5SDimitry Andric return CSR_32_RegMask;
5250b57cec5SDimitry Andric }
5260b57cec5SDimitry Andric
5270b57cec5SDimitry Andric const uint32_t*
getNoPreservedMask() const5280b57cec5SDimitry Andric X86RegisterInfo::getNoPreservedMask() const {
5290b57cec5SDimitry Andric return CSR_NoRegs_RegMask;
5300b57cec5SDimitry Andric }
5310b57cec5SDimitry Andric
getDarwinTLSCallPreservedMask() const5320b57cec5SDimitry Andric const uint32_t *X86RegisterInfo::getDarwinTLSCallPreservedMask() const {
5330b57cec5SDimitry Andric return CSR_64_TLS_Darwin_RegMask;
5340b57cec5SDimitry Andric }
5350b57cec5SDimitry Andric
getReservedRegs(const MachineFunction & MF) const5360b57cec5SDimitry Andric BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
5370b57cec5SDimitry Andric BitVector Reserved(getNumRegs());
5380b57cec5SDimitry Andric const X86FrameLowering *TFI = getFrameLowering(MF);
5390b57cec5SDimitry Andric
5400b57cec5SDimitry Andric // Set the floating point control register as reserved.
5410b57cec5SDimitry Andric Reserved.set(X86::FPCW);
5420b57cec5SDimitry Andric
543480093f4SDimitry Andric // Set the floating point status register as reserved.
544480093f4SDimitry Andric Reserved.set(X86::FPSW);
545480093f4SDimitry Andric
546480093f4SDimitry Andric // Set the SIMD floating point control register as reserved.
547480093f4SDimitry Andric Reserved.set(X86::MXCSR);
548480093f4SDimitry Andric
5490b57cec5SDimitry Andric // Set the stack-pointer register and its aliases as reserved.
550480093f4SDimitry Andric for (const MCPhysReg &SubReg : subregs_inclusive(X86::RSP))
551480093f4SDimitry Andric Reserved.set(SubReg);
5520b57cec5SDimitry Andric
5530b57cec5SDimitry Andric // Set the Shadow Stack Pointer as reserved.
5540b57cec5SDimitry Andric Reserved.set(X86::SSP);
5550b57cec5SDimitry Andric
5560b57cec5SDimitry Andric // Set the instruction pointer register and its aliases as reserved.
557480093f4SDimitry Andric for (const MCPhysReg &SubReg : subregs_inclusive(X86::RIP))
558480093f4SDimitry Andric Reserved.set(SubReg);
5590b57cec5SDimitry Andric
5600b57cec5SDimitry Andric // Set the frame-pointer register and its aliases as reserved if needed.
5610b57cec5SDimitry Andric if (TFI->hasFP(MF)) {
562480093f4SDimitry Andric for (const MCPhysReg &SubReg : subregs_inclusive(X86::RBP))
563480093f4SDimitry Andric Reserved.set(SubReg);
5640b57cec5SDimitry Andric }
5650b57cec5SDimitry Andric
5660b57cec5SDimitry Andric // Set the base-pointer register and its aliases as reserved if needed.
5670b57cec5SDimitry Andric if (hasBasePointer(MF)) {
5680b57cec5SDimitry Andric CallingConv::ID CC = MF.getFunction().getCallingConv();
5690b57cec5SDimitry Andric const uint32_t *RegMask = getCallPreservedMask(MF, CC);
5700b57cec5SDimitry Andric if (MachineOperand::clobbersPhysReg(RegMask, getBaseRegister()))
5710b57cec5SDimitry Andric report_fatal_error(
5720b57cec5SDimitry Andric "Stack realignment in presence of dynamic allocas is not supported with"
5730b57cec5SDimitry Andric "this calling convention.");
5740b57cec5SDimitry Andric
5758bcb0991SDimitry Andric Register BasePtr = getX86SubSuperRegister(getBaseRegister(), 64);
576480093f4SDimitry Andric for (const MCPhysReg &SubReg : subregs_inclusive(BasePtr))
577480093f4SDimitry Andric Reserved.set(SubReg);
5780b57cec5SDimitry Andric }
5790b57cec5SDimitry Andric
5800b57cec5SDimitry Andric // Mark the segment registers as reserved.
5810b57cec5SDimitry Andric Reserved.set(X86::CS);
5820b57cec5SDimitry Andric Reserved.set(X86::SS);
5830b57cec5SDimitry Andric Reserved.set(X86::DS);
5840b57cec5SDimitry Andric Reserved.set(X86::ES);
5850b57cec5SDimitry Andric Reserved.set(X86::FS);
5860b57cec5SDimitry Andric Reserved.set(X86::GS);
5870b57cec5SDimitry Andric
5880b57cec5SDimitry Andric // Mark the floating point stack registers as reserved.
5890b57cec5SDimitry Andric for (unsigned n = 0; n != 8; ++n)
5900b57cec5SDimitry Andric Reserved.set(X86::ST0 + n);
5910b57cec5SDimitry Andric
5920b57cec5SDimitry Andric // Reserve the registers that only exist in 64-bit mode.
5930b57cec5SDimitry Andric if (!Is64Bit) {
5940b57cec5SDimitry Andric // These 8-bit registers are part of the x86-64 extension even though their
5950b57cec5SDimitry Andric // super-registers are old 32-bits.
5960b57cec5SDimitry Andric Reserved.set(X86::SIL);
5970b57cec5SDimitry Andric Reserved.set(X86::DIL);
5980b57cec5SDimitry Andric Reserved.set(X86::BPL);
5990b57cec5SDimitry Andric Reserved.set(X86::SPL);
6000b57cec5SDimitry Andric Reserved.set(X86::SIH);
6010b57cec5SDimitry Andric Reserved.set(X86::DIH);
6020b57cec5SDimitry Andric Reserved.set(X86::BPH);
6030b57cec5SDimitry Andric Reserved.set(X86::SPH);
6040b57cec5SDimitry Andric
6050b57cec5SDimitry Andric for (unsigned n = 0; n != 8; ++n) {
6060b57cec5SDimitry Andric // R8, R9, ...
6070b57cec5SDimitry Andric for (MCRegAliasIterator AI(X86::R8 + n, this, true); AI.isValid(); ++AI)
6080b57cec5SDimitry Andric Reserved.set(*AI);
6090b57cec5SDimitry Andric
6100b57cec5SDimitry Andric // XMM8, XMM9, ...
6110b57cec5SDimitry Andric for (MCRegAliasIterator AI(X86::XMM8 + n, this, true); AI.isValid(); ++AI)
6120b57cec5SDimitry Andric Reserved.set(*AI);
6130b57cec5SDimitry Andric }
6140b57cec5SDimitry Andric }
6150b57cec5SDimitry Andric if (!Is64Bit || !MF.getSubtarget<X86Subtarget>().hasAVX512()) {
6165f757f3fSDimitry Andric for (unsigned n = 0; n != 16; ++n) {
6175f757f3fSDimitry Andric for (MCRegAliasIterator AI(X86::XMM16 + n, this, true); AI.isValid();
6185f757f3fSDimitry Andric ++AI)
6190b57cec5SDimitry Andric Reserved.set(*AI);
6200b57cec5SDimitry Andric }
6210b57cec5SDimitry Andric }
6220b57cec5SDimitry Andric
6235f757f3fSDimitry Andric // Reserve the extended general purpose registers.
6245f757f3fSDimitry Andric if (!Is64Bit || !MF.getSubtarget<X86Subtarget>().hasEGPR())
6255f757f3fSDimitry Andric Reserved.set(X86::R16, X86::R31WH + 1);
6265f757f3fSDimitry Andric
6275f757f3fSDimitry Andric if (MF.getFunction().getCallingConv() == CallingConv::GRAAL) {
6285f757f3fSDimitry Andric for (MCRegAliasIterator AI(X86::R14, this, true); AI.isValid(); ++AI)
6295f757f3fSDimitry Andric Reserved.set(*AI);
6305f757f3fSDimitry Andric for (MCRegAliasIterator AI(X86::R15, this, true); AI.isValid(); ++AI)
6315f757f3fSDimitry Andric Reserved.set(*AI);
6325f757f3fSDimitry Andric }
6335f757f3fSDimitry Andric
6340b57cec5SDimitry Andric assert(checkAllSuperRegsMarked(Reserved,
6350b57cec5SDimitry Andric {X86::SIL, X86::DIL, X86::BPL, X86::SPL,
6360b57cec5SDimitry Andric X86::SIH, X86::DIH, X86::BPH, X86::SPH}));
6370b57cec5SDimitry Andric return Reserved;
6380b57cec5SDimitry Andric }
6390b57cec5SDimitry Andric
getNumSupportedRegs(const MachineFunction & MF) const6405f757f3fSDimitry Andric unsigned X86RegisterInfo::getNumSupportedRegs(const MachineFunction &MF) const {
6415f757f3fSDimitry Andric // All existing Intel CPUs that support AMX support AVX512 and all existing
6425f757f3fSDimitry Andric // Intel CPUs that support APX support AMX. AVX512 implies AVX.
6435f757f3fSDimitry Andric //
6445f757f3fSDimitry Andric // We enumerate the registers in X86GenRegisterInfo.inc in this order:
6455f757f3fSDimitry Andric //
6465f757f3fSDimitry Andric // Registers before AVX512,
6475f757f3fSDimitry Andric // AVX512 registers (X/YMM16-31, ZMM0-31, K registers)
6485f757f3fSDimitry Andric // AMX registers (TMM)
6495f757f3fSDimitry Andric // APX registers (R16-R31)
6505f757f3fSDimitry Andric //
6515f757f3fSDimitry Andric // and try to return the minimum number of registers supported by the target.
652*0fca6ea1SDimitry Andric static_assert((X86::R15WH + 1 == X86::YMM0) && (X86::YMM15 + 1 == X86::K0) &&
653*0fca6ea1SDimitry Andric (X86::K6_K7 + 1 == X86::TMMCFG) &&
654*0fca6ea1SDimitry Andric (X86::TMM7 + 1 == X86::R16) &&
655*0fca6ea1SDimitry Andric (X86::R31WH + 1 == X86::NUM_TARGET_REGS),
6565f757f3fSDimitry Andric "Register number may be incorrect");
6575f757f3fSDimitry Andric
6585f757f3fSDimitry Andric const X86Subtarget &ST = MF.getSubtarget<X86Subtarget>();
6595f757f3fSDimitry Andric if (ST.hasEGPR())
6605f757f3fSDimitry Andric return X86::NUM_TARGET_REGS;
6615f757f3fSDimitry Andric if (ST.hasAMXTILE())
6625f757f3fSDimitry Andric return X86::TMM7 + 1;
6635f757f3fSDimitry Andric if (ST.hasAVX512())
6645f757f3fSDimitry Andric return X86::K6_K7 + 1;
6655f757f3fSDimitry Andric if (ST.hasAVX())
6665f757f3fSDimitry Andric return X86::YMM15 + 1;
6675f757f3fSDimitry Andric return X86::R15WH + 1;
6685f757f3fSDimitry Andric }
6695f757f3fSDimitry Andric
isArgumentRegister(const MachineFunction & MF,MCRegister Reg) const67081ad6265SDimitry Andric bool X86RegisterInfo::isArgumentRegister(const MachineFunction &MF,
67181ad6265SDimitry Andric MCRegister Reg) const {
67281ad6265SDimitry Andric const X86Subtarget &ST = MF.getSubtarget<X86Subtarget>();
67381ad6265SDimitry Andric const TargetRegisterInfo &TRI = *ST.getRegisterInfo();
67481ad6265SDimitry Andric auto IsSubReg = [&](MCRegister RegA, MCRegister RegB) {
67581ad6265SDimitry Andric return TRI.isSuperOrSubRegisterEq(RegA, RegB);
67681ad6265SDimitry Andric };
67781ad6265SDimitry Andric
67881ad6265SDimitry Andric if (!ST.is64Bit())
67981ad6265SDimitry Andric return llvm::any_of(
68081ad6265SDimitry Andric SmallVector<MCRegister>{X86::EAX, X86::ECX, X86::EDX},
68181ad6265SDimitry Andric [&](MCRegister &RegA) { return IsSubReg(RegA, Reg); }) ||
68281ad6265SDimitry Andric (ST.hasMMX() && X86::VR64RegClass.contains(Reg));
68381ad6265SDimitry Andric
68481ad6265SDimitry Andric CallingConv::ID CC = MF.getFunction().getCallingConv();
68581ad6265SDimitry Andric
68681ad6265SDimitry Andric if (CC == CallingConv::X86_64_SysV && IsSubReg(X86::RAX, Reg))
68781ad6265SDimitry Andric return true;
68881ad6265SDimitry Andric
68981ad6265SDimitry Andric if (llvm::any_of(
69081ad6265SDimitry Andric SmallVector<MCRegister>{X86::RDX, X86::RCX, X86::R8, X86::R9},
69181ad6265SDimitry Andric [&](MCRegister &RegA) { return IsSubReg(RegA, Reg); }))
69281ad6265SDimitry Andric return true;
69381ad6265SDimitry Andric
69481ad6265SDimitry Andric if (CC != CallingConv::Win64 &&
69581ad6265SDimitry Andric llvm::any_of(SmallVector<MCRegister>{X86::RDI, X86::RSI},
69681ad6265SDimitry Andric [&](MCRegister &RegA) { return IsSubReg(RegA, Reg); }))
69781ad6265SDimitry Andric return true;
69881ad6265SDimitry Andric
69981ad6265SDimitry Andric if (ST.hasSSE1() &&
70081ad6265SDimitry Andric llvm::any_of(SmallVector<MCRegister>{X86::XMM0, X86::XMM1, X86::XMM2,
70181ad6265SDimitry Andric X86::XMM3, X86::XMM4, X86::XMM5,
70281ad6265SDimitry Andric X86::XMM6, X86::XMM7},
70381ad6265SDimitry Andric [&](MCRegister &RegA) { return IsSubReg(RegA, Reg); }))
70481ad6265SDimitry Andric return true;
70581ad6265SDimitry Andric
70681ad6265SDimitry Andric return X86GenRegisterInfo::isArgumentRegister(MF, Reg);
70781ad6265SDimitry Andric }
70881ad6265SDimitry Andric
isFixedRegister(const MachineFunction & MF,MCRegister PhysReg) const70981ad6265SDimitry Andric bool X86RegisterInfo::isFixedRegister(const MachineFunction &MF,
71081ad6265SDimitry Andric MCRegister PhysReg) const {
71181ad6265SDimitry Andric const X86Subtarget &ST = MF.getSubtarget<X86Subtarget>();
71281ad6265SDimitry Andric const TargetRegisterInfo &TRI = *ST.getRegisterInfo();
71381ad6265SDimitry Andric
71481ad6265SDimitry Andric // Stack pointer.
71581ad6265SDimitry Andric if (TRI.isSuperOrSubRegisterEq(X86::RSP, PhysReg))
71681ad6265SDimitry Andric return true;
71781ad6265SDimitry Andric
71881ad6265SDimitry Andric // Don't use the frame pointer if it's being used.
71981ad6265SDimitry Andric const X86FrameLowering &TFI = *getFrameLowering(MF);
72081ad6265SDimitry Andric if (TFI.hasFP(MF) && TRI.isSuperOrSubRegisterEq(X86::RBP, PhysReg))
72181ad6265SDimitry Andric return true;
72281ad6265SDimitry Andric
72381ad6265SDimitry Andric return X86GenRegisterInfo::isFixedRegister(MF, PhysReg);
72481ad6265SDimitry Andric }
72581ad6265SDimitry Andric
isTileRegisterClass(const TargetRegisterClass * RC) const72681ad6265SDimitry Andric bool X86RegisterInfo::isTileRegisterClass(const TargetRegisterClass *RC) const {
72781ad6265SDimitry Andric return RC->getID() == X86::TILERegClassID;
72881ad6265SDimitry Andric }
72981ad6265SDimitry Andric
adjustStackMapLiveOutMask(uint32_t * Mask) const7300b57cec5SDimitry Andric void X86RegisterInfo::adjustStackMapLiveOutMask(uint32_t *Mask) const {
7310b57cec5SDimitry Andric // Check if the EFLAGS register is marked as live-out. This shouldn't happen,
7320b57cec5SDimitry Andric // because the calling convention defines the EFLAGS register as NOT
7330b57cec5SDimitry Andric // preserved.
7340b57cec5SDimitry Andric //
7350b57cec5SDimitry Andric // Unfortunatelly the EFLAGS show up as live-out after branch folding. Adding
7360b57cec5SDimitry Andric // an assert to track this and clear the register afterwards to avoid
7370b57cec5SDimitry Andric // unnecessary crashes during release builds.
7380b57cec5SDimitry Andric assert(!(Mask[X86::EFLAGS / 32] & (1U << (X86::EFLAGS % 32))) &&
7390b57cec5SDimitry Andric "EFLAGS are not live-out from a patchpoint.");
7400b57cec5SDimitry Andric
7410b57cec5SDimitry Andric // Also clean other registers that don't need preserving (IP).
7420b57cec5SDimitry Andric for (auto Reg : {X86::EFLAGS, X86::RIP, X86::EIP, X86::IP})
7430b57cec5SDimitry Andric Mask[Reg / 32] &= ~(1U << (Reg % 32));
7440b57cec5SDimitry Andric }
7450b57cec5SDimitry Andric
7460b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
7470b57cec5SDimitry Andric // Stack Frame Processing methods
7480b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
7490b57cec5SDimitry Andric
CantUseSP(const MachineFrameInfo & MFI)7500b57cec5SDimitry Andric static bool CantUseSP(const MachineFrameInfo &MFI) {
7510b57cec5SDimitry Andric return MFI.hasVarSizedObjects() || MFI.hasOpaqueSPAdjustment();
7520b57cec5SDimitry Andric }
7530b57cec5SDimitry Andric
hasBasePointer(const MachineFunction & MF) const7540b57cec5SDimitry Andric bool X86RegisterInfo::hasBasePointer(const MachineFunction &MF) const {
7555ffd83dbSDimitry Andric const X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
75606c3fb27SDimitry Andric // We have a virtual register to reference argument, and don't need base
75706c3fb27SDimitry Andric // pointer.
75806c3fb27SDimitry Andric if (X86FI->getStackPtrSaveMI() != nullptr)
75906c3fb27SDimitry Andric return false;
76006c3fb27SDimitry Andric
7615ffd83dbSDimitry Andric if (X86FI->hasPreallocatedCall())
7625ffd83dbSDimitry Andric return true;
7635ffd83dbSDimitry Andric
7640b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo();
7650b57cec5SDimitry Andric
7660b57cec5SDimitry Andric if (!EnableBasePointer)
7670b57cec5SDimitry Andric return false;
7680b57cec5SDimitry Andric
7690b57cec5SDimitry Andric // When we need stack realignment, we can't address the stack from the frame
7700b57cec5SDimitry Andric // pointer. When we have dynamic allocas or stack-adjusting inline asm, we
7710b57cec5SDimitry Andric // can't address variables from the stack pointer. MS inline asm can
7720b57cec5SDimitry Andric // reference locals while also adjusting the stack pointer. When we can't
7730b57cec5SDimitry Andric // use both the SP and the FP, we need a separate base pointer register.
774fe6060f1SDimitry Andric bool CantUseFP = hasStackRealignment(MF);
7750b57cec5SDimitry Andric return CantUseFP && CantUseSP(MFI);
7760b57cec5SDimitry Andric }
7770b57cec5SDimitry Andric
canRealignStack(const MachineFunction & MF) const7780b57cec5SDimitry Andric bool X86RegisterInfo::canRealignStack(const MachineFunction &MF) const {
7790b57cec5SDimitry Andric if (!TargetRegisterInfo::canRealignStack(MF))
7800b57cec5SDimitry Andric return false;
7810b57cec5SDimitry Andric
7820b57cec5SDimitry Andric const MachineFrameInfo &MFI = MF.getFrameInfo();
7830b57cec5SDimitry Andric const MachineRegisterInfo *MRI = &MF.getRegInfo();
7840b57cec5SDimitry Andric
7850b57cec5SDimitry Andric // Stack realignment requires a frame pointer. If we already started
7860b57cec5SDimitry Andric // register allocation with frame pointer elimination, it is too late now.
7870b57cec5SDimitry Andric if (!MRI->canReserveReg(FramePtr))
7880b57cec5SDimitry Andric return false;
7890b57cec5SDimitry Andric
7900b57cec5SDimitry Andric // If a base pointer is necessary. Check that it isn't too late to reserve
7910b57cec5SDimitry Andric // it.
7920b57cec5SDimitry Andric if (CantUseSP(MFI))
7930b57cec5SDimitry Andric return MRI->canReserveReg(BasePtr);
7940b57cec5SDimitry Andric return true;
7950b57cec5SDimitry Andric }
7960b57cec5SDimitry Andric
shouldRealignStack(const MachineFunction & MF) const79706c3fb27SDimitry Andric bool X86RegisterInfo::shouldRealignStack(const MachineFunction &MF) const {
79806c3fb27SDimitry Andric if (TargetRegisterInfo::shouldRealignStack(MF))
79906c3fb27SDimitry Andric return true;
80006c3fb27SDimitry Andric
80106c3fb27SDimitry Andric return !Is64Bit && MF.getFunction().getCallingConv() == CallingConv::X86_INTR;
80206c3fb27SDimitry Andric }
80306c3fb27SDimitry Andric
8040b57cec5SDimitry Andric // tryOptimizeLEAtoMOV - helper function that tries to replace a LEA instruction
8050b57cec5SDimitry Andric // of the form 'lea (%esp), %ebx' --> 'mov %esp, %ebx'.
8060b57cec5SDimitry Andric // TODO: In this case we should be really trying first to entirely eliminate
8070b57cec5SDimitry Andric // this instruction which is a plain copy.
tryOptimizeLEAtoMOV(MachineBasicBlock::iterator II)8080b57cec5SDimitry Andric static bool tryOptimizeLEAtoMOV(MachineBasicBlock::iterator II) {
8090b57cec5SDimitry Andric MachineInstr &MI = *II;
8100b57cec5SDimitry Andric unsigned Opc = II->getOpcode();
8110b57cec5SDimitry Andric // Check if this is a LEA of the form 'lea (%esp), %ebx'
8120b57cec5SDimitry Andric if ((Opc != X86::LEA32r && Opc != X86::LEA64r && Opc != X86::LEA64_32r) ||
8130b57cec5SDimitry Andric MI.getOperand(2).getImm() != 1 ||
8140b57cec5SDimitry Andric MI.getOperand(3).getReg() != X86::NoRegister ||
8150b57cec5SDimitry Andric MI.getOperand(4).getImm() != 0 ||
8160b57cec5SDimitry Andric MI.getOperand(5).getReg() != X86::NoRegister)
8170b57cec5SDimitry Andric return false;
8188bcb0991SDimitry Andric Register BasePtr = MI.getOperand(1).getReg();
8190b57cec5SDimitry Andric // In X32 mode, ensure the base-pointer is a 32-bit operand, so the LEA will
8200b57cec5SDimitry Andric // be replaced with a 32-bit operand MOV which will zero extend the upper
8210b57cec5SDimitry Andric // 32-bits of the super register.
8220b57cec5SDimitry Andric if (Opc == X86::LEA64_32r)
8230b57cec5SDimitry Andric BasePtr = getX86SubSuperRegister(BasePtr, 32);
8248bcb0991SDimitry Andric Register NewDestReg = MI.getOperand(0).getReg();
8250b57cec5SDimitry Andric const X86InstrInfo *TII =
8260b57cec5SDimitry Andric MI.getParent()->getParent()->getSubtarget<X86Subtarget>().getInstrInfo();
8270b57cec5SDimitry Andric TII->copyPhysReg(*MI.getParent(), II, MI.getDebugLoc(), NewDestReg, BasePtr,
8280b57cec5SDimitry Andric MI.getOperand(1).isKill());
8290b57cec5SDimitry Andric MI.eraseFromParent();
8300b57cec5SDimitry Andric return true;
8310b57cec5SDimitry Andric }
8320b57cec5SDimitry Andric
isFuncletReturnInstr(MachineInstr & MI)833c14a5a88SDimitry Andric static bool isFuncletReturnInstr(MachineInstr &MI) {
834c14a5a88SDimitry Andric switch (MI.getOpcode()) {
835c14a5a88SDimitry Andric case X86::CATCHRET:
836c14a5a88SDimitry Andric case X86::CLEANUPRET:
837c14a5a88SDimitry Andric return true;
838c14a5a88SDimitry Andric default:
839c14a5a88SDimitry Andric return false;
840c14a5a88SDimitry Andric }
841c14a5a88SDimitry Andric llvm_unreachable("impossible");
842c14a5a88SDimitry Andric }
843c14a5a88SDimitry Andric
eliminateFrameIndex(MachineBasicBlock::iterator II,unsigned FIOperandNum,Register BaseReg,int FIOffset) const84406c3fb27SDimitry Andric void X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
84506c3fb27SDimitry Andric unsigned FIOperandNum,
84606c3fb27SDimitry Andric Register BaseReg,
84706c3fb27SDimitry Andric int FIOffset) const {
84806c3fb27SDimitry Andric MachineInstr &MI = *II;
84906c3fb27SDimitry Andric unsigned Opc = MI.getOpcode();
85006c3fb27SDimitry Andric if (Opc == TargetOpcode::LOCAL_ESCAPE) {
85106c3fb27SDimitry Andric MachineOperand &FI = MI.getOperand(FIOperandNum);
85206c3fb27SDimitry Andric FI.ChangeToImmediate(FIOffset);
85306c3fb27SDimitry Andric return;
85406c3fb27SDimitry Andric }
85506c3fb27SDimitry Andric
85606c3fb27SDimitry Andric MI.getOperand(FIOperandNum).ChangeToRegister(BaseReg, false);
85706c3fb27SDimitry Andric
85806c3fb27SDimitry Andric // The frame index format for stackmaps and patchpoints is different from the
85906c3fb27SDimitry Andric // X86 format. It only has a FI and an offset.
86006c3fb27SDimitry Andric if (Opc == TargetOpcode::STACKMAP || Opc == TargetOpcode::PATCHPOINT) {
86106c3fb27SDimitry Andric assert(BasePtr == FramePtr && "Expected the FP as base register");
86206c3fb27SDimitry Andric int64_t Offset = MI.getOperand(FIOperandNum + 1).getImm() + FIOffset;
86306c3fb27SDimitry Andric MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
86406c3fb27SDimitry Andric return;
86506c3fb27SDimitry Andric }
86606c3fb27SDimitry Andric
86706c3fb27SDimitry Andric if (MI.getOperand(FIOperandNum + 3).isImm()) {
86806c3fb27SDimitry Andric // Offset is a 32-bit integer.
86906c3fb27SDimitry Andric int Imm = (int)(MI.getOperand(FIOperandNum + 3).getImm());
87006c3fb27SDimitry Andric int Offset = FIOffset + Imm;
87106c3fb27SDimitry Andric assert((!Is64Bit || isInt<32>((long long)FIOffset + Imm)) &&
87206c3fb27SDimitry Andric "Requesting 64-bit offset in 32-bit immediate!");
87306c3fb27SDimitry Andric if (Offset != 0)
87406c3fb27SDimitry Andric MI.getOperand(FIOperandNum + 3).ChangeToImmediate(Offset);
87506c3fb27SDimitry Andric } else {
87606c3fb27SDimitry Andric // Offset is symbolic. This is extremely rare.
87706c3fb27SDimitry Andric uint64_t Offset =
87806c3fb27SDimitry Andric FIOffset + (uint64_t)MI.getOperand(FIOperandNum + 3).getOffset();
87906c3fb27SDimitry Andric MI.getOperand(FIOperandNum + 3).setOffset(Offset);
88006c3fb27SDimitry Andric }
88106c3fb27SDimitry Andric }
88206c3fb27SDimitry Andric
883bdd1243dSDimitry Andric bool
eliminateFrameIndex(MachineBasicBlock::iterator II,int SPAdj,unsigned FIOperandNum,RegScavenger * RS) const8840b57cec5SDimitry Andric X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
8850b57cec5SDimitry Andric int SPAdj, unsigned FIOperandNum,
8860b57cec5SDimitry Andric RegScavenger *RS) const {
8870b57cec5SDimitry Andric MachineInstr &MI = *II;
888c14a5a88SDimitry Andric MachineBasicBlock &MBB = *MI.getParent();
889c14a5a88SDimitry Andric MachineFunction &MF = *MBB.getParent();
890c14a5a88SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
891c14a5a88SDimitry Andric bool IsEHFuncletEpilogue = MBBI == MBB.end() ? false
892c14a5a88SDimitry Andric : isFuncletReturnInstr(*MBBI);
8930b57cec5SDimitry Andric const X86FrameLowering *TFI = getFrameLowering(MF);
8940b57cec5SDimitry Andric int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
8950b57cec5SDimitry Andric
8960b57cec5SDimitry Andric // Determine base register and offset.
8970b57cec5SDimitry Andric int FIOffset;
8985ffd83dbSDimitry Andric Register BasePtr;
8990b57cec5SDimitry Andric if (MI.isReturn()) {
900fe6060f1SDimitry Andric assert((!hasStackRealignment(MF) ||
9010b57cec5SDimitry Andric MF.getFrameInfo().isFixedObjectIndex(FrameIndex)) &&
9020b57cec5SDimitry Andric "Return instruction can only reference SP relative frame objects");
903e8d8bef9SDimitry Andric FIOffset =
904e8d8bef9SDimitry Andric TFI->getFrameIndexReferenceSP(MF, FrameIndex, BasePtr, 0).getFixed();
905c14a5a88SDimitry Andric } else if (TFI->Is64Bit && (MBB.isEHFuncletEntry() || IsEHFuncletEpilogue)) {
906c14a5a88SDimitry Andric FIOffset = TFI->getWin64EHFrameIndexRef(MF, FrameIndex, BasePtr);
9070b57cec5SDimitry Andric } else {
908e8d8bef9SDimitry Andric FIOffset = TFI->getFrameIndexReference(MF, FrameIndex, BasePtr).getFixed();
9090b57cec5SDimitry Andric }
9100b57cec5SDimitry Andric
9110b57cec5SDimitry Andric // LOCAL_ESCAPE uses a single offset, with no register. It only works in the
9120b57cec5SDimitry Andric // simple FP case, and doesn't work with stack realignment. On 32-bit, the
9130b57cec5SDimitry Andric // offset is from the traditional base pointer location. On 64-bit, the
9140b57cec5SDimitry Andric // offset is from the SP at the end of the prologue, not the FP location. This
9150b57cec5SDimitry Andric // matches the behavior of llvm.frameaddress.
9160b57cec5SDimitry Andric unsigned Opc = MI.getOpcode();
9170b57cec5SDimitry Andric if (Opc == TargetOpcode::LOCAL_ESCAPE) {
9180b57cec5SDimitry Andric MachineOperand &FI = MI.getOperand(FIOperandNum);
9190b57cec5SDimitry Andric FI.ChangeToImmediate(FIOffset);
920bdd1243dSDimitry Andric return false;
9210b57cec5SDimitry Andric }
9220b57cec5SDimitry Andric
9230b57cec5SDimitry Andric // For LEA64_32r when BasePtr is 32-bits (X32) we can use full-size 64-bit
9240b57cec5SDimitry Andric // register as source operand, semantic is the same and destination is
9250b57cec5SDimitry Andric // 32-bits. It saves one byte per lea in code since 0x67 prefix is avoided.
9260b57cec5SDimitry Andric // Don't change BasePtr since it is used later for stack adjustment.
9278bcb0991SDimitry Andric Register MachineBasePtr = BasePtr;
9280b57cec5SDimitry Andric if (Opc == X86::LEA64_32r && X86::GR32RegClass.contains(BasePtr))
9290b57cec5SDimitry Andric MachineBasePtr = getX86SubSuperRegister(BasePtr, 64);
9300b57cec5SDimitry Andric
9310b57cec5SDimitry Andric // This must be part of a four operand memory reference. Replace the
9320b57cec5SDimitry Andric // FrameIndex with base register. Add an offset to the offset.
9330b57cec5SDimitry Andric MI.getOperand(FIOperandNum).ChangeToRegister(MachineBasePtr, false);
9340b57cec5SDimitry Andric
9350b57cec5SDimitry Andric if (BasePtr == StackPtr)
9360b57cec5SDimitry Andric FIOffset += SPAdj;
9370b57cec5SDimitry Andric
9380b57cec5SDimitry Andric // The frame index format for stackmaps and patchpoints is different from the
9390b57cec5SDimitry Andric // X86 format. It only has a FI and an offset.
9400b57cec5SDimitry Andric if (Opc == TargetOpcode::STACKMAP || Opc == TargetOpcode::PATCHPOINT) {
9410b57cec5SDimitry Andric assert(BasePtr == FramePtr && "Expected the FP as base register");
9420b57cec5SDimitry Andric int64_t Offset = MI.getOperand(FIOperandNum + 1).getImm() + FIOffset;
9430b57cec5SDimitry Andric MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
944bdd1243dSDimitry Andric return false;
9450b57cec5SDimitry Andric }
9460b57cec5SDimitry Andric
9470b57cec5SDimitry Andric if (MI.getOperand(FIOperandNum+3).isImm()) {
9480b57cec5SDimitry Andric // Offset is a 32-bit integer.
9490b57cec5SDimitry Andric int Imm = (int)(MI.getOperand(FIOperandNum + 3).getImm());
9500b57cec5SDimitry Andric int Offset = FIOffset + Imm;
9510b57cec5SDimitry Andric assert((!Is64Bit || isInt<32>((long long)FIOffset + Imm)) &&
9520b57cec5SDimitry Andric "Requesting 64-bit offset in 32-bit immediate!");
9530b57cec5SDimitry Andric if (Offset != 0 || !tryOptimizeLEAtoMOV(II))
9540b57cec5SDimitry Andric MI.getOperand(FIOperandNum + 3).ChangeToImmediate(Offset);
9550b57cec5SDimitry Andric } else {
9560b57cec5SDimitry Andric // Offset is symbolic. This is extremely rare.
9570b57cec5SDimitry Andric uint64_t Offset = FIOffset +
9580b57cec5SDimitry Andric (uint64_t)MI.getOperand(FIOperandNum+3).getOffset();
9590b57cec5SDimitry Andric MI.getOperand(FIOperandNum + 3).setOffset(Offset);
9600b57cec5SDimitry Andric }
961bdd1243dSDimitry Andric return false;
9620b57cec5SDimitry Andric }
9630b57cec5SDimitry Andric
findDeadCallerSavedReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator & MBBI) const964e8d8bef9SDimitry Andric unsigned X86RegisterInfo::findDeadCallerSavedReg(
965e8d8bef9SDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI) const {
966e8d8bef9SDimitry Andric const MachineFunction *MF = MBB.getParent();
967e8d8bef9SDimitry Andric if (MF->callsEHReturn())
968e8d8bef9SDimitry Andric return 0;
969e8d8bef9SDimitry Andric
970e8d8bef9SDimitry Andric const TargetRegisterClass &AvailableRegs = *getGPRsForTailCall(*MF);
971e8d8bef9SDimitry Andric
972e8d8bef9SDimitry Andric if (MBBI == MBB.end())
973e8d8bef9SDimitry Andric return 0;
974e8d8bef9SDimitry Andric
975e8d8bef9SDimitry Andric switch (MBBI->getOpcode()) {
976e8d8bef9SDimitry Andric default:
977e8d8bef9SDimitry Andric return 0;
978e8d8bef9SDimitry Andric case TargetOpcode::PATCHABLE_RET:
979e8d8bef9SDimitry Andric case X86::RET:
980349cc55cSDimitry Andric case X86::RET32:
981349cc55cSDimitry Andric case X86::RET64:
982349cc55cSDimitry Andric case X86::RETI32:
983349cc55cSDimitry Andric case X86::RETI64:
984e8d8bef9SDimitry Andric case X86::TCRETURNdi:
985e8d8bef9SDimitry Andric case X86::TCRETURNri:
986e8d8bef9SDimitry Andric case X86::TCRETURNmi:
987e8d8bef9SDimitry Andric case X86::TCRETURNdi64:
988e8d8bef9SDimitry Andric case X86::TCRETURNri64:
989e8d8bef9SDimitry Andric case X86::TCRETURNmi64:
990e8d8bef9SDimitry Andric case X86::EH_RETURN:
991e8d8bef9SDimitry Andric case X86::EH_RETURN64: {
992e8d8bef9SDimitry Andric SmallSet<uint16_t, 8> Uses;
99306c3fb27SDimitry Andric for (MachineOperand &MO : MBBI->operands()) {
994e8d8bef9SDimitry Andric if (!MO.isReg() || MO.isDef())
995e8d8bef9SDimitry Andric continue;
996e8d8bef9SDimitry Andric Register Reg = MO.getReg();
997e8d8bef9SDimitry Andric if (!Reg)
998e8d8bef9SDimitry Andric continue;
999e8d8bef9SDimitry Andric for (MCRegAliasIterator AI(Reg, this, true); AI.isValid(); ++AI)
1000e8d8bef9SDimitry Andric Uses.insert(*AI);
1001e8d8bef9SDimitry Andric }
1002e8d8bef9SDimitry Andric
1003e8d8bef9SDimitry Andric for (auto CS : AvailableRegs)
1004e8d8bef9SDimitry Andric if (!Uses.count(CS) && CS != X86::RIP && CS != X86::RSP && CS != X86::ESP)
1005e8d8bef9SDimitry Andric return CS;
1006e8d8bef9SDimitry Andric }
1007e8d8bef9SDimitry Andric }
1008e8d8bef9SDimitry Andric
1009e8d8bef9SDimitry Andric return 0;
1010e8d8bef9SDimitry Andric }
1011e8d8bef9SDimitry Andric
getFrameRegister(const MachineFunction & MF) const10120b57cec5SDimitry Andric Register X86RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
10130b57cec5SDimitry Andric const X86FrameLowering *TFI = getFrameLowering(MF);
10140b57cec5SDimitry Andric return TFI->hasFP(MF) ? FramePtr : StackPtr;
10150b57cec5SDimitry Andric }
10160b57cec5SDimitry Andric
10170b57cec5SDimitry Andric unsigned
getPtrSizedFrameRegister(const MachineFunction & MF) const10180b57cec5SDimitry Andric X86RegisterInfo::getPtrSizedFrameRegister(const MachineFunction &MF) const {
10190b57cec5SDimitry Andric const X86Subtarget &Subtarget = MF.getSubtarget<X86Subtarget>();
10208bcb0991SDimitry Andric Register FrameReg = getFrameRegister(MF);
10210b57cec5SDimitry Andric if (Subtarget.isTarget64BitILP32())
10220b57cec5SDimitry Andric FrameReg = getX86SubSuperRegister(FrameReg, 32);
10230b57cec5SDimitry Andric return FrameReg;
10240b57cec5SDimitry Andric }
10250b57cec5SDimitry Andric
10260b57cec5SDimitry Andric unsigned
getPtrSizedStackRegister(const MachineFunction & MF) const10270b57cec5SDimitry Andric X86RegisterInfo::getPtrSizedStackRegister(const MachineFunction &MF) const {
10280b57cec5SDimitry Andric const X86Subtarget &Subtarget = MF.getSubtarget<X86Subtarget>();
10298bcb0991SDimitry Andric Register StackReg = getStackRegister();
10300b57cec5SDimitry Andric if (Subtarget.isTarget64BitILP32())
10310b57cec5SDimitry Andric StackReg = getX86SubSuperRegister(StackReg, 32);
10320b57cec5SDimitry Andric return StackReg;
10330b57cec5SDimitry Andric }
1034e8d8bef9SDimitry Andric
getTileShape(Register VirtReg,VirtRegMap * VRM,const MachineRegisterInfo * MRI)1035e8d8bef9SDimitry Andric static ShapeT getTileShape(Register VirtReg, VirtRegMap *VRM,
1036e8d8bef9SDimitry Andric const MachineRegisterInfo *MRI) {
1037e8d8bef9SDimitry Andric if (VRM->hasShape(VirtReg))
1038e8d8bef9SDimitry Andric return VRM->getShape(VirtReg);
1039e8d8bef9SDimitry Andric
1040e8d8bef9SDimitry Andric const MachineOperand &Def = *MRI->def_begin(VirtReg);
1041e8d8bef9SDimitry Andric MachineInstr *MI = const_cast<MachineInstr *>(Def.getParent());
1042e8d8bef9SDimitry Andric unsigned OpCode = MI->getOpcode();
1043e8d8bef9SDimitry Andric switch (OpCode) {
1044e8d8bef9SDimitry Andric default:
1045e8d8bef9SDimitry Andric llvm_unreachable("Unexpected machine instruction on tile register!");
1046e8d8bef9SDimitry Andric break;
1047fe6060f1SDimitry Andric case X86::COPY: {
1048fe6060f1SDimitry Andric Register SrcReg = MI->getOperand(1).getReg();
1049fe6060f1SDimitry Andric ShapeT Shape = getTileShape(SrcReg, VRM, MRI);
1050fe6060f1SDimitry Andric VRM->assignVirt2Shape(VirtReg, Shape);
1051fe6060f1SDimitry Andric return Shape;
1052fe6060f1SDimitry Andric }
1053e8d8bef9SDimitry Andric // We only collect the tile shape that is defined.
1054e8d8bef9SDimitry Andric case X86::PTILELOADDV:
1055fe6060f1SDimitry Andric case X86::PTILELOADDT1V:
1056e8d8bef9SDimitry Andric case X86::PTDPBSSDV:
1057fe6060f1SDimitry Andric case X86::PTDPBSUDV:
1058fe6060f1SDimitry Andric case X86::PTDPBUSDV:
1059fe6060f1SDimitry Andric case X86::PTDPBUUDV:
1060e8d8bef9SDimitry Andric case X86::PTILEZEROV:
1061fe6060f1SDimitry Andric case X86::PTDPBF16PSV:
1062bdd1243dSDimitry Andric case X86::PTDPFP16PSV:
106306c3fb27SDimitry Andric case X86::PTCMMIMFP16PSV:
106406c3fb27SDimitry Andric case X86::PTCMMRLFP16PSV:
1065e8d8bef9SDimitry Andric MachineOperand &MO1 = MI->getOperand(1);
1066e8d8bef9SDimitry Andric MachineOperand &MO2 = MI->getOperand(2);
1067e8d8bef9SDimitry Andric ShapeT Shape(&MO1, &MO2, MRI);
1068e8d8bef9SDimitry Andric VRM->assignVirt2Shape(VirtReg, Shape);
1069e8d8bef9SDimitry Andric return Shape;
1070e8d8bef9SDimitry Andric }
1071e8d8bef9SDimitry Andric }
1072e8d8bef9SDimitry Andric
getRegAllocationHints(Register VirtReg,ArrayRef<MCPhysReg> Order,SmallVectorImpl<MCPhysReg> & Hints,const MachineFunction & MF,const VirtRegMap * VRM,const LiveRegMatrix * Matrix) const1073e8d8bef9SDimitry Andric bool X86RegisterInfo::getRegAllocationHints(Register VirtReg,
1074e8d8bef9SDimitry Andric ArrayRef<MCPhysReg> Order,
1075e8d8bef9SDimitry Andric SmallVectorImpl<MCPhysReg> &Hints,
1076e8d8bef9SDimitry Andric const MachineFunction &MF,
1077e8d8bef9SDimitry Andric const VirtRegMap *VRM,
1078e8d8bef9SDimitry Andric const LiveRegMatrix *Matrix) const {
1079e8d8bef9SDimitry Andric const MachineRegisterInfo *MRI = &MF.getRegInfo();
1080e8d8bef9SDimitry Andric const TargetRegisterClass &RC = *MRI->getRegClass(VirtReg);
1081e8d8bef9SDimitry Andric bool BaseImplRetVal = TargetRegisterInfo::getRegAllocationHints(
1082e8d8bef9SDimitry Andric VirtReg, Order, Hints, MF, VRM, Matrix);
1083e8d8bef9SDimitry Andric
10845f757f3fSDimitry Andric unsigned ID = RC.getID();
10855f757f3fSDimitry Andric if (ID != X86::TILERegClassID)
1086e8d8bef9SDimitry Andric return BaseImplRetVal;
1087e8d8bef9SDimitry Andric
1088e8d8bef9SDimitry Andric ShapeT VirtShape = getTileShape(VirtReg, const_cast<VirtRegMap *>(VRM), MRI);
1089e8d8bef9SDimitry Andric auto AddHint = [&](MCPhysReg PhysReg) {
1090e8d8bef9SDimitry Andric Register VReg = Matrix->getOneVReg(PhysReg);
1091e8d8bef9SDimitry Andric if (VReg == MCRegister::NoRegister) { // Not allocated yet
1092e8d8bef9SDimitry Andric Hints.push_back(PhysReg);
1093e8d8bef9SDimitry Andric return;
1094e8d8bef9SDimitry Andric }
1095e8d8bef9SDimitry Andric ShapeT PhysShape = getTileShape(VReg, const_cast<VirtRegMap *>(VRM), MRI);
1096e8d8bef9SDimitry Andric if (PhysShape == VirtShape)
1097e8d8bef9SDimitry Andric Hints.push_back(PhysReg);
1098e8d8bef9SDimitry Andric };
1099e8d8bef9SDimitry Andric
1100e8d8bef9SDimitry Andric SmallSet<MCPhysReg, 4> CopyHints;
1101e8d8bef9SDimitry Andric CopyHints.insert(Hints.begin(), Hints.end());
1102e8d8bef9SDimitry Andric Hints.clear();
1103e8d8bef9SDimitry Andric for (auto Hint : CopyHints) {
1104e8d8bef9SDimitry Andric if (RC.contains(Hint) && !MRI->isReserved(Hint))
1105e8d8bef9SDimitry Andric AddHint(Hint);
1106e8d8bef9SDimitry Andric }
1107e8d8bef9SDimitry Andric for (MCPhysReg PhysReg : Order) {
1108e8d8bef9SDimitry Andric if (!CopyHints.count(PhysReg) && RC.contains(PhysReg) &&
1109e8d8bef9SDimitry Andric !MRI->isReserved(PhysReg))
1110e8d8bef9SDimitry Andric AddHint(PhysReg);
1111e8d8bef9SDimitry Andric }
1112e8d8bef9SDimitry Andric
1113e8d8bef9SDimitry Andric #define DEBUG_TYPE "tile-hint"
1114e8d8bef9SDimitry Andric LLVM_DEBUG({
1115e8d8bef9SDimitry Andric dbgs() << "Hints for virtual register " << format_hex(VirtReg, 8) << "\n";
1116e8d8bef9SDimitry Andric for (auto Hint : Hints) {
1117e8d8bef9SDimitry Andric dbgs() << "tmm" << Hint << ",";
1118e8d8bef9SDimitry Andric }
1119e8d8bef9SDimitry Andric dbgs() << "\n";
1120e8d8bef9SDimitry Andric });
1121e8d8bef9SDimitry Andric #undef DEBUG_TYPE
1122e8d8bef9SDimitry Andric
1123e8d8bef9SDimitry Andric return true;
1124e8d8bef9SDimitry Andric }
1125