Skip to content

Commit 6093128

Browse files
committed
Changed implementation of the third field to make LLVM optimize it better.
1 parent 6e0dd9e commit 6093128

File tree

3 files changed

+39
-31
lines changed

3 files changed

+39
-31
lines changed

src/libcore/iter/mod.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -787,19 +787,19 @@ where
787787
#[inline]
788788
fn spec_next(&mut self) -> Option<Self::Item> {
789789
self.first_take = false;
790-
if self.iter.is_empty() {
791-
self.iter.is_iterating = Some(false);
790+
self.iter.compute_is_empty();
791+
if self.iter.is_empty.unwrap_or_default() {
792792
return None;
793793
}
794794
// add 1 to self.step to get original step size back
795795
// it was decremented for the general case on construction
796796
if let Some(n) = self.iter.start.add_usize(self.step+1) {
797-
self.iter.is_iterating = Some(n <= self.iter.end);
797+
self.iter.is_empty = Some(!(n <= self.iter.end));
798798
let next = mem::replace(&mut self.iter.start, n);
799799
Some(next)
800800
} else {
801801
let last = self.iter.start.clone();
802-
self.iter.is_iterating = Some(false);
802+
self.iter.is_empty = Some(true);
803803
Some(last)
804804
}
805805
}

src/libcore/iter/range.rs

+21-21
Original file line numberDiff line numberDiff line change
@@ -330,18 +330,18 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
330330

331331
#[inline]
332332
fn next(&mut self) -> Option<A> {
333-
if self.is_empty() {
334-
self.is_iterating = Some(false);
333+
self.compute_is_empty();
334+
if self.is_empty.unwrap_or_default() {
335335
return None;
336336
}
337-
if self.start < self.end {
337+
let is_iterating = self.start < self.end;
338+
self.is_empty = Some(!is_iterating);
339+
Some(if is_iterating {
338340
let n = self.start.add_one();
339-
self.is_iterating = Some(true);
340-
Some(mem::replace(&mut self.start, n))
341+
mem::replace(&mut self.start, n)
341342
} else {
342-
self.is_iterating = Some(false);
343-
Some(self.start.clone())
344-
}
343+
self.start.clone()
344+
})
345345
}
346346

347347
#[inline]
@@ -358,8 +358,8 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
358358

359359
#[inline]
360360
fn nth(&mut self, n: usize) -> Option<A> {
361-
if self.is_empty() {
362-
self.is_iterating = Some(false);
361+
self.compute_is_empty();
362+
if self.is_empty.unwrap_or_default() {
363363
return None;
364364
}
365365

@@ -368,19 +368,19 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
368368

369369
match plus_n.partial_cmp(&self.end) {
370370
Some(Less) => {
371-
self.is_iterating = Some(true);
371+
self.is_empty = Some(false);
372372
self.start = plus_n.add_one();
373373
return Some(plus_n)
374374
}
375375
Some(Equal) => {
376-
self.is_iterating = Some(false);
376+
self.is_empty = Some(true);
377377
return Some(plus_n)
378378
}
379379
_ => {}
380380
}
381381
}
382382

383-
self.is_iterating = Some(false);
383+
self.is_empty = Some(true);
384384
None
385385
}
386386

@@ -404,18 +404,18 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
404404
impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
405405
#[inline]
406406
fn next_back(&mut self) -> Option<A> {
407-
if self.is_empty() {
408-
self.is_iterating = Some(false);
407+
self.compute_is_empty();
408+
if self.is_empty.unwrap_or_default() {
409409
return None;
410410
}
411-
if self.start < self.end {
411+
let is_iterating = self.start < self.end;
412+
self.is_empty = Some(!is_iterating);
413+
Some(if is_iterating {
412414
let n = self.end.sub_one();
413-
self.is_iterating = Some(true);
414-
Some(mem::replace(&mut self.end, n))
415+
mem::replace(&mut self.end, n)
415416
} else {
416-
self.is_iterating = Some(false);
417-
Some(self.end.clone())
418-
}
417+
self.end.clone()
418+
})
419419
}
420420
}
421421

src/libcore/ops/range.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -332,11 +332,11 @@ impl<Idx: PartialOrd<Idx>> RangeTo<Idx> {
332332
pub struct RangeInclusive<Idx> {
333333
pub(crate) start: Idx,
334334
pub(crate) end: Idx,
335-
pub(crate) is_iterating: Option<bool>,
335+
pub(crate) is_empty: Option<bool>,
336336
// This field is:
337337
// - `None` when next() or next_back() was never called
338-
// - `Some(true)` when `start <= end` assuming no overflow
339-
// - `Some(false)` otherwise
338+
// - `Some(false)` when `start <= end` assuming no overflow
339+
// - `Some(true)` otherwise
340340
// The field cannot be a simple `bool` because the `..=` constructor can
341341
// accept non-PartialOrd types, also we want the constructor to be const.
342342
}
@@ -347,7 +347,7 @@ trait RangeInclusiveEquality: Sized {
347347
impl<T> RangeInclusiveEquality for T {
348348
#[inline]
349349
default fn canonicalized_is_empty(range: &RangeInclusive<Self>) -> bool {
350-
!range.is_iterating.unwrap_or(false)
350+
range.is_empty.unwrap_or_default()
351351
}
352352
}
353353
impl<T: PartialOrd> RangeInclusiveEquality for T {
@@ -392,7 +392,7 @@ impl<Idx> RangeInclusive<Idx> {
392392
#[stable(feature = "inclusive_range_methods", since = "1.27.0")]
393393
#[inline]
394394
pub const fn new(start: Idx, end: Idx) -> Self {
395-
Self { start, end, is_iterating: None }
395+
Self { start, end, is_empty: None }
396396
}
397397

398398
/// Returns the lower bound of the range (inclusive).
@@ -536,7 +536,15 @@ impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
536536
#[unstable(feature = "range_is_empty", reason = "recently added", issue = "48111")]
537537
#[inline]
538538
pub fn is_empty(&self) -> bool {
539-
!self.is_iterating.unwrap_or_else(|| self.start <= self.end)
539+
self.is_empty.unwrap_or_else(|| !(self.start <= self.end))
540+
}
541+
542+
// If this range's `is_empty` is field is unknown (`None`), update it to be a concrete value.
543+
#[inline]
544+
pub(crate) fn compute_is_empty(&mut self) {
545+
if self.is_empty.is_none() {
546+
self.is_empty = Some(!(self.start <= self.end));
547+
}
540548
}
541549
}
542550

0 commit comments

Comments
 (0)