Having a separate counting method runs the risk of a mismatch between the actual reduction method and the counting method. Instead, create an Oracle that always returns true for shouldKeep(), run the reduction, and count how many times shouldKeep() was called. The module should not be modified if shouldKeep() always returns true. Reviewed By: Meinersbur Differential Revision: https://reviews.llvm.org/D113537
126 lines
3.9 KiB
C++
126 lines
3.9 KiB
C++
//===- ReduceInstructionsMIR.cpp - Specialized Delta Pass -----------------===//
|
|
//
|
|
// 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 a function which calls the Generic Delta pass in order
|
|
// to reduce uninteresting MachineInstr from the MachineFunction.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "ReduceInstructionsMIR.h"
|
|
|
|
#include "llvm/CodeGen/MachineDominators.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
#include "llvm/CodeGen/TargetInstrInfo.h"
|
|
|
|
using namespace llvm;
|
|
|
|
static Register getPrevDefOfRCInMBB(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::reverse_iterator &RI,
|
|
const TargetRegisterClass *RC,
|
|
SetVector<MachineInstr *> &ExcludeMIs) {
|
|
auto MRI = &MBB.getParent()->getRegInfo();
|
|
for (MachineBasicBlock::reverse_instr_iterator E = MBB.instr_rend(); RI != E;
|
|
++RI) {
|
|
auto &MI = *RI;
|
|
// All Def operands explicit and implicit.
|
|
for (auto &MO : MI.operands()) {
|
|
if (!MO.isReg() || !MO.isDef())
|
|
continue;
|
|
auto Reg = MO.getReg();
|
|
if (Register::isPhysicalRegister(Reg))
|
|
continue;
|
|
|
|
if (MRI->getRegClass(Reg) == RC && !ExcludeMIs.count(MO.getParent()))
|
|
return Reg;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void extractInstrFromModule(Oracle &O, MachineFunction &MF) {
|
|
MachineDominatorTree MDT;
|
|
MDT.runOnMachineFunction(MF);
|
|
|
|
auto MRI = &MF.getRegInfo();
|
|
SetVector<MachineInstr *> ToDelete;
|
|
|
|
MachineInstr *TopMI = nullptr;
|
|
|
|
// Mark MIs for deletion according to some criteria.
|
|
for (auto &MBB : MF) {
|
|
for (auto &MI : MBB) {
|
|
if (MI.isTerminator())
|
|
continue;
|
|
if (MBB.isEntryBlock() && !TopMI) {
|
|
TopMI = &MI;
|
|
continue;
|
|
}
|
|
if (!O.shouldKeep())
|
|
ToDelete.insert(&MI);
|
|
}
|
|
}
|
|
|
|
// For each MI to be deleted update users of regs defined by that MI to use
|
|
// some other dominating definition (that is not to be deleted).
|
|
for (auto *MI : ToDelete) {
|
|
for (auto &MO : MI->operands()) {
|
|
if (!MO.isReg() || !MO.isDef())
|
|
continue;
|
|
auto Reg = MO.getReg();
|
|
if (Register::isPhysicalRegister(Reg))
|
|
continue;
|
|
auto UI = MRI->use_begin(Reg);
|
|
auto UE = MRI->use_end();
|
|
|
|
auto RegRC = MRI->getRegClass(Reg);
|
|
Register NewReg = 0;
|
|
// If this is not a physical register and there are some uses.
|
|
if (UI != UE) {
|
|
MachineBasicBlock::reverse_iterator RI(*MI);
|
|
MachineBasicBlock *BB = MI->getParent();
|
|
++RI;
|
|
while (NewReg == 0 && BB) {
|
|
NewReg = getPrevDefOfRCInMBB(*BB, RI, RegRC, ToDelete);
|
|
// Prepare for idom(BB).
|
|
if (auto *IDM = MDT.getNode(BB)->getIDom()) {
|
|
BB = IDM->getBlock();
|
|
RI = BB->rbegin();
|
|
} else {
|
|
BB = nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If no dominating definition was found then add an implicit one to the
|
|
// first instruction in the entry block.
|
|
if (!NewReg && TopMI) {
|
|
NewReg = MRI->createVirtualRegister(RegRC);
|
|
TopMI->addOperand(MachineOperand::CreateReg(
|
|
NewReg, true /*IsDef*/, true /*IsImp*/, false /*IsKill*/));
|
|
}
|
|
|
|
// Update all uses.
|
|
while (UI != UE) {
|
|
auto &UMO = *UI++;
|
|
UMO.setReg(NewReg);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Finally delete the MIs.
|
|
for (auto *MI : ToDelete)
|
|
MI->eraseFromParent();
|
|
}
|
|
|
|
void llvm::reduceInstructionsMIRDeltaPass(TestRunner &Test) {
|
|
outs() << "*** Reducing Instructions...\n";
|
|
runDeltaPass(Test, extractInstrFromModule);
|
|
}
|