blob: 4d47debdaa74a3917ecd0f73b4c2a4951bc04f2e [file] [log] [blame]
Alexei Starovoitove4c8c802015-01-24 17:51:26 +00001//===-- BPFInstrInfo.cpp - BPF Instruction Information ----------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the BPF implementation of the TargetInstrInfo class.
11//
12//===----------------------------------------------------------------------===//
13
Alexei Starovoitove4c8c802015-01-24 17:51:26 +000014#include "BPFInstrInfo.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000015#include "BPF.h"
Alexei Starovoitove4c8c802015-01-24 17:51:26 +000016#include "llvm/ADT/SmallVector.h"
Eugene Zelenko4282c402017-01-06 23:06:25 +000017#include "llvm/CodeGen/MachineBasicBlock.h"
18#include "llvm/CodeGen/MachineInstrBuilder.h"
19#include "llvm/IR/DebugLoc.h"
20#include "llvm/Support/ErrorHandling.h"
21#include <cassert>
22#include <iterator>
Alexei Starovoitove4c8c802015-01-24 17:51:26 +000023
24#define GET_INSTRINFO_CTOR_DTOR
25#include "BPFGenInstrInfo.inc"
26
27using namespace llvm;
28
29BPFInstrInfo::BPFInstrInfo()
30 : BPFGenInstrInfo(BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP) {}
31
32void BPFInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
Benjamin Kramerbdc49562016-06-12 15:39:02 +000033 MachineBasicBlock::iterator I,
34 const DebugLoc &DL, unsigned DestReg,
35 unsigned SrcReg, bool KillSrc) const {
Alexei Starovoitove4c8c802015-01-24 17:51:26 +000036 if (BPF::GPRRegClass.contains(DestReg, SrcReg))
37 BuildMI(MBB, I, DL, get(BPF::MOV_rr), DestReg)
38 .addReg(SrcReg, getKillRegState(KillSrc));
Yonghong Songfcd1e0f2018-02-23 23:49:29 +000039 else if (BPF::GPR32RegClass.contains(DestReg, SrcReg))
40 BuildMI(MBB, I, DL, get(BPF::MOV_rr_32), DestReg)
41 .addReg(SrcReg, getKillRegState(KillSrc));
Alexei Starovoitove4c8c802015-01-24 17:51:26 +000042 else
43 llvm_unreachable("Impossible reg-to-reg copy");
44}
45
Yonghong Song71d81e52018-07-25 22:40:02 +000046void BPFInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const {
47 unsigned DstReg = MI->getOperand(0).getReg();
48 unsigned SrcReg = MI->getOperand(1).getReg();
49 uint64_t CopyLen = MI->getOperand(2).getImm();
50 uint64_t Alignment = MI->getOperand(3).getImm();
51 unsigned ScratchReg = MI->getOperand(4).getReg();
52 MachineBasicBlock *BB = MI->getParent();
53 DebugLoc dl = MI->getDebugLoc();
54 unsigned LdOpc, StOpc;
55
56 switch (Alignment) {
57 case 1:
58 LdOpc = BPF::LDB;
59 StOpc = BPF::STB;
60 break;
61 case 2:
62 LdOpc = BPF::LDH;
63 StOpc = BPF::STH;
64 break;
65 case 4:
66 LdOpc = BPF::LDW;
67 StOpc = BPF::STW;
68 break;
69 case 8:
70 LdOpc = BPF::LDD;
71 StOpc = BPF::STD;
72 break;
73 default:
74 llvm_unreachable("unsupported memcpy alignment");
75 }
76
77 unsigned IterationNum = CopyLen >> Log2_64(Alignment);
78 for(unsigned I = 0; I < IterationNum; ++I) {
79 BuildMI(*BB, MI, dl, get(LdOpc))
Yonghong Song04ccfda2018-07-27 16:58:52 +000080 .addReg(ScratchReg, RegState::Define).addReg(SrcReg)
81 .addImm(I * Alignment);
Yonghong Song71d81e52018-07-25 22:40:02 +000082 BuildMI(*BB, MI, dl, get(StOpc))
Yonghong Song04ccfda2018-07-27 16:58:52 +000083 .addReg(ScratchReg, RegState::Kill).addReg(DstReg)
84 .addImm(I * Alignment);
Yonghong Song71d81e52018-07-25 22:40:02 +000085 }
86
87 unsigned BytesLeft = CopyLen & (Alignment - 1);
88 unsigned Offset = IterationNum * Alignment;
89 bool Hanging4Byte = BytesLeft & 0x4;
90 bool Hanging2Byte = BytesLeft & 0x2;
91 bool Hanging1Byte = BytesLeft & 0x1;
92 if (Hanging4Byte) {
93 BuildMI(*BB, MI, dl, get(BPF::LDW))
Yonghong Song04ccfda2018-07-27 16:58:52 +000094 .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
Yonghong Song71d81e52018-07-25 22:40:02 +000095 BuildMI(*BB, MI, dl, get(BPF::STW))
Yonghong Song04ccfda2018-07-27 16:58:52 +000096 .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
Yonghong Song71d81e52018-07-25 22:40:02 +000097 Offset += 4;
98 }
99 if (Hanging2Byte) {
100 BuildMI(*BB, MI, dl, get(BPF::LDH))
Yonghong Song04ccfda2018-07-27 16:58:52 +0000101 .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
Yonghong Song71d81e52018-07-25 22:40:02 +0000102 BuildMI(*BB, MI, dl, get(BPF::STH))
Yonghong Song04ccfda2018-07-27 16:58:52 +0000103 .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
Yonghong Song71d81e52018-07-25 22:40:02 +0000104 Offset += 2;
105 }
106 if (Hanging1Byte) {
107 BuildMI(*BB, MI, dl, get(BPF::LDB))
Yonghong Song04ccfda2018-07-27 16:58:52 +0000108 .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
Yonghong Song71d81e52018-07-25 22:40:02 +0000109 BuildMI(*BB, MI, dl, get(BPF::STB))
Yonghong Song04ccfda2018-07-27 16:58:52 +0000110 .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
Yonghong Song71d81e52018-07-25 22:40:02 +0000111 }
112
113 BB->erase(MI);
114}
115
116bool BPFInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
117 if (MI.getOpcode() == BPF::MEMCPY) {
118 expandMEMCPY(MI);
119 return true;
120 }
121
122 return false;
123}
124
Alexei Starovoitove4c8c802015-01-24 17:51:26 +0000125void BPFInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
126 MachineBasicBlock::iterator I,
127 unsigned SrcReg, bool IsKill, int FI,
128 const TargetRegisterClass *RC,
129 const TargetRegisterInfo *TRI) 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);
Yonghong Songfcd1e0f2018-02-23 23:49:29 +0000139 else if (RC == &BPF::GPR32RegClass)
140 BuildMI(MBB, I, DL, get(BPF::STW32))
141 .addReg(SrcReg, getKillRegState(IsKill))
142 .addFrameIndex(FI)
143 .addImm(0);
Alexei Starovoitove4c8c802015-01-24 17:51:26 +0000144 else
145 llvm_unreachable("Can't store this register to stack slot");
146}
147
148void BPFInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
149 MachineBasicBlock::iterator I,
150 unsigned DestReg, int FI,
151 const TargetRegisterClass *RC,
152 const TargetRegisterInfo *TRI) const {
153 DebugLoc DL;
154 if (I != MBB.end())
155 DL = I->getDebugLoc();
156
157 if (RC == &BPF::GPRRegClass)
158 BuildMI(MBB, I, DL, get(BPF::LDD), DestReg).addFrameIndex(FI).addImm(0);
Yonghong Songfcd1e0f2018-02-23 23:49:29 +0000159 else if (RC == &BPF::GPR32RegClass)
160 BuildMI(MBB, I, DL, get(BPF::LDW32), DestReg).addFrameIndex(FI).addImm(0);
Alexei Starovoitove4c8c802015-01-24 17:51:26 +0000161 else
162 llvm_unreachable("Can't load this register from stack slot");
163}
164
Jacques Pienaar71c30a12016-07-15 14:41:04 +0000165bool BPFInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
Alexei Starovoitove4c8c802015-01-24 17:51:26 +0000166 MachineBasicBlock *&TBB,
167 MachineBasicBlock *&FBB,
168 SmallVectorImpl<MachineOperand> &Cond,
169 bool AllowModify) const {
170 // Start from the bottom of the block and work up, examining the
171 // terminator instructions.
172 MachineBasicBlock::iterator I = MBB.end();
173 while (I != MBB.begin()) {
174 --I;
Shiva Chen801bf7e2018-05-09 02:42:00 +0000175 if (I->isDebugInstr())
Alexei Starovoitove4c8c802015-01-24 17:51:26 +0000176 continue;
177
178 // Working from the bottom, when we see a non-terminator
179 // instruction, we're done.
Duncan P. N. Exon Smith6307eb52016-02-23 02:46:52 +0000180 if (!isUnpredicatedTerminator(*I))
Alexei Starovoitove4c8c802015-01-24 17:51:26 +0000181 break;
182
183 // A terminator that isn't a branch can't easily be handled
184 // by this analysis.
185 if (!I->isBranch())
186 return true;
187
188 // Handle unconditional branches.
189 if (I->getOpcode() == BPF::JMP) {
190 if (!AllowModify) {
191 TBB = I->getOperand(0).getMBB();
192 continue;
193 }
194
195 // If the block has any instructions after a J, delete them.
196 while (std::next(I) != MBB.end())
197 std::next(I)->eraseFromParent();
198 Cond.clear();
Eugene Zelenko4282c402017-01-06 23:06:25 +0000199 FBB = nullptr;
Alexei Starovoitove4c8c802015-01-24 17:51:26 +0000200
201 // Delete the J if it's equivalent to a fall-through.
202 if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
Eugene Zelenko4282c402017-01-06 23:06:25 +0000203 TBB = nullptr;
Alexei Starovoitove4c8c802015-01-24 17:51:26 +0000204 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
Matt Arsenaulte8e0f5c2016-09-14 17:24:15 +0000220unsigned BPFInstrInfo::insertBranch(MachineBasicBlock &MBB,
Alexei Starovoitove4c8c802015-01-24 17:51:26 +0000221 MachineBasicBlock *TBB,
222 MachineBasicBlock *FBB,
Ahmed Bougachac88bf542015-06-11 19:30:37 +0000223 ArrayRef<MachineOperand> Cond,
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000224 const DebugLoc &DL,
225 int *BytesAdded) const {
226 assert(!BytesAdded && "code size not handled");
227
Alexei Starovoitove4c8c802015-01-24 17:51:26 +0000228 // Shouldn't be a fall through.
Matt Arsenaulte8e0f5c2016-09-14 17:24:15 +0000229 assert(TBB && "insertBranch must not be told to insert a fallthrough");
Alexei Starovoitove4c8c802015-01-24 17:51:26 +0000230
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
Matt Arsenault1b9fc8e2016-09-14 20:43:16 +0000241unsigned BPFInstrInfo::removeBranch(MachineBasicBlock &MBB,
Matt Arsenaulta2b036e2016-09-14 17:23:48 +0000242 int *BytesRemoved) const {
243 assert(!BytesRemoved && "code size not handled");
244
Alexei Starovoitove4c8c802015-01-24 17:51:26 +0000245 MachineBasicBlock::iterator I = MBB.end();
246 unsigned Count = 0;
247
248 while (I != MBB.begin()) {
249 --I;
Shiva Chen801bf7e2018-05-09 02:42:00 +0000250 if (I->isDebugInstr())
Alexei Starovoitove4c8c802015-01-24 17:51:26 +0000251 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}