blob: 4f04a258094303a37ccdfb8b9bafe987e62ccfee [file]
//===-- 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;
}