Skip to content

Commit 453a88f

Browse files
authored
Merge pull request #3211 from mthom/setof_correction_and_opt
Correct and optimize setof/3 and bagof/3
2 parents 4e8f338 + c79fd74 commit 453a88f

17 files changed

Lines changed: 699 additions & 772 deletions

build/instructions_template.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -643,11 +643,6 @@ enum SystemClauseType {
643643
UnattributedVar,
644644
#[strum_discriminants(strum(props(Arity = "4", Name = "$get_db_refs")))]
645645
GetDBRefs,
646-
#[strum_discriminants(strum(props(
647-
Arity = "2",
648-
Name = "$keysort_with_constant_var_ordering"
649-
)))]
650-
KeySortWithConstantVarOrdering,
651646
#[strum_discriminants(strum(props(Arity = "0", Name = "$inference_limit_exceeded")))]
652647
InferenceLimitExceeded,
653648
#[strum_discriminants(strum(props(Arity = "1", Name = "$argv")))]

src/codegen.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,10 @@ impl CodeGenerator {
639639
}
640640
},
641641
InlinedClauseType::IsRational(..) => match terms[0] {
642-
Term::Literal(_, Literal::Rational(_)) => {
642+
Term::Literal(
643+
_,
644+
Literal::Rational(_) | Literal::Fixnum(_) | Literal::Integer(_),
645+
) => {
643646
instr!("$succeed")
644647
}
645648
Term::Var(ref vr, ref name) => {
@@ -679,10 +682,13 @@ impl CodeGenerator {
679682
}
680683
},
681684
InlinedClauseType::IsNumber(..) => match terms[0] {
682-
Term::Literal(_, Literal::F64(..))
683-
| Term::Literal(_, Literal::Rational(_))
684-
| Term::Literal(_, Literal::Integer(_))
685-
| Term::Literal(_, Literal::Fixnum(_)) => {
685+
Term::Literal(
686+
_,
687+
Literal::F64(..)
688+
| Literal::Rational(_)
689+
| Literal::Integer(_)
690+
| Literal::Fixnum(_),
691+
) => {
686692
instr!("$succeed")
687693
}
688694
Term::Var(ref vr, ref name) => {
@@ -988,20 +994,27 @@ impl CodeGenerator {
988994
self.marker.in_tail_position = false;
989995
self.marker.reset_contents();
990996
}
991-
ClauseItem::FirstBranch(num_branches) => {
997+
ClauseItem::FirstBranch {
998+
branch_num,
999+
num_branches,
1000+
} => {
9921001
branch_code_stack.add_new_branch_stack();
9931002
branch_code_stack.add_new_branch();
9941003

995-
self.marker.branch_stack.add_branch_stack(num_branches);
1004+
self.marker
1005+
.branch_stack
1006+
.add_branch_stack(branch_num.clone(), num_branches);
9961007
self.marker.add_branch();
9971008
}
998-
ClauseItem::NextBranch => {
1009+
ClauseItem::NextBranch { branch_num } => {
9991010
branch_code_stack.add_new_branch();
10001011

10011012
self.marker.add_branch();
1002-
self.marker.branch_stack.incr_current_branch();
1013+
self.marker
1014+
.branch_stack
1015+
.incr_current_branch(branch_num.clone());
10031016
}
1004-
ClauseItem::BranchEnd(depth) => {
1017+
ClauseItem::BranchEnd { depth } => {
10051018
if !clause_iter.in_tail_position() {
10061019
let subsumed_hits =
10071020
branch_code_stack.push_missing_vars(depth, &mut self.marker);

src/debray_allocator.rs

Lines changed: 29 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::allocator::*;
22
use crate::codegen::SubsumedBranchHits;
3-
use crate::forms::{GenContext, Level};
3+
use crate::forms::{BranchNumber, GenContext, Level};
44
use crate::instructions::*;
55
use crate::machine::disjuncts::VarData;
66
use crate::parser::ast::*;
@@ -24,32 +24,34 @@ pub struct BranchOccurrences {
2424
pub shallow_safety: BitSet<usize>, // unset means safe, set means unsafe (after the branch merge)
2525
pub deep_safety: BitSet<usize>,
2626
pub num_branches: usize,
27-
pub current_branch: usize,
27+
pub current_branch_idx: usize,
28+
pub current_branch_num: BranchNumber,
2829
pub subsumed_hits: SubsumedBranchHits,
2930
}
3031

3132
impl BranchOccurrences {
32-
fn new(num_branches: usize) -> Self {
33+
fn new(current_branch_num: BranchNumber, num_branches: usize) -> Self {
3334
Self {
3435
hits: BranchHits::with_hasher(FxBuildHasher::default()),
3536
shallow_safety: BitSet::default(),
3637
deep_safety: BitSet::default(),
3738
num_branches,
38-
current_branch: 0,
39+
current_branch_idx: 0,
40+
current_branch_num,
3941
subsumed_hits: SubsumedBranchHits::with_hasher(FxBuildHasher::default()),
4042
}
4143
}
4244

4345
pub(crate) fn add_branch_occurrence(&mut self, var_num: usize) {
44-
debug_assert!(self.current_branch < self.num_branches);
46+
debug_assert!(self.current_branch_idx < self.num_branches);
4547
let num_branches = self.num_branches;
4648

4749
let entry = self
4850
.hits
4951
.entry(var_num)
5052
.or_insert_with(|| BitVec::repeat(false, num_branches));
5153

52-
entry.set(self.current_branch, true);
54+
entry.set(self.current_branch_idx, true);
5355
self.subsumed_hits.insert(var_num);
5456
}
5557
}
@@ -76,29 +78,16 @@ impl DerefMut for BranchStack {
7678
}
7779

7880
impl BranchStack {
79-
fn branch_subsumes(&self, branch: &BranchDesignator, sub_branch: &BranchDesignator) -> bool {
80-
if branch.branch_stack_num < sub_branch.branch_stack_num {
81-
if branch.branch_stack_num == 0 {
82-
true
83-
} else {
84-
let idx = branch.branch_stack_num - 1;
85-
self[idx].current_branch == branch.branch_num
86-
}
87-
} else {
88-
branch == sub_branch
89-
}
90-
}
91-
9281
fn safety_unneeded_in_branch(
9382
&self,
9483
safety: &VarSafetyStatus,
9584
branch: &BranchDesignator,
9685
) -> bool {
9786
match safety {
9887
VarSafetyStatus::Needed => false,
99-
VarSafetyStatus::LocallyUnneeded(planter_branch) => {
100-
self.branch_subsumes(planter_branch, branch)
101-
}
88+
VarSafetyStatus::LocallyUnneeded(planter_branch) => planter_branch
89+
.branch_num
90+
.has_as_subbranch(&branch.branch_num),
10291
VarSafetyStatus::GloballyUnneeded => true,
10392
}
10493
}
@@ -109,27 +98,24 @@ impl BranchStack {
10998
}
11099
}
111100

112-
pub(crate) fn add_branch_stack(&mut self, num_branches: usize) {
113-
self.push(BranchOccurrences::new(num_branches));
101+
pub(crate) fn add_branch_stack(&mut self, branch_num: BranchNumber, num_branches: usize) {
102+
self.push(BranchOccurrences::new(branch_num, num_branches));
114103
}
115104

116105
pub(crate) fn current_branch_designator(&self) -> BranchDesignator {
117-
let branch_stack_num = self.len();
118106
let branch_num = self
119107
.last()
120-
.map(|occurrences| occurrences.current_branch)
121-
.unwrap_or(0);
108+
.map(|occurrences| occurrences.current_branch_num.clone())
109+
.unwrap_or_else(|| BranchNumber::default());
122110

123-
BranchDesignator {
124-
branch_stack_num,
125-
branch_num,
126-
}
111+
BranchDesignator { branch_num }
127112
}
128113

129114
#[inline]
130-
pub(crate) fn incr_current_branch(&mut self) {
115+
pub(crate) fn incr_current_branch(&mut self, branch_num: BranchNumber) {
131116
let branch_occurrences = self.last_mut().unwrap();
132-
branch_occurrences.current_branch += 1;
117+
branch_occurrences.current_branch_idx += 1;
118+
branch_occurrences.current_branch_num = branch_num;
133119
}
134120

135121
#[inline]
@@ -235,12 +221,12 @@ impl DebrayAllocator {
235221
VarAlloc::Perm(_, allocation) => {
236222
let shallow_safety = VarSafetyStatus::needed_if(
237223
shallow_safety.contains(var_num),
238-
branch_designator,
224+
&branch_designator,
239225
);
240226

241227
let deep_safety = VarSafetyStatus::needed_if(
242228
deep_safety.contains(var_num),
243-
branch_designator,
229+
&branch_designator,
244230
);
245231

246232
if running_count < num_occurrences {
@@ -531,11 +517,11 @@ impl DebrayAllocator {
531517
..
532518
},
533519
) => {
534-
*deep_safety = VarSafetyStatus::unneeded(branch_designator);
535-
*shallow_safety = VarSafetyStatus::unneeded(branch_designator);
520+
*deep_safety = VarSafetyStatus::unneeded(&branch_designator);
521+
*shallow_safety = VarSafetyStatus::unneeded(&branch_designator);
536522
}
537523
VarAlloc::Temp { safety, .. } => {
538-
*safety = VarSafetyStatus::unneeded(branch_designator);
524+
*safety = VarSafetyStatus::unneeded(&branch_designator);
539525
}
540526
_ => {
541527
unreachable!()
@@ -557,8 +543,8 @@ impl DebrayAllocator {
557543
) => {
558544
// GetVariable in head chunk is considered safe.
559545
if lvl == Level::Deep {
560-
*deep_safety = VarSafetyStatus::unneeded(branch_designator);
561-
*shallow_safety = VarSafetyStatus::unneeded(branch_designator);
546+
*deep_safety = VarSafetyStatus::unneeded(&branch_designator);
547+
*shallow_safety = VarSafetyStatus::unneeded(&branch_designator);
562548
} else if term_loc == GenContext::Head {
563549
*shallow_safety = VarSafetyStatus::GloballyUnneeded;
564550
} else if let Some(&temp_var_num) = self.shallow_temp_mappings.get(&self.arg_c) {
@@ -605,7 +591,7 @@ impl DebrayAllocator {
605591
{
606592
Target::argument_to_value(r, arg_c)
607593
} else {
608-
*shallow_safety = VarSafetyStatus::unneeded(branch_designator);
594+
*shallow_safety = VarSafetyStatus::unneeded(&branch_designator);
609595
Target::unsafe_argument_to_value(r, arg_c)
610596
}
611597
}
@@ -640,7 +626,7 @@ impl DebrayAllocator {
640626
{
641627
Target::subterm_to_value(r)
642628
} else {
643-
*deep_safety = VarSafetyStatus::unneeded(branch_designator);
629+
*deep_safety = VarSafetyStatus::unneeded(&branch_designator);
644630
Target::unsafe_subterm_to_value(r)
645631
}
646632
}
@@ -651,7 +637,7 @@ impl DebrayAllocator {
651637
{
652638
Target::subterm_to_value(r)
653639
} else {
654-
*safety = VarSafetyStatus::unneeded(branch_designator);
640+
*safety = VarSafetyStatus::unneeded(&branch_designator);
655641
Target::unsafe_subterm_to_value(r)
656642
}
657643
}

src/forms.rs

Lines changed: 83 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ use indexmap::{IndexMap, IndexSet};
1818
use ordered_float::OrderedFloat;
1919

2020
use std::cell::Cell;
21+
use std::cmp::Ordering;
2122
use std::collections::VecDeque;
2223
use std::convert::TryFrom;
2324
use std::fmt;
25+
use std::hash::{Hash, Hasher};
2426
use std::ops::{AddAssign, Deref, DerefMut};
2527
use std::path::PathBuf;
2628

@@ -42,12 +44,6 @@ impl AppendOrPrepend {
4244
}
4345
}
4446

45-
#[derive(Debug, Clone, Copy)]
46-
pub enum VarComparison {
47-
Indistinct,
48-
Distinct,
49-
}
50-
5147
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5248
pub enum Level {
5349
Deep,
@@ -128,10 +124,82 @@ impl ChunkType {
128124
}
129125
}
130126

127+
#[derive(Debug, Clone)] //, PartialOrd, PartialEq, Eq, Hash)]
128+
pub(crate) struct BranchNumber {
129+
pub(crate) branch_num: Rational,
130+
pub(crate) delta: Rational,
131+
}
132+
133+
impl Default for BranchNumber {
134+
fn default() -> Self {
135+
Self {
136+
branch_num: Rational::from(0),
137+
delta: Rational::from(1u64 << 31),
138+
}
139+
}
140+
}
141+
142+
impl PartialEq<BranchNumber> for BranchNumber {
143+
#[inline]
144+
fn eq(&self, rhs: &BranchNumber) -> bool {
145+
self.branch_num == rhs.branch_num
146+
}
147+
}
148+
149+
impl Eq for BranchNumber {}
150+
151+
impl Hash for BranchNumber {
152+
#[inline(always)]
153+
fn hash<H: Hasher>(&self, hasher: &mut H) {
154+
self.branch_num.hash(hasher)
155+
}
156+
}
157+
158+
impl PartialOrd<BranchNumber> for BranchNumber {
159+
#[inline]
160+
fn partial_cmp(&self, rhs: &BranchNumber) -> Option<Ordering> {
161+
self.branch_num.partial_cmp(&rhs.branch_num)
162+
}
163+
}
164+
165+
impl BranchNumber {
166+
pub(crate) fn has_as_subbranch(&self, other: &Self) -> bool {
167+
other.delta <= self.delta
168+
&& other.branch_num >= self.branch_num
169+
&& other.branch_num < &self.branch_num + &self.delta
170+
}
171+
172+
pub(crate) fn split(&self) -> BranchNumber {
173+
BranchNumber {
174+
branch_num: self.branch_num.clone() + &self.delta / Rational::from(2),
175+
delta: &self.delta / Rational::from(4),
176+
}
177+
}
178+
179+
pub(crate) fn incr_by_delta(&self) -> BranchNumber {
180+
BranchNumber {
181+
branch_num: self.branch_num.clone() + &self.delta,
182+
delta: self.delta.clone(),
183+
}
184+
}
185+
186+
pub(crate) fn halve_delta(&self) -> BranchNumber {
187+
BranchNumber {
188+
branch_num: self.branch_num.clone(),
189+
delta: &self.delta / Rational::from(2),
190+
}
191+
}
192+
}
193+
131194
#[derive(Debug)]
132195
pub enum ChunkedTerms {
133-
Branch(Vec<VecDeque<ChunkedTerms>>),
134-
Chunk { terms: VecDeque<QueryTerm> },
196+
Branch {
197+
branch_nums: Vec<BranchNumber>,
198+
arms: Vec<VecDeque<ChunkedTerms>>,
199+
},
200+
Chunk {
201+
terms: VecDeque<QueryTerm>,
202+
},
135203
}
136204

137205
#[derive(Debug)]
@@ -165,21 +233,22 @@ impl ChunkedTermVec {
165233
}
166234

167235
pub fn reserve_branch(&mut self, capacity: usize) {
168-
self.chunk_vec
169-
.push_back(ChunkedTerms::Branch(Vec::with_capacity(capacity)));
236+
self.chunk_vec.push_back(ChunkedTerms::Branch {
237+
branch_nums: Vec::with_capacity(capacity),
238+
arms: Vec::with_capacity(capacity),
239+
});
170240
}
171241

172242
#[inline]
173243
pub fn add_chunk(&mut self) {
174-
let chunk = ChunkedTerms::Chunk {
244+
self.chunk_vec.push_back(ChunkedTerms::Chunk {
175245
terms: VecDeque::from(vec![]),
176-
};
177-
self.chunk_vec.push_back(chunk);
246+
});
178247
}
179248

180249
pub fn push_chunk_term(&mut self, term: QueryTerm) {
181250
match self.chunk_vec.back_mut() {
182-
Some(ChunkedTerms::Branch(_)) => {
251+
Some(ChunkedTerms::Branch { .. }) => {
183252
let chunk = ChunkedTerms::Chunk {
184253
terms: VecDeque::from(vec![term]),
185254
};

0 commit comments

Comments
 (0)