summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorQuentin Colombet <qcolombet@apple.com>2014-01-02 22:47:22 +0000
committerQuentin Colombet <qcolombet@apple.com>2014-01-02 22:47:22 +0000
commitfb57392a8d9a2a69732d71185c7b763add493278 (patch)
tree4f14a5dad4f35590324000643a63401bab47dc07 /lib
parent79d8722b1181e19bf7ee13b17c10c061ab952912 (diff)
downloadllvm-fb57392a8d9a2a69732d71185c7b763add493278.tar.gz
llvm-fb57392a8d9a2a69732d71185c7b763add493278.tar.bz2
llvm-fb57392a8d9a2a69732d71185c7b763add493278.tar.xz
[RegAlloc] Make tryInstructionSplit less aggressive.
The greedy register allocator tries to split a live-range around each instruction where it is used or defined to relax the constraints on the entire live-range (this is a last chance split before falling back to spill). The goal is to have a big live-range that is unconstrained (i.e., that can use the largest legal register class) and several small local live-range that carry the constraints implied by each instruction. E.g., Let csti be the constraints on operation i. V1= op1 V1(cst1) op2 V1(cst2) V1 live-range is constrained on the intersection of cst1 and cst2. tryInstructionSplit relaxes those constraints by aggressively splitting each def/use point: V1= V2 = V1 V3 = V2 op1 V3(cst1) V4 = V2 op2 V4(cst2) Because of how the coalescer infrastructure works, each new variable (V3, V4) that is alive at the same time as V1 (or its copy, here V2) interfere with V1. Thus, we end up with an uncoalescable copy for each split point. To make tryInstructionSplit less aggressive, we check if the split point actually relaxes the constraints on the whole live-range. If it does not, we do not insert it. Indeed, it will not help the global allocation problem: - V1 will have the same constraints. - V1 will have the same interference + possibly the newly added split variable VS. - VS will produce an uncoalesceable copy if alive at the same time as V1. <rdar://problem/15570057> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198369 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/MachineInstr.cpp48
-rw-r--r--lib/CodeGen/MachineRegisterInfo.cpp14
-rw-r--r--lib/CodeGen/RegAllocGreedy.cpp40
3 files changed, 88 insertions, 14 deletions
diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp
index 79939d075d..e3df010312 100644
--- a/lib/CodeGen/MachineInstr.cpp
+++ b/lib/CodeGen/MachineInstr.cpp
@@ -993,6 +993,54 @@ MachineInstr::getRegClassConstraint(unsigned OpIdx,
return NULL;
}
+const TargetRegisterClass *MachineInstr::getRegClassConstraintEffectForVReg(
+ unsigned Reg, const TargetRegisterClass *CurRC, const TargetInstrInfo *TII,
+ const TargetRegisterInfo *TRI, bool ExploreBundle) const {
+ // Check every operands inside the bundle if we have
+ // been asked to.
+ if (ExploreBundle)
+ for (ConstMIBundleOperands OpndIt(this); OpndIt.isValid() && CurRC;
+ ++OpndIt)
+ CurRC = OpndIt->getParent()->getRegClassConstraintEffectForVRegImpl(
+ OpndIt.getOperandNo(), Reg, CurRC, TII, TRI);
+ else
+ // Otherwise, just check the current operands.
+ for (ConstMIOperands OpndIt(this); OpndIt.isValid() && CurRC; ++OpndIt)
+ CurRC = getRegClassConstraintEffectForVRegImpl(OpndIt.getOperandNo(), Reg,
+ CurRC, TII, TRI);
+ return CurRC;
+}
+
+const TargetRegisterClass *MachineInstr::getRegClassConstraintEffectForVRegImpl(
+ unsigned OpIdx, unsigned Reg, const TargetRegisterClass *CurRC,
+ const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const {
+ assert(CurRC && "Invalid initial register class");
+ // Check if Reg is constrained by some of its use/def from MI.
+ const MachineOperand &MO = getOperand(OpIdx);
+ if (!MO.isReg() || MO.getReg() != Reg)
+ return CurRC;
+ // If yes, accumulate the constraints through the operand.
+ return getRegClassConstraintEffect(OpIdx, CurRC, TII, TRI);
+}
+
+const TargetRegisterClass *MachineInstr::getRegClassConstraintEffect(
+ unsigned OpIdx, const TargetRegisterClass *CurRC,
+ const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const {
+ const TargetRegisterClass *OpRC = getRegClassConstraint(OpIdx, TII, TRI);
+ const MachineOperand &MO = getOperand(OpIdx);
+ assert(MO.isReg() &&
+ "Cannot get register constraints for non-register operand");
+ assert(CurRC && "Invalid initial register class");
+ if (unsigned SubIdx = MO.getSubReg()) {
+ if (OpRC)
+ CurRC = TRI->getMatchingSuperRegClass(CurRC, OpRC, SubIdx);
+ else
+ CurRC = TRI->getSubClassWithSubReg(CurRC, SubIdx);
+ } else if (OpRC)
+ CurRC = TRI->getCommonSubClass(CurRC, OpRC);
+ return CurRC;
+}
+
/// Return the number of instructions inside the MI bundle, not counting the
/// header instruction.
unsigned MachineInstr::getBundleSize() const {
diff --git a/lib/CodeGen/MachineRegisterInfo.cpp b/lib/CodeGen/MachineRegisterInfo.cpp
index f8b8796b25..bf4c23dcf7 100644
--- a/lib/CodeGen/MachineRegisterInfo.cpp
+++ b/lib/CodeGen/MachineRegisterInfo.cpp
@@ -79,17 +79,9 @@ MachineRegisterInfo::recomputeRegClass(unsigned Reg, const TargetMachine &TM) {
// Accumulate constraints from all uses.
for (reg_nodbg_iterator I = reg_nodbg_begin(Reg), E = reg_nodbg_end(); I != E;
++I) {
- const TargetRegisterClass *OpRC =
- I->getRegClassConstraint(I.getOperandNo(), TII,
- getTargetRegisterInfo());
- if (unsigned SubIdx = I.getOperand().getSubReg()) {
- if (OpRC)
- NewRC = getTargetRegisterInfo()->getMatchingSuperRegClass(NewRC, OpRC,
- SubIdx);
- else
- NewRC = getTargetRegisterInfo()->getSubClassWithSubReg(NewRC, SubIdx);
- } else if (OpRC)
- NewRC = getTargetRegisterInfo()->getCommonSubClass(NewRC, OpRC);
+ // Apply the effect of the given operand to NewRC.
+ NewRC = I->getRegClassConstraintEffect(I.getOperandNo(), NewRC, TII,
+ getTargetRegisterInfo());
if (!NewRC || NewRC == OldRC)
return false;
}
diff --git a/lib/CodeGen/RegAllocGreedy.cpp b/lib/CodeGen/RegAllocGreedy.cpp
index ca9573138c..50b7553ad1 100644
--- a/lib/CodeGen/RegAllocGreedy.cpp
+++ b/lib/CodeGen/RegAllocGreedy.cpp
@@ -35,6 +35,7 @@
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegAllocRegistry.h"
+#include "llvm/CodeGen/RegisterClassInfo.h"
#include "llvm/CodeGen/VirtRegMap.h"
#include "llvm/PassAnalysisSupport.h"
#include "llvm/Support/CommandLine.h"
@@ -70,6 +71,11 @@ class RAGreedy : public MachineFunctionPass,
// context
MachineFunction *MF;
+ // Shortcuts to some useful interface.
+ const TargetInstrInfo *TII;
+ const TargetRegisterInfo *TRI;
+ RegisterClassInfo RCI;
+
// analyses
SlotIndexes *Indexes;
MachineBlockFrequencyInfo *MBFI;
@@ -1368,6 +1374,22 @@ unsigned RAGreedy::tryBlockSplit(LiveInterval &VirtReg, AllocationOrder &Order,
// Per-Instruction Splitting
//===----------------------------------------------------------------------===//
+/// Get the number of allocatable registers that match the constraints of \p Reg
+/// on \p MI and that are also in \p SuperRC.
+static unsigned getNumAllocatableRegsForConstraints(
+ const MachineInstr *MI, unsigned Reg, const TargetRegisterClass *SuperRC,
+ const TargetInstrInfo *TII, const TargetRegisterInfo *TRI,
+ const RegisterClassInfo &RCI) {
+ assert(SuperRC && "Invalid register class");
+
+ const TargetRegisterClass *ConstrainedRC =
+ MI->getRegClassConstraintEffectForVReg(Reg, SuperRC, TII, TRI,
+ /* ExploreBundle */ true);
+ if (!ConstrainedRC)
+ return 0;
+ return RCI.getNumAllocatableRegs(ConstrainedRC);
+}
+
/// tryInstructionSplit - Split a live range around individual instructions.
/// This is normally not worthwhile since the spiller is doing essentially the
/// same thing. However, when the live range is in a constrained register
@@ -1378,8 +1400,9 @@ unsigned RAGreedy::tryBlockSplit(LiveInterval &VirtReg, AllocationOrder &Order,
unsigned
RAGreedy::tryInstructionSplit(LiveInterval &VirtReg, AllocationOrder &Order,
SmallVectorImpl<unsigned> &NewVRegs) {
+ const TargetRegisterClass *CurRC = MRI->getRegClass(VirtReg.reg);
// There is no point to this if there are no larger sub-classes.
- if (!RegClassInfo.isProperSubClass(MRI->getRegClass(VirtReg.reg)))
+ if (!RegClassInfo.isProperSubClass(CurRC))
return 0;
// Always enable split spill mode, since we're effectively spilling to a
@@ -1393,10 +1416,18 @@ RAGreedy::tryInstructionSplit(LiveInterval &VirtReg, AllocationOrder &Order,
DEBUG(dbgs() << "Split around " << Uses.size() << " individual instrs.\n");
- // Split around every non-copy instruction.
+ const TargetRegisterClass *SuperRC = TRI->getLargestLegalSuperClass(CurRC);
+ unsigned SuperRCNumAllocatableRegs = RCI.getNumAllocatableRegs(SuperRC);
+ // Split around every non-copy instruction if this split will relax
+ // the constraints on the virtual register.
+ // Otherwise, splitting just inserts uncoalescable copies that do not help
+ // the allocation.
for (unsigned i = 0; i != Uses.size(); ++i) {
if (const MachineInstr *MI = Indexes->getInstructionFromIndex(Uses[i]))
- if (MI->isFullCopy()) {
+ if (MI->isFullCopy() ||
+ SuperRCNumAllocatableRegs ==
+ getNumAllocatableRegsForConstraints(MI, VirtReg.reg, SuperRC, TII,
+ TRI, RCI)) {
DEBUG(dbgs() << " skip:\t" << Uses[i] << '\t' << *MI);
continue;
}
@@ -1843,6 +1874,9 @@ bool RAGreedy::runOnMachineFunction(MachineFunction &mf) {
<< "********** Function: " << mf.getName() << '\n');
MF = &mf;
+ TRI = MF->getTarget().getRegisterInfo();
+ TII = MF->getTarget().getInstrInfo();
+ RCI.runOnMachineFunction(mf);
if (VerifyEnabled)
MF->verify(this, "Before greedy register allocator");