LLVM 20.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"
18#include "llvm/IR/DebugLoc.h"
20#include <cassert>
21#include <iterator>
22
23#define GET_INSTRINFO_CTOR_DTOR
24#include "BPFGenInstrInfo.inc"
25
26using namespace llvm;
27
29 : BPFGenInstrInfo(BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP) {}
30
33 const DebugLoc &DL, MCRegister DestReg,
34 MCRegister SrcReg, bool KillSrc,
35 bool RenamableDest, bool RenamableSrc) const {
36 if (BPF::GPRRegClass.contains(DestReg, SrcReg))
37 BuildMI(MBB, I, DL, get(BPF::MOV_rr), DestReg)
38 .addReg(SrcReg, getKillRegState(KillSrc));
39 else if (BPF::GPR32RegClass.contains(DestReg, SrcReg))
40 BuildMI(MBB, I, DL, get(BPF::MOV_rr_32), DestReg)
41 .addReg(SrcReg, getKillRegState(KillSrc));
42 else
43 llvm_unreachable("Impossible reg-to-reg copy");
44}
45
46void BPFInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const {
47 Register DstReg = MI->getOperand(0).getReg();
48 Register SrcReg = MI->getOperand(1).getReg();
49 uint64_t CopyLen = MI->getOperand(2).getImm();
50 uint64_t Alignment = MI->getOperand(3).getImm();
51 Register ScratchReg = MI->getOperand(4).getReg();
52 MachineBasicBlock *BB = MI->getParent();
53 DebugLoc dl = MI->getDebugLoc();
54 unsigned LdOpc, StOpc;
55
56 switch (Alignment) {
57 case 1:
58 LdOpc = BPF::LDB;
59 StOpc = BPF::STB;
60 break;
61 case 2:
62 LdOpc = BPF::LDH;
63 StOpc = BPF::STH;
64 break;
65 case 4:
66 LdOpc = BPF::LDW;
67 StOpc = BPF::STW;
68 break;
69 case 8:
70 LdOpc = BPF::LDD;
71 StOpc = BPF::STD;
72 break;
73 default:
74 llvm_unreachable("unsupported memcpy alignment");
75 }
76
77 unsigned IterationNum = CopyLen >> Log2_64(Alignment);
78 for(unsigned I = 0; I < IterationNum; ++I) {
79 BuildMI(*BB, MI, dl, get(LdOpc))
80 .addReg(ScratchReg, RegState::Define).addReg(SrcReg)
81 .addImm(I * Alignment);
82 BuildMI(*BB, MI, dl, get(StOpc))
83 .addReg(ScratchReg, RegState::Kill).addReg(DstReg)
84 .addImm(I * Alignment);
85 }
86
87 unsigned BytesLeft = CopyLen & (Alignment - 1);
88 unsigned Offset = IterationNum * Alignment;
89 bool Hanging4Byte = BytesLeft & 0x4;
90 bool Hanging2Byte = BytesLeft & 0x2;
91 bool Hanging1Byte = BytesLeft & 0x1;
92 if (Hanging4Byte) {
93 BuildMI(*BB, MI, dl, get(BPF::LDW))
94 .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
95 BuildMI(*BB, MI, dl, get(BPF::STW))
96 .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
97 Offset += 4;
98 }
99 if (Hanging2Byte) {
100 BuildMI(*BB, MI, dl, get(BPF::LDH))
101 .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
102 BuildMI(*BB, MI, dl, get(BPF::STH))
103 .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
104 Offset += 2;
105 }
106 if (Hanging1Byte) {
107 BuildMI(*BB, MI, dl, get(BPF::LDB))
108 .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
109 BuildMI(*BB, MI, dl, get(BPF::STB))
110 .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
111 }
112
113 BB->erase(MI);
114}
115
117 if (MI.getOpcode() == BPF::MEMCPY) {
118 expandMEMCPY(MI);
119 return true;
120 }
121
122 return false;
123}
124
127 Register SrcReg, bool IsKill, int FI,
128 const TargetRegisterClass *RC,
129 const TargetRegisterInfo *TRI,
130 Register VReg) const {
131 DebugLoc DL;
132 if (I != MBB.end())
133 DL = I->getDebugLoc();
134
135 if (RC == &BPF::GPRRegClass)
136 BuildMI(MBB, I, DL, get(BPF::STD))
137 .addReg(SrcReg, getKillRegState(IsKill))
138 .addFrameIndex(FI)
139 .addImm(0);
140 else if (RC == &BPF::GPR32RegClass)
141 BuildMI(MBB, I, DL, get(BPF::STW32))
142 .addReg(SrcReg, getKillRegState(IsKill))
143 .addFrameIndex(FI)
144 .addImm(0);
145 else
146 llvm_unreachable("Can't store this register to stack slot");
147}
148
151 Register DestReg, int FI,
152 const TargetRegisterClass *RC,
153 const TargetRegisterInfo *TRI,
154 Register VReg) 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 // A terminator that isn't a branch can't easily be handled
186 // by this analysis.
187 if (!I->isBranch())
188 return true;
189
190 // Handle unconditional branches.
191 if (I->getOpcode() == BPF::JMP) {
192 if (!AllowModify) {
193 TBB = I->getOperand(0).getMBB();
194 continue;
195 }
196
197 // If the block has any instructions after a J, delete them.
198 MBB.erase(std::next(I), MBB.end());
199 Cond.clear();
200 FBB = nullptr;
201
202 // Delete the J if it's equivalent to a fall-through.
203 if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
204 TBB = nullptr;
205 I->eraseFromParent();
206 I = MBB.end();
207 continue;
208 }
209
210 // TBB is used to indicate the unconditinal destination.
211 TBB = I->getOperand(0).getMBB();
212 continue;
213 }
214 // Cannot handle conditional branches
215 return true;
216 }
217
218 return false;
219}
220
225 const DebugLoc &DL,
226 int *BytesAdded) const {
227 assert(!BytesAdded && "code size not handled");
228
229 // Shouldn't be a fall through.
230 assert(TBB && "insertBranch must not be told to insert a fallthrough");
231
232 if (Cond.empty()) {
233 // Unconditional branch
234 assert(!FBB && "Unconditional branch with multiple successors!");
235 BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB);
236 return 1;
237 }
238
239 llvm_unreachable("Unexpected conditional branch");
240}
241
243 int *BytesRemoved) const {
244 assert(!BytesRemoved && "code size not handled");
245
247 unsigned Count = 0;
248
249 while (I != MBB.begin()) {
250 --I;
251 if (I->isDebugInstr())
252 continue;
253 if (I->getOpcode() != BPF::JMP)
254 break;
255 // Remove the branch.
256 I->eraseFromParent();
257 I = MBB.end();
258 ++Count;
259 }
260
261 return Count;
262}
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
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
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
bool expandPostRAPseudo(MachineInstr &MI) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
A debug info location.
Definition: DebugLoc.h:33
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
bool isLayoutSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB will be emitted immediately after this block, such that if this bloc...
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
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.
Definition: MachineInstr.h:69
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...
Definition: SmallVector.h:573
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.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
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:346
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
unsigned getKillRegState(bool B)