diff --git a/lib/cretonne/meta/cdsl/isa.py b/lib/cretonne/meta/cdsl/isa.py index f1125f59da..9239bf2f70 100644 --- a/lib/cretonne/meta/cdsl/isa.py +++ b/lib/cretonne/meta/cdsl/isa.py @@ -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): diff --git a/lib/cretonne/meta/cdsl/registers.py b/lib/cretonne/meta/cdsl/registers.py index c16e760a5c..caaacd20e4 100644 --- a/lib/cretonne/meta/cdsl/registers.py +++ b/lib/cretonne/meta/cdsl/registers.py @@ -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 """ diff --git a/lib/cretonne/meta/gen_registers.py b/lib/cretonne/meta/gen_registers.py index 4199dce268..463364709a 100644 --- a/lib/cretonne/meta/gen_registers.py +++ b/lib/cretonne/meta/gen_registers.py @@ -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[{}];' diff --git a/lib/cretonne/src/isa/registers.rs b/lib/cretonne/src/isa/registers.rs index 461309a9e9..a4527733c5 100644 --- a/lib/cretonne/src/isa/registers.rs +++ b/lib/cretonne/src/isa/registers.rs @@ -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, diff --git a/lib/cretonne/src/regalloc/allocatable_set.rs b/lib/cretonne/src/regalloc/allocatable_set.rs index fa3e7a9153..756ad1d349 100644 --- a/lib/cretonne/src/regalloc/allocatable_set.rs +++ b/lib/cretonne/src/regalloc/allocatable_set.rs @@ -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],