122 changes: 122 additions & 0 deletions llvm/tools/llvm-reduce/deltas/ReduceRegisterDefs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
//===- ReduceRegisterDefs.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 register uses from the MachineFunction.
//
//===----------------------------------------------------------------------===//

#include "ReduceRegisterDefs.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"

using namespace llvm;

static void removeDefsFromFunction(Oracle &O, MachineFunction &MF) {
MachineRegisterInfo &MRI = MF.getRegInfo();
const TargetSubtargetInfo &STI = MF.getSubtarget();
const TargetInstrInfo *TII = STI.getInstrInfo();

DenseSet<MachineOperand *> KeepDefs;
DenseSet<TargetInstrInfo::RegSubRegPair> DeleteDefs;

for (MachineBasicBlock &MBB : MF) {
for (MachineBasicBlock::iterator It = MBB.begin(),
E = MBB.getFirstTerminator();
It != E;) {
MachineBasicBlock::iterator InsPt = It;
MachineInstr &MI = *It;
++It;

KeepDefs.clear();
DeleteDefs.clear();

int NumOperands = MI.getNumOperands();
int NumRequiredOps = MI.getNumExplicitOperands() +
MI.getDesc().getNumImplicitDefs() +
MI.getDesc().getNumImplicitUses();

bool HaveDelete = false;
// Do an initial scan in case the instruction defines the same register
// multiple times.
for (int I = NumOperands - 1; I >= 0; --I) {
MachineOperand &MO = MI.getOperand(I);
if (!MO.isReg() || !MO.isDef())
continue;

TargetInstrInfo::RegSubRegPair RegPair(MO.getReg(), MO.getSubReg());
if (!RegPair.Reg.isVirtual())
continue;

if (O.shouldKeep())
KeepDefs.insert(&MO);
else
HaveDelete = true;
}

if (!HaveDelete)
continue;

bool HaveKeptDef = !KeepDefs.empty();
for (int I = NumOperands - 1; I >= 0; --I) {
MachineOperand &MO = MI.getOperand(I);
if (!MO.isReg() || !MO.isDef())
continue;

if (KeepDefs.count(&MO))
continue;

TargetInstrInfo::RegSubRegPair RegPair(MO.getReg(), MO.getSubReg());
if (!RegPair.Reg.isVirtual())
continue;

if (!DeleteDefs.insert(RegPair).second)
continue;

if (MRI.use_empty(RegPair.Reg)) {
if (I >= NumRequiredOps) {
// Delete implicit def operands that aren't part of the instruction
// definition
MI.removeOperand(I);
}

continue;
}

// If we aren't going to delete the instruction, replace it with a dead
// def.
if (HaveKeptDef)
MO.setReg(MRI.cloneVirtualRegister(MO.getReg()));

bool IsGeneric = MRI.getRegClassOrNull(RegPair.Reg) == nullptr;
unsigned ImpDef = IsGeneric ? TargetOpcode::G_IMPLICIT_DEF
: TargetOpcode::IMPLICIT_DEF;

unsigned OpFlags = getRegState(MO) & ~RegState::Implicit;
InsPt = BuildMI(MBB, InsPt, DebugLoc(), TII->get(ImpDef))
.addReg(RegPair.Reg, OpFlags, RegPair.SubReg);
}

if (!HaveKeptDef)
MI.eraseFromParent();
}
}
}

static void removeDefsFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
for (const Function &F : WorkItem.getModule()) {
if (auto *MF = WorkItem.MMI->getMachineFunction(F))
removeDefsFromFunction(O, *MF);
}
}

void llvm::reduceRegisterDefsMIRDeltaPass(TestRunner &Test) {
outs() << "*** Reducing register defs...\n";
runDeltaPass(Test, removeDefsFromModule);
}
23 changes: 23 additions & 0 deletions llvm/tools/llvm-reduce/deltas/ReduceRegisterDefs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//===- ReduceRegisterDefs.h - Specialized Delta Pass -----------*- C++ -*-===//
//
// 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 register defs from the MachineFunction.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEREGISTERDEFS_H
#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEREGISTERDEFS_H

#include "Delta.h"

namespace llvm {
void reduceRegisterDefsMIRDeltaPass(TestRunner &Test);
} // namespace llvm

#endif
73 changes: 73 additions & 0 deletions llvm/tools/llvm-reduce/deltas/ReduceRegisterMasks.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//===- ReduceRegisterMasks.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 custom register masks from the MachineFunction.
//
//===----------------------------------------------------------------------===//

#include "ReduceRegisterMasks.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"

using namespace llvm;

static void reduceMasksInFunction(Oracle &O, MachineFunction &MF) {
DenseSet<const uint32_t *> ConstRegisterMasks;
const auto *TRI = MF.getSubtarget().getRegisterInfo();

// Track predefined/named regmasks which we ignore.
const unsigned NumRegs = TRI->getNumRegs();
for (const uint32_t *Mask : TRI->getRegMasks())
ConstRegisterMasks.insert(Mask);

for (MachineBasicBlock &MBB : MF) {
for (MachineInstr &MI : MBB) {
for (MachineOperand &MO : MI.operands()) {
if (!MO.isRegMask())
continue;

const uint32_t *OldRegMask = MO.getRegMask();
// We're only reducing custom reg masks.
if (ConstRegisterMasks.count(OldRegMask))
continue;
unsigned RegMaskSize =
MachineOperand::getRegMaskSize(TRI->getNumRegs());
std::vector<uint32_t> NewMask(RegMaskSize);

bool MadeChange = false;
for (unsigned I = 0; I != NumRegs; ++I) {
if (OldRegMask[I / 32] >> I % 32) {
if (O.shouldKeep())
NewMask[I / 32] |= 1u << (I % 32);
} else
MadeChange = true;
}

if (MadeChange) {
uint32_t *UpdatedMask = MF.allocateRegMask();
std::memcpy(UpdatedMask, NewMask.data(),
RegMaskSize * sizeof(*OldRegMask));
MO.setRegMask(UpdatedMask);
}
}
}
}
}

static void reduceMasksInModule(Oracle &O, ReducerWorkItem &WorkItem) {
for (const Function &F : WorkItem.getModule()) {
if (auto *MF = WorkItem.MMI->getMachineFunction(F))
reduceMasksInFunction(O, *MF);
}
}

void llvm::reduceRegisterMasksMIRDeltaPass(TestRunner &Test) {
outs() << "*** Reducing register masks...\n";
runDeltaPass(Test, reduceMasksInModule);
}
18 changes: 18 additions & 0 deletions llvm/tools/llvm-reduce/deltas/ReduceRegisterMasks.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//===- ReduceRegisterMasks.h - Specialized Delta Pass ----------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEREGISTERMASKS_H
#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEREGISTERMASKS_H

#include "Delta.h"

namespace llvm {
void reduceRegisterMasksMIRDeltaPass(TestRunner &Test);
} // namespace llvm

#endif