From: Mark Thom Date: Fri, 29 Apr 2022 07:25:36 +0000 (-0600) Subject: remove redundant register assignments in numeric comparisons (#1438, #1448) X-Git-Tag: v0.9.1~43 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=72536037caeec32609fd5c8c3b42cdb6322cea42;p=scryer-prolog.git remove redundant register assignments in numeric comparisons (#1438, #1448) --- diff --git a/src/arithmetic.rs b/src/arithmetic.rs index 70188ab8..432926c8 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -1,7 +1,7 @@ use crate::allocator::*; use crate::arena::*; use crate::atom_table::*; -use crate::fixtures::*; +use crate::debray_allocator::*; use crate::forms::*; use crate::instructions::*; use crate::iterators::*; @@ -143,8 +143,8 @@ impl<'a> Iterator for ArithInstructionIterator<'a> { } #[derive(Debug)] -pub(crate) struct ArithmeticEvaluator<'a, TermMarker> { - marker: &'a mut TermMarker, +pub(crate) struct ArithmeticEvaluator<'a> { + marker: &'a mut DebrayAllocator, interm: Vec, interm_c: usize, } @@ -184,8 +184,8 @@ fn push_literal(interm: &mut Vec, c: &Literal) -> Result<(), Ari Ok(()) } -impl<'a, TermMarker: Allocator> ArithmeticEvaluator<'a, TermMarker> { - pub(crate) fn new(marker: &'a mut TermMarker, target_int: usize) -> Self { +impl<'a> ArithmeticEvaluator<'a> { + pub(crate) fn new(marker: &'a mut DebrayAllocator, target_int: usize) -> Self { ArithmeticEvaluator { marker, interm: Vec::new(), @@ -317,6 +317,7 @@ impl<'a, TermMarker: Allocator> ArithmeticEvaluator<'a, TermMarker> { &mut self, src: &'a Term, term_loc: GenContext, + arg: usize, ) -> Result { let mut code = vec![]; @@ -326,18 +327,15 @@ impl<'a, TermMarker: Allocator> ArithmeticEvaluator<'a, TermMarker> { match term_ref? { ArithTermRef::Literal(c) => push_literal(&mut self.interm, c)?, ArithTermRef::Var(lvl, cell, name) => { - let r = if lvl == Level::Shallow && term_loc.is_last() { - self.marker.mark_var::( + let r = if lvl == Level::Shallow { + self.marker.mark_non_callable( name.clone(), - lvl, - cell, + arg, term_loc, + cell, &mut code, - ); - - self.interm.push(ArithmeticTerm::Reg(temp_v!(2))); - continue; - } else if cell.get().norm().reg_num() == 0 { + ) + } else if term_loc.is_last() || cell.get().norm().reg_num() == 0 { self.marker.mark_var::( name.clone(), lvl, @@ -346,15 +344,7 @@ impl<'a, TermMarker: Allocator> ArithmeticEvaluator<'a, TermMarker> { &mut code, ); - match self.marker.bindings().get(&name) { - Some(&VarData::Temp(_, t, _)) if t != 0 => - RegType::Temp(t), - Some(&VarData::Perm(p)) if p != 0 => - RegType::Perm(p), - _ => { - unreachable!() - } - } + self.marker.get_binding(&name).unwrap() } else { cell.get().norm() }; diff --git a/src/codegen.rs b/src/codegen.rs index 4b3d1c26..0224d298 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -4,6 +4,7 @@ use crate::{perm_v, temp_v}; use crate::allocator::*; use crate::arithmetic::*; +use crate::debray_allocator::*; use crate::fixtures::*; use crate::forms::*; use crate::indexing::*; @@ -198,9 +199,9 @@ impl CodeGenSettings { } #[derive(Debug)] -pub(crate) struct CodeGenerator<'a, TermMarker> { +pub(crate) struct CodeGenerator<'a> { pub(crate) atom_tbl: &'a mut AtomTable, - marker: TermMarker, + marker: DebrayAllocator, pub(crate) var_count: IndexMap, usize>, settings: CodeGenSettings, pub(crate) skeleton: PredicateSkeleton, @@ -208,32 +209,7 @@ pub(crate) struct CodeGenerator<'a, TermMarker> { global_jmp_by_locs_offset: usize, } -impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { - pub(crate) fn new(atom_tbl: &'b mut AtomTable, settings: CodeGenSettings) -> Self { - CodeGenerator { - atom_tbl, - marker: Allocator::new(), - var_count: IndexMap::new(), - settings, - skeleton: PredicateSkeleton::new(), - jmp_by_locs: vec![], - global_jmp_by_locs_offset: 0, - } - } - - fn update_var_count<'a, Iter: Iterator>>(&mut self, iter: Iter) { - for term in iter { - if let TermRef::Var(_, _, var) = term { - let entry = self.var_count.entry(var).or_insert(0); - *entry += 1; - } - } - } - - fn get_var_count(&self, var: &String) -> usize { - *self.var_count.get(var).unwrap() - } - +impl DebrayAllocator { fn mark_var_in_non_callable( &mut self, name: Rc, @@ -241,17 +217,20 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { vr: &Cell, code: &mut Code, ) -> RegType { - let mut target = Code::new(); - self.marker.mark_var::(name, Level::Shallow, vr, term_loc, &mut target); + self.mark_var::(name, Level::Shallow, vr, term_loc, code); + vr.get().norm() + } - if !target.is_empty() { - code.extend(target.into_iter()); + #[inline(always)] + pub(crate) fn get_binding(&self, name: &String) -> Option { + match self.bindings().get(name) { + Some(&VarData::Temp(_, t, _)) if t != 0 => Some(RegType::Temp(t)), + Some(&VarData::Perm(p)) if p != 0 => Some(RegType::Perm(p)), + _ => None, } - - vr.get().norm() } - fn mark_non_callable( + pub(crate) fn mark_non_callable( &mut self, name: Rc, arg: usize, @@ -259,9 +238,9 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { vr: &Cell, code: &mut Code, ) -> RegType { - match self.marker.bindings().get(&name) { - Some(&VarData::Temp(_, t, _)) if t != 0 => RegType::Temp(t), - Some(&VarData::Perm(p)) if p != 0 => { + match self.get_binding(&name) { + Some(RegType::Temp(t)) => RegType::Temp(t), + Some(RegType::Perm(p)) => { if let GenContext::Last(_) = term_loc { self.mark_var_in_non_callable(name.clone(), term_loc, vr, code); temp_v!(arg) @@ -269,9 +248,36 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { RegType::Perm(p) } } - _ => self.mark_var_in_non_callable(name, term_loc, vr, code), + None => self.mark_var_in_non_callable(name, term_loc, vr, code), } } +} + +impl<'b> CodeGenerator<'b> { + pub(crate) fn new(atom_tbl: &'b mut AtomTable, settings: CodeGenSettings) -> Self { + CodeGenerator { + atom_tbl, + marker: DebrayAllocator::new(), + var_count: IndexMap::new(), + settings, + skeleton: PredicateSkeleton::new(), + jmp_by_locs: vec![], + global_jmp_by_locs_offset: 0, + } + } + + fn update_var_count<'a, Iter: Iterator>>(&mut self, iter: Iter) { + for term in iter { + if let TermRef::Var(_, _, var) = term { + let entry = self.var_count.entry(var).or_insert(0); + *entry += 1; + } + } + } + + fn get_var_count(&self, var: &String) -> usize { + *self.var_count.get(var).unwrap() + } fn add_or_increment_void_instr<'a, Target>(target: &mut Code) where @@ -316,9 +322,9 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { &Term::AnonVar => { Self::add_or_increment_void_instr::(target); } - &Term::Cons(ref cell, ..) - | &Term::Clause(ref cell, ..) - | Term::PartialString(ref cell, ..) => { + &Term::Cons(ref cell, ..) | + &Term::Clause(ref cell, ..) | + Term::PartialString(ref cell, ..) => { self.marker.mark_non_var::(Level::Deep, term_loc, cell, target); target.push(Target::clause_arg_to_instr(cell.get())); } @@ -501,36 +507,39 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { &InlinedClauseType::CompareNumber(mut cmp) => { self.marker.reset_arg(2); - let (mut lcode, at_1) = self.compile_arith_expr(&terms[0], 1, term_loc)?; - let (mut rcode, at_2) = self.compile_arith_expr(&terms[1], 2, term_loc)?; + let (mut lcode, at_1) = self.compile_arith_expr(&terms[0], 1, term_loc, 1)?; - let at_1 = if let &Term::Var(ref vr, ref name) = &terms[0] { - ArithmeticTerm::Reg(self.mark_non_callable(name.clone(), 1, term_loc, vr, code)) - } else { + if !matches!(terms[0], Term::Var(..)) { self.marker.advance_arg(); - at_1.unwrap_or(interm!(1)) - }; + } - let at_2 = if let &Term::Var(ref vr, ref name) = &terms[1] { - ArithmeticTerm::Reg(self.mark_non_callable(name.clone(), 2, term_loc, vr, code)) - } else { - at_2.unwrap_or(interm!(2)) - }; + let (mut rcode, at_2) = self.compile_arith_expr(&terms[1], 2, term_loc, 2)?; code.append(&mut lcode); code.append(&mut rcode); + let at_1 = at_1.unwrap_or(interm!(1)); + let at_2 = at_2.unwrap_or(interm!(2)); + code.push(compare_number_instr!(cmp, at_1, at_2)); } &InlinedClauseType::IsAtom(..) => match &terms[0] { - &Term::Literal(_, Literal::Char(_)) - | &Term::Literal(_, Literal::Atom(atom!("[]"))) - | &Term::Literal(_, Literal::Atom(..)) => { + &Term::Literal(_, Literal::Char(_)) | + &Term::Literal(_, Literal::Atom(atom!("[]"))) | + &Term::Literal(_, Literal::Atom(..)) => { code.push(instr!("$succeed", 0)); } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); - let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); + + let r = self.marker.mark_non_callable( + name.clone(), + 1, + term_loc, + vr, + code, + ); + code.push(instr!("atom", r, 0)); } _ => { @@ -538,7 +547,10 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { } }, &InlinedClauseType::IsAtomic(..) => match &terms[0] { - &Term::AnonVar | &Term::Clause(..) | &Term::Cons(..) | &Term::PartialString(..) => { + &Term::AnonVar | + &Term::Clause(..) | + &Term::Cons(..) | + &Term::PartialString(..) => { code.push(instr!("$fail", 0)); } &Term::Literal(_, Literal::String(_)) => { @@ -549,18 +561,36 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); - let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); + + let r = self.marker.mark_non_callable( + name.clone(), + 1, + term_loc, + vr, + code, + ); + code.push(instr!("atomic", r, 0)); } }, &InlinedClauseType::IsCompound(..) => match &terms[0] { - &Term::Clause(..) | &Term::Cons(..) | &Term::PartialString(..) | + &Term::Clause(..) | + &Term::Cons(..) | + &Term::PartialString(..) | &Term::Literal(_, Literal::String(..)) => { code.push(instr!("$succeed", 0)); } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); - let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); + + let r = self.marker.mark_non_callable( + name.clone(), + 1, + term_loc, + vr, + code, + ); + code.push(instr!("compound", r, 0)); } _ => { @@ -573,7 +603,7 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); - let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); + let r = self.marker.mark_non_callable(name.clone(), 1, term_loc, vr, code); code.push(instr!("rational", r, 0)); } _ => { @@ -586,7 +616,15 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); - let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); + + let r = self.marker.mark_non_callable( + name.clone(), + 1, + term_loc, + vr, + code, + ); + code.push(instr!("float", r, 0)); } _ => { @@ -594,15 +632,23 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { } }, &InlinedClauseType::IsNumber(..) => match &terms[0] { - &Term::Literal(_, Literal::Float(_)) - | &Term::Literal(_, Literal::Rational(_)) - | &Term::Literal(_, Literal::Integer(_)) - | &Term::Literal(_, Literal::Fixnum(_)) => { + &Term::Literal(_, Literal::Float(_)) | + &Term::Literal(_, Literal::Rational(_)) | + &Term::Literal(_, Literal::Integer(_)) | + &Term::Literal(_, Literal::Fixnum(_)) => { code.push(instr!("$succeed", 0)); } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); - let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); + + let r = self.marker.mark_non_callable( + name.clone(), + 1, + term_loc, + vr, + code, + ); + code.push(instr!("number", r, 0)); } _ => { @@ -615,7 +661,15 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); - let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); + + let r = self.marker.mark_non_callable( + name.clone(), + 1, + term_loc, + vr, + code, + ); + code.push(instr!("nonvar", r, 0)); } _ => { @@ -623,12 +677,21 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { } }, &InlinedClauseType::IsInteger(..) => match &terms[0] { - &Term::Literal(_, Literal::Integer(_)) | &Term::Literal(_, Literal::Fixnum(_)) => { + &Term::Literal(_, Literal::Integer(_)) | + &Term::Literal(_, Literal::Fixnum(_)) => { code.push(instr!("$succeed", 0)); } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); - let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); + + let r = self.marker.mark_non_callable( + name.clone(), + 1, + term_loc, + vr, + code, + ); + code.push(instr!("integer", r, 0)); } _ => { @@ -636,10 +699,10 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { } }, &InlinedClauseType::IsVar(..) => match &terms[0] { - &Term::Literal(..) - | &Term::Clause(..) - | &Term::Cons(..) - | &Term::PartialString(..) => { + &Term::Literal(..) | + &Term::Clause(..) | + &Term::Cons(..) | + &Term::PartialString(..) => { code.push(instr!("$fail", 0)); } &Term::AnonVar => { @@ -647,7 +710,15 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { } &Term::Var(ref vr, ref name) => { self.marker.reset_arg(1); - let r = self.mark_non_callable(name.clone(), 1, term_loc, vr, code); + + let r = self.marker.mark_non_callable( + name.clone(), + 1, + term_loc, + vr, + code, + ); + code.push(instr!("var", r, 0)); } }, @@ -661,9 +732,10 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { term: &Term, target_int: usize, term_loc: GenContext, + arg: usize, ) -> Result { let mut evaluator = ArithmeticEvaluator::new(&mut self.marker, target_int); - evaluator.compile_is(term, term_loc) + evaluator.compile_is(term, term_loc, arg) } fn compile_is_call( @@ -675,7 +747,7 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> { ) -> Result<(), CompilationError> { macro_rules! compile_expr { ($self:expr, $terms:expr, $term_loc:expr, $code:expr) => ({ - let (acode, at) = $self.compile_arith_expr(&$terms[1], 1, $term_loc)?; + let (acode, at) = $self.compile_arith_expr(&$terms[1], 1, $term_loc, 2)?; $code.extend(acode.into_iter()); at }); diff --git a/src/machine/compile.rs b/src/machine/compile.rs index bbfa1c00..d31f14a3 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -1,6 +1,5 @@ use crate::atom_table::*; use crate::codegen::*; -use crate::debray_allocator::*; use crate::forms::*; use crate::indexing::{merge_clause_index, remove_index}; use crate::instructions::*; @@ -47,7 +46,7 @@ pub(super) fn bootstrapping_compile( // throw errors if declaration or query found. pub(super) fn compile_relation( - cg: &mut CodeGenerator, + cg: &mut CodeGenerator, tl: &TopLevel, ) -> Result { match tl { @@ -87,7 +86,7 @@ pub(super) fn compile_appendix( non_counted_bt, }; - let mut cg = CodeGenerator::::new(atom_tbl, settings); + let mut cg = CodeGenerator::new(atom_tbl, settings); let tl = queue.pop_front().unwrap(); let decl_code = compile_relation(&mut cg, &tl)?; @@ -1345,7 +1344,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { let clause = self.try_term_to_tl(term, &mut preprocessor)?; let queue = preprocessor.parse_queue(self)?; - let mut cg = CodeGenerator::::new( + let mut cg = CodeGenerator::new( &mut LS::machine_st(&mut self.payload).atom_tbl, settings, ); @@ -1388,7 +1387,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { let queue = preprocessor.parse_queue(self)?; - let mut cg = CodeGenerator::::new( + let mut cg = CodeGenerator::new( &mut LS::machine_st(&mut self.payload).atom_tbl, settings, ); diff --git a/src/parser/ast.rs b/src/parser/ast.rs index 6f73fd55..9f728867 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -489,7 +489,7 @@ impl Fixnum { .with_num(u64::from_ne_bytes(num.to_ne_bytes()) & ((1 << 56) - 1)) .with_tag(HeapCellValueTag::Fixnum as u8) .with_m(false) - //num as u64).with__m(false) + .with_f(false) } #[inline] @@ -500,6 +500,7 @@ impl Fixnum { if LOWER_BOUND <= num && num <= UPPER_BOUND { Ok(Fixnum::new() .with_m(false) + .with_f(false) .with_tag(HeapCellValueTag::Fixnum as u8) .with_num(u64::from_ne_bytes(num.to_ne_bytes()) & ((1 << 56) - 1))) } else {