1 //===- NVPTXProxyRegErasure.cpp - NVPTX Proxy Register Instruction Erasure -==// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // The pass is needed to remove ProxyReg instructions and restore related 11 // registers. The instructions were needed at instruction selection stage to 12 // make sure that callseq_end nodes won't be removed as "dead nodes". This can 13 // happen when we expand instructions into libcalls and the call site doesn't 14 // care about the libcall chain. Call site cares about data flow only, and the 15 // latest data flow node happens to be before callseq_end. Therefore the node 16 // becomes dangling and "dead". The ProxyReg acts like an additional data flow 17 // node *after* the callseq_end in the chain and ensures that everything will be 18 // preserved. 19 // 20 //===----------------------------------------------------------------------===// 21 22 #include "NVPTX.h" 23 #include "llvm/CodeGen/MachineFunctionPass.h" 24 #include "llvm/CodeGen/MachineInstrBuilder.h" 25 #include "llvm/CodeGen/MachineRegisterInfo.h" 26 #include "llvm/CodeGen/TargetInstrInfo.h" 27 #include "llvm/CodeGen/TargetRegisterInfo.h" 28 29 using namespace llvm; 30 31 namespace llvm { 32 void initializeNVPTXProxyRegErasurePass(PassRegistry &); 33 } 34 35 namespace { 36 37 struct NVPTXProxyRegErasure : public MachineFunctionPass { 38 public: 39 static char ID; 40 NVPTXProxyRegErasure() : MachineFunctionPass(ID) { 41 initializeNVPTXProxyRegErasurePass(*PassRegistry::getPassRegistry()); 42 } 43 44 bool runOnMachineFunction(MachineFunction &MF) override; 45 46 StringRef getPassName() const override { 47 return "NVPTX Proxy Register Instruction Erasure"; 48 } 49 50 void getAnalysisUsage(AnalysisUsage &AU) const override { 51 MachineFunctionPass::getAnalysisUsage(AU); 52 } 53 54 private: 55 void replaceMachineInstructionUsage(MachineFunction &MF, MachineInstr &MI); 56 57 void replaceRegisterUsage(MachineInstr &Instr, MachineOperand &From, 58 MachineOperand &To); 59 }; 60 61 } // namespace 62 63 char NVPTXProxyRegErasure::ID = 0; 64 65 INITIALIZE_PASS(NVPTXProxyRegErasure, "nvptx-proxyreg-erasure", "NVPTX ProxyReg Erasure", false, false) 66 67 bool NVPTXProxyRegErasure::runOnMachineFunction(MachineFunction &MF) { 68 SmallVector<MachineInstr *, 16> RemoveList; 69 70 for (auto &BB : MF) { 71 for (auto &MI : BB) { 72 switch (MI.getOpcode()) { 73 case NVPTX::ProxyRegI1: 74 case NVPTX::ProxyRegI16: 75 case NVPTX::ProxyRegI32: 76 case NVPTX::ProxyRegI64: 77 case NVPTX::ProxyRegF16: 78 case NVPTX::ProxyRegF16x2: 79 case NVPTX::ProxyRegF32: 80 case NVPTX::ProxyRegF64: 81 replaceMachineInstructionUsage(MF, MI); 82 RemoveList.push_back(&MI); 83 break; 84 } 85 } 86 } 87 88 for (auto *MI : RemoveList) { 89 MI->eraseFromParent(); 90 } 91 92 return !RemoveList.empty(); 93 } 94 95 void NVPTXProxyRegErasure::replaceMachineInstructionUsage(MachineFunction &MF, 96 MachineInstr &MI) { 97 auto &InOp = *MI.uses().begin(); 98 auto &OutOp = *MI.defs().begin(); 99 100 assert(InOp.isReg() && "ProxyReg input operand should be a register."); 101 assert(OutOp.isReg() && "ProxyReg output operand should be a register."); 102 103 for (auto &BB : MF) { 104 for (auto &I : BB) { 105 replaceRegisterUsage(I, OutOp, InOp); 106 } 107 } 108 } 109 110 void NVPTXProxyRegErasure::replaceRegisterUsage(MachineInstr &Instr, 111 MachineOperand &From, 112 MachineOperand &To) { 113 for (auto &Op : Instr.uses()) { 114 if (Op.isReg() && Op.getReg() == From.getReg()) { 115 Op.setReg(To.getReg()); 116 } 117 } 118 } 119 120 MachineFunctionPass *llvm::createNVPTXProxyRegErasurePass() { 121 return new NVPTXProxyRegErasure(); 122 } 123