123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- //===-- BPFInstrInfo.cpp - BPF Instruction Information ----------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file contains the BPF implementation of the TargetInstrInfo class.
- //
- //===----------------------------------------------------------------------===//
- #include "BPFInstrInfo.h"
- #include "BPF.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/CodeGen/MachineBasicBlock.h"
- #include "llvm/CodeGen/MachineInstrBuilder.h"
- #include "llvm/IR/DebugLoc.h"
- #include "llvm/Support/ErrorHandling.h"
- #include <cassert>
- #include <iterator>
- #define GET_INSTRINFO_CTOR_DTOR
- #include "BPFGenInstrInfo.inc"
- using namespace llvm;
- BPFInstrInfo::BPFInstrInfo()
- : BPFGenInstrInfo(BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP) {}
- void BPFInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- const DebugLoc &DL, MCRegister DestReg,
- MCRegister SrcReg, bool KillSrc) const {
- if (BPF::GPRRegClass.contains(DestReg, SrcReg))
- BuildMI(MBB, I, DL, get(BPF::MOV_rr), DestReg)
- .addReg(SrcReg, getKillRegState(KillSrc));
- else if (BPF::GPR32RegClass.contains(DestReg, SrcReg))
- BuildMI(MBB, I, DL, get(BPF::MOV_rr_32), DestReg)
- .addReg(SrcReg, getKillRegState(KillSrc));
- else
- llvm_unreachable("Impossible reg-to-reg copy");
- }
- void BPFInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const {
- Register DstReg = MI->getOperand(0).getReg();
- Register SrcReg = MI->getOperand(1).getReg();
- uint64_t CopyLen = MI->getOperand(2).getImm();
- uint64_t Alignment = MI->getOperand(3).getImm();
- Register ScratchReg = MI->getOperand(4).getReg();
- MachineBasicBlock *BB = MI->getParent();
- DebugLoc dl = MI->getDebugLoc();
- unsigned LdOpc, StOpc;
- switch (Alignment) {
- case 1:
- LdOpc = BPF::LDB;
- StOpc = BPF::STB;
- break;
- case 2:
- LdOpc = BPF::LDH;
- StOpc = BPF::STH;
- break;
- case 4:
- LdOpc = BPF::LDW;
- StOpc = BPF::STW;
- break;
- case 8:
- LdOpc = BPF::LDD;
- StOpc = BPF::STD;
- break;
- default:
- llvm_unreachable("unsupported memcpy alignment");
- }
- unsigned IterationNum = CopyLen >> Log2_64(Alignment);
- for(unsigned I = 0; I < IterationNum; ++I) {
- BuildMI(*BB, MI, dl, get(LdOpc))
- .addReg(ScratchReg, RegState::Define).addReg(SrcReg)
- .addImm(I * Alignment);
- BuildMI(*BB, MI, dl, get(StOpc))
- .addReg(ScratchReg, RegState::Kill).addReg(DstReg)
- .addImm(I * Alignment);
- }
- unsigned BytesLeft = CopyLen & (Alignment - 1);
- unsigned Offset = IterationNum * Alignment;
- bool Hanging4Byte = BytesLeft & 0x4;
- bool Hanging2Byte = BytesLeft & 0x2;
- bool Hanging1Byte = BytesLeft & 0x1;
- if (Hanging4Byte) {
- BuildMI(*BB, MI, dl, get(BPF::LDW))
- .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
- BuildMI(*BB, MI, dl, get(BPF::STW))
- .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
- Offset += 4;
- }
- if (Hanging2Byte) {
- BuildMI(*BB, MI, dl, get(BPF::LDH))
- .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
- BuildMI(*BB, MI, dl, get(BPF::STH))
- .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
- Offset += 2;
- }
- if (Hanging1Byte) {
- BuildMI(*BB, MI, dl, get(BPF::LDB))
- .addReg(ScratchReg, RegState::Define).addReg(SrcReg).addImm(Offset);
- BuildMI(*BB, MI, dl, get(BPF::STB))
- .addReg(ScratchReg, RegState::Kill).addReg(DstReg).addImm(Offset);
- }
- BB->erase(MI);
- }
- bool BPFInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
- if (MI.getOpcode() == BPF::MEMCPY) {
- expandMEMCPY(MI);
- return true;
- }
- return false;
- }
- void BPFInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- Register SrcReg, bool IsKill, int FI,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI) const {
- DebugLoc DL;
- if (I != MBB.end())
- DL = I->getDebugLoc();
- if (RC == &BPF::GPRRegClass)
- BuildMI(MBB, I, DL, get(BPF::STD))
- .addReg(SrcReg, getKillRegState(IsKill))
- .addFrameIndex(FI)
- .addImm(0);
- else if (RC == &BPF::GPR32RegClass)
- BuildMI(MBB, I, DL, get(BPF::STW32))
- .addReg(SrcReg, getKillRegState(IsKill))
- .addFrameIndex(FI)
- .addImm(0);
- else
- llvm_unreachable("Can't store this register to stack slot");
- }
- void BPFInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- Register DestReg, int FI,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI) const {
- DebugLoc DL;
- if (I != MBB.end())
- DL = I->getDebugLoc();
- if (RC == &BPF::GPRRegClass)
- BuildMI(MBB, I, DL, get(BPF::LDD), DestReg).addFrameIndex(FI).addImm(0);
- else if (RC == &BPF::GPR32RegClass)
- BuildMI(MBB, I, DL, get(BPF::LDW32), DestReg).addFrameIndex(FI).addImm(0);
- else
- llvm_unreachable("Can't load this register from stack slot");
- }
- bool BPFInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
- MachineBasicBlock *&TBB,
- MachineBasicBlock *&FBB,
- SmallVectorImpl<MachineOperand> &Cond,
- bool AllowModify) const {
- // Start from the bottom of the block and work up, examining the
- // terminator instructions.
- MachineBasicBlock::iterator I = MBB.end();
- while (I != MBB.begin()) {
- --I;
- if (I->isDebugInstr())
- continue;
- // Working from the bottom, when we see a non-terminator
- // instruction, we're done.
- if (!isUnpredicatedTerminator(*I))
- break;
- // A terminator that isn't a branch can't easily be handled
- // by this analysis.
- if (!I->isBranch())
- return true;
- // Handle unconditional branches.
- if (I->getOpcode() == BPF::JMP) {
- if (!AllowModify) {
- TBB = I->getOperand(0).getMBB();
- continue;
- }
- // If the block has any instructions after a J, delete them.
- while (std::next(I) != MBB.end())
- std::next(I)->eraseFromParent();
- Cond.clear();
- FBB = nullptr;
- // Delete the J if it's equivalent to a fall-through.
- if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
- TBB = nullptr;
- I->eraseFromParent();
- I = MBB.end();
- continue;
- }
- // TBB is used to indicate the unconditinal destination.
- TBB = I->getOperand(0).getMBB();
- continue;
- }
- // Cannot handle conditional branches
- return true;
- }
- return false;
- }
- unsigned BPFInstrInfo::insertBranch(MachineBasicBlock &MBB,
- MachineBasicBlock *TBB,
- MachineBasicBlock *FBB,
- ArrayRef<MachineOperand> Cond,
- const DebugLoc &DL,
- int *BytesAdded) const {
- assert(!BytesAdded && "code size not handled");
- // Shouldn't be a fall through.
- assert(TBB && "insertBranch must not be told to insert a fallthrough");
- if (Cond.empty()) {
- // Unconditional branch
- assert(!FBB && "Unconditional branch with multiple successors!");
- BuildMI(&MBB, DL, get(BPF::JMP)).addMBB(TBB);
- return 1;
- }
- llvm_unreachable("Unexpected conditional branch");
- }
- unsigned BPFInstrInfo::removeBranch(MachineBasicBlock &MBB,
- int *BytesRemoved) const {
- assert(!BytesRemoved && "code size not handled");
- MachineBasicBlock::iterator I = MBB.end();
- unsigned Count = 0;
- while (I != MBB.begin()) {
- --I;
- if (I->isDebugInstr())
- continue;
- if (I->getOpcode() != BPF::JMP)
- break;
- // Remove the branch.
- I->eraseFromParent();
- I = MBB.end();
- ++Count;
- }
- return Count;
- }
|