| //===-- llvm/CodeGen/AllocationOrder.cpp - Allocation Order ---------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file implements an allocation order for virtual registers. |
| // |
| // The preferred allocation order for a virtual register depends on allocation |
| // hints, anti-hints, and target hooks. The AllocationOrder class encapsulates |
| // all of that. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "AllocationOrder.h" |
| #include "llvm/ADT/BitVector.h" |
| #include "llvm/CodeGen/MachineFunction.h" |
| #include "llvm/CodeGen/MachineRegisterInfo.h" |
| #include "llvm/CodeGen/RegisterClassInfo.h" |
| #include "llvm/CodeGen/VirtRegMap.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| using namespace llvm; |
| |
| #define DEBUG_TYPE "regalloc" |
| |
| static void getBitVecRegAntiHints(Register VReg, BitVector &AntiHintedRegUnits, |
| const VirtRegMap &VRM, |
| const MachineRegisterInfo &MRI, |
| const TargetRegisterInfo &TRI) { |
| assert(VReg.isVirtual() && "Anti-hints are only for virtual registers"); |
| for (Register AntiHintVReg : MRI.getRegAllocationAntiHints(VReg)) { |
| // Check if the anti-hinted register has been allocated. |
| if (!VRM.hasPhys(AntiHintVReg)) |
| continue; |
| // Delay until first allocated anti-hinted register so unused cases keep |
| // default empty BitVector. |
| if (AntiHintedRegUnits.empty()) |
| AntiHintedRegUnits.resize(TRI.getNumRegUnits()); |
| for (MCRegUnit Unit : TRI.regunits(VRM.getPhys(AntiHintVReg))) |
| AntiHintedRegUnits.set(static_cast<unsigned>(Unit)); |
| } |
| } |
| |
| // Compare VirtRegMap::getRegAllocPref(). |
| AllocationOrder AllocationOrder::create(Register VirtReg, const VirtRegMap &VRM, |
| const RegisterClassInfo &RegClassInfo, |
| const LiveRegMatrix *Matrix) { |
| const MachineFunction &MF = VRM.getMachineFunction(); |
| const TargetRegisterInfo *TRI = &VRM.getTargetRegInfo(); |
| const MachineRegisterInfo &MRI = MF.getRegInfo(); |
| auto Order = RegClassInfo.getOrder(MF.getRegInfo().getRegClass(VirtReg)); |
| // Get Hints. |
| SmallSetVector<MCPhysReg, 16> Hints; |
| bool HardHints = |
| TRI->getRegAllocationHints(VirtReg, Order, Hints, MF, &VRM, Matrix); |
| |
| // HintsAndCustomOrder holds Hints first followed by the custom order if the |
| // anti-hints reorders it. |
| SmallVector<MCPhysReg, 16> HintsAndCustomOrder = Hints.takeVector(); |
| const int NumHints = static_cast<int>(HintsAndCustomOrder.size()); |
| |
| // HintsAndCustomOrder only holds Hints (custom order is not added yet). |
| LLVM_DEBUG({ |
| if (NumHints) { |
| dbgs() << "hints:"; |
| for (MCPhysReg Hint : HintsAndCustomOrder) |
| dbgs() << ' ' << printReg(Hint, TRI); |
| dbgs() << '\n'; |
| } |
| }); |
| |
| // Get anti-hints. |
| BitVector AntiHintedRegUnits; |
| getBitVecRegAntiHints(VirtReg, AntiHintedRegUnits, VRM, MRI, *TRI); |
| |
| LLVM_DEBUG({ |
| if (AntiHintedRegUnits.any()) { |
| dbgs() << "anti-hints:"; |
| for (Register AntiHintVReg : MRI.getRegAllocationAntiHints(VirtReg)) { |
| if (!VRM.hasPhys(AntiHintVReg)) |
| continue; |
| dbgs() << ' ' << printReg(VRM.getPhys(AntiHintVReg), TRI); |
| } |
| dbgs() << '\n'; |
| } |
| }); |
| |
| if (AntiHintedRegUnits.any()) |
| TRI->applyRegAllocationAntiHints(VirtReg, Order, HintsAndCustomOrder, |
| NumHints, AntiHintedRegUnits, MF, Matrix, |
| &RegClassInfo); |
| |
| // Create allocation order object. |
| AllocationOrder AO(std::move(HintsAndCustomOrder), NumHints, Order, |
| HardHints); |
| |
| assert(all_of(AO.hints(), |
| [&](MCPhysReg Hint) { return is_contained(AO.Order, Hint); }) && |
| "Target hint is outside allocation order."); |
| return AO; |
| } |