11462faadSDan Gohman //===-- WebAssemblyRegColoring.cpp - Register coloring --------------------===//
21462faadSDan Gohman //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61462faadSDan Gohman //
71462faadSDan Gohman //===----------------------------------------------------------------------===//
81462faadSDan Gohman ///
91462faadSDan Gohman /// \file
105f8f34e4SAdrian Prantl /// This file implements a virtual register coloring pass.
111462faadSDan Gohman ///
121462faadSDan Gohman /// WebAssembly doesn't have a fixed number of registers, but it is still
131462faadSDan Gohman /// desirable to minimize the total number of registers used in each function.
141462faadSDan Gohman ///
151462faadSDan Gohman /// This code is modeled after lib/CodeGen/StackSlotColoring.cpp.
161462faadSDan Gohman ///
171462faadSDan Gohman //===----------------------------------------------------------------------===//
181462faadSDan Gohman
191462faadSDan Gohman #include "WebAssembly.h"
201462faadSDan Gohman #include "WebAssemblyMachineFunctionInfo.h"
21f842297dSMatthias Braun #include "llvm/CodeGen/LiveIntervals.h"
221462faadSDan Gohman #include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
231462faadSDan Gohman #include "llvm/CodeGen/MachineRegisterInfo.h"
241462faadSDan Gohman #include "llvm/CodeGen/Passes.h"
251462faadSDan Gohman #include "llvm/Support/Debug.h"
261462faadSDan Gohman #include "llvm/Support/raw_ostream.h"
271462faadSDan Gohman using namespace llvm;
281462faadSDan Gohman
291462faadSDan Gohman #define DEBUG_TYPE "wasm-reg-coloring"
301462faadSDan Gohman
311462faadSDan Gohman namespace {
321462faadSDan Gohman class WebAssemblyRegColoring final : public MachineFunctionPass {
331462faadSDan Gohman public:
341462faadSDan Gohman static char ID; // Pass identification, replacement for typeid
WebAssemblyRegColoring()351462faadSDan Gohman WebAssemblyRegColoring() : MachineFunctionPass(ID) {}
361462faadSDan Gohman
getPassName() const37117296c0SMehdi Amini StringRef getPassName() const override {
381462faadSDan Gohman return "WebAssembly Register Coloring";
391462faadSDan Gohman }
401462faadSDan Gohman
getAnalysisUsage(AnalysisUsage & AU) const411462faadSDan Gohman void getAnalysisUsage(AnalysisUsage &AU) const override {
421462faadSDan Gohman AU.setPreservesCFG();
431462faadSDan Gohman AU.addRequired<LiveIntervals>();
441462faadSDan Gohman AU.addRequired<MachineBlockFrequencyInfo>();
451462faadSDan Gohman AU.addPreserved<MachineBlockFrequencyInfo>();
461462faadSDan Gohman AU.addPreservedID(MachineDominatorsID);
471462faadSDan Gohman MachineFunctionPass::getAnalysisUsage(AU);
481462faadSDan Gohman }
491462faadSDan Gohman
501462faadSDan Gohman bool runOnMachineFunction(MachineFunction &MF) override;
511462faadSDan Gohman
521462faadSDan Gohman private:
531462faadSDan Gohman };
541462faadSDan Gohman } // end anonymous namespace
551462faadSDan Gohman
561462faadSDan Gohman char WebAssemblyRegColoring::ID = 0;
5740926451SJacob Gravelle INITIALIZE_PASS(WebAssemblyRegColoring, DEBUG_TYPE,
5840926451SJacob Gravelle "Minimize number of registers used", false, false)
5940926451SJacob Gravelle
createWebAssemblyRegColoring()601462faadSDan Gohman FunctionPass *llvm::createWebAssemblyRegColoring() {
611462faadSDan Gohman return new WebAssemblyRegColoring();
621462faadSDan Gohman }
631462faadSDan Gohman
641462faadSDan Gohman // Compute the total spill weight for VReg.
computeWeight(const MachineRegisterInfo * MRI,const MachineBlockFrequencyInfo * MBFI,unsigned VReg)651462faadSDan Gohman static float computeWeight(const MachineRegisterInfo *MRI,
661462faadSDan Gohman const MachineBlockFrequencyInfo *MBFI,
671462faadSDan Gohman unsigned VReg) {
6818c56a07SHeejin Ahn float Weight = 0.0f;
691462faadSDan Gohman for (MachineOperand &MO : MRI->reg_nodbg_operands(VReg))
7018c56a07SHeejin Ahn Weight += LiveIntervals::getSpillWeight(MO.isDef(), MO.isUse(), MBFI,
711afd1e2bSJF Bastien *MO.getParent());
7218c56a07SHeejin Ahn return Weight;
731462faadSDan Gohman }
741462faadSDan Gohman
runOnMachineFunction(MachineFunction & MF)751462faadSDan Gohman bool WebAssemblyRegColoring::runOnMachineFunction(MachineFunction &MF) {
76d34e60caSNicola Zaghen LLVM_DEBUG({
771462faadSDan Gohman dbgs() << "********** Register Coloring **********\n"
781462faadSDan Gohman << "********** Function: " << MF.getName() << '\n';
791462faadSDan Gohman });
801462faadSDan Gohman
811462faadSDan Gohman // If there are calls to setjmp or sigsetjmp, don't perform coloring. Virtual
821462faadSDan Gohman // registers could be modified before the longjmp is executed, resulting in
831462faadSDan Gohman // the wrong value being used afterwards. (See <rdar://problem/8007500>.)
841462faadSDan Gohman // TODO: Does WebAssembly need to care about setjmp for register coloring?
851462faadSDan Gohman if (MF.exposesReturnsTwice())
861462faadSDan Gohman return false;
871462faadSDan Gohman
881462faadSDan Gohman MachineRegisterInfo *MRI = &MF.getRegInfo();
891462faadSDan Gohman LiveIntervals *Liveness = &getAnalysis<LiveIntervals>();
901462faadSDan Gohman const MachineBlockFrequencyInfo *MBFI =
911462faadSDan Gohman &getAnalysis<MachineBlockFrequencyInfo>();
921462faadSDan Gohman WebAssemblyFunctionInfo &MFI = *MF.getInfo<WebAssemblyFunctionInfo>();
931462faadSDan Gohman
941462faadSDan Gohman // Gather all register intervals into a list and sort them.
951462faadSDan Gohman unsigned NumVRegs = MRI->getNumVirtRegs();
961462faadSDan Gohman SmallVector<LiveInterval *, 0> SortedIntervals;
971462faadSDan Gohman SortedIntervals.reserve(NumVRegs);
981462faadSDan Gohman
99d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Interesting register intervals:\n");
10018c56a07SHeejin Ahn for (unsigned I = 0; I < NumVRegs; ++I) {
101*d6b07348SJim Lin Register VReg = Register::index2VirtReg(I);
1021462faadSDan Gohman if (MFI.isVRegStackified(VReg))
1031462faadSDan Gohman continue;
10471008090SDan Gohman // Skip unused registers, which can use $drop.
1057054ac1bSDan Gohman if (MRI->use_empty(VReg))
1067054ac1bSDan Gohman continue;
1071462faadSDan Gohman
1081462faadSDan Gohman LiveInterval *LI = &Liveness->getInterval(VReg);
1096e85c3d5SMircea Trofin assert(LI->weight() == 0.0f);
1106e85c3d5SMircea Trofin LI->setWeight(computeWeight(MRI, MBFI, VReg));
111d34e60caSNicola Zaghen LLVM_DEBUG(LI->dump());
1121462faadSDan Gohman SortedIntervals.push_back(LI);
1131462faadSDan Gohman }
114d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << '\n');
1151462faadSDan Gohman
1161462faadSDan Gohman // Sort them to put arguments first (since we don't want to rename live-in
1171462faadSDan Gohman // registers), by weight next, and then by position.
1181462faadSDan Gohman // TODO: Investigate more intelligent sorting heuristics. For starters, we
1191462faadSDan Gohman // should try to coalesce adjacent live intervals before non-adjacent ones.
1200cac726aSFangrui Song llvm::sort(SortedIntervals, [MRI](LiveInterval *LHS, LiveInterval *RHS) {
1216e85c3d5SMircea Trofin if (MRI->isLiveIn(LHS->reg()) != MRI->isLiveIn(RHS->reg()))
1226e85c3d5SMircea Trofin return MRI->isLiveIn(LHS->reg());
1236e85c3d5SMircea Trofin if (LHS->weight() != RHS->weight())
1246e85c3d5SMircea Trofin return LHS->weight() > RHS->weight();
1251462faadSDan Gohman if (LHS->empty() || RHS->empty())
1261462faadSDan Gohman return !LHS->empty() && RHS->empty();
1271462faadSDan Gohman return *LHS < *RHS;
1281462faadSDan Gohman });
1291462faadSDan Gohman
130d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "Coloring register intervals:\n");
1311462faadSDan Gohman SmallVector<unsigned, 16> SlotMapping(SortedIntervals.size(), -1u);
1321462faadSDan Gohman SmallVector<SmallVector<LiveInterval *, 4>, 16> Assignments(
1331462faadSDan Gohman SortedIntervals.size());
1341462faadSDan Gohman BitVector UsedColors(SortedIntervals.size());
1351462faadSDan Gohman bool Changed = false;
13618c56a07SHeejin Ahn for (size_t I = 0, E = SortedIntervals.size(); I < E; ++I) {
13718c56a07SHeejin Ahn LiveInterval *LI = SortedIntervals[I];
138*d6b07348SJim Lin Register Old = LI->reg();
13918c56a07SHeejin Ahn size_t Color = I;
1401462faadSDan Gohman const TargetRegisterClass *RC = MRI->getRegClass(Old);
1411462faadSDan Gohman
1421462faadSDan Gohman // Check if it's possible to reuse any of the used colors.
1431462faadSDan Gohman if (!MRI->isLiveIn(Old))
144b52e0366SFrancis Visoiu Mistrih for (unsigned C : UsedColors.set_bits()) {
1456e85c3d5SMircea Trofin if (MRI->getRegClass(SortedIntervals[C]->reg()) != RC)
1461462faadSDan Gohman continue;
1471462faadSDan Gohman for (LiveInterval *OtherLI : Assignments[C])
1481462faadSDan Gohman if (!OtherLI->empty() && OtherLI->overlaps(*LI))
1491462faadSDan Gohman goto continue_outer;
1501462faadSDan Gohman Color = C;
1511462faadSDan Gohman break;
1521462faadSDan Gohman continue_outer:;
1531462faadSDan Gohman }
1541462faadSDan Gohman
155*d6b07348SJim Lin Register New = SortedIntervals[Color]->reg();
15618c56a07SHeejin Ahn SlotMapping[I] = New;
1571462faadSDan Gohman Changed |= Old != New;
1581462faadSDan Gohman UsedColors.set(Color);
1591462faadSDan Gohman Assignments[Color].push_back(LI);
160d966bf83SDerek Schuff // If we reassigned the stack pointer, update the debug frame base info.
161d966bf83SDerek Schuff if (Old != New && MFI.isFrameBaseVirtual() && MFI.getFrameBaseVreg() == Old)
162d966bf83SDerek Schuff MFI.setFrameBaseVreg(New);
1636e85c3d5SMircea Trofin LLVM_DEBUG(dbgs() << "Assigning vreg" << Register::virtReg2Index(LI->reg())
1642bea69bfSDaniel Sanders << " to vreg" << Register::virtReg2Index(New) << "\n");
1651462faadSDan Gohman }
1661462faadSDan Gohman if (!Changed)
1671462faadSDan Gohman return false;
1681462faadSDan Gohman
1691462faadSDan Gohman // Rewrite register operands.
17018c56a07SHeejin Ahn for (size_t I = 0, E = SortedIntervals.size(); I < E; ++I) {
171*d6b07348SJim Lin Register Old = SortedIntervals[I]->reg();
17218c56a07SHeejin Ahn unsigned New = SlotMapping[I];
1731462faadSDan Gohman if (Old != New)
1741462faadSDan Gohman MRI->replaceRegWith(Old, New);
1751462faadSDan Gohman }
1761462faadSDan Gohman return true;
1771462faadSDan Gohman }
178