xref: /llvm-project/llvm/lib/CodeGen/GlobalISel/Localizer.cpp (revision 2946cd701067404b99c39fb29dc9c74bd7193eb3)
1 //===- Localizer.cpp ---------------------- Localize some instrs -*- C++ -*-==//
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 /// \file
9 /// This file implements the Localizer class.
10 //===----------------------------------------------------------------------===//
11 
12 #include "llvm/CodeGen/GlobalISel/Localizer.h"
13 #include "llvm/ADT/DenseMap.h"
14 #include "llvm/ADT/SmallPtrSet.h"
15 #include "llvm/CodeGen/MachineRegisterInfo.h"
16 #include "llvm/Support/Debug.h"
17 
18 #define DEBUG_TYPE "localizer"
19 
20 using namespace llvm;
21 
22 char Localizer::ID = 0;
23 INITIALIZE_PASS(Localizer, DEBUG_TYPE,
24                 "Move/duplicate certain instructions close to their use", false,
25                 false)
26 
27 Localizer::Localizer() : MachineFunctionPass(ID) {
28   initializeLocalizerPass(*PassRegistry::getPassRegistry());
29 }
30 
31 void Localizer::init(MachineFunction &MF) { MRI = &MF.getRegInfo(); }
32 
33 bool Localizer::shouldLocalize(const MachineInstr &MI) {
34   switch (MI.getOpcode()) {
35   default:
36     return false;
37   // Constants-like instructions should be close to their users.
38   // We don't want long live-ranges for them.
39   case TargetOpcode::G_CONSTANT:
40   case TargetOpcode::G_FCONSTANT:
41   case TargetOpcode::G_FRAME_INDEX:
42     return true;
43   }
44 }
45 
46 void Localizer::getAnalysisUsage(AnalysisUsage &AU) const {
47   getSelectionDAGFallbackAnalysisUsage(AU);
48   MachineFunctionPass::getAnalysisUsage(AU);
49 }
50 
51 bool Localizer::isLocalUse(MachineOperand &MOUse, const MachineInstr &Def,
52                            MachineBasicBlock *&InsertMBB) {
53   MachineInstr &MIUse = *MOUse.getParent();
54   InsertMBB = MIUse.getParent();
55   if (MIUse.isPHI())
56     InsertMBB = MIUse.getOperand(MIUse.getOperandNo(&MOUse) + 1).getMBB();
57   return InsertMBB == Def.getParent();
58 }
59 
60 bool Localizer::runOnMachineFunction(MachineFunction &MF) {
61   // If the ISel pipeline failed, do not bother running that pass.
62   if (MF.getProperties().hasProperty(
63           MachineFunctionProperties::Property::FailedISel))
64     return false;
65 
66   LLVM_DEBUG(dbgs() << "Localize instructions for: " << MF.getName() << '\n');
67 
68   init(MF);
69 
70   bool Changed = false;
71   // Keep track of the instructions we localized.
72   // We won't need to process them if we see them later in the CFG.
73   SmallPtrSet<MachineInstr *, 16> LocalizedInstrs;
74   DenseMap<std::pair<MachineBasicBlock *, unsigned>, unsigned> MBBWithLocalDef;
75   // TODO: Do bottom up traversal.
76   for (MachineBasicBlock &MBB : MF) {
77     for (MachineInstr &MI : MBB) {
78       if (LocalizedInstrs.count(&MI) || !shouldLocalize(MI))
79         continue;
80       LLVM_DEBUG(dbgs() << "Should localize: " << MI);
81       assert(MI.getDesc().getNumDefs() == 1 &&
82              "More than one definition not supported yet");
83       unsigned Reg = MI.getOperand(0).getReg();
84       // Check if all the users of MI are local.
85       // We are going to invalidation the list of use operands, so we
86       // can't use range iterator.
87       for (auto MOIt = MRI->use_begin(Reg), MOItEnd = MRI->use_end();
88            MOIt != MOItEnd;) {
89         MachineOperand &MOUse = *MOIt++;
90         // Check if the use is already local.
91         MachineBasicBlock *InsertMBB;
92         LLVM_DEBUG(MachineInstr &MIUse = *MOUse.getParent();
93                    dbgs() << "Checking use: " << MIUse
94                           << " #Opd: " << MIUse.getOperandNo(&MOUse) << '\n');
95         if (isLocalUse(MOUse, MI, InsertMBB))
96           continue;
97         LLVM_DEBUG(dbgs() << "Fixing non-local use\n");
98         Changed = true;
99         auto MBBAndReg = std::make_pair(InsertMBB, Reg);
100         auto NewVRegIt = MBBWithLocalDef.find(MBBAndReg);
101         if (NewVRegIt == MBBWithLocalDef.end()) {
102           // Create the localized instruction.
103           MachineInstr *LocalizedMI = MF.CloneMachineInstr(&MI);
104           LocalizedInstrs.insert(LocalizedMI);
105           // Don't try to be smart for the insertion point.
106           // There is no guarantee that the first seen use is the first
107           // use in the block.
108           InsertMBB->insert(InsertMBB->SkipPHIsAndLabels(InsertMBB->begin()),
109                             LocalizedMI);
110 
111           // Set a new register for the definition.
112           unsigned NewReg =
113               MRI->createGenericVirtualRegister(MRI->getType(Reg));
114           MRI->setRegClassOrRegBank(NewReg, MRI->getRegClassOrRegBank(Reg));
115           LocalizedMI->getOperand(0).setReg(NewReg);
116           NewVRegIt =
117               MBBWithLocalDef.insert(std::make_pair(MBBAndReg, NewReg)).first;
118           LLVM_DEBUG(dbgs() << "Inserted: " << *LocalizedMI);
119         }
120         LLVM_DEBUG(dbgs() << "Update use with: " << printReg(NewVRegIt->second)
121                           << '\n');
122         // Update the user reg.
123         MOUse.setReg(NewVRegIt->second);
124       }
125     }
126   }
127   return Changed;
128 }
129