xref: /llvm-project/llvm/lib/Target/BPF/BPFMIChecking.cpp (revision ed8019d9fbed2e6a6b08f8f73e9fa54a24f3ed52)
1 //===-------------- BPFMIChecking.cpp - MI Checking Legality -------------===//
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 performs checking to signal errors for certain illegal usages at
10 // MachineInstruction layer. Specially, the result of XADD{32,64} insn should
11 // not be used. The pass is done at the PreEmit pass right before the
12 // machine code is emitted at which point the register liveness information
13 // is still available.
14 //
15 //===----------------------------------------------------------------------===//
16 
17 #include "BPF.h"
18 #include "BPFTargetMachine.h"
19 #include "llvm/CodeGen/MachineFunctionPass.h"
20 #include "llvm/IR/DiagnosticInfo.h"
21 #include "llvm/Support/Debug.h"
22 
23 using namespace llvm;
24 
25 #define DEBUG_TYPE "bpf-mi-checking"
26 
27 namespace {
28 
29 struct BPFMIPreEmitChecking : public MachineFunctionPass {
30 
31   static char ID;
32   MachineFunction *MF;
33   const TargetRegisterInfo *TRI;
34 
35   BPFMIPreEmitChecking() : MachineFunctionPass(ID) {
36     initializeBPFMIPreEmitCheckingPass(*PassRegistry::getPassRegistry());
37   }
38 
39 private:
40   // Initialize class variables.
41   void initialize(MachineFunction &MFParm);
42 
43   void processAtomicInsts();
44 
45 public:
46   // Main entry point for this pass.
47   bool runOnMachineFunction(MachineFunction &MF) override {
48     if (!skipFunction(MF.getFunction())) {
49       initialize(MF);
50       processAtomicInsts();
51     }
52     return false;
53   }
54 };
55 
56 // Initialize class variables.
57 void BPFMIPreEmitChecking::initialize(MachineFunction &MFParm) {
58   MF = &MFParm;
59   TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo();
60   LLVM_DEBUG(dbgs() << "*** BPF PreEmit checking pass ***\n\n");
61 }
62 
63 // Make sure all Defs of XADD are dead, meaning any result of XADD insn is not
64 // used.
65 //
66 // NOTE: BPF backend hasn't enabled sub-register liveness track, so when the
67 // source and destination operands of XADD are GPR32, there is no sub-register
68 // dead info. If we rely on the generic MachineInstr::allDefsAreDead, then we
69 // will raise false alarm on GPR32 Def.
70 //
71 // To support GPR32 Def, ideally we could just enable sub-registr liveness track
72 // on BPF backend, then allDefsAreDead could work on GPR32 Def. This requires
73 // implementing TargetSubtargetInfo::enableSubRegLiveness on BPF.
74 //
75 // However, sub-register liveness tracking module inside LLVM is actually
76 // designed for the situation where one register could be split into more than
77 // one sub-registers for which case each sub-register could have their own
78 // liveness and kill one of them doesn't kill others. So, tracking liveness for
79 // each make sense.
80 //
81 // For BPF, each 64-bit register could only have one 32-bit sub-register. This
82 // is exactly the case which LLVM think brings no benefits for doing
83 // sub-register tracking, because the live range of sub-register must always
84 // equal to its parent register, therefore liveness tracking is disabled even
85 // the back-end has implemented enableSubRegLiveness. The detailed information
86 // is at r232695:
87 //
88 //   Author: Matthias Braun <matze@braunis.de>
89 //   Date:   Thu Mar 19 00:21:58 2015 +0000
90 //   Do not track subregister liveness when it brings no benefits
91 //
92 // Hence, for BPF, we enhance MachineInstr::allDefsAreDead. Given the solo
93 // sub-register always has the same liveness as its parent register, LLVM is
94 // already attaching a implicit 64-bit register Def whenever the there is
95 // a sub-register Def. The liveness of the implicit 64-bit Def is available.
96 // For example, for "lock *(u32 *)(r0 + 4) += w9", the MachineOperand info could
97 // be:
98 //
99 //   $w9 = XADDW32 killed $r0, 4, $w9(tied-def 0),
100 //                        implicit killed $r9, implicit-def dead $r9
101 //
102 // Even though w9 is not marked as Dead, the parent register r9 is marked as
103 // Dead correctly, and it is safe to use such information or our purpose.
104 static bool hasLiveDefs(const MachineInstr &MI, const TargetRegisterInfo *TRI) {
105   const MCRegisterClass *GPR64RegClass =
106       &BPFMCRegisterClasses[BPF::GPRRegClassID];
107   std::vector<unsigned> GPR32LiveDefs;
108   std::vector<unsigned> GPR64DeadDefs;
109 
110   for (const MachineOperand &MO : MI.operands()) {
111     bool RegIsGPR64;
112 
113     if (!MO.isReg() || MO.isUse())
114       continue;
115 
116     RegIsGPR64 = GPR64RegClass->contains(MO.getReg());
117     if (!MO.isDead()) {
118       // It is a GPR64 live Def, we are sure it is live.
119       if (RegIsGPR64)
120         return true;
121       // It is a GPR32 live Def, we are unsure whether it is really dead due to
122       // no sub-register liveness tracking. Push it to vector for deferred
123       // check.
124       GPR32LiveDefs.push_back(MO.getReg());
125       continue;
126     }
127 
128     // Record any GPR64 dead Def as some unmarked GPR32 could be alias of its
129     // low 32-bit.
130     if (RegIsGPR64)
131       GPR64DeadDefs.push_back(MO.getReg());
132   }
133 
134   // No GPR32 live Def, safe to return false.
135   if (GPR32LiveDefs.empty())
136     return false;
137 
138   // No GPR64 dead Def, so all those GPR32 live Def can't have alias, therefore
139   // must be truely live, safe to return true.
140   if (GPR64DeadDefs.empty())
141     return true;
142 
143   // Otherwise, return true if any aliased SuperReg of GPR32 is not dead.
144   for (auto I : GPR32LiveDefs)
145     for (MCPhysReg SR : TRI->superregs(I))
146       if (!llvm::is_contained(GPR64DeadDefs, SR))
147         return true;
148 
149   return false;
150 }
151 
152 void BPFMIPreEmitChecking::processAtomicInsts() {
153   if (MF->getSubtarget<BPFSubtarget>().getHasJmp32())
154     return;
155 
156   // Only check for cpu version 1 and 2.
157   for (MachineBasicBlock &MBB : *MF) {
158     for (MachineInstr &MI : MBB) {
159       if (MI.getOpcode() != BPF::XADDW && MI.getOpcode() != BPF::XADDD)
160         continue;
161 
162       LLVM_DEBUG(MI.dump());
163       if (hasLiveDefs(MI, TRI)) {
164         DebugLoc Empty;
165         const DebugLoc &DL = MI.getDebugLoc();
166         const Function &F = MF->getFunction();
167         F.getContext().diagnose(DiagnosticInfoUnsupported{
168             F, "Invalid usage of the XADD return value", DL});
169       }
170     }
171   }
172 }
173 
174 } // namespace
175 
176 INITIALIZE_PASS(BPFMIPreEmitChecking, "bpf-mi-pemit-checking",
177                 "BPF PreEmit Checking", false, false)
178 
179 char BPFMIPreEmitChecking::ID = 0;
180 FunctionPass *llvm::createBPFMIPreEmitCheckingPass() {
181   return new BPFMIPreEmitChecking();
182 }
183