mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-10 17:07:06 +00:00
ce665bd2e2
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@115996 91177308-0d34-0410-b5e6-96231b3b80d8
197 lines
6.3 KiB
C++
197 lines
6.3 KiB
C++
//===- RegisterCoalescer.cpp - Generic Register Coalescing Interface -------==//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the generic RegisterCoalescer interface which
|
|
// is used as the common interface used by all clients and
|
|
// implementations of register coalescing.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#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;
|
|
|
|
// Register the RegisterCoalescer interface, providing a nice name to refer to.
|
|
INITIALIZE_ANALYSIS_GROUP(RegisterCoalescer, "Register Coalescer")
|
|
char RegisterCoalescer::ID = 0;
|
|
|
|
// RegisterCoalescer destructor: DO NOT move this to the header file
|
|
// for RegisterCoalescer or else clients of the RegisterCoalescer
|
|
// class may not depend on the RegisterCoalescer.o file in the current
|
|
// .a file, causing alias analysis support to not be included in the
|
|
// tool correctly!
|
|
//
|
|
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 one register is a physreg, it must be Dst.
|
|
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)) {
|
|
// Eliminate DstSub on a physreg.
|
|
if (DstSub) {
|
|
Dst = tri_.getSubReg(Dst, DstSub);
|
|
if (!Dst) return false;
|
|
DstSub = 0;
|
|
}
|
|
|
|
// Eliminate SrcSub by picking a corresponding Dst superregister.
|
|
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 {
|
|
// Both registers are virtual.
|
|
|
|
// Both registers have subreg indices.
|
|
if (SrcSub && DstSub) {
|
|
// For now we only handle the case of identical indices in commensurate
|
|
// registers: Dreg:ssub_1 + Dreg:ssub_1 -> Dreg
|
|
// FIXME: Handle Qreg:ssub_3 + Dreg:ssub_1 as QReg:dsub_1 + Dreg.
|
|
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;
|
|
}
|
|
|
|
// There can be no SrcSub.
|
|
if (SrcSub) {
|
|
std::swap(Src, Dst);
|
|
DstSub = SrcSub;
|
|
SrcSub = 0;
|
|
assert(!flipped_ && "Unexpected flip");
|
|
flipped_ = true;
|
|
}
|
|
|
|
// Find the new register class.
|
|
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;
|
|
}
|
|
// Check our invariants
|
|
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;
|
|
|
|
// Find the virtual register that is srcReg_.
|
|
if (Dst == srcReg_) {
|
|
std::swap(Src, Dst);
|
|
std::swap(SrcSub, DstSub);
|
|
} else if (Src != srcReg_) {
|
|
return false;
|
|
}
|
|
|
|
// Now check that Dst matches dstReg_.
|
|
if (TargetRegisterInfo::isPhysicalRegister(dstReg_)) {
|
|
if (!TargetRegisterInfo::isPhysicalRegister(Dst))
|
|
return false;
|
|
assert(!subIdx_ && "Inconsistent CoalescerPair state.");
|
|
// DstSub could be set for a physreg from INSERT_SUBREG.
|
|
if (DstSub)
|
|
Dst = tri_.getSubReg(Dst, DstSub);
|
|
// Full copy of Src.
|
|
if (!SrcSub)
|
|
return dstReg_ == Dst;
|
|
// This is a partial register copy. Check that the parts match.
|
|
return tri_.getSubReg(dstReg_, SrcSub) == Dst;
|
|
} else {
|
|
// dstReg_ is virtual.
|
|
if (dstReg_ != Dst)
|
|
return false;
|
|
// Registers match, do the subregisters line up?
|
|
return compose(subIdx_, SrcSub) == DstSub;
|
|
}
|
|
}
|
|
|
|
// Because of the way .a files work, we must force the SimpleRC
|
|
// implementation to be pulled in if the RegisterCoalescer classes are
|
|
// pulled in. Otherwise we run the risk of RegisterCoalescer being
|
|
// used, but the default implementation not being linked into the tool
|
|
// that uses it.
|
|
DEFINING_FILE_FOR(RegisterCoalescer)
|