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 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 800b57cec5SDimitry Andric X86RegisterInfo::getSEHRegNum(unsigned i) const { 810b57cec5SDimitry Andric return getEncodingValue(i); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric const TargetRegisterClass * 850b57cec5SDimitry 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 * 970b57cec5SDimitry 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 * 1100b57cec5SDimitry 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 * 1810b57cec5SDimitry 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 2210b57cec5SDimitry 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 * 2370b57cec5SDimitry 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 * 2510b57cec5SDimitry 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 2620b57cec5SDimitry 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 * 2820b57cec5SDimitry 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 4110b57cec5SDimitry 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 * 4210b57cec5SDimitry 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* 5280b57cec5SDimitry Andric X86RegisterInfo::getNoPreservedMask() const { 5290b57cec5SDimitry Andric return CSR_NoRegs_RegMask; 5300b57cec5SDimitry Andric } 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric const uint32_t *X86RegisterInfo::getDarwinTLSCallPreservedMask() const { 5330b57cec5SDimitry Andric return CSR_64_TLS_Darwin_RegMask; 5340b57cec5SDimitry Andric } 5350b57cec5SDimitry Andric 5360b57cec5SDimitry 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 6405f757f3fSDimitry 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 67081ad6265SDimitry 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 70981ad6265SDimitry 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 72681ad6265SDimitry Andric bool X86RegisterInfo::isTileRegisterClass(const TargetRegisterClass *RC) const { 72781ad6265SDimitry Andric return RC->getID() == X86::TILERegClassID; 72881ad6265SDimitry Andric } 72981ad6265SDimitry Andric 7300b57cec5SDimitry 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 7500b57cec5SDimitry Andric static bool CantUseSP(const MachineFrameInfo &MFI) { 7510b57cec5SDimitry Andric return MFI.hasVarSizedObjects() || MFI.hasOpaqueSPAdjustment(); 7520b57cec5SDimitry Andric } 7530b57cec5SDimitry Andric 7540b57cec5SDimitry 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 7780b57cec5SDimitry 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 79706c3fb27SDimitry 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. 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 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 84406c3fb27SDimitry 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 8840b57cec5SDimitry 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 964e8d8bef9SDimitry 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 10120b57cec5SDimitry 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 10180b57cec5SDimitry 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 10270b57cec5SDimitry 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 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 1073e8d8bef9SDimitry 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