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