2016-04-06 03:06:01 +08:00
|
|
|
//===- llvm/CodeGen/GlobalISel/RegBankSelect.cpp - RegBankSelect -*- C++ -*-==//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// \file
|
|
|
|
/// This file implements the RegBankSelect class.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
|
2016-04-08 02:19:27 +08:00
|
|
|
#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
|
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2016-04-08 07:53:55 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
2016-04-08 02:19:27 +08:00
|
|
|
#include "llvm/Target/TargetSubtargetInfo.h"
|
2016-04-06 03:06:01 +08:00
|
|
|
|
|
|
|
#define DEBUG_TYPE "regbankselect"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
char RegBankSelect::ID = 0;
|
|
|
|
INITIALIZE_PASS(RegBankSelect, "regbankselect",
|
|
|
|
"Assign register bank of generic virtual registers",
|
|
|
|
false, false);
|
|
|
|
|
2016-04-08 02:19:27 +08:00
|
|
|
RegBankSelect::RegBankSelect()
|
|
|
|
: MachineFunctionPass(ID), RBI(nullptr), MRI(nullptr) {
|
2016-04-06 03:06:01 +08:00
|
|
|
initializeRegBankSelectPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
|
|
|
|
2016-04-08 02:19:27 +08:00
|
|
|
void RegBankSelect::init(MachineFunction &MF) {
|
|
|
|
RBI = MF.getSubtarget().getRegBankInfo();
|
|
|
|
assert(RBI && "Cannot work without RegisterBankInfo");
|
|
|
|
MRI = &MF.getRegInfo();
|
2016-04-08 05:32:23 +08:00
|
|
|
TRI = MF.getSubtarget().getRegisterInfo();
|
2016-04-08 02:19:27 +08:00
|
|
|
MIRBuilder.setMF(MF);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RegBankSelect::assignmentMatch(
|
|
|
|
unsigned Reg, const RegisterBankInfo::ValueMapping &ValMapping) const {
|
|
|
|
// Each part of a break down needs to end up in a different register.
|
|
|
|
// In other word, Reg assignement does not match.
|
|
|
|
if (ValMapping.BreakDown.size() > 1)
|
|
|
|
return false;
|
|
|
|
|
2016-04-09 00:48:16 +08:00
|
|
|
const RegisterBank *CurRegBank = RBI->getRegBank(Reg, *MRI, *TRI);
|
|
|
|
const RegisterBank *DesiredRegBrank = ValMapping.BreakDown[0].RegBank;
|
|
|
|
DEBUG(dbgs() << "Does assignment already match: ";
|
|
|
|
if (CurRegBank) dbgs() << *CurRegBank; else dbgs() << "none";
|
|
|
|
dbgs() << " against ";
|
|
|
|
assert(DesiredRegBrank && "The mapping must be valid");
|
|
|
|
dbgs() << *DesiredRegBrank << '\n';);
|
|
|
|
return CurRegBank == DesiredRegBrank;
|
2016-04-08 02:19:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned
|
|
|
|
RegBankSelect::repairReg(unsigned Reg,
|
|
|
|
const RegisterBankInfo::ValueMapping &ValMapping) {
|
|
|
|
assert(ValMapping.BreakDown.size() == 1 &&
|
|
|
|
"Support for complex break down not supported yet");
|
|
|
|
const RegisterBankInfo::PartialMapping &PartialMap = ValMapping.BreakDown[0];
|
|
|
|
assert(PartialMap.Mask.getBitWidth() == MRI->getSize(Reg) &&
|
|
|
|
"Repairing other than copy not implemented yet");
|
|
|
|
unsigned NewReg =
|
|
|
|
MRI->createGenericVirtualRegister(PartialMap.Mask.getBitWidth());
|
|
|
|
(void)MIRBuilder.buildInstr(TargetOpcode::COPY, NewReg, Reg);
|
2016-04-08 07:53:55 +08:00
|
|
|
DEBUG(dbgs() << "Repair: " << PrintReg(Reg) << " with: "
|
|
|
|
<< PrintReg(NewReg) << '\n');
|
2016-04-08 02:19:27 +08:00
|
|
|
return NewReg;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RegBankSelect::assignInstr(MachineInstr &MI) {
|
2016-04-08 07:53:55 +08:00
|
|
|
DEBUG(dbgs() << "Assign: " << MI);
|
2016-04-08 02:19:27 +08:00
|
|
|
const RegisterBankInfo::InstructionMapping DefaultMapping =
|
|
|
|
RBI->getInstrMapping(MI);
|
|
|
|
// Make sure the mapping is valid for MI.
|
|
|
|
DefaultMapping.verify(MI);
|
2016-04-08 07:53:55 +08:00
|
|
|
|
|
|
|
DEBUG(dbgs() << "Mapping: " << DefaultMapping << '\n');
|
|
|
|
|
2016-04-08 02:19:27 +08:00
|
|
|
// Set the insertion point before MI.
|
|
|
|
// This is where we are going to insert the repairing code if any.
|
|
|
|
MIRBuilder.setInstr(MI, /*Before*/ true);
|
|
|
|
|
|
|
|
// For now, do not look for alternative mappings.
|
|
|
|
// Alternative mapping may require to rewrite MI and we do not support
|
|
|
|
// that yet.
|
|
|
|
// Walk the operands and assign then to the chosen mapping, possibly with
|
|
|
|
// the insertion of repair code for uses.
|
|
|
|
for (unsigned OpIdx = 0, EndIdx = MI.getNumOperands(); OpIdx != EndIdx;
|
|
|
|
++OpIdx) {
|
|
|
|
MachineOperand &MO = MI.getOperand(OpIdx);
|
|
|
|
// Nothing to be done for non-register operands.
|
|
|
|
if (!MO.isReg())
|
|
|
|
continue;
|
|
|
|
unsigned Reg = MO.getReg();
|
|
|
|
if (!Reg)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
const RegisterBankInfo::ValueMapping &ValMapping =
|
|
|
|
DefaultMapping.getOperandMapping(OpIdx);
|
|
|
|
// If Reg is already properly mapped, move on.
|
|
|
|
if (assignmentMatch(Reg, ValMapping))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// For uses, we may need to create a new temporary.
|
|
|
|
// Indeed, if Reg is already assigned a register bank, at this
|
|
|
|
// point, we know it is different from the one defined by the
|
|
|
|
// chosen mapping, we need to adjust for that.
|
|
|
|
assert(ValMapping.BreakDown.size() == 1 &&
|
|
|
|
"Support for complex break down not supported yet");
|
|
|
|
if (!MO.isDef() && MRI->getRegClassOrRegBank(Reg)) {
|
|
|
|
// For phis, we need to change the insertion point to the end of
|
|
|
|
// the related predecessor block.
|
|
|
|
assert(!MI.isPHI() && "PHI support not implemented yet");
|
|
|
|
Reg = repairReg(Reg, ValMapping);
|
|
|
|
}
|
|
|
|
// If we end up here, MO should be free of encoding constraints,
|
|
|
|
// i.e., we do not have to constrained the RegBank of Reg to
|
|
|
|
// the requirement of the operands.
|
|
|
|
// If that is not the case, this means the code was broken before
|
|
|
|
// hands because we should have found that the assignment match.
|
|
|
|
// This will not hold when we will consider alternative mappings.
|
2016-04-09 00:48:16 +08:00
|
|
|
DEBUG(dbgs() << "Assign: " << *ValMapping.BreakDown[0].RegBank << " to "
|
|
|
|
<< PrintReg(Reg) << '\n');
|
2016-04-08 02:19:27 +08:00
|
|
|
MRI->setRegBank(Reg, *ValMapping.BreakDown[0].RegBank);
|
|
|
|
MO.setReg(Reg);
|
|
|
|
}
|
2016-04-08 07:53:55 +08:00
|
|
|
DEBUG(dbgs() << "Assigned: " << MI);
|
2016-04-08 02:19:27 +08:00
|
|
|
}
|
|
|
|
|
2016-04-06 03:06:01 +08:00
|
|
|
bool RegBankSelect::runOnMachineFunction(MachineFunction &MF) {
|
2016-04-08 07:53:55 +08:00
|
|
|
DEBUG(dbgs() << "Assign register banks for: " << MF.getName() << '\n');
|
2016-04-08 02:19:27 +08:00
|
|
|
init(MF);
|
|
|
|
// Walk the function and assign register banks to all operands.
|
|
|
|
for (MachineBasicBlock &MBB : MF)
|
|
|
|
for (MachineInstr &MI : MBB)
|
|
|
|
assignInstr(MI);
|
2016-04-06 03:06:01 +08:00
|
|
|
return false;
|
|
|
|
}
|