//===- HexagonGatherPacketize.cpp -----------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// This pass ensures that producer and consumer of VTMP are paired in a bundle.
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "gather-packetize"
#include "HexagonTargetMachine.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
cl::opt<bool> EnableGatherPacketize(
"hexagon-enable-gather-packetize", cl::Hidden, cl::init(true),
cl::desc("Generate gather packets before packetization"));
namespace llvm {
FunctionPass *createHexagonGatherPacketize();
void initializeHexagonGatherPacketizePass(PassRegistry &);
}
namespace {
class HexagonGatherPacketize : public MachineFunctionPass {
public:
static char ID;
HexagonGatherPacketize() : MachineFunctionPass(ID) {
PassRegistry &Registry = *PassRegistry::getPassRegistry();
initializeHexagonGatherPacketizePass(Registry);
}
StringRef getPassName() const override {
return "Hexagon Gather Packetize Code";
}
bool runOnMachineFunction(MachineFunction &Fn) override;
};
char HexagonGatherPacketize::ID = 0;
static inline bool isVtmpDef(const MachineInstr &MI) {
for (const MachineOperand &MO : MI.operands())
if (MO.isReg() && MO.isDef() && MO.isImplicit() &&
(MO.getReg() == Hexagon::VTMP)) {
return true;
}
return false;
}
static inline bool isVtmpUse(const MachineInstr &MI) {
return (MI.mayStore() && (MI.getOperand(2)).isReg() &&
((MI.getOperand(2)).getReg() == Hexagon::VTMP));
}
bool HexagonGatherPacketize::runOnMachineFunction(MachineFunction &Fn) {
if (!EnableGatherPacketize)
return false;
auto &ST = Fn.getSubtarget<HexagonSubtarget>();
bool HasV65 = ST.hasV65Ops();
bool UseHVX = ST.useHVXOps();
if (!(HasV65 & UseHVX))
return false;
for (auto &MBB : Fn) {
bool VtmpDef = false;
MachineBasicBlock::iterator MII, MIE, DefMII;
for (MII = MBB.begin(), MIE = MBB.end(); MII != MIE; ++MII) {
MachineInstr &MI = *MII;
if (VtmpDef) {
if (!isVtmpUse(MI))
continue;
MBB.splice(std::next(DefMII), &MBB, MII);
finalizeBundle(MBB, DefMII.getInstrIterator(),
std::next(MII).getInstrIterator());
VtmpDef = false;
continue;
}
if (!(isVtmpDef(MI)))
continue;
VtmpDef = true;
DefMII = MII;
}
assert(!VtmpDef && "VTMP producer and consumer not in same block");
}
return true;
}
}
//===----------------------------------------------------------------------===//
// Public Constructor Functions
//===----------------------------------------------------------------------===//
INITIALIZE_PASS(HexagonGatherPacketize, "hexagon-gather-packetize",
"Hexagon gather packetize Code", false, false)
FunctionPass *llvm::createHexagonGatherPacketize() {
return new HexagonGatherPacketize();
}