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