10b57cec5SDimitry Andric //===-------------- BPFMIChecking.cpp - MI Checking Legality -------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This pass performs checking to signal errors for certain illegal usages at 100b57cec5SDimitry Andric // MachineInstruction layer. Specially, the result of XADD{32,64} insn should 110b57cec5SDimitry Andric // not be used. The pass is done at the PreEmit pass right before the 120b57cec5SDimitry Andric // machine code is emitted at which point the register liveness information 130b57cec5SDimitry Andric // is still available. 140b57cec5SDimitry Andric // 150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "BPF.h" 180b57cec5SDimitry Andric #include "BPFInstrInfo.h" 190b57cec5SDimitry Andric #include "BPFTargetMachine.h" 2081ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 23*0fca6ea1SDimitry Andric #include "llvm/IR/DiagnosticInfo.h" 248bcb0991SDimitry Andric #include "llvm/Support/Debug.h" 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric using namespace llvm; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric #define DEBUG_TYPE "bpf-mi-checking" 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric namespace { 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric struct BPFMIPreEmitChecking : public MachineFunctionPass { 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric static char ID; 350b57cec5SDimitry Andric MachineFunction *MF; 360b57cec5SDimitry Andric const TargetRegisterInfo *TRI; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric BPFMIPreEmitChecking() : MachineFunctionPass(ID) { 390b57cec5SDimitry Andric initializeBPFMIPreEmitCheckingPass(*PassRegistry::getPassRegistry()); 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric private: 430b57cec5SDimitry Andric // Initialize class variables. 440b57cec5SDimitry Andric void initialize(MachineFunction &MFParm); 450b57cec5SDimitry Andric 4604eeddc0SDimitry Andric bool processAtomicInsts(); 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric public: 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric // Main entry point for this pass. 510b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override { 520b57cec5SDimitry Andric if (!skipFunction(MF.getFunction())) { 530b57cec5SDimitry Andric initialize(MF); 54e8d8bef9SDimitry Andric return processAtomicInsts(); 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric return false; 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric }; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric // Initialize class variables. 610b57cec5SDimitry Andric void BPFMIPreEmitChecking::initialize(MachineFunction &MFParm) { 620b57cec5SDimitry Andric MF = &MFParm; 630b57cec5SDimitry Andric TRI = MF->getSubtarget<BPFSubtarget>().getRegisterInfo(); 640b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "*** BPF PreEmit checking pass ***\n\n"); 650b57cec5SDimitry Andric } 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric // Make sure all Defs of XADD are dead, meaning any result of XADD insn is not 680b57cec5SDimitry Andric // used. 690b57cec5SDimitry Andric // 700b57cec5SDimitry Andric // NOTE: BPF backend hasn't enabled sub-register liveness track, so when the 710b57cec5SDimitry Andric // source and destination operands of XADD are GPR32, there is no sub-register 720b57cec5SDimitry Andric // dead info. If we rely on the generic MachineInstr::allDefsAreDead, then we 730b57cec5SDimitry Andric // will raise false alarm on GPR32 Def. 740b57cec5SDimitry Andric // 750b57cec5SDimitry Andric // To support GPR32 Def, ideally we could just enable sub-registr liveness track 760b57cec5SDimitry Andric // on BPF backend, then allDefsAreDead could work on GPR32 Def. This requires 770b57cec5SDimitry Andric // implementing TargetSubtargetInfo::enableSubRegLiveness on BPF. 780b57cec5SDimitry Andric // 790b57cec5SDimitry Andric // However, sub-register liveness tracking module inside LLVM is actually 800b57cec5SDimitry Andric // designed for the situation where one register could be split into more than 810b57cec5SDimitry Andric // one sub-registers for which case each sub-register could have their own 820b57cec5SDimitry Andric // liveness and kill one of them doesn't kill others. So, tracking liveness for 830b57cec5SDimitry Andric // each make sense. 840b57cec5SDimitry Andric // 850b57cec5SDimitry Andric // For BPF, each 64-bit register could only have one 32-bit sub-register. This 860b57cec5SDimitry Andric // is exactly the case which LLVM think brings no benefits for doing 870b57cec5SDimitry Andric // sub-register tracking, because the live range of sub-register must always 880b57cec5SDimitry Andric // equal to its parent register, therefore liveness tracking is disabled even 890b57cec5SDimitry Andric // the back-end has implemented enableSubRegLiveness. The detailed information 900b57cec5SDimitry Andric // is at r232695: 910b57cec5SDimitry Andric // 920b57cec5SDimitry Andric // Author: Matthias Braun <matze@braunis.de> 930b57cec5SDimitry Andric // Date: Thu Mar 19 00:21:58 2015 +0000 940b57cec5SDimitry Andric // Do not track subregister liveness when it brings no benefits 950b57cec5SDimitry Andric // 960b57cec5SDimitry Andric // Hence, for BPF, we enhance MachineInstr::allDefsAreDead. Given the solo 970b57cec5SDimitry Andric // sub-register always has the same liveness as its parent register, LLVM is 980b57cec5SDimitry Andric // already attaching a implicit 64-bit register Def whenever the there is 990b57cec5SDimitry Andric // a sub-register Def. The liveness of the implicit 64-bit Def is available. 1000b57cec5SDimitry Andric // For example, for "lock *(u32 *)(r0 + 4) += w9", the MachineOperand info could 1010b57cec5SDimitry Andric // be: 1020b57cec5SDimitry Andric // 1030b57cec5SDimitry Andric // $w9 = XADDW32 killed $r0, 4, $w9(tied-def 0), 1040b57cec5SDimitry Andric // implicit killed $r9, implicit-def dead $r9 1050b57cec5SDimitry Andric // 1060b57cec5SDimitry Andric // Even though w9 is not marked as Dead, the parent register r9 is marked as 1070b57cec5SDimitry Andric // Dead correctly, and it is safe to use such information or our purpose. 1080b57cec5SDimitry Andric static bool hasLiveDefs(const MachineInstr &MI, const TargetRegisterInfo *TRI) { 1090b57cec5SDimitry Andric const MCRegisterClass *GPR64RegClass = 1100b57cec5SDimitry Andric &BPFMCRegisterClasses[BPF::GPRRegClassID]; 1110b57cec5SDimitry Andric std::vector<unsigned> GPR32LiveDefs; 1120b57cec5SDimitry Andric std::vector<unsigned> GPR64DeadDefs; 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric for (const MachineOperand &MO : MI.operands()) { 1150b57cec5SDimitry Andric bool RegIsGPR64; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric if (!MO.isReg() || MO.isUse()) 1180b57cec5SDimitry Andric continue; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric RegIsGPR64 = GPR64RegClass->contains(MO.getReg()); 1210b57cec5SDimitry Andric if (!MO.isDead()) { 1220b57cec5SDimitry Andric // It is a GPR64 live Def, we are sure it is live. */ 1230b57cec5SDimitry Andric if (RegIsGPR64) 1240b57cec5SDimitry Andric return true; 1250b57cec5SDimitry Andric // It is a GPR32 live Def, we are unsure whether it is really dead due to 1260b57cec5SDimitry Andric // no sub-register liveness tracking. Push it to vector for deferred 1270b57cec5SDimitry Andric // check. 1280b57cec5SDimitry Andric GPR32LiveDefs.push_back(MO.getReg()); 1290b57cec5SDimitry Andric continue; 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric // Record any GPR64 dead Def as some unmarked GPR32 could be alias of its 1330b57cec5SDimitry Andric // low 32-bit. 1340b57cec5SDimitry Andric if (RegIsGPR64) 1350b57cec5SDimitry Andric GPR64DeadDefs.push_back(MO.getReg()); 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric // No GPR32 live Def, safe to return false. 1390b57cec5SDimitry Andric if (GPR32LiveDefs.empty()) 1400b57cec5SDimitry Andric return false; 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric // No GPR64 dead Def, so all those GPR32 live Def can't have alias, therefore 1430b57cec5SDimitry Andric // must be truely live, safe to return true. 1440b57cec5SDimitry Andric if (GPR64DeadDefs.empty()) 1450b57cec5SDimitry Andric return true; 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric // Otherwise, return true if any aliased SuperReg of GPR32 is not dead. 1480b57cec5SDimitry Andric for (auto I : GPR32LiveDefs) 14906c3fb27SDimitry Andric for (MCPhysReg SR : TRI->superregs(I)) 15006c3fb27SDimitry Andric if (!llvm::is_contained(GPR64DeadDefs, SR)) 1510b57cec5SDimitry Andric return true; 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric return false; 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric 15604eeddc0SDimitry Andric bool BPFMIPreEmitChecking::processAtomicInsts() { 1570b57cec5SDimitry Andric for (MachineBasicBlock &MBB : *MF) { 1580b57cec5SDimitry Andric for (MachineInstr &MI : MBB) { 1590b57cec5SDimitry Andric if (MI.getOpcode() != BPF::XADDW && 1600b57cec5SDimitry Andric MI.getOpcode() != BPF::XADDD && 1610b57cec5SDimitry Andric MI.getOpcode() != BPF::XADDW32) 1620b57cec5SDimitry Andric continue; 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric LLVM_DEBUG(MI.dump()); 1650b57cec5SDimitry Andric if (hasLiveDefs(MI, TRI)) { 1660b57cec5SDimitry Andric DebugLoc Empty; 1670b57cec5SDimitry Andric const DebugLoc &DL = MI.getDebugLoc(); 168*0fca6ea1SDimitry Andric const Function &F = MF->getFunction(); 169*0fca6ea1SDimitry Andric F.getContext().diagnose(DiagnosticInfoUnsupported{ 170*0fca6ea1SDimitry Andric F, "Invalid usage of the XADD return value", DL}); 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric } 1740b57cec5SDimitry Andric 175e8d8bef9SDimitry Andric // Check return values of atomic_fetch_and_{add,and,or,xor}. 176e8d8bef9SDimitry Andric // If the return is not used, the atomic_fetch_and_<op> instruction 177e8d8bef9SDimitry Andric // is replaced with atomic_<op> instruction. 178e8d8bef9SDimitry Andric MachineInstr *ToErase = nullptr; 179e8d8bef9SDimitry Andric bool Changed = false; 180e8d8bef9SDimitry Andric const BPFInstrInfo *TII = MF->getSubtarget<BPFSubtarget>().getInstrInfo(); 181e8d8bef9SDimitry Andric for (MachineBasicBlock &MBB : *MF) { 182e8d8bef9SDimitry Andric for (MachineInstr &MI : MBB) { 183e8d8bef9SDimitry Andric if (ToErase) { 184e8d8bef9SDimitry Andric ToErase->eraseFromParent(); 185e8d8bef9SDimitry Andric ToErase = nullptr; 186e8d8bef9SDimitry Andric } 187e8d8bef9SDimitry Andric 188e8d8bef9SDimitry Andric if (MI.getOpcode() != BPF::XFADDW32 && MI.getOpcode() != BPF::XFADDD && 189e8d8bef9SDimitry Andric MI.getOpcode() != BPF::XFANDW32 && MI.getOpcode() != BPF::XFANDD && 190e8d8bef9SDimitry Andric MI.getOpcode() != BPF::XFXORW32 && MI.getOpcode() != BPF::XFXORD && 191e8d8bef9SDimitry Andric MI.getOpcode() != BPF::XFORW32 && MI.getOpcode() != BPF::XFORD) 192e8d8bef9SDimitry Andric continue; 193e8d8bef9SDimitry Andric 194e8d8bef9SDimitry Andric if (hasLiveDefs(MI, TRI)) 195e8d8bef9SDimitry Andric continue; 196e8d8bef9SDimitry Andric 197e8d8bef9SDimitry Andric LLVM_DEBUG(dbgs() << "Transforming "; MI.dump()); 198e8d8bef9SDimitry Andric unsigned newOpcode; 199e8d8bef9SDimitry Andric switch (MI.getOpcode()) { 200e8d8bef9SDimitry Andric case BPF::XFADDW32: 201e8d8bef9SDimitry Andric newOpcode = BPF::XADDW32; 202e8d8bef9SDimitry Andric break; 203e8d8bef9SDimitry Andric case BPF::XFADDD: 204e8d8bef9SDimitry Andric newOpcode = BPF::XADDD; 205e8d8bef9SDimitry Andric break; 206e8d8bef9SDimitry Andric case BPF::XFANDW32: 207e8d8bef9SDimitry Andric newOpcode = BPF::XANDW32; 208e8d8bef9SDimitry Andric break; 209e8d8bef9SDimitry Andric case BPF::XFANDD: 210e8d8bef9SDimitry Andric newOpcode = BPF::XANDD; 211e8d8bef9SDimitry Andric break; 212e8d8bef9SDimitry Andric case BPF::XFXORW32: 213e8d8bef9SDimitry Andric newOpcode = BPF::XXORW32; 214e8d8bef9SDimitry Andric break; 215e8d8bef9SDimitry Andric case BPF::XFXORD: 216e8d8bef9SDimitry Andric newOpcode = BPF::XXORD; 217e8d8bef9SDimitry Andric break; 218e8d8bef9SDimitry Andric case BPF::XFORW32: 219e8d8bef9SDimitry Andric newOpcode = BPF::XORW32; 220e8d8bef9SDimitry Andric break; 221e8d8bef9SDimitry Andric case BPF::XFORD: 222e8d8bef9SDimitry Andric newOpcode = BPF::XORD; 223e8d8bef9SDimitry Andric break; 224e8d8bef9SDimitry Andric default: 225e8d8bef9SDimitry Andric llvm_unreachable("Incorrect Atomic Instruction Opcode"); 226e8d8bef9SDimitry Andric } 227e8d8bef9SDimitry Andric 228e8d8bef9SDimitry Andric BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(newOpcode)) 229e8d8bef9SDimitry Andric .add(MI.getOperand(0)) 230e8d8bef9SDimitry Andric .add(MI.getOperand(1)) 231e8d8bef9SDimitry Andric .add(MI.getOperand(2)) 232e8d8bef9SDimitry Andric .add(MI.getOperand(3)); 233e8d8bef9SDimitry Andric 234e8d8bef9SDimitry Andric ToErase = &MI; 235e8d8bef9SDimitry Andric Changed = true; 236e8d8bef9SDimitry Andric } 237e8d8bef9SDimitry Andric } 238e8d8bef9SDimitry Andric 239e8d8bef9SDimitry Andric return Changed; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric } // end default namespace 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric INITIALIZE_PASS(BPFMIPreEmitChecking, "bpf-mi-pemit-checking", 2450b57cec5SDimitry Andric "BPF PreEmit Checking", false, false) 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric char BPFMIPreEmitChecking::ID = 0; 2480b57cec5SDimitry Andric FunctionPass* llvm::createBPFMIPreEmitCheckingPass() 2490b57cec5SDimitry Andric { 2500b57cec5SDimitry Andric return new BPFMIPreEmitChecking(); 2510b57cec5SDimitry Andric } 252