class MachineBranchProbabilityInfo;
class MachineBlockFrequencyInfo;
class MachineRegisterInfo;
+class TargetPassConfig;
class TargetRegisterInfo;
/// This pass implements the reg bank selector pass used in the GlobalISel
/// Optimization mode of the pass.
Mode OptMode;
+ /// Current target configuration. Controls how the pass handles errors.
+ const TargetPassConfig *TPC;
+
/// Assign the register bank of each operand of \p MI.
- void assignInstr(MachineInstr &MI);
+ /// \return True on success, false otherwise.
+ bool assignInstr(MachineInstr &MI);
/// Initialize the field members using \p MF.
void init(MachineFunction &MF);
///
/// \note The caller is supposed to do the rewriting of op if need be.
/// I.e., Reg = op ... => <NewRegs> = NewOp ...
- void repairReg(MachineOperand &MO,
+ ///
+ /// \return True if the repairing worked, false otherwise.
+ bool repairReg(MachineOperand &MO,
const RegisterBankInfo::ValueMapping &ValMapping,
RegBankSelect::RepairingPlacement &RepairPt,
const iterator_range<SmallVectorImpl<unsigned>::const_iterator>
/// Apply \p Mapping to \p MI. \p RepairPts represents the different
/// mapping action that need to happen for the mapping to be
/// applied.
- void applyMapping(MachineInstr &MI,
+ /// \return True if the mapping was applied sucessfully, false otherwise.
+ bool applyMapping(MachineInstr &MI,
const RegisterBankInfo::InstructionMapping &InstrMapping,
SmallVectorImpl<RepairingPlacement> &RepairPts);
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/BlockFrequency.h"
#include "llvm/Support/CommandLine.h"
false, false);
INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfo)
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
+INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
INITIALIZE_PASS_END(RegBankSelect, "regbankselect",
"Assign register bank of generic virtual registers", false,
false)
assert(RBI && "Cannot work without RegisterBankInfo");
MRI = &MF.getRegInfo();
TRI = MF.getSubtarget().getRegisterInfo();
+ TPC = &getAnalysis<TargetPassConfig>();
if (OptMode != Mode::Fast) {
MBFI = &getAnalysis<MachineBlockFrequencyInfo>();
MBPI = &getAnalysis<MachineBranchProbabilityInfo>();
AU.addRequired<MachineBlockFrequencyInfo>();
AU.addRequired<MachineBranchProbabilityInfo>();
}
+ AU.addRequired<TargetPassConfig>();
MachineFunctionPass::getAnalysisUsage(AU);
}
return CurRegBank == DesiredRegBrank;
}
-void RegBankSelect::repairReg(
+bool RegBankSelect::repairReg(
MachineOperand &MO, const RegisterBankInfo::ValueMapping &ValMapping,
RegBankSelect::RepairingPlacement &RepairPt,
const iterator_range<SmallVectorImpl<unsigned>::const_iterator> &NewVRegs) {
+ if (ValMapping.BreakDown.size() != 1 && !TPC->isGlobalISelAbortEnabled())
+ return false;
assert(ValMapping.BreakDown.size() == 1 && "Not yet implemented");
// An empty range of new register means no repairing.
assert(NewVRegs.begin() != NewVRegs.end() && "We should not have to repair");
}
// TODO:
// Legalize NewInstrs if need be.
+ return true;
}
uint64_t RegBankSelect::getRepairCost(
// TODO: use a dedicated constant for ImpossibleCost.
if (Cost != UINT_MAX)
return Cost;
- assert(false && "Legalization not available yet");
+ assert(!TPC->isGlobalISelAbortEnabled() &&
+ "Legalization not available yet");
// Return the legalization cost of that repairing.
}
- assert(false && "Complex repairing not implemented yet");
- return 1;
+ assert(!TPC->isGlobalISelAbortEnabled() &&
+ "Complex repairing not implemented yet");
+ return UINT_MAX;
}
RegisterBankInfo::InstructionMapping &RegBankSelect::findBestMapping(
MachineInstr &MI, RegisterBankInfo::InstructionMappings &PossibleMappings,
SmallVectorImpl<RepairingPlacement> &RepairPts) {
+ assert(!PossibleMappings.empty() &&
+ "Do not know how to map this instruction");
RegisterBankInfo::InstructionMapping *BestMapping = nullptr;
MappingCost Cost = MappingCost::ImpossibleCost();
RepairPts.emplace_back(std::move(RepairPt));
}
}
- assert(BestMapping && "No suitable mapping for instruction");
+ if (!BestMapping && !TPC->isGlobalISelAbortEnabled()) {
+ // If none of the mapping worked that means they are all impossible.
+ // Thus, pick the first one and set an impossible repairing point.
+ // It will trigger the failed isel mode.
+ BestMapping = &(*PossibleMappings.begin());
+ RepairPts.emplace_back(
+ RepairingPlacement(MI, 0, *TRI, *this, RepairingPlacement::Impossible));
+ } else
+ assert(BestMapping && "No suitable mapping for instruction");
return *BestMapping;
}
return Cost;
}
-void RegBankSelect::applyMapping(
+bool RegBankSelect::applyMapping(
MachineInstr &MI, const RegisterBankInfo::InstructionMapping &InstrMapping,
SmallVectorImpl<RegBankSelect::RepairingPlacement> &RepairPts) {
// OpdMapper will hold all the information needed for the rewritting.
// First, place the repairing code.
for (RepairingPlacement &RepairPt : RepairPts) {
- assert(RepairPt.canMaterialize() &&
- RepairPt.getKind() != RepairingPlacement::Impossible &&
- "This mapping is impossible");
+ if (!RepairPt.canMaterialize() ||
+ RepairPt.getKind() == RepairingPlacement::Impossible)
+ return false;
assert(RepairPt.getKind() != RepairingPlacement::None &&
"This should not make its way in the list");
unsigned OpIdx = RepairPt.getOpIdx();
break;
case RepairingPlacement::Insert:
OpdMapper.createVRegs(OpIdx);
- repairReg(MO, ValMapping, RepairPt, OpdMapper.getVRegs(OpIdx));
+ if (!repairReg(MO, ValMapping, RepairPt, OpdMapper.getVRegs(OpIdx)))
+ return false;
break;
default:
llvm_unreachable("Other kind should not happen");
// Second, rewrite the instruction.
DEBUG(dbgs() << "Actual mapping of the operands: " << OpdMapper << '\n');
RBI->applyMapping(OpdMapper);
+ return true;
}
-void RegBankSelect::assignInstr(MachineInstr &MI) {
+bool RegBankSelect::assignInstr(MachineInstr &MI) {
DEBUG(dbgs() << "Assign: " << MI);
// Remember the repairing placement for all the operands.
SmallVector<RepairingPlacement, 4> RepairPts;
BestMapping = RBI->getInstrMapping(MI);
MappingCost DefaultCost = computeMapping(MI, BestMapping, RepairPts);
(void)DefaultCost;
- assert(DefaultCost != MappingCost::ImpossibleCost() &&
- "Default mapping is not suited");
+ if (DefaultCost == MappingCost::ImpossibleCost())
+ return false;
} else {
RegisterBankInfo::InstructionMappings PossibleMappings =
RBI->getInstrPossibleMappings(MI);
- assert(!PossibleMappings.empty() &&
- "Do not know how to map this instruction");
+ if (PossibleMappings.empty())
+ return false;
BestMapping = std::move(findBestMapping(MI, PossibleMappings, RepairPts));
}
// Make sure the mapping is valid for MI.
// After this call, MI may not be valid anymore.
// Do not use it.
- applyMapping(MI, BestMapping, RepairPts);
+ return applyMapping(MI, BestMapping, RepairPts);
}
bool RegBankSelect::runOnMachineFunction(MachineFunction &MF) {
for (const MachineBasicBlock &MBB : MF) {
for (const MachineInstr &MI : MBB) {
if (isPreISelGenericOpcode(MI.getOpcode()) && !MLI->isLegal(MI)) {
+ if (!TPC->isGlobalISelAbortEnabled()) {
+ MF.getProperties().set(
+ MachineFunctionProperties::Property::FailedISel);
+ return false;
+ }
std::string ErrStorage;
raw_string_ostream Err(ErrStorage);
Err << "Instruction is not legal: " << MI << '\n';
if (isTargetSpecificOpcode(MI.getOpcode()))
continue;
- assignInstr(MI);
+ if (!assignInstr(MI)) {
+ if (TPC->isGlobalISelAbortEnabled())
+ report_fatal_error("Unable to map instruction");
+ MF.getProperties().set(MachineFunctionProperties::Property::FailedISel);
+ return false;
+ }
}
}
OptMode = SaveOptMode;