mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-09 11:25:55 +00:00
Allow overlaps between virtreg and physreg live ranges.
The RegisterCoalescer understands overlapping live ranges where one register is defined as a copy of the other. With this change, register allocators using LiveRegMatrix can do the same, at least for copies between physical and virtual registers. When a physreg is defined by a copy from a virtreg, allow those live ranges to overlap: %CL<def> = COPY %vreg11:sub_8bit; GR32_ABCD:%vreg11 %vreg13<def,tied1> = SAR32rCL %vreg13<tied0>, %CL<imp-use,kill> We can assign %vreg11 to %ECX, overlapping the live range of %CL. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163336 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -29,6 +29,7 @@
|
|||||||
#include <climits>
|
#include <climits>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
class CoalescerPair;
|
||||||
class LiveIntervals;
|
class LiveIntervals;
|
||||||
class MachineInstr;
|
class MachineInstr;
|
||||||
class MachineRegisterInfo;
|
class MachineRegisterInfo;
|
||||||
@@ -366,6 +367,14 @@ namespace llvm {
|
|||||||
return overlapsFrom(other, other.begin());
|
return overlapsFrom(other, other.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// overlaps - Return true if the two intervals have overlapping segments
|
||||||
|
/// that are not coalescable according to CP.
|
||||||
|
///
|
||||||
|
/// Overlapping segments where one interval is defined by a coalescable
|
||||||
|
/// copy are allowed.
|
||||||
|
bool overlaps(const LiveInterval &Other, const CoalescerPair &CP,
|
||||||
|
const SlotIndexes&) const;
|
||||||
|
|
||||||
/// overlaps - Return true if the live interval overlaps a range specified
|
/// overlaps - Return true if the live interval overlaps a range specified
|
||||||
/// by [Start, End).
|
/// by [Start, End).
|
||||||
bool overlaps(SlotIndex Start, SlotIndex End) const;
|
bool overlaps(SlotIndex Start, SlotIndex End) const;
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#include "llvm/Support/Debug.h"
|
#include "llvm/Support/Debug.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
#include "llvm/Target/TargetRegisterInfo.h"
|
#include "llvm/Target/TargetRegisterInfo.h"
|
||||||
|
#include "RegisterCoalescer.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
@@ -142,6 +143,48 @@ bool LiveInterval::overlapsFrom(const LiveInterval& other,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool LiveInterval::overlaps(const LiveInterval &Other,
|
||||||
|
const CoalescerPair &CP,
|
||||||
|
const SlotIndexes &Indexes) const {
|
||||||
|
assert(!empty() && "empty interval");
|
||||||
|
if (Other.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Use binary searches to find initial positions.
|
||||||
|
const_iterator I = find(Other.beginIndex());
|
||||||
|
const_iterator IE = end();
|
||||||
|
if (I == IE)
|
||||||
|
return false;
|
||||||
|
const_iterator J = Other.find(I->start);
|
||||||
|
const_iterator JE = Other.end();
|
||||||
|
if (J == JE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
// J has just been advanced to satisfy:
|
||||||
|
assert(J->end >= I->start);
|
||||||
|
// Check for an overlap.
|
||||||
|
if (J->start < I->end) {
|
||||||
|
// I and J are overlapping. Find the later start.
|
||||||
|
SlotIndex Def = std::max(I->start, J->start);
|
||||||
|
// Allow the overlap if Def is a coalescable copy.
|
||||||
|
if (Def.isBlock() ||
|
||||||
|
!CP.isCoalescable(Indexes.getInstructionFromIndex(Def)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Advance the iterator that ends first to check for more overlaps.
|
||||||
|
if (J->end > I->end) {
|
||||||
|
std::swap(I, J);
|
||||||
|
std::swap(IE, JE);
|
||||||
|
}
|
||||||
|
// Advance J until J->end >= I->start.
|
||||||
|
do
|
||||||
|
if (++J == JE)
|
||||||
|
return false;
|
||||||
|
while (J->end < I->start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// overlaps - Return true if the live interval overlaps a range specified
|
/// overlaps - Return true if the live interval overlaps a range specified
|
||||||
/// by [Start, End).
|
/// by [Start, End).
|
||||||
bool LiveInterval::overlaps(SlotIndex Start, SlotIndex End) const {
|
bool LiveInterval::overlaps(SlotIndex Start, SlotIndex End) const {
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#define DEBUG_TYPE "regalloc"
|
#define DEBUG_TYPE "regalloc"
|
||||||
#include "LiveRegMatrix.h"
|
#include "LiveRegMatrix.h"
|
||||||
|
#include "RegisterCoalescer.h"
|
||||||
#include "VirtRegMap.h"
|
#include "VirtRegMap.h"
|
||||||
#include "llvm/ADT/Statistic.h"
|
#include "llvm/ADT/Statistic.h"
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||||
@@ -117,8 +118,9 @@ bool LiveRegMatrix::checkRegUnitInterference(LiveInterval &VirtReg,
|
|||||||
unsigned PhysReg) {
|
unsigned PhysReg) {
|
||||||
if (VirtReg.empty())
|
if (VirtReg.empty())
|
||||||
return false;
|
return false;
|
||||||
|
CoalescerPair CP(VirtReg.reg, PhysReg, *TRI);
|
||||||
for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units)
|
for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units)
|
||||||
if (VirtReg.overlaps(LIS->getRegUnit(*Units)))
|
if (VirtReg.overlaps(LIS->getRegUnit(*Units), CP, *LIS->getSlotIndexes()))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -63,6 +63,13 @@ namespace llvm {
|
|||||||
: TRI(tri), DstReg(0), SrcReg(0), DstIdx(0), SrcIdx(0),
|
: TRI(tri), DstReg(0), SrcReg(0), DstIdx(0), SrcIdx(0),
|
||||||
Partial(false), CrossClass(false), Flipped(false), NewRC(0) {}
|
Partial(false), CrossClass(false), Flipped(false), NewRC(0) {}
|
||||||
|
|
||||||
|
/// Create a CoalescerPair representing a virtreg-to-physreg copy.
|
||||||
|
/// No need to call setRegisters().
|
||||||
|
CoalescerPair(unsigned VirtReg, unsigned PhysReg,
|
||||||
|
const TargetRegisterInfo &tri)
|
||||||
|
: TRI(tri), DstReg(PhysReg), SrcReg(VirtReg), DstIdx(0), SrcIdx(0),
|
||||||
|
Partial(false), CrossClass(false), Flipped(false), NewRC(0) {}
|
||||||
|
|
||||||
/// setRegisters - set registers to match the copy instruction MI. Return
|
/// setRegisters - set registers to match the copy instruction MI. Return
|
||||||
/// false if MI is not a coalescable copy instruction.
|
/// false if MI is not a coalescable copy instruction.
|
||||||
bool setRegisters(const MachineInstr*);
|
bool setRegisters(const MachineInstr*);
|
||||||
|
@@ -9,9 +9,8 @@ target triple = "powerpc-apple-darwin11.0"
|
|||||||
|
|
||||||
define void @foo() nounwind ssp {
|
define void @foo() nounwind ssp {
|
||||||
entry:
|
entry:
|
||||||
; Better: mtctr r12
|
; CHECK: mtctr r12
|
||||||
; CHECK: mr r12, [[REG:r[0-9]+]]
|
; CHECK: bctrl
|
||||||
; CHECK: mtctr [[REG]]
|
|
||||||
%0 = load void (...)** @p, align 4 ; <void (...)*> [#uses=1]
|
%0 = load void (...)** @p, align 4 ; <void (...)*> [#uses=1]
|
||||||
call void (...)* %0() nounwind
|
call void (...)* %0() nounwind
|
||||||
br label %return
|
br label %return
|
||||||
|
@@ -1,14 +1,10 @@
|
|||||||
; RUN: llc < %s -mtriple=i386-apple-darwin | FileCheck %s
|
; RUN: llc < %s -mtriple=i386-apple-darwin | FileCheck %s
|
||||||
; XFAIL: *
|
|
||||||
; rdar://5571034
|
; rdar://5571034
|
||||||
|
|
||||||
; This requires physreg joining, %vreg13 is live everywhere:
|
; This requires physreg joining, %vreg13 is live everywhere:
|
||||||
; 304L %CL<def> = COPY %vreg13:sub_8bit; GR32_ABCD:%vreg13
|
; 304L %CL<def> = COPY %vreg13:sub_8bit; GR32_ABCD:%vreg13
|
||||||
; 320L %vreg15<def> = COPY %vreg19; GR32:%vreg15 GR32_NOSP:%vreg19
|
; 320L %vreg15<def> = COPY %vreg19; GR32:%vreg15 GR32_NOSP:%vreg19
|
||||||
; 336L %vreg15<def> = SAR32rCL %vreg15, %EFLAGS<imp-def,dead>, %CL<imp-use,kill>; GR32:%vreg15
|
; 336L %vreg15<def> = SAR32rCL %vreg15, %EFLAGS<imp-def,dead>, %CL<imp-use,kill>; GR32:%vreg15
|
||||||
;
|
|
||||||
; This test is XFAIL until the register allocator understands trivial physreg
|
|
||||||
; interference. <rdar://9802098>
|
|
||||||
|
|
||||||
define void @foo(i32* nocapture %quadrant, i32* nocapture %ptr, i32 %bbSize, i32 %bbStart, i32 %shifts) nounwind ssp {
|
define void @foo(i32* nocapture %quadrant, i32* nocapture %ptr, i32 %bbSize, i32 %bbStart, i32 %shifts) nounwind ssp {
|
||||||
; CHECK: foo:
|
; CHECK: foo:
|
||||||
|
@@ -76,12 +76,12 @@ entry:
|
|||||||
|
|
||||||
; X32: f5:
|
; X32: f5:
|
||||||
; X32: leal {{[jk]}}@TLSLDM(%ebx)
|
; X32: leal {{[jk]}}@TLSLDM(%ebx)
|
||||||
; X32-NEXT: calll ___tls_get_addr@PLT
|
; X32: calll ___tls_get_addr@PLT
|
||||||
; X32-NEXT: movl {{[jk]}}@DTPOFF(%eax)
|
; X32: movl {{[jk]}}@DTPOFF(%e
|
||||||
; X32-NEXT: addl {{[jk]}}@DTPOFF(%eax)
|
; X32: addl {{[jk]}}@DTPOFF(%e
|
||||||
|
|
||||||
; X64: f5:
|
; X64: f5:
|
||||||
; X64: leaq {{[jk]}}@TLSLD(%rip), %rdi
|
; X64: leaq {{[jk]}}@TLSLD(%rip), %rdi
|
||||||
; X64-NEXT: callq __tls_get_addr@PLT
|
; X64: callq __tls_get_addr@PLT
|
||||||
; X64-NEXT: movl {{[jk]}}@DTPOFF(%rax)
|
; X64: movl {{[jk]}}@DTPOFF(%r
|
||||||
; X64-NEXT: addl {{[jk]}}@DTPOFF(%rax)
|
; X64: addl {{[jk]}}@DTPOFF(%r
|
||||||
|
Reference in New Issue
Block a user