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
RISCVMachineFunctionInfo(const llvm::RISCVMachineFunctionInfo & MFI)18 yaml::RISCVMachineFunctionInfo::RISCVMachineFunctionInfo(
19 const llvm::RISCVMachineFunctionInfo &MFI)
20 : VarArgsFrameIndex(MFI.getVarArgsFrameIndex()),
21 VarArgsSaveSize(MFI.getVarArgsSaveSize()) {}
22
clone(BumpPtrAllocator & Allocator,MachineFunction & DestMF,const DenseMap<MachineBasicBlock *,MachineBasicBlock * > & Src2DstMBB) const23 MachineFunctionInfo *RISCVMachineFunctionInfo::clone(
24 BumpPtrAllocator &Allocator, MachineFunction &DestMF,
25 const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
26 const {
27 return DestMF.cloneInfo<RISCVMachineFunctionInfo>(*this);
28 }
29
RISCVMachineFunctionInfo(const Function & F,const RISCVSubtarget * STI)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
getInterruptStackKind(const MachineFunction & MF) const60 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
mappingImpl(yaml::IO & YamlIO)83 void yaml::RISCVMachineFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
84 MappingTraits<RISCVMachineFunctionInfo>::mapping(YamlIO, *this);
85 }
86
87 RISCVMachineFunctionInfo::PushPopKind
getPushPopKind(const MachineFunction & MF) const88 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
hasImplicitFPUpdates(const MachineFunction & MF) const112 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
initializeBaseYamlFields(const yaml::RISCVMachineFunctionInfo & YamlMFI)135 void RISCVMachineFunctionInfo::initializeBaseYamlFields(
136 const yaml::RISCVMachineFunctionInfo &YamlMFI) {
137 VarArgsFrameIndex = YamlMFI.VarArgsFrameIndex;
138 VarArgsSaveSize = YamlMFI.VarArgsSaveSize;
139 }
140
addSExt32Register(Register Reg)141 void RISCVMachineFunctionInfo::addSExt32Register(Register Reg) {
142 SExt32Registers.push_back(Reg);
143 }
144
isSExt32Register(Register Reg) const145 bool RISCVMachineFunctionInfo::isSExt32Register(Register Reg) const {
146 return is_contained(SExt32Registers, Reg);
147 }
148