1 //=- RISCVMachineFunctionInfo.cpp - RISC-V machine function info --*- C++ -*-=// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file declares RISCV-specific per-machine-function information. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "RISCVMachineFunctionInfo.h" 14 #include "llvm/IR/Module.h" 15 16 using namespace llvm; 17 18 yaml::RISCVMachineFunctionInfo::RISCVMachineFunctionInfo( 19 const llvm::RISCVMachineFunctionInfo &MFI) 20 : VarArgsFrameIndex(MFI.getVarArgsFrameIndex()), 21 VarArgsSaveSize(MFI.getVarArgsSaveSize()) {} 22 23 MachineFunctionInfo *RISCVMachineFunctionInfo::clone( 24 BumpPtrAllocator &Allocator, MachineFunction &DestMF, 25 const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB) 26 const { 27 return DestMF.cloneInfo<RISCVMachineFunctionInfo>(*this); 28 } 29 30 RISCVMachineFunctionInfo::RISCVMachineFunctionInfo(const Function &F, 31 const RISCVSubtarget *STI) { 32 33 // The default stack probe size is 4096 if the function has no 34 // stack-probe-size attribute. This is a safe default because it is the 35 // smallest possible guard page size. 36 uint64_t ProbeSize = 4096; 37 if (F.hasFnAttribute("stack-probe-size")) 38 ProbeSize = F.getFnAttributeAsParsedInteger("stack-probe-size"); 39 else if (const auto *PS = mdconst::extract_or_null<ConstantInt>( 40 F.getParent()->getModuleFlag("stack-probe-size"))) 41 ProbeSize = PS->getZExtValue(); 42 assert(int64_t(ProbeSize) > 0 && "Invalid stack probe size"); 43 44 // Round down to the stack alignment. 45 uint64_t StackAlign = 46 STI->getFrameLowering()->getTransientStackAlign().value(); 47 ProbeSize = std::max(StackAlign, alignDown(ProbeSize, StackAlign)); 48 StringRef ProbeKind; 49 if (F.hasFnAttribute("probe-stack")) 50 ProbeKind = F.getFnAttribute("probe-stack").getValueAsString(); 51 else if (const auto *PS = dyn_cast_or_null<MDString>( 52 F.getParent()->getModuleFlag("probe-stack"))) 53 ProbeKind = PS->getString(); 54 if (ProbeKind.size()) { 55 StackProbeSize = ProbeSize; 56 } 57 } 58 59 RISCVMachineFunctionInfo::InterruptStackKind 60 RISCVMachineFunctionInfo::getInterruptStackKind( 61 const MachineFunction &MF) const { 62 if (!MF.getFunction().hasFnAttribute("interrupt")) 63 return InterruptStackKind::None; 64 65 assert(VarArgsSaveSize == 0 && 66 "Interrupt functions should not having incoming varargs"); 67 68 StringRef InterruptVal = 69 MF.getFunction().getFnAttribute("interrupt").getValueAsString(); 70 71 return StringSwitch<RISCVMachineFunctionInfo::InterruptStackKind>( 72 InterruptVal) 73 .Case("qci-nest", InterruptStackKind::QCINest) 74 .Case("qci-nonest", InterruptStackKind::QCINoNest) 75 .Case("SiFive-CLIC-preemptible", 76 InterruptStackKind::SiFiveCLICPreemptible) 77 .Case("SiFive-CLIC-stack-swap", InterruptStackKind::SiFiveCLICStackSwap) 78 .Case("SiFive-CLIC-preemptible-stack-swap", 79 InterruptStackKind::SiFiveCLICPreemptibleStackSwap) 80 .Default(InterruptStackKind::None); 81 } 82 83 void yaml::RISCVMachineFunctionInfo::mappingImpl(yaml::IO &YamlIO) { 84 MappingTraits<RISCVMachineFunctionInfo>::mapping(YamlIO, *this); 85 } 86 87 RISCVMachineFunctionInfo::PushPopKind 88 RISCVMachineFunctionInfo::getPushPopKind(const MachineFunction &MF) const { 89 // We cannot use fixed locations for the callee saved spill slots if the 90 // function uses a varargs save area. 91 // TODO: Use a separate placement for vararg registers to enable Zcmp. 92 if (VarArgsSaveSize != 0) 93 return PushPopKind::None; 94 95 // SiFive interrupts are not compatible with push/pop. 96 if (useSiFiveInterrupt(MF)) 97 return PushPopKind::None; 98 99 // Zcmp is not compatible with the frame pointer convention. 100 if (MF.getSubtarget<RISCVSubtarget>().hasStdExtZcmp() && 101 !MF.getTarget().Options.DisableFramePointerElim(MF)) 102 return PushPopKind::StdExtZcmp; 103 104 // Xqccmp is Zcmp but has a push order compatible with the frame-pointer 105 // convention. 106 if (MF.getSubtarget<RISCVSubtarget>().hasVendorXqccmp()) 107 return PushPopKind::VendorXqccmp; 108 109 return PushPopKind::None; 110 } 111 112 bool RISCVMachineFunctionInfo::hasImplicitFPUpdates( 113 const MachineFunction &MF) const { 114 switch (getInterruptStackKind(MF)) { 115 case InterruptStackKind::QCINest: 116 case InterruptStackKind::QCINoNest: 117 // QC.C.MIENTER and QC.C.MIENTER.NEST both update FP on function entry. 118 return true; 119 default: 120 break; 121 } 122 123 switch (getPushPopKind(MF)) { 124 case PushPopKind::VendorXqccmp: 125 // When using Xqccmp, we will use `QC.CM.PUSHFP` when Frame Pointers are 126 // enabled, which will update FP. 127 return true; 128 default: 129 break; 130 } 131 132 return false; 133 } 134 135 void RISCVMachineFunctionInfo::initializeBaseYamlFields( 136 const yaml::RISCVMachineFunctionInfo &YamlMFI) { 137 VarArgsFrameIndex = YamlMFI.VarArgsFrameIndex; 138 VarArgsSaveSize = YamlMFI.VarArgsSaveSize; 139 } 140 141 void RISCVMachineFunctionInfo::addSExt32Register(Register Reg) { 142 SExt32Registers.push_back(Reg); 143 } 144 145 bool RISCVMachineFunctionInfo::isSExt32Register(Register Reg) const { 146 return is_contained(SExt32Registers, Reg); 147 } 148