LLVM  9.0.0svn
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"
15 #include "llvm/ADT/SmallVector.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 
26 using namespace llvm;
27 
29  : BPFGenInstrInfo(BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP) {}
30 
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));
41  else
42  llvm_unreachable("Impossible reg-to-reg copy");
43 }
44 
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;
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 
116  if (MI.getOpcode() == BPF::MEMCPY) {
117  expandMEMCPY(MI);
118  return true;
119  }
120 
121  return false;
122 }
123 
126  unsigned SrcReg, bool IsKill, int FI,
127  const TargetRegisterClass *RC,
128  const TargetRegisterInfo *TRI) const {
129  DebugLoc DL;
130  if (I != MBB.end())
131  DL = I->getDebugLoc();
132 
133  if (RC == &BPF::GPRRegClass)
134  BuildMI(MBB, I, DL, get(BPF::STD))
135  .addReg(SrcReg, getKillRegState(IsKill))
136  .addFrameIndex(FI)
137  .addImm(0);
138  else if (RC == &BPF::GPR32RegClass)
139  BuildMI(MBB, I, DL, get(BPF::STW32))
140  .addReg(SrcReg, getKillRegState(IsKill))
141  .addFrameIndex(FI)
142  .addImm(0);
143  else
144  llvm_unreachable("Can't store this register to stack slot");
145 }
146 
149  unsigned DestReg, int FI,
150  const TargetRegisterClass *RC,
151  const TargetRegisterInfo *TRI) const {
152  DebugLoc DL;
153  if (I != MBB.end())
154  DL = I->getDebugLoc();
155 
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);
160  else
161  llvm_unreachable("Can't load this register from stack slot");
162 }
163 
165  MachineBasicBlock *&TBB,
166  MachineBasicBlock *&FBB,
168  bool AllowModify) const {
169  // Start from the bottom of the block and work up, examining the
170  // terminator instructions.
172  while (I != MBB.begin()) {
173  --I;
174  if (I->isDebugInstr())
175  continue;
176 
177  // Working from the bottom, when we see a non-terminator
178  // instruction, we're done.
179  if (!isUnpredicatedTerminator(*I))
180  break;
181 
182  // A terminator that isn't a branch can't easily be handled
183  // by this analysis.
184  if (!I->isBranch())
185  return true;
186 
187  // Handle unconditional branches.
188  if (I->getOpcode() == BPF::JMP) {
189  if (!AllowModify) {
190  TBB = I->getOperand(0).getMBB();
191  continue;
192  }
193 
194  // If the block has any instructions after a J, delete them.
195  while (std::next(I) != MBB.end())
196  std::next(I)->eraseFromParent();
197  Cond.clear();
198  FBB = nullptr;
199 
200  // Delete the J if it's equivalent to a fall-through.
201  if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
202  TBB = nullptr;
203  I->eraseFromParent();
204  I = MBB.end();
205  continue;
206  }
207 
208  // TBB is used to indicate the unconditinal destination.
209  TBB = I->getOperand(0).getMBB();
210  continue;
211  }
212  // Cannot handle conditional branches
213  return true;
214  }
215 
216  return false;
217 }
218 
220  MachineBasicBlock *TBB,
221  MachineBasicBlock *FBB,
223  const DebugLoc &DL,
224  int *BytesAdded) const {
225  assert(!BytesAdded && "code size not handled");
226 
227  // Shouldn't be a fall through.
228  assert(TBB && "insertBranch must not be told to insert a fallthrough");
229 
230  if (Cond.empty()) {
231  // Unconditional branch
232  assert(!FBB && "Unconditional branch with multiple successors!");
233  BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB);
234  return 1;
235  }
236 
237  llvm_unreachable("Unexpected conditional branch");
238 }
239 
241  int *BytesRemoved) const {
242  assert(!BytesRemoved && "code size not handled");
243 
245  unsigned Count = 0;
246 
247  while (I != MBB.begin()) {
248  --I;
249  if (I->isDebugInstr())
250  continue;
251  if (I->getOpcode() != BPF::JMP)
252  break;
253  // Remove the branch.
254  I->eraseFromParent();
255  I = MBB.end();
256  ++Count;
257  }
258 
259  return Count;
260 }
This class represents lattice values for constants.
Definition: AllocatorList.h:23
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
unsigned const TargetRegisterInfo * TRI
A debug info location.
Definition: DebugLoc.h:33
return AArch64::GPR64RegClass contains(Reg)
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:41
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:408
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:32
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
unsigned getKillRegState(bool B)
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
const MachineInstrBuilder & addFrameIndex(int Idx) const
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.
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const override
bool isLayoutSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB will be emitted immediately after this block, such that if this bloc...
bool expandPostRAPseudo(MachineInstr &MI) const override
Representation of each machine instruction.
Definition: MachineInstr.h:63
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
#define I(x, y, z)
Definition: MD5.cpp:58
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
IRTranslator LLVM IR MI
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned char TargetFlags=0) const
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const override
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:544
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:143