| Alexei Starovoitov | e4c8c80 | 2015-01-24 17:51:26 +0000 | [diff] [blame] | 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 |  | 
|  | 31 | BPFInstrInfo::BPFInstrInfo() | 
|  | 32 | : BPFGenInstrInfo(BPF::ADJCALLSTACKDOWN, BPF::ADJCALLSTACKUP) {} | 
|  | 33 |  | 
|  | 34 | void BPFInstrInfo::copyPhysReg(MachineBasicBlock &MBB, | 
| Benjamin Kramer | bdc4956 | 2016-06-12 15:39:02 +0000 | [diff] [blame^] | 35 | MachineBasicBlock::iterator I, | 
|  | 36 | const DebugLoc &DL, unsigned DestReg, | 
|  | 37 | unsigned SrcReg, bool KillSrc) const { | 
| Alexei Starovoitov | e4c8c80 | 2015-01-24 17:51:26 +0000 | [diff] [blame] | 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 |  | 
|  | 45 | 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 |  | 
|  | 63 | 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 |  | 
|  | 78 | 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. | 
| Duncan P. N. Exon Smith | 6307eb5 | 2016-02-23 02:46:52 +0000 | [diff] [blame] | 93 | if (!isUnpredicatedTerminator(*I)) | 
| Alexei Starovoitov | e4c8c80 | 2015-01-24 17:51:26 +0000 | [diff] [blame] | 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 |  | 
|  | 133 | unsigned BPFInstrInfo::InsertBranch(MachineBasicBlock &MBB, | 
|  | 134 | MachineBasicBlock *TBB, | 
|  | 135 | MachineBasicBlock *FBB, | 
| Ahmed Bougacha | c88bf54 | 2015-06-11 19:30:37 +0000 | [diff] [blame] | 136 | ArrayRef<MachineOperand> Cond, | 
| Benjamin Kramer | bdc4956 | 2016-06-12 15:39:02 +0000 | [diff] [blame^] | 137 | const DebugLoc &DL) const { | 
| Alexei Starovoitov | e4c8c80 | 2015-01-24 17:51:26 +0000 | [diff] [blame] | 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 |  | 
|  | 151 | 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 | } |