Thanks to visit codestin.com
Credit goes to llvm.org

LLVM 22.0.0git
BPFInstrInfo.cpp
Go to the documentation of this file.
1//===-- BPFInstrInfo.cpp - BPF Instruction Information ----------*- 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 contains the BPF implementation of the TargetInstrInfo class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "BPFInstrInfo.h"
14#include "BPF.h"
15#include "BPFSubtarget.h"
19#include "llvm/IR/DebugLoc.h"
21#include <cassert>
22#include <iterator>
23
24#define GET_INSTRINFO_CTOR_DTOR
25#include "BPFGenInstrInfo.inc"
26
27using namespace llvm;
28
30 : BPFGenInstrInfo(STI, BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP) {}
31
34 const DebugLoc &DL, Register DestReg,
35 Register SrcReg, bool KillSrc,
36 bool RenamableDest, bool RenamableSrc) const {
37 if (BPF::GPRRegClass.contains(DestReg, SrcReg))
38 BuildMI(MBB, I, DL, get(BPF::MOV_rr), DestReg)
39 .addReg(SrcReg, getKillRegState(KillSrc));
40 else if (BPF::GPR32RegClass.contains(DestReg, SrcReg))
41 BuildMI(MBB, I, DL, get(BPF::MOV_rr_32), DestReg)
42 .addReg(SrcReg, getKillRegState(KillSrc));
43 else
44 llvm_unreachable("Impossible reg-to-reg copy");
45}
46
47void BPFInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const {
48 Register DstReg = MI->getOperand(0).getReg();
49 Register SrcReg = MI->getOperand(1).getReg();
50 uint64_t CopyLen = MI->getOperand(2).getImm();
51 uint64_t Alignment = MI->getOperand(3).getImm();
52 Register ScratchReg = MI->getOperand(4).getReg();
53 MachineBasicBlock *BB = MI->getParent();
54 DebugLoc dl = MI->getDebugLoc();
55 unsigned LdOpc, StOpc;
56
57 switch (Alignment) {
58 case 1:
59 LdOpc = BPF::LDB;
60 StOpc = BPF::STB;
61 break;
62 case 2:
63 LdOpc = BPF::LDH;
64 StOpc = BPF::STH;
65 break;
66 case 4:
67 LdOpc = BPF::LDW;
68 StOpc = BPF::STW;
69 break;
70 case 8:
71 LdOpc = BPF::LDD;
72 StOpc = BPF::STD;
73 break;
74 default:
75 llvm_unreachable("unsupported memcpy alignment");
76 }
77
78 unsigned IterationNum = CopyLen >> Log2_64(Alignment);
79 for(unsigned I = 0; I < IterationNum; ++I) {
80 BuildMI(*BB, MI, dl, get(LdOpc))
81 .addReg(ScratchReg, RegState::Define).addReg(SrcReg)
82 .addImm(I * Alignment);
83 BuildMI(*BB, MI, dl, get(StOpc))
84 .addReg(ScratchReg, RegState::Kill).addReg(DstReg)
85 .addImm(I * Alignment);
86 }
87
88 unsigned BytesLeft = CopyLen & (Alignment - 1);
89 unsigned Offset = IterationNum * Alignment;
90 bool Hanging4Byte = BytesLeft & 0x4;
91 bool Hanging2Byte = BytesLeft & 0x2;
92 bool Hanging1Byte = BytesLeft & 0x1;
93 if (Hanging4Byte) {
94 BuildMI(*BB, MI, dl, get(BPF::LDW))
95 .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
96 BuildMI(*BB, MI, dl, get(BPF::STW))
97 .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
98 Offset += 4;
99 }
100 if (Hanging2Byte) {
101 BuildMI(*BB, MI, dl, get(BPF::LDH))
102 .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
103 BuildMI(*BB, MI, dl, get(BPF::STH))
104 .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
105 Offset += 2;
106 }
107 if (Hanging1Byte) {
108 BuildMI(*BB, MI, dl, get(BPF::LDB))
109 .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
110 BuildMI(*BB, MI, dl, get(BPF::STB))
111 .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
112 }
113
114 BB->erase(MI);
115}
116
118 if (MI.getOpcode() == BPF::MEMCPY) {
119 expandMEMCPY(MI);
120 return true;
121 }
122
123 return false;
124}
125
128 Register SrcReg, bool IsKill, int FI,
129 const TargetRegisterClass *RC,
130 const TargetRegisterInfo *TRI,
131 Register VReg,
132 MachineInstr::MIFlag Flags) const {
133 DebugLoc DL;
134 if (I != MBB.end())
135 DL = I->getDebugLoc();
136
137 if (RC == &BPF::GPRRegClass)
138 BuildMI(MBB, I, DL, get(BPF::STD))
139 .addReg(SrcReg, getKillRegState(IsKill))
140 .addFrameIndex(FI)
141 .addImm(0);
142 else if (RC == &BPF::GPR32RegClass)
143 BuildMI(MBB, I, DL, get(BPF::STW32))
144 .addReg(SrcReg, getKillRegState(IsKill))
145 .addFrameIndex(FI)
146 .addImm(0);
147 else
148 llvm_unreachable("Can't store this register to stack slot");
149}
150
153 int FI, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI,
154 Register VReg, MachineInstr::MIFlag Flags) const {
155 DebugLoc DL;
156 if (I != MBB.end())
157 DL = I->getDebugLoc();
158
159 if (RC == &BPF::GPRRegClass)
160 BuildMI(MBB, I, DL, get(BPF::LDD), DestReg).addFrameIndex(FI).addImm(0);
161 else if (RC == &BPF::GPR32RegClass)
162 BuildMI(MBB, I, DL, get(BPF::LDW32), DestReg).addFrameIndex(FI).addImm(0);
163 else
164 llvm_unreachable("Can't load this register from stack slot");
165}
166
169 MachineBasicBlock *&FBB,
171 bool AllowModify) const {
172 // Start from the bottom of the block and work up, examining the
173 // terminator instructions.
175 while (I != MBB.begin()) {
176 --I;
177 if (I->isDebugInstr())
178 continue;
179
180 // Working from the bottom, when we see a non-terminator
181 // instruction, we're done.
182 if (!isUnpredicatedTerminator(*I))
183 break;
184
185 // From base method doc: ... returning true if it cannot be understood ...
186 // Indirect branch has multiple destinations and no true/false concepts.
187 if (I->isIndirectBranch())
188 return true;
189
190 // A terminator that isn't a branch can't easily be handled
191 // by this analysis.
192 if (!I->isBranch())
193 return true;
194
195 // Handle unconditional branches.
196 if (I->getOpcode() == BPF::JMP) {
197 if (!AllowModify) {
198 TBB = I->getOperand(0).getMBB();
199 continue;
200 }
201
202 // If the block has any instructions after a J, delete them.
203 MBB.erase(std::next(I), MBB.end());
204 Cond.clear();
205 FBB = nullptr;
206
207 // Delete the J if it's equivalent to a fall-through.
208 if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
209 TBB = nullptr;
210 I->eraseFromParent();
211 I = MBB.end();
212 continue;
213 }
214
215 // TBB is used to indicate the unconditinal destination.
216 TBB = I->getOperand(0).getMBB();
217 continue;
218 }
219 // Cannot handle conditional branches
220 return true;
221 }
222
223 return false;
224}
225
230 const DebugLoc &DL,
231 int *BytesAdded) const {
232 assert(!BytesAdded && "code size not handled");
233
234 // Shouldn't be a fall through.
235 assert(TBB && "insertBranch must not be told to insert a fallthrough");
236
237 if (Cond.empty()) {
238 // Unconditional branch
239 assert(!FBB && "Unconditional branch with multiple successors!");
240 BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB);
241 return 1;
242 }
243
244 llvm_unreachable("Unexpected conditional branch");
245}
246
248 int *BytesRemoved) const {
249 assert(!BytesRemoved && "code size not handled");
250
252 unsigned Count = 0;
253
254 while (I != MBB.begin()) {
255 --I;
256 if (I->isDebugInstr())
257 continue;
258 if (I->getOpcode() != BPF::JMP)
259 break;
260 // Remove the branch.
261 I->eraseFromParent();
262 I = MBB.end();
263 ++Count;
264 }
265
266 return Count;
267}
268
270 if (MI.getOpcode() != BPF::JX)
271 return -1;
272
273 // The pattern looks like:
274 // %0 = LD_imm64 %jump-table.0 ; load jump-table address
275 // %1 = ADD_rr %0, $another_reg ; address + offset
276 // %2 = LDD %1, 0 ; load the actual label
277 // JX %2
278 const MachineFunction &MF = *MI.getParent()->getParent();
279 const MachineRegisterInfo &MRI = MF.getRegInfo();
280
281 Register Reg = MI.getOperand(0).getReg();
282 if (!Reg.isVirtual())
283 return -1;
284 MachineInstr *Ldd = MRI.getUniqueVRegDef(Reg);
285 if (Ldd == nullptr || Ldd->getOpcode() != BPF::LDD)
286 return -1;
287
288 Reg = Ldd->getOperand(1).getReg();
289 if (!Reg.isVirtual())
290 return -1;
291 MachineInstr *Add = MRI.getUniqueVRegDef(Reg);
292 if (Add == nullptr || Add->getOpcode() != BPF::ADD_rr)
293 return -1;
294
295 Reg = Add->getOperand(1).getReg();
296 if (!Reg.isVirtual())
297 return -1;
298 MachineInstr *LDimm64 = MRI.getUniqueVRegDef(Reg);
299 if (LDimm64 == nullptr || LDimm64->getOpcode() != BPF::LD_imm64)
300 return -1;
301
302 const MachineOperand &MO = LDimm64->getOperand(1);
303 if (!MO.isJTI())
304 return -1;
305
306 return MO.getIndex();
307}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:58
Register const TargetRegisterInfo * TRI
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:480
This file defines the SmallVector class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
int getJumpTableIndex(const MachineInstr &MI) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
bool expandPostRAPseudo(MachineInstr &MI) const override
BPFInstrInfo(const BPFSubtarget &STI)
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
A debug info location.
Definition DebugLoc.h:124
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineInstrBundleIterator< MachineInstr > iterator
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition Register.h:19
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Define
Register definition.
@ Kill
The last use of a register.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:348
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
@ Add
Sum of integers.
unsigned getKillRegState(bool B)