mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-07 12:30:57 +00:00
d79789afc6
This re-applies r336929 with a fix to accomodate for the Mips target scheduling multiple SelectionDAG instances into the pass pipeline. PrologEpilogInserter and StackColoring depend on the StackProtector analysis being alive from the point it is run until PEI, which requires that they are all scheduled in the same FunctionPassManager. Inserting a (machine) ModulePass between StackProtector and PEI results in these passes being in separate FunctionPassManagers and the StackProtector is not available for PEI. PEI and StackColoring don't use much information from the StackProtector pass, so transfering the required information to MachineFrameInfo is cleaner than keeping the StackProtector pass around. This commit moves the SSP layout information to MFI instead of keeping it in the pass. This patch set (D37580, D37581, D37582, D37583, D37584, D37585, D37586, D37587) is a first draft of the pagerando implementation described in http://lists.llvm.org/pipermail/llvm-dev/2017-June/113794.html. Patch by Stephen Crane <sjc@immunant.com> Differential Revision: https://reviews.llvm.org/D49256 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@336964 91177308-0d34-0410-b5e6-96231b3b80d8
130 lines
4.8 KiB
C++
130 lines
4.8 KiB
C++
//===- Localizer.cpp ---------------------- Localize some instrs -*- 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 Localizer class.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/CodeGen/GlobalISel/Localizer.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#define DEBUG_TYPE "localizer"
|
|
|
|
using namespace llvm;
|
|
|
|
char Localizer::ID = 0;
|
|
INITIALIZE_PASS(Localizer, DEBUG_TYPE,
|
|
"Move/duplicate certain instructions close to their use", false,
|
|
false)
|
|
|
|
Localizer::Localizer() : MachineFunctionPass(ID) {
|
|
initializeLocalizerPass(*PassRegistry::getPassRegistry());
|
|
}
|
|
|
|
void Localizer::init(MachineFunction &MF) { MRI = &MF.getRegInfo(); }
|
|
|
|
bool Localizer::shouldLocalize(const MachineInstr &MI) {
|
|
switch (MI.getOpcode()) {
|
|
default:
|
|
return false;
|
|
// Constants-like instructions should be close to their users.
|
|
// We don't want long live-ranges for them.
|
|
case TargetOpcode::G_CONSTANT:
|
|
case TargetOpcode::G_FCONSTANT:
|
|
case TargetOpcode::G_FRAME_INDEX:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
void Localizer::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
getSelectionDAGFallbackAnalysisUsage(AU);
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
}
|
|
|
|
bool Localizer::isLocalUse(MachineOperand &MOUse, const MachineInstr &Def,
|
|
MachineBasicBlock *&InsertMBB) {
|
|
MachineInstr &MIUse = *MOUse.getParent();
|
|
InsertMBB = MIUse.getParent();
|
|
if (MIUse.isPHI())
|
|
InsertMBB = MIUse.getOperand(MIUse.getOperandNo(&MOUse) + 1).getMBB();
|
|
return InsertMBB == Def.getParent();
|
|
}
|
|
|
|
bool Localizer::runOnMachineFunction(MachineFunction &MF) {
|
|
// If the ISel pipeline failed, do not bother running that pass.
|
|
if (MF.getProperties().hasProperty(
|
|
MachineFunctionProperties::Property::FailedISel))
|
|
return false;
|
|
|
|
LLVM_DEBUG(dbgs() << "Localize instructions for: " << MF.getName() << '\n');
|
|
|
|
init(MF);
|
|
|
|
bool Changed = false;
|
|
// Keep track of the instructions we localized.
|
|
// We won't need to process them if we see them later in the CFG.
|
|
SmallPtrSet<MachineInstr *, 16> LocalizedInstrs;
|
|
DenseMap<std::pair<MachineBasicBlock *, unsigned>, unsigned> MBBWithLocalDef;
|
|
// TODO: Do bottom up traversal.
|
|
for (MachineBasicBlock &MBB : MF) {
|
|
for (MachineInstr &MI : MBB) {
|
|
if (LocalizedInstrs.count(&MI) || !shouldLocalize(MI))
|
|
continue;
|
|
LLVM_DEBUG(dbgs() << "Should localize: " << MI);
|
|
assert(MI.getDesc().getNumDefs() == 1 &&
|
|
"More than one definition not supported yet");
|
|
unsigned Reg = MI.getOperand(0).getReg();
|
|
// Check if all the users of MI are local.
|
|
// We are going to invalidation the list of use operands, so we
|
|
// can't use range iterator.
|
|
for (auto MOIt = MRI->use_begin(Reg), MOItEnd = MRI->use_end();
|
|
MOIt != MOItEnd;) {
|
|
MachineOperand &MOUse = *MOIt++;
|
|
// Check if the use is already local.
|
|
MachineBasicBlock *InsertMBB;
|
|
LLVM_DEBUG(MachineInstr &MIUse = *MOUse.getParent();
|
|
dbgs() << "Checking use: " << MIUse
|
|
<< " #Opd: " << MIUse.getOperandNo(&MOUse) << '\n');
|
|
if (isLocalUse(MOUse, MI, InsertMBB))
|
|
continue;
|
|
LLVM_DEBUG(dbgs() << "Fixing non-local use\n");
|
|
Changed = true;
|
|
auto MBBAndReg = std::make_pair(InsertMBB, Reg);
|
|
auto NewVRegIt = MBBWithLocalDef.find(MBBAndReg);
|
|
if (NewVRegIt == MBBWithLocalDef.end()) {
|
|
// Create the localized instruction.
|
|
MachineInstr *LocalizedMI = MF.CloneMachineInstr(&MI);
|
|
LocalizedInstrs.insert(LocalizedMI);
|
|
// Don't try to be smart for the insertion point.
|
|
// There is no guarantee that the first seen use is the first
|
|
// use in the block.
|
|
InsertMBB->insert(InsertMBB->SkipPHIsAndLabels(InsertMBB->begin()),
|
|
LocalizedMI);
|
|
|
|
// Set a new register for the definition.
|
|
unsigned NewReg =
|
|
MRI->createGenericVirtualRegister(MRI->getType(Reg));
|
|
MRI->setRegClassOrRegBank(NewReg, MRI->getRegClassOrRegBank(Reg));
|
|
LocalizedMI->getOperand(0).setReg(NewReg);
|
|
NewVRegIt =
|
|
MBBWithLocalDef.insert(std::make_pair(MBBAndReg, NewReg)).first;
|
|
LLVM_DEBUG(dbgs() << "Inserted: " << *LocalizedMI);
|
|
}
|
|
LLVM_DEBUG(dbgs() << "Update use with: " << printReg(NewVRegIt->second)
|
|
<< '\n');
|
|
// Update the user reg.
|
|
MOUse.setReg(NewVRegIt->second);
|
|
}
|
|
}
|
|
}
|
|
return Changed;
|
|
}
|