LLVM 22.0.0git
RISCVIndirectBranchTracking.cpp
Go to the documentation of this file.
1//===------ RISCVIndirectBranchTracking.cpp - Enables lpad mechanism ------===//
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// The pass adds LPAD (AUIPC with rd = X0) machine instructions at the
10// beginning of each basic block or function that is referenced by an indirect
11// jump/call instruction.
12//
13//===----------------------------------------------------------------------===//
14
15#include "RISCV.h"
16#include "RISCVInstrInfo.h"
17#include "RISCVSubtarget.h"
18#include "llvm/ADT/Statistic.h"
23
24#define DEBUG_TYPE "riscv-indirect-branch-tracking"
25#define PASS_NAME "RISC-V Indirect Branch Tracking"
26
27using namespace llvm;
28
30 "riscv-landing-pad-label", cl::ReallyHidden,
31 cl::desc("Use preferred fixed label for all labels"));
32
33namespace {
34class RISCVIndirectBranchTracking : public MachineFunctionPass {
35public:
36 static char ID;
37 RISCVIndirectBranchTracking() : MachineFunctionPass(ID) {}
38
39 StringRef getPassName() const override { return PASS_NAME; }
40
41 bool runOnMachineFunction(MachineFunction &MF) override;
42
43private:
44 const Align LpadAlign = Align(4);
45};
46
47} // end anonymous namespace
48
49INITIALIZE_PASS(RISCVIndirectBranchTracking, DEBUG_TYPE, PASS_NAME, false,
50 false)
51
52char RISCVIndirectBranchTracking::ID = 0;
53
55 return new RISCVIndirectBranchTracking();
56}
57
58static void
61 if (!I.isValid())
62 I = MBB.begin();
63 BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(RISCV::AUIPC), RISCV::X0)
64 .addImm(Label);
65}
66
67static bool isCallReturnTwice(const MachineOperand &MOp) {
68 if (!MOp.isGlobal())
69 return false;
70 auto *CalleeFn = dyn_cast<Function>(MOp.getGlobal());
71 if (!CalleeFn)
72 return false;
73 AttributeList Attrs = CalleeFn->getAttributes();
74 return Attrs.hasFnAttr(Attribute::ReturnsTwice);
75}
76
77bool RISCVIndirectBranchTracking::runOnMachineFunction(MachineFunction &MF) {
78 const auto &Subtarget = MF.getSubtarget<RISCVSubtarget>();
79 const RISCVInstrInfo *TII = Subtarget.getInstrInfo();
80 if (!Subtarget.hasStdExtZicfilp())
81 return false;
82
83 uint32_t FixedLabel = 0;
84 if (PreferredLandingPadLabel.getNumOccurrences() > 0) {
86 report_fatal_error("riscv-landing-pad-label=<val>, <val> needs to fit in "
87 "unsigned 20-bits");
88 FixedLabel = PreferredLandingPadLabel;
89 }
90
91 bool Changed = false;
92 for (MachineBasicBlock &MBB : MF) {
93 if (&MBB == &MF.front()) {
94 Function &F = MF.getFunction();
95 // When trap is taken, landing pad is not needed.
96 if (F.hasFnAttribute("interrupt"))
97 continue;
98
99 if (F.hasAddressTaken() || !F.hasLocalLinkage()) {
100 emitLpad(MBB, TII, FixedLabel);
101 if (MF.getAlignment() < LpadAlign)
102 MF.setAlignment(LpadAlign);
103 Changed = true;
104 }
105 continue;
106 }
107
108 if (MBB.hasAddressTaken()) {
109 emitLpad(MBB, TII, FixedLabel);
110 if (MBB.getAlignment() < LpadAlign)
111 MBB.setAlignment(LpadAlign);
112 Changed = true;
113 }
114 }
115
116 // Check for calls to functions with ReturnsTwice attribute and insert
117 // LPAD after such calls
118 for (MachineBasicBlock &MBB : MF) {
119 for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
120 if (I->isCall() && I->getNumOperands() > 0 &&
121 isCallReturnTwice(I->getOperand(0))) {
122 auto NextI = std::next(I);
123 emitLpad(MBB, TII, FixedLabel, NextI);
124 Changed = true;
125 }
126 }
127 }
128
129 return Changed;
130}
MachineBasicBlock & MBB
#define DEBUG_TYPE
const HexagonInstrInfo * TII
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool isCallReturnTwice(const MachineOperand &MOp)
cl::opt< uint32_t > PreferredLandingPadLabel("riscv-landing-pad-label", cl::ReallyHidden, cl::desc("Use preferred fixed label for all labels"))
static void emitLpad(MachineBasicBlock &MBB, const RISCVInstrInfo *TII, uint32_t Label, MachineBasicBlock::iterator I=MachineBasicBlock::iterator{})
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define PASS_NAME
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
bool hasAddressTaken() const
Test whether this block is used as something other than the target of a terminator,...
void setAlignment(Align A)
Set alignment of the basic block.
Align getAlignment() const
Return alignment of the basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
Changed
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
Definition MathExtras.h:189
FunctionPass * createRISCVIndirectBranchTrackingPass()