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 "BPFInstrInfo.h" 156bda14b3SChandler Carruth #include "BPF.h" 16e4c8c807SAlexei Starovoitov #include "llvm/ADT/SmallVector.h" 174282c404SEugene Zelenko #include "llvm/CodeGen/MachineBasicBlock.h" 184282c404SEugene Zelenko #include "llvm/CodeGen/MachineInstrBuilder.h" 194282c404SEugene Zelenko #include "llvm/IR/DebugLoc.h" 204282c404SEugene Zelenko #include "llvm/Support/ErrorHandling.h" 214282c404SEugene Zelenko #include <cassert> 224282c404SEugene Zelenko #include <iterator> 23e4c8c807SAlexei Starovoitov 24e4c8c807SAlexei Starovoitov #define GET_INSTRINFO_CTOR_DTOR 25e4c8c807SAlexei Starovoitov #include "BPFGenInstrInfo.inc" 26e4c8c807SAlexei Starovoitov 27e4c8c807SAlexei Starovoitov using namespace llvm; 28e4c8c807SAlexei Starovoitov 29e4c8c807SAlexei Starovoitov BPFInstrInfo::BPFInstrInfo() 30e4c8c807SAlexei Starovoitov : BPFGenInstrInfo(BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP) {} 31e4c8c807SAlexei Starovoitov 32e4c8c807SAlexei Starovoitov void BPFInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 33bdc4956bSBenjamin Kramer MachineBasicBlock::iterator I, 34bdc4956bSBenjamin Kramer const DebugLoc &DL, unsigned DestReg, 35bdc4956bSBenjamin Kramer unsigned SrcReg, bool KillSrc) const { 36e4c8c807SAlexei Starovoitov if (BPF::GPRRegClass.contains(DestReg, SrcReg)) 37e4c8c807SAlexei Starovoitov BuildMI(MBB, I, DL, get(BPF::MOV_rr), DestReg) 38e4c8c807SAlexei Starovoitov .addReg(SrcReg, getKillRegState(KillSrc)); 39fcd1e0f6SYonghong Song else if (BPF::GPR32RegClass.contains(DestReg, SrcReg)) 40fcd1e0f6SYonghong Song BuildMI(MBB, I, DL, get(BPF::MOV_rr_32), DestReg) 41fcd1e0f6SYonghong Song .addReg(SrcReg, getKillRegState(KillSrc)); 42e4c8c807SAlexei Starovoitov else 43e4c8c807SAlexei Starovoitov llvm_unreachable("Impossible reg-to-reg copy"); 44e4c8c807SAlexei Starovoitov } 45e4c8c807SAlexei Starovoitov 46*71d81e5cSYonghong Song void BPFInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const { 47*71d81e5cSYonghong Song unsigned DstReg = MI->getOperand(0).getReg(); 48*71d81e5cSYonghong Song unsigned SrcReg = MI->getOperand(1).getReg(); 49*71d81e5cSYonghong Song uint64_t CopyLen = MI->getOperand(2).getImm(); 50*71d81e5cSYonghong Song uint64_t Alignment = MI->getOperand(3).getImm(); 51*71d81e5cSYonghong Song unsigned ScratchReg = MI->getOperand(4).getReg(); 52*71d81e5cSYonghong Song MachineBasicBlock *BB = MI->getParent(); 53*71d81e5cSYonghong Song DebugLoc dl = MI->getDebugLoc(); 54*71d81e5cSYonghong Song unsigned LdOpc, StOpc; 55*71d81e5cSYonghong Song 56*71d81e5cSYonghong Song switch (Alignment) { 57*71d81e5cSYonghong Song case 1: 58*71d81e5cSYonghong Song LdOpc = BPF::LDB; 59*71d81e5cSYonghong Song StOpc = BPF::STB; 60*71d81e5cSYonghong Song break; 61*71d81e5cSYonghong Song case 2: 62*71d81e5cSYonghong Song LdOpc = BPF::LDH; 63*71d81e5cSYonghong Song StOpc = BPF::STH; 64*71d81e5cSYonghong Song break; 65*71d81e5cSYonghong Song case 4: 66*71d81e5cSYonghong Song LdOpc = BPF::LDW; 67*71d81e5cSYonghong Song StOpc = BPF::STW; 68*71d81e5cSYonghong Song break; 69*71d81e5cSYonghong Song case 8: 70*71d81e5cSYonghong Song LdOpc = BPF::LDD; 71*71d81e5cSYonghong Song StOpc = BPF::STD; 72*71d81e5cSYonghong Song break; 73*71d81e5cSYonghong Song default: 74*71d81e5cSYonghong Song llvm_unreachable("unsupported memcpy alignment"); 75*71d81e5cSYonghong Song } 76*71d81e5cSYonghong Song 77*71d81e5cSYonghong Song unsigned IterationNum = CopyLen >> Log2_64(Alignment); 78*71d81e5cSYonghong Song for(unsigned I = 0; I < IterationNum; ++I) { 79*71d81e5cSYonghong Song BuildMI(*BB, MI, dl, get(LdOpc)) 80*71d81e5cSYonghong Song .addReg(ScratchReg).addReg(SrcReg).addImm(I * Alignment); 81*71d81e5cSYonghong Song BuildMI(*BB, MI, dl, get(StOpc)) 82*71d81e5cSYonghong Song .addReg(ScratchReg).addReg(DstReg).addImm(I * Alignment); 83*71d81e5cSYonghong Song } 84*71d81e5cSYonghong Song 85*71d81e5cSYonghong Song unsigned BytesLeft = CopyLen & (Alignment - 1); 86*71d81e5cSYonghong Song unsigned Offset = IterationNum * Alignment; 87*71d81e5cSYonghong Song bool Hanging4Byte = BytesLeft & 0x4; 88*71d81e5cSYonghong Song bool Hanging2Byte = BytesLeft & 0x2; 89*71d81e5cSYonghong Song bool Hanging1Byte = BytesLeft & 0x1; 90*71d81e5cSYonghong Song if (Hanging4Byte) { 91*71d81e5cSYonghong Song BuildMI(*BB, MI, dl, get(BPF::LDW)) 92*71d81e5cSYonghong Song .addReg(ScratchReg).addReg(SrcReg).addImm(Offset); 93*71d81e5cSYonghong Song BuildMI(*BB, MI, dl, get(BPF::STW)) 94*71d81e5cSYonghong Song .addReg(ScratchReg).addReg(DstReg).addImm(Offset); 95*71d81e5cSYonghong Song Offset += 4; 96*71d81e5cSYonghong Song } 97*71d81e5cSYonghong Song if (Hanging2Byte) { 98*71d81e5cSYonghong Song BuildMI(*BB, MI, dl, get(BPF::LDH)) 99*71d81e5cSYonghong Song .addReg(ScratchReg).addReg(SrcReg).addImm(Offset); 100*71d81e5cSYonghong Song BuildMI(*BB, MI, dl, get(BPF::STH)) 101*71d81e5cSYonghong Song .addReg(ScratchReg).addReg(DstReg).addImm(Offset); 102*71d81e5cSYonghong Song Offset += 2; 103*71d81e5cSYonghong Song } 104*71d81e5cSYonghong Song if (Hanging1Byte) { 105*71d81e5cSYonghong Song BuildMI(*BB, MI, dl, get(BPF::LDB)) 106*71d81e5cSYonghong Song .addReg(ScratchReg).addReg(SrcReg).addImm(Offset); 107*71d81e5cSYonghong Song BuildMI(*BB, MI, dl, get(BPF::STB)) 108*71d81e5cSYonghong Song .addReg(ScratchReg).addReg(DstReg).addImm(Offset); 109*71d81e5cSYonghong Song } 110*71d81e5cSYonghong Song 111*71d81e5cSYonghong Song BB->erase(MI); 112*71d81e5cSYonghong Song } 113*71d81e5cSYonghong Song 114*71d81e5cSYonghong Song bool BPFInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { 115*71d81e5cSYonghong Song if (MI.getOpcode() == BPF::MEMCPY) { 116*71d81e5cSYonghong Song expandMEMCPY(MI); 117*71d81e5cSYonghong Song return true; 118*71d81e5cSYonghong Song } 119*71d81e5cSYonghong Song 120*71d81e5cSYonghong Song return false; 121*71d81e5cSYonghong Song } 122*71d81e5cSYonghong Song 123e4c8c807SAlexei Starovoitov void BPFInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 124e4c8c807SAlexei Starovoitov MachineBasicBlock::iterator I, 125e4c8c807SAlexei Starovoitov unsigned SrcReg, bool IsKill, int FI, 126e4c8c807SAlexei Starovoitov const TargetRegisterClass *RC, 127e4c8c807SAlexei Starovoitov const TargetRegisterInfo *TRI) const { 128e4c8c807SAlexei Starovoitov DebugLoc DL; 129e4c8c807SAlexei Starovoitov if (I != MBB.end()) 130e4c8c807SAlexei Starovoitov DL = I->getDebugLoc(); 131e4c8c807SAlexei Starovoitov 132e4c8c807SAlexei Starovoitov if (RC == &BPF::GPRRegClass) 133e4c8c807SAlexei Starovoitov BuildMI(MBB, I, DL, get(BPF::STD)) 134e4c8c807SAlexei Starovoitov .addReg(SrcReg, getKillRegState(IsKill)) 135e4c8c807SAlexei Starovoitov .addFrameIndex(FI) 136e4c8c807SAlexei Starovoitov .addImm(0); 137fcd1e0f6SYonghong Song else if (RC == &BPF::GPR32RegClass) 138fcd1e0f6SYonghong Song BuildMI(MBB, I, DL, get(BPF::STW32)) 139fcd1e0f6SYonghong Song .addReg(SrcReg, getKillRegState(IsKill)) 140fcd1e0f6SYonghong Song .addFrameIndex(FI) 141fcd1e0f6SYonghong Song .addImm(0); 142e4c8c807SAlexei Starovoitov else 143e4c8c807SAlexei Starovoitov llvm_unreachable("Can't store this register to stack slot"); 144e4c8c807SAlexei Starovoitov } 145e4c8c807SAlexei Starovoitov 146e4c8c807SAlexei Starovoitov void BPFInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 147e4c8c807SAlexei Starovoitov MachineBasicBlock::iterator I, 148e4c8c807SAlexei Starovoitov unsigned DestReg, int FI, 149e4c8c807SAlexei Starovoitov const TargetRegisterClass *RC, 150e4c8c807SAlexei Starovoitov const TargetRegisterInfo *TRI) const { 151e4c8c807SAlexei Starovoitov DebugLoc DL; 152e4c8c807SAlexei Starovoitov if (I != MBB.end()) 153e4c8c807SAlexei Starovoitov DL = I->getDebugLoc(); 154e4c8c807SAlexei Starovoitov 155e4c8c807SAlexei Starovoitov if (RC == &BPF::GPRRegClass) 156e4c8c807SAlexei Starovoitov BuildMI(MBB, I, DL, get(BPF::LDD), DestReg).addFrameIndex(FI).addImm(0); 157fcd1e0f6SYonghong Song else if (RC == &BPF::GPR32RegClass) 158fcd1e0f6SYonghong Song BuildMI(MBB, I, DL, get(BPF::LDW32), DestReg).addFrameIndex(FI).addImm(0); 159e4c8c807SAlexei Starovoitov else 160e4c8c807SAlexei Starovoitov llvm_unreachable("Can't load this register from stack slot"); 161e4c8c807SAlexei Starovoitov } 162e4c8c807SAlexei Starovoitov 16371c30a14SJacques Pienaar bool BPFInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 164e4c8c807SAlexei Starovoitov MachineBasicBlock *&TBB, 165e4c8c807SAlexei Starovoitov MachineBasicBlock *&FBB, 166e4c8c807SAlexei Starovoitov SmallVectorImpl<MachineOperand> &Cond, 167e4c8c807SAlexei Starovoitov bool AllowModify) const { 168e4c8c807SAlexei Starovoitov // Start from the bottom of the block and work up, examining the 169e4c8c807SAlexei Starovoitov // terminator instructions. 170e4c8c807SAlexei Starovoitov MachineBasicBlock::iterator I = MBB.end(); 171e4c8c807SAlexei Starovoitov while (I != MBB.begin()) { 172e4c8c807SAlexei Starovoitov --I; 173801bf7ebSShiva Chen if (I->isDebugInstr()) 174e4c8c807SAlexei Starovoitov continue; 175e4c8c807SAlexei Starovoitov 176e4c8c807SAlexei Starovoitov // Working from the bottom, when we see a non-terminator 177e4c8c807SAlexei Starovoitov // instruction, we're done. 1786307eb55SDuncan P. N. Exon Smith if (!isUnpredicatedTerminator(*I)) 179e4c8c807SAlexei Starovoitov break; 180e4c8c807SAlexei Starovoitov 181e4c8c807SAlexei Starovoitov // A terminator that isn't a branch can't easily be handled 182e4c8c807SAlexei Starovoitov // by this analysis. 183e4c8c807SAlexei Starovoitov if (!I->isBranch()) 184e4c8c807SAlexei Starovoitov return true; 185e4c8c807SAlexei Starovoitov 186e4c8c807SAlexei Starovoitov // Handle unconditional branches. 187e4c8c807SAlexei Starovoitov if (I->getOpcode() == BPF::JMP) { 188e4c8c807SAlexei Starovoitov if (!AllowModify) { 189e4c8c807SAlexei Starovoitov TBB = I->getOperand(0).getMBB(); 190e4c8c807SAlexei Starovoitov continue; 191e4c8c807SAlexei Starovoitov } 192e4c8c807SAlexei Starovoitov 193e4c8c807SAlexei Starovoitov // If the block has any instructions after a J, delete them. 194e4c8c807SAlexei Starovoitov while (std::next(I) != MBB.end()) 195e4c8c807SAlexei Starovoitov std::next(I)->eraseFromParent(); 196e4c8c807SAlexei Starovoitov Cond.clear(); 1974282c404SEugene Zelenko FBB = nullptr; 198e4c8c807SAlexei Starovoitov 199e4c8c807SAlexei Starovoitov // Delete the J if it's equivalent to a fall-through. 200e4c8c807SAlexei Starovoitov if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { 2014282c404SEugene Zelenko TBB = nullptr; 202e4c8c807SAlexei Starovoitov I->eraseFromParent(); 203e4c8c807SAlexei Starovoitov I = MBB.end(); 204e4c8c807SAlexei Starovoitov continue; 205e4c8c807SAlexei Starovoitov } 206e4c8c807SAlexei Starovoitov 207e4c8c807SAlexei Starovoitov // TBB is used to indicate the unconditinal destination. 208e4c8c807SAlexei Starovoitov TBB = I->getOperand(0).getMBB(); 209e4c8c807SAlexei Starovoitov continue; 210e4c8c807SAlexei Starovoitov } 211e4c8c807SAlexei Starovoitov // Cannot handle conditional branches 212e4c8c807SAlexei Starovoitov return true; 213e4c8c807SAlexei Starovoitov } 214e4c8c807SAlexei Starovoitov 215e4c8c807SAlexei Starovoitov return false; 216e4c8c807SAlexei Starovoitov } 217e4c8c807SAlexei Starovoitov 218e8e0f5caSMatt Arsenault unsigned BPFInstrInfo::insertBranch(MachineBasicBlock &MBB, 219e4c8c807SAlexei Starovoitov MachineBasicBlock *TBB, 220e4c8c807SAlexei Starovoitov MachineBasicBlock *FBB, 221c88bf543SAhmed Bougacha ArrayRef<MachineOperand> Cond, 222a2b036e8SMatt Arsenault const DebugLoc &DL, 223a2b036e8SMatt Arsenault int *BytesAdded) const { 224a2b036e8SMatt Arsenault assert(!BytesAdded && "code size not handled"); 225a2b036e8SMatt Arsenault 226e4c8c807SAlexei Starovoitov // Shouldn't be a fall through. 227e8e0f5caSMatt Arsenault assert(TBB && "insertBranch must not be told to insert a fallthrough"); 228e4c8c807SAlexei Starovoitov 229e4c8c807SAlexei Starovoitov if (Cond.empty()) { 230e4c8c807SAlexei Starovoitov // Unconditional branch 231e4c8c807SAlexei Starovoitov assert(!FBB && "Unconditional branch with multiple successors!"); 232e4c8c807SAlexei Starovoitov BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB); 233e4c8c807SAlexei Starovoitov return 1; 234e4c8c807SAlexei Starovoitov } 235e4c8c807SAlexei Starovoitov 236e4c8c807SAlexei Starovoitov llvm_unreachable("Unexpected conditional branch"); 237e4c8c807SAlexei Starovoitov } 238e4c8c807SAlexei Starovoitov 2391b9fc8edSMatt Arsenault unsigned BPFInstrInfo::removeBranch(MachineBasicBlock &MBB, 240a2b036e8SMatt Arsenault int *BytesRemoved) const { 241a2b036e8SMatt Arsenault assert(!BytesRemoved && "code size not handled"); 242a2b036e8SMatt Arsenault 243e4c8c807SAlexei Starovoitov MachineBasicBlock::iterator I = MBB.end(); 244e4c8c807SAlexei Starovoitov unsigned Count = 0; 245e4c8c807SAlexei Starovoitov 246e4c8c807SAlexei Starovoitov while (I != MBB.begin()) { 247e4c8c807SAlexei Starovoitov --I; 248801bf7ebSShiva Chen if (I->isDebugInstr()) 249e4c8c807SAlexei Starovoitov continue; 250e4c8c807SAlexei Starovoitov if (I->getOpcode() != BPF::JMP) 251e4c8c807SAlexei Starovoitov break; 252e4c8c807SAlexei Starovoitov // Remove the branch. 253e4c8c807SAlexei Starovoitov I->eraseFromParent(); 254e4c8c807SAlexei Starovoitov I = MBB.end(); 255e4c8c807SAlexei Starovoitov ++Count; 256e4c8c807SAlexei Starovoitov } 257e4c8c807SAlexei Starovoitov 258e4c8c807SAlexei Starovoitov return Count; 259e4c8c807SAlexei Starovoitov } 260