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();