1 //===-------------- BPFMIChecking.cpp - MI Checking Legality -------------===//
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 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.
15 //===----------------------------------------------------------------------===//
18 #include "BPFInstrInfo.h"
19 #include "BPFTargetMachine.h"
20 #include "llvm/CodeGen/MachineInstrBuilder.h"
21 #include "llvm/CodeGen/MachineRegisterInfo.h"
22 #include "llvm/Support/Debug.h"
26 #define DEBUG_TYPE "bpf-mi-checking"
30 struct BPFMIPreEmitChecking
: public MachineFunctionPass
{
34 const TargetRegisterInfo
*TRI
;
36 BPFMIPreEmitChecking() : MachineFunctionPass(ID
) {
37 initializeBPFMIPreEmitCheckingPass(*PassRegistry::getPassRegistry());
41 // Initialize class variables.
42 void initialize(MachineFunction
&MFParm
);
44 bool processAtomicInsts(void);
48 // Main entry point for this pass.
49 bool runOnMachineFunction(MachineFunction
&MF
) override
{
50 if (!skipFunction(MF
.getFunction())) {
52 return processAtomicInsts();
58 // Initialize class variables.
59 void BPFMIPreEmitChecking::initialize(MachineFunction
&MFParm
) {
61 TRI
= MF
->getSubtarget
<BPFSubtarget
>().getRegisterInfo();
62 LLVM_DEBUG(dbgs() << "*** BPF PreEmit checking pass ***\n\n");
65 // Make sure all Defs of XADD are dead, meaning any result of XADD insn is not
68 // NOTE: BPF backend hasn't enabled sub-register liveness track, so when the
69 // source and destination operands of XADD are GPR32, there is no sub-register
70 // dead info. If we rely on the generic MachineInstr::allDefsAreDead, then we
71 // will raise false alarm on GPR32 Def.
73 // To support GPR32 Def, ideally we could just enable sub-registr liveness track
74 // on BPF backend, then allDefsAreDead could work on GPR32 Def. This requires
75 // implementing TargetSubtargetInfo::enableSubRegLiveness on BPF.
77 // However, sub-register liveness tracking module inside LLVM is actually
78 // designed for the situation where one register could be split into more than
79 // one sub-registers for which case each sub-register could have their own
80 // liveness and kill one of them doesn't kill others. So, tracking liveness for
83 // For BPF, each 64-bit register could only have one 32-bit sub-register. This
84 // is exactly the case which LLVM think brings no benefits for doing
85 // sub-register tracking, because the live range of sub-register must always
86 // equal to its parent register, therefore liveness tracking is disabled even
87 // the back-end has implemented enableSubRegLiveness. The detailed information
90 // Author: Matthias Braun <matze@braunis.de>
91 // Date: Thu Mar 19 00:21:58 2015 +0000
92 // Do not track subregister liveness when it brings no benefits
94 // Hence, for BPF, we enhance MachineInstr::allDefsAreDead. Given the solo
95 // sub-register always has the same liveness as its parent register, LLVM is
96 // already attaching a implicit 64-bit register Def whenever the there is
97 // a sub-register Def. The liveness of the implicit 64-bit Def is available.
98 // For example, for "lock *(u32 *)(r0 + 4) += w9", the MachineOperand info could
101 // $w9 = XADDW32 killed $r0, 4, $w9(tied-def 0),
102 // implicit killed $r9, implicit-def dead $r9
104 // Even though w9 is not marked as Dead, the parent register r9 is marked as
105 // Dead correctly, and it is safe to use such information or our purpose.
106 static bool hasLiveDefs(const MachineInstr
&MI
, const TargetRegisterInfo
*TRI
) {
107 const MCRegisterClass
*GPR64RegClass
=
108 &BPFMCRegisterClasses
[BPF::GPRRegClassID
];
109 std::vector
<unsigned> GPR32LiveDefs
;
110 std::vector
<unsigned> GPR64DeadDefs
;
112 for (const MachineOperand
&MO
: MI
.operands()) {
115 if (!MO
.isReg() || MO
.isUse())
118 RegIsGPR64
= GPR64RegClass
->contains(MO
.getReg());
120 // It is a GPR64 live Def, we are sure it is live. */
123 // It is a GPR32 live Def, we are unsure whether it is really dead due to
124 // no sub-register liveness tracking. Push it to vector for deferred
126 GPR32LiveDefs
.push_back(MO
.getReg());
130 // Record any GPR64 dead Def as some unmarked GPR32 could be alias of its
133 GPR64DeadDefs
.push_back(MO
.getReg());
136 // No GPR32 live Def, safe to return false.
137 if (GPR32LiveDefs
.empty())
140 // No GPR64 dead Def, so all those GPR32 live Def can't have alias, therefore
141 // must be truely live, safe to return true.
142 if (GPR64DeadDefs
.empty())
145 // Otherwise, return true if any aliased SuperReg of GPR32 is not dead.
146 for (auto I
: GPR32LiveDefs
)
147 for (MCSuperRegIterator
SR(I
, TRI
); SR
.isValid(); ++SR
)
148 if (!llvm::is_contained(GPR64DeadDefs
, *SR
))
154 bool BPFMIPreEmitChecking::processAtomicInsts(void) {
155 for (MachineBasicBlock
&MBB
: *MF
) {
156 for (MachineInstr
&MI
: MBB
) {
157 if (MI
.getOpcode() != BPF::XADDW
&&
158 MI
.getOpcode() != BPF::XADDD
&&
159 MI
.getOpcode() != BPF::XADDW32
)
162 LLVM_DEBUG(MI
.dump());
163 if (hasLiveDefs(MI
, TRI
)) {
165 const DebugLoc
&DL
= MI
.getDebugLoc();
167 report_fatal_error("line " + std::to_string(DL
.getLine()) +
168 ": Invalid usage of the XADD return value", false);
170 report_fatal_error("Invalid usage of the XADD return value", false);
175 // Check return values of atomic_fetch_and_{add,and,or,xor}.
176 // If the return is not used, the atomic_fetch_and_<op> instruction
177 // is replaced with atomic_<op> instruction.
178 MachineInstr
*ToErase
= nullptr;
179 bool Changed
= false;
180 const BPFInstrInfo
*TII
= MF
->getSubtarget
<BPFSubtarget
>().getInstrInfo();
181 for (MachineBasicBlock
&MBB
: *MF
) {
182 for (MachineInstr
&MI
: MBB
) {
184 ToErase
->eraseFromParent();
188 if (MI
.getOpcode() != BPF::XFADDW32
&& MI
.getOpcode() != BPF::XFADDD
&&
189 MI
.getOpcode() != BPF::XFANDW32
&& MI
.getOpcode() != BPF::XFANDD
&&
190 MI
.getOpcode() != BPF::XFXORW32
&& MI
.getOpcode() != BPF::XFXORD
&&
191 MI
.getOpcode() != BPF::XFORW32
&& MI
.getOpcode() != BPF::XFORD
)
194 if (hasLiveDefs(MI
, TRI
))
197 LLVM_DEBUG(dbgs() << "Transforming "; MI
.dump());
199 switch (MI
.getOpcode()) {
201 newOpcode
= BPF::XADDW32
;
204 newOpcode
= BPF::XADDD
;
207 newOpcode
= BPF::XANDW32
;
210 newOpcode
= BPF::XANDD
;
213 newOpcode
= BPF::XXORW32
;
216 newOpcode
= BPF::XXORD
;
219 newOpcode
= BPF::XORW32
;
222 newOpcode
= BPF::XORD
;
225 llvm_unreachable("Incorrect Atomic Instruction Opcode");
228 BuildMI(MBB
, MI
, MI
.getDebugLoc(), TII
->get(newOpcode
))
229 .add(MI
.getOperand(0))
230 .add(MI
.getOperand(1))
231 .add(MI
.getOperand(2))
232 .add(MI
.getOperand(3));
242 } // end default namespace
244 INITIALIZE_PASS(BPFMIPreEmitChecking
, "bpf-mi-pemit-checking",
245 "BPF PreEmit Checking", false, false)
247 char BPFMIPreEmitChecking::ID
= 0;
248 FunctionPass
* llvm::createBPFMIPreEmitCheckingPass()
250 return new BPFMIPreEmitChecking();