Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- TargetFrameLoweringImpl.cpp - Implement target frame interface ------==//
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
// Implements the layout of a stack frame on the target machine.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "llvm/ADT/BitVector.h"
14
#include "llvm/CodeGen/MachineFrameInfo.h"
15
#include "llvm/CodeGen/MachineFunction.h"
16
#include "llvm/CodeGen/MachineRegisterInfo.h"
17
#include "llvm/CodeGen/TargetFrameLowering.h"
18
#include "llvm/CodeGen/TargetSubtargetInfo.h"
19
#include "llvm/IR/Attributes.h"
20
#include "llvm/IR/Function.h"
21
#include "llvm/IR/InstrTypes.h"
22
#include "llvm/MC/MCAsmInfo.h"
23
#include "llvm/MC/MCRegisterInfo.h"
24
#include "llvm/Support/Compiler.h"
25
#include "llvm/Target/TargetMachine.h"
26
#include "llvm/Target/TargetOptions.h"
27
28
using namespace llvm;
29
30
2.54k
TargetFrameLowering::~TargetFrameLowering() = default;
31
32
0
bool TargetFrameLowering::enableCalleeSaveSkip(const MachineFunction &MF) const {
33
0
  assert(MF.getFunction().hasFnAttribute(Attribute::NoReturn) &&
34
0
         MF.getFunction().hasFnAttribute(Attribute::NoUnwind) &&
35
0
         !MF.getFunction().hasFnAttribute(Attribute::UWTable));
36
0
  return false;
37
0
}
38
39
48.9k
bool TargetFrameLowering::enableCFIFixup(MachineFunction &MF) const {
40
48.9k
  return MF.needsFrameMoves() &&
41
48.9k
         !MF.getTarget().getMCAsmInfo()->usesWindowsCFI();
42
48.9k
}
43
44
/// Returns the displacement from the frame register to the stack
45
/// frame of the specified index, along with the frame register used
46
/// (in output arg FrameReg). This is the default implementation which
47
/// is overridden for some targets.
48
StackOffset
49
TargetFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
50
1.38k
                                            Register &FrameReg) const {
51
1.38k
  const MachineFrameInfo &MFI = MF.getFrameInfo();
52
1.38k
  const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();
53
54
  // By default, assume all frame indices are referenced via whatever
55
  // getFrameRegister() says. The target can override this if it's doing
56
  // something different.
57
1.38k
  FrameReg = RI->getFrameRegister(MF);
58
59
1.38k
  return StackOffset::getFixed(MFI.getObjectOffset(FI) + MFI.getStackSize() -
60
1.38k
                               getOffsetOfLocalArea() +
61
1.38k
                               MFI.getOffsetAdjustment());
62
1.38k
}
63
64
bool TargetFrameLowering::needsFrameIndexResolution(
65
105k
    const MachineFunction &MF) const {
66
105k
  return MF.getFrameInfo().hasStackObjects();
67
105k
}
68
69
void TargetFrameLowering::getCalleeSaves(const MachineFunction &MF,
70
922
                                         BitVector &CalleeSaves) const {
71
922
  const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
72
922
  CalleeSaves.resize(TRI.getNumRegs());
73
74
922
  const MachineFrameInfo &MFI = MF.getFrameInfo();
75
922
  if (!MFI.isCalleeSavedInfoValid())
76
3
    return;
77
78
919
  for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo())
79
2.93k
    CalleeSaves.set(Info.getReg());
80
919
}
81
82
void TargetFrameLowering::determineCalleeSaves(MachineFunction &MF,
83
                                               BitVector &SavedRegs,
84
121k
                                               RegScavenger *RS) const {
85
121k
  const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
86
87
  // Resize before the early returns. Some backends expect that
88
  // SavedRegs.size() == TRI.getNumRegs() after this call even if there are no
89
  // saved registers.
90
121k
  SavedRegs.resize(TRI.getNumRegs());
91
92
  // When interprocedural register allocation is enabled caller saved registers
93
  // are preferred over callee saved registers.
94
121k
  if (MF.getTarget().Options.EnableIPRA &&
95
121k
      isSafeForNoCSROpt(MF.getFunction()) &&
96
121k
      isProfitableForNoCSROpt(MF.getFunction()))
97
0
    return;
98
99
  // Get the callee saved register list...
100
121k
  const MCPhysReg *CSRegs = MF.getRegInfo().getCalleeSavedRegs();
101
102
  // Early exit if there are no callee saved registers.
103
121k
  if (!CSRegs || CSRegs[0] == 0)
104
0
    return;
105
106
  // In Naked functions we aren't going to save any registers.
107
121k
  if (MF.getFunction().hasFnAttribute(Attribute::Naked))
108
0
    return;
109
110
  // Noreturn+nounwind functions never restore CSR, so no saves are needed.
111
  // Purely noreturn functions may still return through throws, so those must
112
  // save CSR for caller exception handlers.
113
  //
114
  // If the function uses longjmp to break out of its current path of
115
  // execution we do not need the CSR spills either: setjmp stores all CSRs
116
  // it was called with into the jmp_buf, which longjmp then restores.
117
121k
  if (MF.getFunction().hasFnAttribute(Attribute::NoReturn) &&
118
121k
        MF.getFunction().hasFnAttribute(Attribute::NoUnwind) &&
119
121k
        !MF.getFunction().hasFnAttribute(Attribute::UWTable) &&
120
121k
        enableCalleeSaveSkip(MF))
121
0
    return;
122
123
  // Functions which call __builtin_unwind_init get all their registers saved.
124
121k
  bool CallsUnwindInit = MF.callsUnwindInit();
125
121k
  const MachineRegisterInfo &MRI = MF.getRegInfo();
126
2.71M
  for (unsigned i = 0; CSRegs[i]; ++i) {
127
2.58M
    unsigned Reg = CSRegs[i];
128
2.58M
    if (CallsUnwindInit || MRI.isPhysRegModified(Reg))
129
216k
      SavedRegs.set(Reg);
130
2.58M
  }
131
121k
}
132
133
bool TargetFrameLowering::allocateScavengingFrameIndexesNearIncomingSP(
134
128k
  const MachineFunction &MF) const {
135
128k
  if (!hasFP(MF))
136
114k
    return false;
137
138
13.8k
  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
139
13.8k
  return RegInfo->useFPForScavengingIndex(MF) &&
140
13.8k
         !RegInfo->hasStackRealignment(MF);
141
128k
}
142
143
0
bool TargetFrameLowering::isSafeForNoCSROpt(const Function &F) {
144
0
  if (!F.hasLocalLinkage() || F.hasAddressTaken() ||
145
0
      !F.hasFnAttribute(Attribute::NoRecurse))
146
0
    return false;
147
  // Function should not be optimized as tail call.
148
0
  for (const User *U : F.users())
149
0
    if (auto *CB = dyn_cast<CallBase>(U))
150
0
      if (CB->isTailCall())
151
0
        return false;
152
0
  return true;
153
0
}
154
155
0
int TargetFrameLowering::getInitialCFAOffset(const MachineFunction &MF) const {
156
0
  llvm_unreachable("getInitialCFAOffset() not implemented!");
157
0
}
158
159
Register
160
0
TargetFrameLowering::getInitialCFARegister(const MachineFunction &MF) const {
161
0
  llvm_unreachable("getInitialCFARegister() not implemented!");
162
0
}
163
164
TargetFrameLowering::DwarfFrameBase
165
683
TargetFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const {
166
683
  const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();
167
683
  return DwarfFrameBase{DwarfFrameBase::Register, {RI->getFrameRegister(MF)}};
168
683
}