1 //===----- BPFMISimplifyPatchable.cpp - MI Simplify Patchable Insts -------===//
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
7 //===----------------------------------------------------------------------===//
9 // This pass targets a subset of instructions like below
10 // ld_imm64 r1, @global
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
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 //===----------------------------------------------------------------------===//
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"
37 #define DEBUG_TYPE "bpf-mi-simplify-patchable"
41 struct BPFMISimplifyPatchable
: public MachineFunctionPass
{
44 const BPFInstrInfo
*TII
;
47 BPFMISimplifyPatchable() : MachineFunctionPass(ID
) {
48 initializeBPFMISimplifyPatchablePass(*PassRegistry::getPassRegistry());
52 // Initialize class variables.
53 void initialize(MachineFunction
&MFParm
);
58 // Main entry point for this pass.
59 bool runOnMachineFunction(MachineFunction
&MF
) override
{
60 if (!skipFunction(MF
.getFunction())) {
67 // Initialize class variables.
68 void BPFMISimplifyPatchable::initialize(MachineFunction
&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;
80 for (MachineBasicBlock
&MBB
: *MF
) {
81 for (MachineInstr
&MI
: MBB
) {
83 ToErase
->eraseFromParent();
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
)
94 if (!MI
.getOperand(0).isReg() || !MI
.getOperand(1).isReg())
97 if (!MI
.getOperand(2).isImm() || MI
.getOperand(2).getImm())
100 Register DstReg
= MI
.getOperand(0).getReg();
101 Register SrcReg
= MI
.getOperand(1).getReg();
103 MachineInstr
*DefInst
= MRI
->getUniqueVRegDef(SrcReg
);
107 bool IsCandidate
= false;
108 if (DefInst
->getOpcode() == BPF::LD_imm64
) {
109 const MachineOperand
&MO
= DefInst
->getOperand(1);
111 const GlobalValue
*GVal
= MO
.getGlobal();
112 auto *GVar
= dyn_cast
<GlobalVariable
>(GVal
);
114 // Global variables representing structure offset or
115 // patchable extern globals.
116 if (GVar
->hasAttribute(BPFCoreSharedInfo::AmaAttr
)) {
117 assert(MI
.getOperand(2).getImm() == 0);
127 auto Begin
= MRI
->use_begin(DstReg
), End
= MRI
->use_end();
129 for (auto I
= Begin
; I
!= End
; I
= NextI
) {
130 NextI
= std::next(I
);
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();