File: iter-repeat-n-trivial-drop.rs

package info (click to toggle)
rustc 1.85.0%2Bdfsg3-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, sid, trixie
  • size: 893,396 kB
  • sloc: xml: 158,127; python: 35,830; javascript: 19,497; cpp: 19,002; sh: 17,245; ansic: 13,127; asm: 4,376; makefile: 1,051; perl: 29; lisp: 29; ruby: 19; sql: 11
file content (69 lines) | stat: -rw-r--r-- 2,272 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//@ compile-flags: -C opt-level=3
//@ only-x86_64

#![crate_type = "lib"]
#![feature(iter_repeat_n)]
#![feature(array_repeat)]

#[derive(Clone)]
pub struct NotCopy(u16);

impl Drop for NotCopy {
    fn drop(&mut self) {}
}

// For a type where `Drop::drop` doesn't do anything observable and a clone is the
// same as a move, make sure that the extra case for the last item disappears.

#[no_mangle]
// CHECK-LABEL: @iter_repeat_n_next
pub fn iter_repeat_n_next(it: &mut std::iter::RepeatN<NotCopy>) -> Option<NotCopy> {
    // CHECK-NEXT: start:
    // CHECK-NOT: br
    // CHECK: %[[COUNT:.+]] = load i64
    // CHECK-NEXT: %[[COUNT_ZERO:.+]] = icmp eq i64 %[[COUNT]], 0
    // CHECK-NEXT: br i1 %[[COUNT_ZERO]], label %[[EMPTY:.+]], label %[[NOT_EMPTY:.+]]

    // CHECK: [[NOT_EMPTY]]:
    // CHECK-NEXT: %[[DEC:.+]] = add i64 %[[COUNT]], -1
    // CHECK-NEXT: store i64 %[[DEC]]
    // CHECK-NOT: br
    // CHECK: %[[VAL:.+]] = load i16
    // CHECK-NEXT: br label %[[EMPTY]]

    // CHECK: [[EMPTY]]:
    // CHECK-NOT: br
    // CHECK: phi i16
    // CHECK-SAME: [ %[[VAL]], %[[NOT_EMPTY]] ]
    // CHECK-NOT: br
    // CHECK: ret

    it.next()
}

// And as a result, using the iterator can optimize without special cases for
// the last iteration, like `memset`ing all the items in one call.

#[no_mangle]
// CHECK-LABEL: @vec_extend_via_iter_repeat_n
pub fn vec_extend_via_iter_repeat_n() -> Vec<u8> {
    // CHECK: %[[ADDR:.+]] = tail call {{(noalias )?}}noundef dereferenceable_or_null(1234) ptr @__rust_alloc(i64 noundef {{(range\(i64 1, 0\) )?}}1234, i64 noundef {{(range\(i64 1, -9223372036854775807\) )?}}1)
    // CHECK: tail call void @llvm.memset.p0.i64(ptr noundef nonnull align 1 dereferenceable(1234) %[[ADDR]], i8 42, i64 1234,

    let n = 1234_usize;
    let mut v = Vec::with_capacity(n);
    v.extend(std::iter::repeat_n(42_u8, n));
    v
}

// Array repeat uses `RepeatN::next_unchecked` internally,
// so also check that the distinction disappears there.

#[no_mangle]
// CHECK-LABEL: @array_repeat_not_copy
pub unsafe fn array_repeat_not_copy(item: NotCopy) -> [NotCopy; 8] {
    // CHECK: insertelement {{.+}} i16 %item
    // CHECK: shufflevector <8 x i16> {{.+}} zeroinitializer
    // CHECK: store <8 x i16>
    std::array::repeat(item)
}