]> Repositorios git - scryer-prolog.git/commitdiff
remove redundant register assignments in numeric comparisons (#1438, #1448)
authorMark Thom <[email protected]>
Fri, 29 Apr 2022 07:25:36 +0000 (01:25 -0600)
committerMark Thom <[email protected]>
Fri, 29 Apr 2022 15:16:22 +0000 (09:16 -0600)
src/arithmetic.rs
src/codegen.rs
src/machine/compile.rs
src/parser/ast.rs

index 70188ab8297ac2e31daed3f254796a0c7776ebc0..432926c872d341788f7af437374e8e10cac4db9e 100644 (file)
@@ -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<ArithmeticTerm>,
     interm_c: usize,
 }
@@ -184,8 +184,8 @@ fn push_literal(interm: &mut Vec<ArithmeticTerm>, 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<ArithCont, ArithmeticError>
     {
         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::<QueryInstruction>(
+                    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::<QueryInstruction>(
                             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()
                     };
index 4b3d1c26ef7388d2d9e71f00d93d0d9b5382e852..0224d2980c97bf0f5f80499a3caba10b3582e89d 100644 (file)
@@ -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<Rc<String>, 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<Item = TermRef<'a>>>(&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<String>,
@@ -241,17 +217,20 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> {
         vr: &Cell<VarReg>,
         code: &mut Code,
     ) -> RegType {
-        let mut target = Code::new();
-        self.marker.mark_var::<QueryInstruction>(name, Level::Shallow, vr, term_loc, &mut target);
+        self.mark_var::<QueryInstruction>(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<RegType> {
+        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<String>,
         arg: usize,
@@ -259,9 +238,9 @@ impl<'b, TermMarker: Allocator> CodeGenerator<'b, TermMarker> {
         vr: &Cell<VarReg>,
         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<Item = TermRef<'a>>>(&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>(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::<Target>(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<ArithCont, ArithmeticError> {
         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
             });
index bbfa1c001ce8c77dadfb646b0705b3e8e9059754..d31f14a31610e5aa53d5cd1c04ae57ae625ea928 100644 (file)
@@ -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<DebrayAllocator>,
+    cg: &mut CodeGenerator,
     tl: &TopLevel,
 ) -> Result<Code, CompilationError> {
     match tl {
@@ -87,7 +86,7 @@ pub(super) fn compile_appendix(
             non_counted_bt,
         };
 
-        let mut cg = CodeGenerator::<DebrayAllocator>::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::<DebrayAllocator>::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::<DebrayAllocator>::new(
+        let mut cg = CodeGenerator::new(
             &mut LS::machine_st(&mut self.payload).atom_tbl,
             settings,
         );
index 6f73fd55f96003393cce48db45b662f96f0c05b7..9f7288675043a5c7ab5e9bb301338497cf6190ad 100644 (file)
@@ -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 {