Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/BPF/BPFInstrInfo.cpp
35268 views
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 "llvm/ADT/SmallVector.h"
16
#include "llvm/CodeGen/MachineBasicBlock.h"
17
#include "llvm/CodeGen/MachineInstrBuilder.h"
18
#include "llvm/IR/DebugLoc.h"
19
#include "llvm/Support/ErrorHandling.h"
20
#include <cassert>
21
#include <iterator>
22
23
#define GET_INSTRINFO_CTOR_DTOR
24
#include "BPFGenInstrInfo.inc"
25
26
using namespace llvm;
27
28
BPFInstrInfo::BPFInstrInfo()
29
: BPFGenInstrInfo(BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP) {}
30
31
void BPFInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
32
MachineBasicBlock::iterator I,
33
const DebugLoc &DL, MCRegister DestReg,
34
MCRegister SrcReg, bool KillSrc) const {
35
if (BPF::GPRRegClass.contains(DestReg, SrcReg))
36
BuildMI(MBB, I, DL, get(BPF::MOV_rr), DestReg)
37
.addReg(SrcReg, getKillRegState(KillSrc));
38
else if (BPF::GPR32RegClass.contains(DestReg, SrcReg))
39
BuildMI(MBB, I, DL, get(BPF::MOV_rr_32), DestReg)
40
.addReg(SrcReg, getKillRegState(KillSrc));
41
else
42
llvm_unreachable("Impossible reg-to-reg copy");
43
}
44
45
void BPFInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const {
46
Register DstReg = MI->getOperand(0).getReg();
47
Register SrcReg = MI->getOperand(1).getReg();
48
uint64_t CopyLen = MI->getOperand(2).getImm();
49
uint64_t Alignment = MI->getOperand(3).getImm();
50
Register ScratchReg = MI->getOperand(4).getReg();
51
MachineBasicBlock *BB = MI->getParent();
52
DebugLoc dl = MI->getDebugLoc();
53
unsigned LdOpc, StOpc;
54
55
switch (Alignment) {
56
case 1:
57
LdOpc = BPF::LDB;
58
StOpc = BPF::STB;
59
break;
60
case 2:
61
LdOpc = BPF::LDH;
62
StOpc = BPF::STH;
63
break;
64
case 4:
65
LdOpc = BPF::LDW;
66
StOpc = BPF::STW;
67
break;
68
case 8:
69
LdOpc = BPF::LDD;
70
StOpc = BPF::STD;
71
break;
72
default:
73
llvm_unreachable("unsupported memcpy alignment");
74
}
75
76
unsigned IterationNum = CopyLen >> Log2_64(Alignment);
77
for(unsigned I = 0; I < IterationNum; ++I) {
78
BuildMI(*BB, MI, dl, get(LdOpc))
79
.addReg(ScratchReg, RegState::Define).addReg(SrcReg)
80
.addImm(I * Alignment);
81
BuildMI(*BB, MI, dl, get(StOpc))
82
.addReg(ScratchReg, RegState::Kill).addReg(DstReg)
83
.addImm(I * Alignment);
84
}
85
86
unsigned BytesLeft = CopyLen & (Alignment - 1);
87
unsigned Offset = IterationNum * Alignment;
88
bool Hanging4Byte = BytesLeft & 0x4;
89
bool Hanging2Byte = BytesLeft & 0x2;
90
bool Hanging1Byte = BytesLeft & 0x1;
91
if (Hanging4Byte) {
92
BuildMI(*BB, MI, dl, get(BPF::LDW))
93
.addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
94
BuildMI(*BB, MI, dl, get(BPF::STW))
95
.addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
96
Offset += 4;
97
}
98
if (Hanging2Byte) {
99
BuildMI(*BB, MI, dl, get(BPF::LDH))
100
.addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
101
BuildMI(*BB, MI, dl, get(BPF::STH))
102
.addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
103
Offset += 2;
104
}
105
if (Hanging1Byte) {
106
BuildMI(*BB, MI, dl, get(BPF::LDB))
107
.addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
108
BuildMI(*BB, MI, dl, get(BPF::STB))
109
.addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
110
}
111
112
BB->erase(MI);
113
}
114
115
bool BPFInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
116
if (MI.getOpcode() == BPF::MEMCPY) {
117
expandMEMCPY(MI);
118
return true;
119
}
120
121
return false;
122
}
123
124
void BPFInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
125
MachineBasicBlock::iterator I,
126
Register SrcReg, bool IsKill, int FI,
127
const TargetRegisterClass *RC,
128
const TargetRegisterInfo *TRI,
129
Register VReg) const {
130
DebugLoc DL;
131
if (I != MBB.end())
132
DL = I->getDebugLoc();
133
134
if (RC == &BPF::GPRRegClass)
135
BuildMI(MBB, I, DL, get(BPF::STD))
136
.addReg(SrcReg, getKillRegState(IsKill))
137
.addFrameIndex(FI)
138
.addImm(0);
139
else if (RC == &BPF::GPR32RegClass)
140
BuildMI(MBB, I, DL, get(BPF::STW32))
141
.addReg(SrcReg, getKillRegState(IsKill))
142
.addFrameIndex(FI)
143
.addImm(0);
144
else
145
llvm_unreachable("Can't store this register to stack slot");
146
}
147
148
void BPFInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
149
MachineBasicBlock::iterator I,
150
Register DestReg, int FI,
151
const TargetRegisterClass *RC,
152
const TargetRegisterInfo *TRI,
153
Register VReg) const {
154
DebugLoc DL;
155
if (I != MBB.end())
156
DL = I->getDebugLoc();
157
158
if (RC == &BPF::GPRRegClass)
159
BuildMI(MBB, I, DL, get(BPF::LDD), DestReg).addFrameIndex(FI).addImm(0);
160
else if (RC == &BPF::GPR32RegClass)
161
BuildMI(MBB, I, DL, get(BPF::LDW32), DestReg).addFrameIndex(FI).addImm(0);
162
else
163
llvm_unreachable("Can't load this register from stack slot");
164
}
165
166
bool BPFInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
167
MachineBasicBlock *&TBB,
168
MachineBasicBlock *&FBB,
169
SmallVectorImpl<MachineOperand> &Cond,
170
bool AllowModify) const {
171
// Start from the bottom of the block and work up, examining the
172
// terminator instructions.
173
MachineBasicBlock::iterator I = MBB.end();
174
while (I != MBB.begin()) {
175
--I;
176
if (I->isDebugInstr())
177
continue;
178
179
// Working from the bottom, when we see a non-terminator
180
// instruction, we're done.
181
if (!isUnpredicatedTerminator(*I))
182
break;
183
184
// A terminator that isn't a branch can't easily be handled
185
// by this analysis.
186
if (!I->isBranch())
187
return true;
188
189
// Handle unconditional branches.
190
if (I->getOpcode() == BPF::JMP) {
191
if (!AllowModify) {
192
TBB = I->getOperand(0).getMBB();
193
continue;
194
}
195
196
// If the block has any instructions after a J, delete them.
197
MBB.erase(std::next(I), MBB.end());
198
Cond.clear();
199
FBB = nullptr;
200
201
// Delete the J if it's equivalent to a fall-through.
202
if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
203
TBB = nullptr;
204
I->eraseFromParent();
205
I = MBB.end();
206
continue;
207
}
208
209
// TBB is used to indicate the unconditinal destination.
210
TBB = I->getOperand(0).getMBB();
211
continue;
212
}
213
// Cannot handle conditional branches
214
return true;
215
}
216
217
return false;
218
}
219
220
unsigned BPFInstrInfo::insertBranch(MachineBasicBlock &MBB,
221
MachineBasicBlock *TBB,
222
MachineBasicBlock *FBB,
223
ArrayRef<MachineOperand> Cond,
224
const DebugLoc &DL,
225
int *BytesAdded) const {
226
assert(!BytesAdded && "code size not handled");
227
228
// Shouldn't be a fall through.
229
assert(TBB && "insertBranch must not be told to insert a fallthrough");
230
231
if (Cond.empty()) {
232
// Unconditional branch
233
assert(!FBB && "Unconditional branch with multiple successors!");
234
BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB);
235
return 1;
236
}
237
238
llvm_unreachable("Unexpected conditional branch");
239
}
240
241
unsigned BPFInstrInfo::removeBranch(MachineBasicBlock &MBB,
242
int *BytesRemoved) const {
243
assert(!BytesRemoved && "code size not handled");
244
245
MachineBasicBlock::iterator I = MBB.end();
246
unsigned Count = 0;
247
248
while (I != MBB.begin()) {
249
--I;
250
if (I->isDebugInstr())
251
continue;
252
if (I->getOpcode() != BPF::JMP)
253
break;
254
// Remove the branch.
255
I->eraseFromParent();
256
I = MBB.end();
257
++Count;
258
}
259
260
return Count;
261
}
262
263