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