//===- 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/ADT/PostOrderIterator.h" #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" #include "llvm/CodeGen/GlobalISel/RegisterBank.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Support/Debug.h" #include "llvm/Target/TargetSubtargetInfo.h" #define DEBUG_TYPE "regbankselect" using namespace llvm; char RegBankSelect::ID = 0; INITIALIZE_PASS(RegBankSelect, "regbankselect", "Assign register bank of generic virtual registers", false, false); RegBankSelect::RegBankSelect() : MachineFunctionPass(ID), RBI(nullptr), MRI(nullptr) { initializeRegBankSelectPass(*PassRegistry::getPassRegistry()); } void RegBankSelect::init(MachineFunction &MF) { RBI = MF.getSubtarget().getRegBankInfo(); assert(RBI && "Cannot work without RegisterBankInfo"); MRI = &MF.getRegInfo(); TRI = MF.getSubtarget().getRegisterInfo(); 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; 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; } unsigned RegBankSelect::repairReg(unsigned Reg, const RegisterBankInfo::ValueMapping &ValMapping, MachineInstr &DefUseMI, bool IsDef) { assert(ValMapping.BreakDown.size() == 1 && "Support for complex break down not supported yet"); const RegisterBankInfo::PartialMapping &PartialMap = ValMapping.BreakDown[0]; assert(PartialMap.Length == (TargetRegisterInfo::isPhysicalRegister(Reg) ? TRI->getMinimalPhysRegClass(Reg)->getSize() * 8 : MRI->getSize(Reg)) && "Repairing other than copy not implemented yet"); // If the MIRBuilder is configured to insert somewhere else than // DefUseMI, we may not use this function like was it first // internded (local repairing), so make sure we pay attention before // we remove the assert. // In particular, it is likely that we will have to properly save // the insertion point of the MIRBuilder and restore it at the end // of this method. assert(&DefUseMI == &(*MIRBuilder.getInsertPt()) && "Need to save and restore the insertion point"); // For use, we will add a copy just in front of the instruction. // For def, we will add a copy just after the instruction. // In either case, the insertion point must be valid. In particular, // make sure we do not insert in the middle of terminators or phis. bool Before = !IsDef; setSafeInsertionPoint(DefUseMI, Before); if (DefUseMI.isTerminator() && Before) { // Check that the insertion point does not happen // before the definition of Reg. // This can happen if Reg is defined by a terminator // and used by another one. // In that case the repairing code is actually more involved // because we have to split the block. // Assert that this is not a physical register. // The target independent code does not insert physical registers // on terminators, so if we end up in this situation, this is // likely a bug in the target. assert(!TargetRegisterInfo::isPhysicalRegister(Reg) && "Check for physical register not implemented"); const MachineInstr *RegDef = MRI->getVRegDef(Reg); assert(RegDef && "Reg has more than one definition?"); // Assert to make the code more readable; Reg is used by DefUseMI, i.e., // (Before == !IsDef == true), so DefUseMI != RegDef otherwise we have // a use (that is not a PHI) that is not dominated by its def. assert(&DefUseMI != RegDef && "Def does not dominate all of its uses"); if (RegDef->isTerminator() && RegDef->getParent() == DefUseMI.getParent()) // By construction, the repairing should happen between two // terminators: RegDef and DefUseMI. // This is not implemented. report_fatal_error("Repairing between terminators not implemented yet"); } // Create a new temporary to hold the repaired value. unsigned NewReg = MRI->createGenericVirtualRegister(PartialMap.Length); // Set the registers for the source and destination of the copy. unsigned Src = Reg, Dst = NewReg; // If this is a definition that we repair, the copy will be // inverted. if (IsDef) std::swap(Src, Dst); (void)MIRBuilder.buildInstr(TargetOpcode::COPY, Dst, Src); DEBUG(dbgs() << "Repair: " << PrintReg(Reg) << " with: " << PrintReg(NewReg) << '\n'); // Restore the insertion point of the MIRBuilder. MIRBuilder.setInstr(DefUseMI, Before); return NewReg; } void RegBankSelect::setSafeInsertionPoint(MachineInstr &InsertPt, bool Before) { // Check that we are not looking to insert before a phi. // Indeed, we would need more information on what to do. // By default that should be all the predecessors, but this is // probably not what we want in general. assert((!Before || !InsertPt.isPHI()) && "Insertion before phis not implemented"); // The same kind of observation hold for terminators if we try to // insert after them. assert((Before || !InsertPt.isTerminator()) && "Insertion after terminatos not implemented"); if (InsertPt.isPHI()) { assert(!Before && "Not supported!!"); MachineBasicBlock *MBB = InsertPt.getParent(); assert(MBB && "Insertion point is not in a basic block"); MachineBasicBlock::iterator FirstNonPHIPt = MBB->getFirstNonPHI(); if (FirstNonPHIPt == MBB->end()) { // If there is not any non-phi instruction, insert at the end of MBB. MIRBuilder.setMBB(*MBB, /*Beginning*/ false); return; } // The insertion point before the first non-phi instruction. MIRBuilder.setInstr(*FirstNonPHIPt, /*Before*/ true); return; } if (InsertPt.isTerminator()) { MachineBasicBlock *MBB = InsertPt.getParent(); assert(MBB && "Insertion point is not in a basic block"); MIRBuilder.setInstr(*MBB->getFirstTerminator(), /*Before*/ true); return; } MIRBuilder.setInstr(InsertPt, /*Before*/ Before); } void RegBankSelect::assignInstr(MachineInstr &MI) { DEBUG(dbgs() << "Assign: " << MI); const RegisterBankInfo::InstructionMapping DefaultMapping = RBI->getInstrMapping(MI); // Make sure the mapping is valid for MI. assert(DefaultMapping.verify(MI) && "Invalid instruction mapping"); DEBUG(dbgs() << "Mapping: " << DefaultMapping << '\n'); // 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. // For definitions, changing the register bank will affect all // its uses, and in particular the ones we already visited. // Although this is correct, since with the RPO traversal of the // basic blocks the only uses that we already visisted for this // definition are PHIs (i.e., copies), this may not be the best // solution according to the cost model. // Therefore, create a new temporary for Reg. assert(ValMapping.BreakDown.size() == 1 && "Support for complex break down not supported yet"); if (TargetRegisterInfo::isPhysicalRegister(Reg) || MRI->getRegClassOrRegBank(Reg)) { if (!MO.isDef() && MI.isPHI()) { // Phis are already copies, so there is nothing to repair. // Note: This will not hold when we support break downs with // more than one segment. DEBUG(dbgs() << "Skip PHI use\n"); continue; } // If MO is a definition, since repairing after a terminator is // painful, do not repair. Indeed, this is probably not worse // saving the move in the PHIs that will get reassigned. if (!MO.isDef() || !MI.isTerminator()) Reg = repairReg(Reg, ValMapping, MI, MO.isDef()); } // 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. DEBUG(dbgs() << "Assign: " << *ValMapping.BreakDown[0].RegBank << " to " << PrintReg(Reg) << '\n'); MRI->setRegBank(Reg, *ValMapping.BreakDown[0].RegBank); MO.setReg(Reg); } DEBUG(dbgs() << "Assigned: " << MI); } bool RegBankSelect::runOnMachineFunction(MachineFunction &MF) { DEBUG(dbgs() << "Assign register banks for: " << MF.getName() << '\n'); init(MF); // Walk the function and assign register banks to all operands. // Use a RPOT to make sure all registers are assigned before we choose // the best mapping of the current instruction. ReversePostOrderTraversal RPOT(&MF); for (MachineBasicBlock *MBB : RPOT) for (MachineInstr &MI : *MBB) assignInstr(MI); return false; }