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>(Old: *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(Kind: "stack-probe-size" )) |
38 | ProbeSize = F.getFnAttributeAsParsedInteger(Kind: "stack-probe-size" ); |
39 | else if (const auto *PS = mdconst::extract_or_null<ConstantInt>( |
40 | MD: F.getParent()->getModuleFlag(Key: "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(a: StackAlign, b: alignDown(Value: ProbeSize, Align: StackAlign)); |
48 | StringRef ProbeKind; |
49 | if (F.hasFnAttribute(Kind: "probe-stack" )) |
50 | ProbeKind = F.getFnAttribute(Kind: "probe-stack" ).getValueAsString(); |
51 | else if (const auto *PS = dyn_cast_or_null<MDString>( |
52 | Val: F.getParent()->getModuleFlag(Key: "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(Kind: "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(Kind: "interrupt" ).getValueAsString(); |
70 | |
71 | return StringSwitch<RISCVMachineFunctionInfo::InterruptStackKind>( |
72 | InterruptVal) |
73 | .Case(S: "qci-nest" , Value: InterruptStackKind::QCINest) |
74 | .Case(S: "qci-nonest" , Value: InterruptStackKind::QCINoNest) |
75 | .Case(S: "SiFive-CLIC-preemptible" , |
76 | Value: InterruptStackKind::SiFiveCLICPreemptible) |
77 | .Case(S: "SiFive-CLIC-stack-swap" , Value: InterruptStackKind::SiFiveCLICStackSwap) |
78 | .Case(S: "SiFive-CLIC-preemptible-stack-swap" , |
79 | Value: InterruptStackKind::SiFiveCLICPreemptibleStackSwap) |
80 | .Default(Value: InterruptStackKind::None); |
81 | } |
82 | |
83 | void yaml::RISCVMachineFunctionInfo::mappingImpl(yaml::IO &YamlIO) { |
84 | MappingTraits<RISCVMachineFunctionInfo>::mapping(YamlIO, MFI&: *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(Elt: Reg); |
143 | } |
144 | |
145 | bool RISCVMachineFunctionInfo::isSExt32Register(Register Reg) const { |
146 | return is_contained(Range: SExt32Registers, Element: Reg); |
147 | } |
148 | |