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
, 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
));
42 llvm_unreachable("Impossible reg-to-reg copy");
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
;
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 Register SrcReg
, bool IsKill
, int FI
,
127 const TargetRegisterClass
*RC
,
128 const TargetRegisterInfo
*TRI
,
129 Register VReg
) const {
132 DL
= I
->getDebugLoc();
134 if (RC
== &BPF::GPRRegClass
)
135 BuildMI(MBB
, I
, DL
, get(BPF::STD
))
136 .addReg(SrcReg
, getKillRegState(IsKill
))
139 else if (RC
== &BPF::GPR32RegClass
)
140 BuildMI(MBB
, I
, DL
, get(BPF::STW32
))
141 .addReg(SrcReg
, getKillRegState(IsKill
))
145 llvm_unreachable("Can't store this register to stack slot");
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 {
156 DL
= I
->getDebugLoc();
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);
163 llvm_unreachable("Can't load this register from stack slot");
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()) {
176 if (I
->isDebugInstr())
179 // Working from the bottom, when we see a non-terminator
180 // instruction, we're done.
181 if (!isUnpredicatedTerminator(*I
))
184 // A terminator that isn't a branch can't easily be handled
189 // Handle unconditional branches.
190 if (I
->getOpcode() == BPF::JMP
) {
192 TBB
= I
->getOperand(0).getMBB();
196 // If the block has any instructions after a J, delete them.
197 MBB
.erase(std::next(I
), MBB
.end());
201 // Delete the J if it's equivalent to a fall-through.
202 if (MBB
.isLayoutSuccessor(I
->getOperand(0).getMBB())) {
204 I
->eraseFromParent();
209 // TBB is used to indicate the unconditinal destination.
210 TBB
= I
->getOperand(0).getMBB();
213 // Cannot handle conditional branches
220 unsigned BPFInstrInfo::insertBranch(MachineBasicBlock
&MBB
,
221 MachineBasicBlock
*TBB
,
222 MachineBasicBlock
*FBB
,
223 ArrayRef
<MachineOperand
> Cond
,
225 int *BytesAdded
) const {
226 assert(!BytesAdded
&& "code size not handled");
228 // Shouldn't be a fall through.
229 assert(TBB
&& "insertBranch must not be told to insert a fallthrough");
232 // Unconditional branch
233 assert(!FBB
&& "Unconditional branch with multiple successors!");
234 BuildMI(&MBB
, DL
, get(BPF::JMP
)).addMBB(TBB
);
238 llvm_unreachable("Unexpected conditional branch");
241 unsigned BPFInstrInfo::removeBranch(MachineBasicBlock
&MBB
,
242 int *BytesRemoved
) const {
243 assert(!BytesRemoved
&& "code size not handled");
245 MachineBasicBlock::iterator I
= MBB
.end();
248 while (I
!= MBB
.begin()) {
250 if (I
->isDebugInstr())
252 if (I
->getOpcode() != BPF::JMP
)
254 // Remove the branch.
255 I
->eraseFromParent();