xref: /llvm-project/llvm/lib/Target/NVPTX/NVPTXProxyRegErasure.cpp (revision ed8019d9fbed2e6a6b08f8f73e9fa54a24f3ed52)
1 //===- NVPTXProxyRegErasure.cpp - NVPTX Proxy Register Instruction Erasure -==//
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 // The pass is needed to remove ProxyReg instructions and restore related
10 // registers. The instructions were needed at instruction selection stage to
11 // make sure that callseq_end nodes won't be removed as "dead nodes". This can
12 // happen when we expand instructions into libcalls and the call site doesn't
13 // care about the libcall chain. Call site cares about data flow only, and the
14 // latest data flow node happens to be before callseq_end. Therefore the node
15 // becomes dangling and "dead". The ProxyReg acts like an additional data flow
16 // node *after* the callseq_end in the chain and ensures that everything will be
17 // preserved.
18 //
19 //===----------------------------------------------------------------------===//
20 
21 #include "NVPTX.h"
22 #include "llvm/CodeGen/MachineFunctionPass.h"
23 #include "llvm/CodeGen/TargetRegisterInfo.h"
24 
25 using namespace llvm;
26 
27 namespace llvm {
28 void initializeNVPTXProxyRegErasurePass(PassRegistry &);
29 }
30 
31 namespace {
32 
33 struct NVPTXProxyRegErasure : public MachineFunctionPass {
34   static char ID;
35   NVPTXProxyRegErasure() : MachineFunctionPass(ID) {
36     initializeNVPTXProxyRegErasurePass(*PassRegistry::getPassRegistry());
37   }
38 
39   bool runOnMachineFunction(MachineFunction &MF) override;
40 
41   StringRef getPassName() const override {
42     return "NVPTX Proxy Register Instruction Erasure";
43   }
44 
45   void getAnalysisUsage(AnalysisUsage &AU) const override {
46     MachineFunctionPass::getAnalysisUsage(AU);
47   }
48 };
49 
50 } // namespace
51 
52 char NVPTXProxyRegErasure::ID = 0;
53 
54 INITIALIZE_PASS(NVPTXProxyRegErasure, "nvptx-proxyreg-erasure",
55                 "NVPTX ProxyReg Erasure", false, false)
56 
57 bool NVPTXProxyRegErasure::runOnMachineFunction(MachineFunction &MF) {
58   SmallVector<MachineInstr *, 16> RemoveList;
59 
60   // ProxyReg instructions forward a register as another: `%dst = mov.iN %src`.
61   // Bulk RAUW the `%dst` registers in two passes over the machine function.
62   DenseMap<Register, Register> RAUWBatch;
63 
64   for (auto &BB : MF) {
65     for (auto &MI : BB) {
66       switch (MI.getOpcode()) {
67       case NVPTX::ProxyRegI1:
68       case NVPTX::ProxyRegI16:
69       case NVPTX::ProxyRegI32:
70       case NVPTX::ProxyRegI64:
71       case NVPTX::ProxyRegF32:
72       case NVPTX::ProxyRegF64: {
73         auto &InOp = *MI.uses().begin();
74         auto &OutOp = *MI.defs().begin();
75         assert(InOp.isReg() && "ProxyReg input should be a register.");
76         assert(OutOp.isReg() && "ProxyReg output should be a register.");
77         RemoveList.push_back(&MI);
78         Register replacement = InOp.getReg();
79         // Check if the replacement itself has been replaced.
80         if (auto it = RAUWBatch.find(replacement); it != RAUWBatch.end())
81           replacement = it->second;
82         RAUWBatch.try_emplace(OutOp.getReg(), replacement);
83         break;
84       }
85       }
86     }
87   }
88 
89   // If there were no proxy instructions, exit early.
90   if (RemoveList.empty())
91     return false;
92 
93   // Erase the proxy instructions first.
94   for (auto *MI : RemoveList) {
95     MI->eraseFromParent();
96   }
97 
98   // Now go replace the registers.
99   for (auto &BB : MF) {
100     for (auto &MI : BB) {
101       for (auto &Op : MI.uses()) {
102         if (!Op.isReg())
103           continue;
104         auto it = RAUWBatch.find(Op.getReg());
105         if (it != RAUWBatch.end())
106           Op.setReg(it->second);
107       }
108     }
109   }
110 
111   return true;
112 }
113 
114 MachineFunctionPass *llvm::createNVPTXProxyRegErasurePass() {
115   return new NVPTXProxyRegErasure();
116 }
117