From bf92e7c02f7a804faf5fd739714947bd04a3c687 Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Fri, 18 Mar 2022 10:13:56 -0700 Subject: [PATCH] Allow pinned-vregs to be implicit liveins. (#30) Previously, the regalloc required all liveins to be defined by a pseudoinstruction at the start of the function body. The regalloc.rs compatibility shim did this, but it's slightly inconvenient when using the API directly. This change allows pinned vregs to be implicit liveins to the function body instead. --- src/ion/liveranges.rs | 22 +++++++++------------- src/lib.rs | 5 +++++ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/ion/liveranges.rs b/src/ion/liveranges.rs index fefff2f..062917c 100644 --- a/src/ion/liveranges.rs +++ b/src/ion/liveranges.rs @@ -368,19 +368,15 @@ impl<'a, F: Function> Env<'a, F> { self.liveins[block.index()] = live; } - // Check that there are no liveins to the entry block. (The - // client should create a virtual intsruction that defines any - // PReg liveins if necessary.) - if self.liveins[self.func.entry_block().index()] - .iter() - .next() - .is_some() - { - trace!( - "non-empty liveins to entry block: {:?}", - self.liveins[self.func.entry_block().index()] - ); - return Err(RegAllocError::EntryLivein); + // Check that there are no liveins to the entry block, except + // for pinned vregs. (The client should create a virtual + // instruction that defines any other liveins if necessary.) + for livein in self.liveins[self.func.entry_block().index()].iter() { + let livein = self.vreg_regs[livein]; + if self.func.is_pinned_vreg(livein).is_none() { + trace!("non-pinned-vreg livein to entry block: {}", livein); + return Err(RegAllocError::EntryLivein); + } } Ok(()) diff --git a/src/lib.rs b/src/lib.rs index 73a6c1c..29521ae 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -977,6 +977,11 @@ pub trait Function { /// liverange computation will check that this is the case (that /// there are enough remaining allocatable pregs of every class to /// hold all Reg-constrained operands). + /// + /// Pinned vregs are implicitly live-in to the function: that is, + /// one can use a pinned vreg without having first defined it, and + /// this will take the value that that physical register (to which + /// the vreg is pinned) had at function entry. fn is_pinned_vreg(&self, _: VReg) -> Option { None }