#define DEBUG_TYPE "ia64-codegen"
#include "IA64.h"
#include "IA64InstrInfo.h"
#include "IA64TargetMachine.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
#include <set>
using namespace llvm;
STATISTIC(StopBitsAdded, "Number of stop bits added");
namespace {
struct IA64BundlingPass : public MachineFunctionPass {
static char ID;
IA64TargetMachine &TM;
IA64BundlingPass(IA64TargetMachine &tm)
: MachineFunctionPass(&ID), TM(tm) { }
virtual const char *getPassName() const {
return "IA64 (Itanium) Bundling Pass";
}
bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
bool runOnMachineFunction(MachineFunction &F) {
bool Changed = false;
for (MachineFunction::iterator FI = F.begin(), FE = F.end();
FI != FE; ++FI)
Changed |= runOnMachineBasicBlock(*FI);
return Changed;
}
std::set<unsigned> PendingRegWrites;
};
char IA64BundlingPass::ID = 0;
}
FunctionPass *llvm::createIA64BundlingPass(IA64TargetMachine &tm) {
return new IA64BundlingPass(tm);
}
bool IA64BundlingPass::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
bool Changed = false;
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) {
MachineInstr *CurrentInsn = I++;
std::set<unsigned> CurrentReads, CurrentWrites, OrigWrites;
for(unsigned i=0; i < CurrentInsn->getNumOperands(); i++) {
MachineOperand &MO=CurrentInsn->getOperand(i);
if (MO.isReg()) {
if(MO.isUse()) { CurrentReads.insert(MO.getReg());
}
if(MO.isDef()) { CurrentWrites.insert(MO.getReg());
OrigWrites.insert(MO.getReg()); }
}
}
set_intersect(CurrentReads, PendingRegWrites);
set_intersect(CurrentWrites, PendingRegWrites);
if(! (CurrentReads.empty() && CurrentWrites.empty()) ) {
CurrentInsn = BuildMI(MBB, CurrentInsn, CurrentInsn->getDebugLoc(),
TM.getInstrInfo()->get(IA64::STOP), 0);
PendingRegWrites=OrigWrites; Changed=true; StopBitsAdded++; } else { set_union(PendingRegWrites, OrigWrites);
}
}
return Changed;
}