1 //===-- 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
14 #include "BPF.h"
15 #include "BPFInstrInfo.h"
16 #include "BPFSubtarget.h"
17 #include "BPFTargetMachine.h"
18 #include "llvm/CodeGen/MachineFunctionPass.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
20 #include "llvm/CodeGen/MachineRegisterInfo.h"
21 #include "llvm/Support/ErrorHandling.h"
22 #include "llvm/Support/TargetRegistry.h"
23 #include "llvm/ADT/STLExtras.h"
24 #include "llvm/ADT/SmallVector.h"
25
26 #define GET_INSTRINFO_CTOR_DTOR
27 #include "BPFGenInstrInfo.inc"
28
29 using namespace llvm;
30
BPFInstrInfo()31 BPFInstrInfo::BPFInstrInfo()
32 : BPFGenInstrInfo(BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP) {}
33
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,DebugLoc DL,unsigned DestReg,unsigned SrcReg,bool KillSrc) const34 void BPFInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
35 MachineBasicBlock::iterator I, DebugLoc DL,
36 unsigned DestReg, unsigned SrcReg,
37 bool KillSrc) const {
38 if (BPF::GPRRegClass.contains(DestReg, SrcReg))
39 BuildMI(MBB, I, DL, get(BPF::MOV_rr), DestReg)
40 .addReg(SrcReg, getKillRegState(KillSrc));
41 else
42 llvm_unreachable("Impossible reg-to-reg copy");
43 }
44
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,unsigned SrcReg,bool IsKill,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const45 void BPFInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
46 MachineBasicBlock::iterator I,
47 unsigned SrcReg, bool IsKill, int FI,
48 const TargetRegisterClass *RC,
49 const TargetRegisterInfo *TRI) const {
50 DebugLoc DL;
51 if (I != MBB.end())
52 DL = I->getDebugLoc();
53
54 if (RC == &BPF::GPRRegClass)
55 BuildMI(MBB, I, DL, get(BPF::STD))
56 .addReg(SrcReg, getKillRegState(IsKill))
57 .addFrameIndex(FI)
58 .addImm(0);
59 else
60 llvm_unreachable("Can't store this register to stack slot");
61 }
62
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,unsigned DestReg,int FI,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI) const63 void BPFInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
64 MachineBasicBlock::iterator I,
65 unsigned DestReg, int FI,
66 const TargetRegisterClass *RC,
67 const TargetRegisterInfo *TRI) const {
68 DebugLoc DL;
69 if (I != MBB.end())
70 DL = I->getDebugLoc();
71
72 if (RC == &BPF::GPRRegClass)
73 BuildMI(MBB, I, DL, get(BPF::LDD), DestReg).addFrameIndex(FI).addImm(0);
74 else
75 llvm_unreachable("Can't load this register from stack slot");
76 }
77
AnalyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const78 bool BPFInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
79 MachineBasicBlock *&TBB,
80 MachineBasicBlock *&FBB,
81 SmallVectorImpl<MachineOperand> &Cond,
82 bool AllowModify) const {
83 // Start from the bottom of the block and work up, examining the
84 // terminator instructions.
85 MachineBasicBlock::iterator I = MBB.end();
86 while (I != MBB.begin()) {
87 --I;
88 if (I->isDebugValue())
89 continue;
90
91 // Working from the bottom, when we see a non-terminator
92 // instruction, we're done.
93 if (!isUnpredicatedTerminator(I))
94 break;
95
96 // A terminator that isn't a branch can't easily be handled
97 // by this analysis.
98 if (!I->isBranch())
99 return true;
100
101 // Handle unconditional branches.
102 if (I->getOpcode() == BPF::JMP) {
103 if (!AllowModify) {
104 TBB = I->getOperand(0).getMBB();
105 continue;
106 }
107
108 // If the block has any instructions after a J, delete them.
109 while (std::next(I) != MBB.end())
110 std::next(I)->eraseFromParent();
111 Cond.clear();
112 FBB = 0;
113
114 // Delete the J if it's equivalent to a fall-through.
115 if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
116 TBB = 0;
117 I->eraseFromParent();
118 I = MBB.end();
119 continue;
120 }
121
122 // TBB is used to indicate the unconditinal destination.
123 TBB = I->getOperand(0).getMBB();
124 continue;
125 }
126 // Cannot handle conditional branches
127 return true;
128 }
129
130 return false;
131 }
132
InsertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,DebugLoc DL) const133 unsigned BPFInstrInfo::InsertBranch(MachineBasicBlock &MBB,
134 MachineBasicBlock *TBB,
135 MachineBasicBlock *FBB,
136 ArrayRef<MachineOperand> Cond,
137 DebugLoc DL) const {
138 // Shouldn't be a fall through.
139 assert(TBB && "InsertBranch must not be told to insert a fallthrough");
140
141 if (Cond.empty()) {
142 // Unconditional branch
143 assert(!FBB && "Unconditional branch with multiple successors!");
144 BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB);
145 return 1;
146 }
147
148 llvm_unreachable("Unexpected conditional branch");
149 }
150
RemoveBranch(MachineBasicBlock & MBB) const151 unsigned BPFInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
152 MachineBasicBlock::iterator I = MBB.end();
153 unsigned Count = 0;
154
155 while (I != MBB.begin()) {
156 --I;
157 if (I->isDebugValue())
158 continue;
159 if (I->getOpcode() != BPF::JMP)
160 break;
161 // Remove the branch.
162 I->eraseFromParent();
163 I = MBB.end();
164 ++Count;
165 }
166
167 return Count;
168 }
169