mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-30 20:44:34 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			116 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| //@ compile-flags: -Copt-level=3
 | |
| //@ needs-deterministic-layouts
 | |
| #![crate_type = "lib"]
 | |
| #![feature(exact_size_is_empty)]
 | |
| 
 | |
| // The slice iterator used to `assume` that the `start` pointer was non-null.
 | |
| // That ought to be unneeded, though, since the type is `NonNull`, so this test
 | |
| // confirms that the appropriate metadata is included to denote that.
 | |
| 
 | |
| // It also used to `assume` the `end` pointer was non-null, but that's no longer
 | |
| // needed as the code changed to read it as a `NonNull`, and thus gets the
 | |
| // appropriate `!nonnull` annotations naturally.
 | |
| 
 | |
| // CHECK-LABEL: @slice_iter_next(
 | |
| #[no_mangle]
 | |
| pub fn slice_iter_next<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32> {
 | |
|     // CHECK: %[[START:.+]] = load ptr, ptr %it,
 | |
|     // CHECK-SAME: !nonnull
 | |
|     // CHECK-SAME: !noundef
 | |
|     // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}}
 | |
|     // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
 | |
|     // CHECK-SAME: !nonnull
 | |
|     // CHECK-SAME: !noundef
 | |
|     // CHECK: icmp eq ptr %[[START]], %[[END]]
 | |
| 
 | |
|     // CHECK: store ptr{{.+}}, ptr %it,
 | |
| 
 | |
|     it.next()
 | |
| }
 | |
| 
 | |
| // CHECK-LABEL: @slice_iter_next_back(
 | |
| #[no_mangle]
 | |
| pub fn slice_iter_next_back<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32> {
 | |
|     // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}}
 | |
|     // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
 | |
|     // CHECK-SAME: !nonnull
 | |
|     // CHECK-SAME: !noundef
 | |
|     // CHECK: %[[START:.+]] = load ptr, ptr %it,
 | |
|     // CHECK-SAME: !nonnull
 | |
|     // CHECK-SAME: !noundef
 | |
|     // CHECK: icmp eq ptr %[[START]], %[[END]]
 | |
| 
 | |
|     // CHECK: store ptr{{.+}}, ptr %[[ENDP]],
 | |
| 
 | |
|     it.next_back()
 | |
| }
 | |
| 
 | |
| // The slice iterator `new` methods used to `assume` that the pointer is non-null,
 | |
| // but passing slices already requires that, to the extent that LLVM actually
 | |
| // removed the `call @llvm.assume` anyway.  These tests just demonstrate that the
 | |
| // attribute is there, and confirms adding the assume back doesn't do anything.
 | |
| 
 | |
| // CHECK-LABEL: @slice_iter_new
 | |
| // CHECK-SAME: (ptr noalias noundef nonnull {{.+}} %slice.0, {{.+}} noundef %slice.1)
 | |
| #[no_mangle]
 | |
| pub fn slice_iter_new(slice: &[u32]) -> std::slice::Iter<'_, u32> {
 | |
|     // CHECK-NOT: slice
 | |
|     // CHECK: %[[END:.+]] = getelementptr inbounds{{( nuw)?}} i32{{.+}} %slice.0{{.+}} %slice.1
 | |
|     // CHECK-NOT: slice
 | |
|     // CHECK: insertvalue {{.+}} ptr %slice.0, 0
 | |
|     // CHECK-NOT: slice
 | |
|     // CHECK: insertvalue {{.+}} ptr %[[END]], 1
 | |
|     // CHECK-NOT: slice
 | |
|     // CHECK: }
 | |
|     slice.iter()
 | |
| }
 | |
| 
 | |
| // CHECK-LABEL: @slice_iter_mut_new
 | |
| // CHECK-SAME: (ptr noalias noundef nonnull {{.+}} %slice.0, {{.+}} noundef %slice.1)
 | |
| #[no_mangle]
 | |
| pub fn slice_iter_mut_new(slice: &mut [u32]) -> std::slice::IterMut<'_, u32> {
 | |
|     // CHECK-NOT: slice
 | |
|     // CHECK: %[[END:.+]] = getelementptr inbounds{{( nuw)?}} i32{{.+}} %slice.0{{.+}} %slice.1
 | |
|     // CHECK-NOT: slice
 | |
|     // CHECK: insertvalue {{.+}} ptr %slice.0, 0
 | |
|     // CHECK-NOT: slice
 | |
|     // CHECK: insertvalue {{.+}} ptr %[[END]], 1
 | |
|     // CHECK-NOT: slice
 | |
|     // CHECK: }
 | |
|     slice.iter_mut()
 | |
| }
 | |
| 
 | |
| // CHECK-LABEL: @slice_iter_is_empty
 | |
| #[no_mangle]
 | |
| pub fn slice_iter_is_empty(it: &std::slice::Iter<'_, u32>) -> bool {
 | |
|     // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}}
 | |
|     // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
 | |
|     // CHECK-SAME: !nonnull
 | |
|     // CHECK-SAME: !noundef
 | |
|     // CHECK: %[[START:.+]] = load ptr, ptr %it,
 | |
|     // CHECK-SAME: !nonnull
 | |
|     // CHECK-SAME: !noundef
 | |
| 
 | |
|     // CHECK: %[[RET:.+]] = icmp eq ptr %[[START]], %[[END]]
 | |
|     // CHECK: ret i1 %[[RET]]
 | |
|     it.is_empty()
 | |
| }
 | |
| 
 | |
| // CHECK-LABEL: @slice_iter_len
 | |
| #[no_mangle]
 | |
| pub fn slice_iter_len(it: &std::slice::Iter<'_, u32>) -> usize {
 | |
|     // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}}
 | |
|     // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
 | |
|     // CHECK-SAME: !nonnull
 | |
|     // CHECK-SAME: !noundef
 | |
|     // CHECK: %[[START:.+]] = load ptr, ptr %it,
 | |
|     // CHECK-SAME: !nonnull
 | |
|     // CHECK-SAME: !noundef
 | |
| 
 | |
|     // CHECK: ptrtoint
 | |
|     // CHECK: ptrtoint
 | |
|     // CHECK: sub nuw
 | |
|     // CHECK: lshr exact
 | |
|     it.len()
 | |
| }
 | 
