Compute top-level register classes for each register bank.

A top-level register class is one that has no sub-classes. It is
possible to have multiple top-level register classes in the same
register bank. For example, ARM's FPR bank has both D and Q top-level
register classes.

Number register classes such that all top-level register classes appear
as a contiguous sequence starting from 0. This will be used by the
register allocator when counting used registers per top-level register
class.
This commit is contained in:
Jakob Stoklund Olesen
2017-05-15 13:39:59 -07:00
parent 621f3a2f50
commit 71bb7483b7
5 changed files with 66 additions and 24 deletions

View File

@@ -42,6 +42,7 @@ class TargetISA(object):
self.instruction_groups = instruction_groups
self.cpumodes = list() # type: List[CPUMode]
self.regbanks = list() # type: List[RegBank]
self.regclasses = list() # type: List[RegClass]
def finish(self):
# type: () -> TargetISA
@@ -109,11 +110,23 @@ class TargetISA(object):
Every register class needs a unique index, and the classes need to be
topologically ordered.
We also want all the top-level register classes to be first.
"""
rc_index = 0
# Compute subclasses and top-level classes in each bank.
# Collect the top-level classes so they get numbered consecutively.
for bank in self.regbanks:
bank.finish_regclasses(rc_index)
rc_index += len(bank.classes)
bank.finish_regclasses()
self.regclasses.extend(bank.toprcs)
# Collect all of the non-top-level register classes.
# They are numbered strictly after the top-level classes.
for bank in self.regbanks:
self.regclasses.extend(
rc for rc in bank.classes if not rc.is_toprc())
for idx, rc in enumerate(self.regclasses):
rc.index = idx
class CPUMode(object):

View File

@@ -75,6 +75,8 @@ class RegBank(object):
self.prefix = prefix
self.names = names
self.classes = list() # type: List[RegClass]
self.toprcs = list() # type: List[RegClass]
self.first_toprc_index = None # type: int
assert len(names) <= units
@@ -95,11 +97,10 @@ class RegBank(object):
return ('RegBank({}, units={}, first_unit={})'
.format(self.name, self.units, self.first_unit))
def finish_regclasses(self, first_index):
# type: (int) -> None
def finish_regclasses(self):
# type: () -> None
"""
Assign indexes to the register classes in this bank, starting from
`first_index`.
Compute subclasses and the top-level register class.
Verify that the set of register classes satisfies:
@@ -115,14 +116,10 @@ class RegBank(object):
"""
cmap = dict() # type: Dict[RCTup, RegClass]
for idx, rc in enumerate(self.classes):
for rc in self.classes:
# All register classes must be given a name.
assert rc.name, "Anonymous register class found"
# Assign a unique index.
assert rc.index is None
rc.index = idx + first_index
# Check for duplicates.
tup = rc.rctup()
if tup in cmap:
@@ -133,6 +130,7 @@ class RegBank(object):
# Check intersections and topological order.
for idx, rc1 in enumerate(self.classes):
rc1.toprc = rc1
for rc2 in self.classes[0:idx]:
itup = rc1.intersect(rc2)
if itup is None:
@@ -151,6 +149,10 @@ class RegBank(object):
# The intersection of rc1 and rc2 is rc1, so it must be a
# sub-class.
rc2.subclasses.append(rc1)
rc1.toprc = rc2.toprc
if rc1.is_toprc():
self.toprcs.append(rc1)
def unit_by_name(self, name):
# type: (str) -> int
@@ -192,6 +194,7 @@ class RegClass(object):
# This is computed later in `finish_regclasses()`.
self.subclasses = list() # type: List[RegClass]
self.toprc = None # type: RegClass
assert width > 0
assert start >= 0 and start < bank.units
@@ -206,6 +209,16 @@ class RegClass(object):
# type: () -> str
return self.name
def is_toprc(self):
# type: () -> bool
"""
Is this a top-level register class?
A top-level register class has no sub-classes. This can only be
answered aster running `finish_regclasses()`.
"""
return self.toprc is self
def rctup(self):
# type: () -> RCTup
"""

View File

@@ -19,13 +19,15 @@ def gen_regbank(regbank, fmt):
Emit a static data definition for regbank.
"""
with fmt.indented('RegBank {', '},'):
fmt.line('name: "{}",'.format(regbank.name))
fmt.line('first_unit: {},'.format(regbank.first_unit))
fmt.line('units: {},'.format(regbank.units))
fmt.line(
'names: &[{}],'
.format(', '.join('"{}"'.format(n) for n in regbank.names)))
fmt.line('prefix: "{}",'.format(regbank.prefix))
fmt.format('name: "{}",', regbank.name)
fmt.format('first_unit: {},', regbank.first_unit)
fmt.format('units: {},', regbank.units)
fmt.format(
'names: &[{}],',
', '.join('"{}"'.format(n) for n in regbank.names))
fmt.format('prefix: "{}",', regbank.prefix)
fmt.format('first_toprc: {},', regbank.toprcs[0].index)
fmt.format('num_toprcs: {},', len(regbank.toprcs))
def gen_regclass(rc, fmt):
@@ -38,6 +40,7 @@ def gen_regclass(rc, fmt):
fmt.format('index: {},', rc.index)
fmt.format('width: {},', rc.width)
fmt.format('bank: {},', rc.bank.index)
fmt.format('toprc: {},', rc.toprc.index)
fmt.format('first: {},', rc.bank.first_unit + rc.start)
fmt.format('subclasses: 0x{:x},', rc.subclass_mask())
mask = ', '.join('0x{:08x}'.format(x) for x in rc.mask())
@@ -52,24 +55,23 @@ def gen_isa(isa, fmt):
if not isa.regbanks:
print('cargo:warning={} has no register banks'.format(isa.name))
rcs = list() # type: List[RegClass]
with fmt.indented('pub static INFO: RegInfo = RegInfo {', '};'):
# Bank descriptors.
with fmt.indented('banks: &[', '],'):
for regbank in isa.regbanks:
gen_regbank(regbank, fmt)
rcs += regbank.classes
fmt.line('classes: &CLASSES,')
# Register class descriptors.
with fmt.indented(
'const CLASSES: [RegClassData; {}] = ['.format(len(rcs)), '];'):
for idx, rc in enumerate(rcs):
'const CLASSES: [RegClassData; {}] = ['
.format(len(isa.regclasses)), '];'):
for idx, rc in enumerate(isa.regclasses):
assert idx == rc.index
gen_regclass(rc, fmt)
# Emit constants referencing the register classes.
for rc in rcs:
for rc in isa.regclasses:
fmt.line('#[allow(dead_code)]')
fmt.line(
'pub const {}: RegClass = &CLASSES[{}];'

View File

@@ -42,6 +42,15 @@ pub struct RegBank {
/// The remaining register units will be named this prefix followed by their decimal offset in
/// the bank. So with a prefix `r`, registers will be named `r8`, `r9`, ...
pub prefix: &'static str,
/// Index of the first top-level register class in this bank.
pub first_toprc: usize,
/// Number of top-level register classes in this bank.
///
/// The top-level register classes in a bank are guaranteed to be numbered sequentially from
/// `first_toprc`, and all top-level register classes across banks come before any sub-classes.
pub num_toprcs: usize,
}
impl RegBank {
@@ -111,6 +120,9 @@ pub struct RegClassData {
/// Index of the register bank this class belongs to.
pub bank: u8,
/// Index of the top-level register class contains this one.
pub toprc: u8,
/// The first register unit in this class.
pub first: RegUnit,

View File

@@ -141,6 +141,7 @@ mod tests {
index: 0,
width: 1,
bank: 0,
toprc: 0,
first: 28,
subclasses: 0,
mask: [0xf0000000, 0x0000000f, 0],
@@ -150,6 +151,7 @@ mod tests {
index: 0,
width: 2,
bank: 0,
toprc: 0,
first: 28,
subclasses: 0,
mask: [0x50000000, 0x0000000a, 0],