RegisterCoalescer.cpp [plain text]
#include "llvm/CodeGen/RegisterCoalescer.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Pass.h"
using namespace llvm;
INITIALIZE_ANALYSIS_GROUP(RegisterCoalescer, "Register Coalescer",
SimpleRegisterCoalescing)
char RegisterCoalescer::ID = 0;
RegisterCoalescer::~RegisterCoalescer() {}
unsigned CoalescerPair::compose(unsigned a, unsigned b) const {
if (!a) return b;
if (!b) return a;
return tri_.composeSubRegIndices(a, b);
}
bool CoalescerPair::isMoveInstr(const MachineInstr *MI,
unsigned &Src, unsigned &Dst,
unsigned &SrcSub, unsigned &DstSub) const {
if (MI->isCopy()) {
Dst = MI->getOperand(0).getReg();
DstSub = MI->getOperand(0).getSubReg();
Src = MI->getOperand(1).getReg();
SrcSub = MI->getOperand(1).getSubReg();
} else if (MI->isSubregToReg()) {
Dst = MI->getOperand(0).getReg();
DstSub = compose(MI->getOperand(0).getSubReg(), MI->getOperand(3).getImm());
Src = MI->getOperand(2).getReg();
SrcSub = MI->getOperand(2).getSubReg();
} else
return false;
return true;
}
bool CoalescerPair::setRegisters(const MachineInstr *MI) {
srcReg_ = dstReg_ = subIdx_ = 0;
newRC_ = 0;
flipped_ = crossClass_ = false;
unsigned Src, Dst, SrcSub, DstSub;
if (!isMoveInstr(MI, Src, Dst, SrcSub, DstSub))
return false;
partial_ = SrcSub || DstSub;
if (TargetRegisterInfo::isPhysicalRegister(Src)) {
if (TargetRegisterInfo::isPhysicalRegister(Dst))
return false;
std::swap(Src, Dst);
std::swap(SrcSub, DstSub);
flipped_ = true;
}
const MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo();
if (TargetRegisterInfo::isPhysicalRegister(Dst)) {
if (DstSub) {
Dst = tri_.getSubReg(Dst, DstSub);
if (!Dst) return false;
DstSub = 0;
}
if (SrcSub) {
Dst = tri_.getMatchingSuperReg(Dst, SrcSub, MRI.getRegClass(Src));
if (!Dst) return false;
SrcSub = 0;
} else if (!MRI.getRegClass(Src)->contains(Dst)) {
return false;
}
} else {
if (SrcSub && DstSub) {
if (SrcSub != DstSub)
return false;
const TargetRegisterClass *SrcRC = MRI.getRegClass(Src);
const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
if (!getCommonSubClass(DstRC, SrcRC))
return false;
SrcSub = DstSub = 0;
}
if (SrcSub) {
std::swap(Src, Dst);
DstSub = SrcSub;
SrcSub = 0;
assert(!flipped_ && "Unexpected flip");
flipped_ = true;
}
const TargetRegisterClass *SrcRC = MRI.getRegClass(Src);
const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
if (DstSub)
newRC_ = tri_.getMatchingSuperRegClass(DstRC, SrcRC, DstSub);
else
newRC_ = getCommonSubClass(DstRC, SrcRC);
if (!newRC_)
return false;
crossClass_ = newRC_ != DstRC || newRC_ != SrcRC;
}
assert(TargetRegisterInfo::isVirtualRegister(Src) && "Src must be virtual");
assert(!(TargetRegisterInfo::isPhysicalRegister(Dst) && DstSub) &&
"Cannot have a physical SubIdx");
srcReg_ = Src;
dstReg_ = Dst;
subIdx_ = DstSub;
return true;
}
bool CoalescerPair::flip() {
if (subIdx_ || TargetRegisterInfo::isPhysicalRegister(dstReg_))
return false;
std::swap(srcReg_, dstReg_);
flipped_ = !flipped_;
return true;
}
bool CoalescerPair::isCoalescable(const MachineInstr *MI) const {
if (!MI)
return false;
unsigned Src, Dst, SrcSub, DstSub;
if (!isMoveInstr(MI, Src, Dst, SrcSub, DstSub))
return false;
if (Dst == srcReg_) {
std::swap(Src, Dst);
std::swap(SrcSub, DstSub);
} else if (Src != srcReg_) {
return false;
}
if (TargetRegisterInfo::isPhysicalRegister(dstReg_)) {
if (!TargetRegisterInfo::isPhysicalRegister(Dst))
return false;
assert(!subIdx_ && "Inconsistent CoalescerPair state.");
if (DstSub)
Dst = tri_.getSubReg(Dst, DstSub);
if (!SrcSub)
return dstReg_ == Dst;
return tri_.getSubReg(dstReg_, SrcSub) == Dst;
} else {
if (dstReg_ != Dst)
return false;
return compose(subIdx_, SrcSub) == DstSub;
}
}
DEFINING_FILE_FOR(RegisterCoalescer)