[InstCombine] Signed saturation patterns
[llvm-core.git] / lib / Target / BPF / BPFMISimplifyPatchable.cpp
blob9c689aed6417835c969d869ebde69ce4b51c76b1
1 //===----- BPFMISimplifyPatchable.cpp - MI Simplify Patchable Insts -------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass targets a subset of instructions like below
10 // ld_imm64 r1, @global
11 // ldd r2, r1, 0
12 // add r3, struct_base_reg, r2
14 // Here @global should represent an AMA (abstruct member access).
15 // Such an access is subject to bpf load time patching. After this pass, the
16 // code becomes
17 // ld_imm64 r1, @global
18 // add r3, struct_base_reg, r1
20 // Eventually, at BTF output stage, a relocation record will be generated
21 // for ld_imm64 which should be replaced later by bpf loader:
22 // r1 = <calculated field_info>
23 // add r3, struct_base_reg, r1
25 //===----------------------------------------------------------------------===//
27 #include "BPF.h"
28 #include "BPFCORE.h"
29 #include "BPFInstrInfo.h"
30 #include "BPFTargetMachine.h"
31 #include "llvm/CodeGen/MachineInstrBuilder.h"
32 #include "llvm/CodeGen/MachineRegisterInfo.h"
33 #include "llvm/Support/Debug.h"
35 using namespace llvm;
37 #define DEBUG_TYPE "bpf-mi-simplify-patchable"
39 namespace {
41 struct BPFMISimplifyPatchable : public MachineFunctionPass {
43 static char ID;
44 const BPFInstrInfo *TII;
45 MachineFunction *MF;
47 BPFMISimplifyPatchable() : MachineFunctionPass(ID) {
48 initializeBPFMISimplifyPatchablePass(*PassRegistry::getPassRegistry());
51 private:
52 // Initialize class variables.
53 void initialize(MachineFunction &MFParm);
55 bool removeLD(void);
57 public:
58 // Main entry point for this pass.
59 bool runOnMachineFunction(MachineFunction &MF) override {
60 if (!skipFunction(MF.getFunction())) {
61 initialize(MF);
63 return removeLD();
67 // Initialize class variables.
68 void BPFMISimplifyPatchable::initialize(MachineFunction &MFParm) {
69 MF = &MFParm;
70 TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo();
71 LLVM_DEBUG(dbgs() << "*** BPF simplify patchable insts pass ***\n\n");
74 /// Remove unneeded Load instructions.
75 bool BPFMISimplifyPatchable::removeLD() {
76 MachineRegisterInfo *MRI = &MF->getRegInfo();
77 MachineInstr *ToErase = nullptr;
78 bool Changed = false;
80 for (MachineBasicBlock &MBB : *MF) {
81 for (MachineInstr &MI : MBB) {
82 if (ToErase) {
83 ToErase->eraseFromParent();
84 ToErase = nullptr;
87 // Ensure the register format is LOAD <reg>, <reg>, 0
88 if (MI.getOpcode() != BPF::LDD && MI.getOpcode() != BPF::LDW &&
89 MI.getOpcode() != BPF::LDH && MI.getOpcode() != BPF::LDB &&
90 MI.getOpcode() != BPF::LDW32 && MI.getOpcode() != BPF::LDH32 &&
91 MI.getOpcode() != BPF::LDB32)
92 continue;
94 if (!MI.getOperand(0).isReg() || !MI.getOperand(1).isReg())
95 continue;
97 if (!MI.getOperand(2).isImm() || MI.getOperand(2).getImm())
98 continue;
100 Register DstReg = MI.getOperand(0).getReg();
101 Register SrcReg = MI.getOperand(1).getReg();
103 MachineInstr *DefInst = MRI->getUniqueVRegDef(SrcReg);
104 if (!DefInst)
105 continue;
107 bool IsCandidate = false;
108 if (DefInst->getOpcode() == BPF::LD_imm64) {
109 const MachineOperand &MO = DefInst->getOperand(1);
110 if (MO.isGlobal()) {
111 const GlobalValue *GVal = MO.getGlobal();
112 auto *GVar = dyn_cast<GlobalVariable>(GVal);
113 if (GVar) {
114 // Global variables representing structure offset or
115 // patchable extern globals.
116 if (GVar->hasAttribute(BPFCoreSharedInfo::AmaAttr)) {
117 assert(MI.getOperand(2).getImm() == 0);
118 IsCandidate = true;
124 if (!IsCandidate)
125 continue;
127 auto Begin = MRI->use_begin(DstReg), End = MRI->use_end();
128 decltype(End) NextI;
129 for (auto I = Begin; I != End; I = NextI) {
130 NextI = std::next(I);
131 I->setReg(SrcReg);
134 ToErase = &MI;
135 Changed = true;
139 return Changed;
142 } // namespace
144 INITIALIZE_PASS(BPFMISimplifyPatchable, DEBUG_TYPE,
145 "BPF PreEmit SimplifyPatchable", false, false)
147 char BPFMISimplifyPatchable::ID = 0;
148 FunctionPass *llvm::createBPFMISimplifyPatchablePass() {
149 return new BPFMISimplifyPatchable();