1 //===-- BPFInstrInfo.cpp - BPF Instruction Information ----------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains the BPF implementation of the TargetInstrInfo class.
11 //===----------------------------------------------------------------------===//
13 #include "BPFInstrInfo.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"
23 #define GET_INSTRINFO_CTOR_DTOR
24 #include "BPFGenInstrInfo.inc"
28 BPFInstrInfo::BPFInstrInfo()
29 : BPFGenInstrInfo(BPF::ADJCALLSTACKDOWN
, BPF::ADJCALLSTACKUP
) {}
31 void BPFInstrInfo::copyPhysReg(MachineBasicBlock
&MBB
,
32 MachineBasicBlock::iterator I
,
33 const DebugLoc
&DL
, unsigned DestReg
,
34 unsigned 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
));
42 llvm_unreachable("Impossible reg-to-reg copy");
45 void BPFInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI
) const {
46 unsigned DstReg
= MI
->getOperand(0).getReg();
47 unsigned SrcReg
= MI
->getOperand(1).getReg();
48 uint64_t CopyLen
= MI
->getOperand(2).getImm();
49 uint64_t Alignment
= MI
->getOperand(3).getImm();
50 unsigned ScratchReg
= MI
->getOperand(4).getReg();
51 MachineBasicBlock
*BB
= MI
->getParent();
52 DebugLoc dl
= MI
->getDebugLoc();
53 unsigned LdOpc
, StOpc
;
73 llvm_unreachable("unsupported memcpy alignment");
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
);
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;
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
);
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
);
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
);
115 bool BPFInstrInfo::expandPostRAPseudo(MachineInstr
&MI
) const {
116 if (MI
.getOpcode() == BPF::MEMCPY
) {
124 void BPFInstrInfo::storeRegToStackSlot(MachineBasicBlock
&MBB
,
125 MachineBasicBlock::iterator I
,
126 unsigned SrcReg
, bool IsKill
, int FI
,
127 const TargetRegisterClass
*RC
,
128 const TargetRegisterInfo
*TRI
) const {
131 DL
= I
->getDebugLoc();
133 if (RC
== &BPF::GPRRegClass
)
134 BuildMI(MBB
, I
, DL
, get(BPF::STD
))
135 .addReg(SrcReg
, getKillRegState(IsKill
))
138 else if (RC
== &BPF::GPR32RegClass
)
139 BuildMI(MBB
, I
, DL
, get(BPF::STW32
))
140 .addReg(SrcReg
, getKillRegState(IsKill
))
144 llvm_unreachable("Can't store this register to stack slot");
147 void BPFInstrInfo::loadRegFromStackSlot(MachineBasicBlock
&MBB
,
148 MachineBasicBlock::iterator I
,
149 unsigned DestReg
, int FI
,
150 const TargetRegisterClass
*RC
,
151 const TargetRegisterInfo
*TRI
) const {
154 DL
= I
->getDebugLoc();
156 if (RC
== &BPF::GPRRegClass
)
157 BuildMI(MBB
, I
, DL
, get(BPF::LDD
), DestReg
).addFrameIndex(FI
).addImm(0);
158 else if (RC
== &BPF::GPR32RegClass
)
159 BuildMI(MBB
, I
, DL
, get(BPF::LDW32
), DestReg
).addFrameIndex(FI
).addImm(0);
161 llvm_unreachable("Can't load this register from stack slot");
164 bool BPFInstrInfo::analyzeBranch(MachineBasicBlock
&MBB
,
165 MachineBasicBlock
*&TBB
,
166 MachineBasicBlock
*&FBB
,
167 SmallVectorImpl
<MachineOperand
> &Cond
,
168 bool AllowModify
) const {
169 // Start from the bottom of the block and work up, examining the
170 // terminator instructions.
171 MachineBasicBlock::iterator I
= MBB
.end();
172 while (I
!= MBB
.begin()) {
174 if (I
->isDebugInstr())
177 // Working from the bottom, when we see a non-terminator
178 // instruction, we're done.
179 if (!isUnpredicatedTerminator(*I
))
182 // A terminator that isn't a branch can't easily be handled
187 // Handle unconditional branches.
188 if (I
->getOpcode() == BPF::JMP
) {
190 TBB
= I
->getOperand(0).getMBB();
194 // If the block has any instructions after a J, delete them.
195 while (std::next(I
) != MBB
.end())
196 std::next(I
)->eraseFromParent();
200 // Delete the J if it's equivalent to a fall-through.
201 if (MBB
.isLayoutSuccessor(I
->getOperand(0).getMBB())) {
203 I
->eraseFromParent();
208 // TBB is used to indicate the unconditinal destination.
209 TBB
= I
->getOperand(0).getMBB();
212 // Cannot handle conditional branches
219 unsigned BPFInstrInfo::insertBranch(MachineBasicBlock
&MBB
,
220 MachineBasicBlock
*TBB
,
221 MachineBasicBlock
*FBB
,
222 ArrayRef
<MachineOperand
> Cond
,
224 int *BytesAdded
) const {
225 assert(!BytesAdded
&& "code size not handled");
227 // Shouldn't be a fall through.
228 assert(TBB
&& "insertBranch must not be told to insert a fallthrough");
231 // Unconditional branch
232 assert(!FBB
&& "Unconditional branch with multiple successors!");
233 BuildMI(&MBB
, DL
, get(BPF::JMP
)).addMBB(TBB
);
237 llvm_unreachable("Unexpected conditional branch");
240 unsigned BPFInstrInfo::removeBranch(MachineBasicBlock
&MBB
,
241 int *BytesRemoved
) const {
242 assert(!BytesRemoved
&& "code size not handled");
244 MachineBasicBlock::iterator I
= MBB
.end();
247 while (I
!= MBB
.begin()) {
249 if (I
->isDebugInstr())
251 if (I
->getOpcode() != BPF::JMP
)
253 // Remove the branch.
254 I
->eraseFromParent();