Skip to content

Commit 7ba692d

Browse files
committed
Auto merge of rust-lang#122325 - erikdesjardins:array, r=<try>
Stop using LLVM struct types for array/pointer offset GEPs ...and just use a byte array with the same size as the element type instead. This avoids depending on LLVM's struct layout to determine the size of the array/pointer element. Spiritually split out from rust-lang#121577. r? `@nikic`
2 parents c69fda7 + 379de30 commit 7ba692d

File tree

9 files changed

+58
-19
lines changed

9 files changed

+58
-19
lines changed

compiler/rustc_codegen_llvm/src/intrinsic.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2378,7 +2378,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
23782378
}
23792379
let offsets = args[1].immediate();
23802380

2381-
return Ok(bx.gep(bx.backend_type(layout), ptrs, &[offsets]));
2381+
let elem_sized_type = bx.type_array(bx.type_i8(), layout.size.bytes());
2382+
return Ok(bx.gep(elem_sized_type, ptrs, &[offsets]));
23822383
}
23832384

23842385
if name == sym::simd_saturating_add || name == sym::simd_saturating_sub {

compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
139139
let layout = bx.layout_of(ty);
140140
let ptr = args[0].immediate();
141141
let offset = args[1].immediate();
142-
bx.gep(bx.backend_type(layout), ptr, &[offset])
142+
let elem_sized_type = bx.type_array(bx.type_i8(), layout.size.bytes());
143+
bx.gep(elem_sized_type, ptr, &[offset])
143144
}
144145
sym::copy => {
145146
copy_intrinsic(

compiler/rustc_codegen_ssa/src/mir/place.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -356,12 +356,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
356356
layout.size
357357
};
358358

359+
let elem_sized_type = bx.type_array(bx.type_i8(), layout.size.bytes());
359360
PlaceRef {
360-
llval: bx.inbounds_gep(
361-
bx.cx().backend_type(self.layout),
362-
self.llval,
363-
&[bx.cx().const_usize(0), llindex],
364-
),
361+
llval: bx.inbounds_gep(elem_sized_type, self.llval, &[llindex]),
365362
llextra: None,
366363
layout,
367364
align: self.align.restrict_for_offset(offset),

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -862,8 +862,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
862862
// so offsetting a pointer to ZST is a noop.
863863
lhs
864864
} else {
865-
let llty = bx.cx().backend_type(pointee_layout);
866-
bx.inbounds_gep(llty, lhs, &[rhs])
865+
let elem_sized_type = bx.type_array(bx.type_i8(), pointee_layout.size.bytes());
866+
bx.inbounds_gep(elem_sized_type, lhs, &[rhs])
867867
}
868868
}
869869
mir::BinOp::Shl => common::build_masked_lshift(bx, lhs, rhs),
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//@ compile-flags: -O
2+
3+
#![crate_type = "lib"]
4+
#![feature(core_intrinsics)]
5+
6+
use std::intrinsics::arith_offset;
7+
8+
// CHECK-LABEL: ptr @arith_offset_zst
9+
// CHECK-SAME: (ptr noundef{{.*}} %p, [[SIZE:i[0-9]+]] noundef %d)
10+
#[no_mangle]
11+
pub unsafe fn arith_offset_zst(p: *const (), d: isize) -> *const () {
12+
// CHECK-NOT: getelementptr
13+
// CHECK: ret ptr %p
14+
arith_offset(p, d)
15+
}
16+
17+
// CHECK-LABEL: ptr @arith_offset_u32
18+
// CHECK-SAME: (ptr noundef{{.*}} %p, [[SIZE]] noundef %d)
19+
#[no_mangle]
20+
pub unsafe fn arith_offset_u32(p: *const u32, d: isize) -> *const u32 {
21+
// CHECK: %[[R:.*]] = getelementptr [4 x i8], ptr %p, [[SIZE]] %d
22+
// CHECK-NEXT: ret ptr %[[R]]
23+
arith_offset(p, d)
24+
}
25+
26+
// CHECK-LABEL: ptr @arith_offset_u64
27+
// CHECK-SAME: (ptr noundef{{.*}} %p, [[SIZE]] noundef %d)
28+
#[no_mangle]
29+
pub unsafe fn arith_offset_u64(p: *const u64, d: isize) -> *const u64 {
30+
// CHECK: %[[R:.*]] = getelementptr [8 x i8], ptr %p, [[SIZE]] %d
31+
// CHECK-NEXT: ret ptr %[[R]]
32+
arith_offset(p, d)
33+
}

tests/codegen/intrinsics/offset.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub unsafe fn offset_zst(p: *const (), d: usize) -> *const () {
1818
// CHECK-SAME: (ptr noundef %p, [[SIZE]] noundef %d)
1919
#[no_mangle]
2020
pub unsafe fn offset_isize(p: *const u32, d: isize) -> *const u32 {
21-
// CHECK: %[[R:.*]] = getelementptr inbounds i32, ptr %p, [[SIZE]] %d
21+
// CHECK: %[[R:.*]] = getelementptr inbounds [4 x i8], ptr %p, [[SIZE]] %d
2222
// CHECK-NEXT: ret ptr %[[R]]
2323
offset(p, d)
2424
}
@@ -27,7 +27,7 @@ pub unsafe fn offset_isize(p: *const u32, d: isize) -> *const u32 {
2727
// CHECK-SAME: (ptr noundef %p, [[SIZE]] noundef %d)
2828
#[no_mangle]
2929
pub unsafe fn offset_usize(p: *const u64, d: usize) -> *const u64 {
30-
// CHECK: %[[R:.*]] = getelementptr inbounds i64, ptr %p, [[SIZE]] %d
30+
// CHECK: %[[R:.*]] = getelementptr inbounds [8 x i8], ptr %p, [[SIZE]] %d
3131
// CHECK-NEXT: ret ptr %[[R]]
3232
offset(p, d)
3333
}

tests/codegen/ptr-arithmetic.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// CHECK-SAME: [[WORD:i[0-9]+]] noundef %n)
77
#[no_mangle]
88
pub unsafe fn i32_add(p: *const i32, n: usize) -> *const i32 {
9-
// CHECK: %[[TEMP:.+]] = getelementptr inbounds i32, ptr %p, [[WORD]] %n
9+
// CHECK: %[[TEMP:.+]] = getelementptr inbounds [4 x i8], ptr %p, [[WORD]] %n
1010
// CHECK: ret ptr %[[TEMP]]
1111
p.add(n)
1212
}
@@ -18,7 +18,7 @@ pub unsafe fn i32_add(p: *const i32, n: usize) -> *const i32 {
1818
#[no_mangle]
1919
pub unsafe fn i32_sub(p: *const i32, n: usize) -> *const i32 {
2020
// CHECK: %[[DELTA:.+]] = sub nsw [[WORD]] 0, %n
21-
// CHECK: %[[TEMP:.+]] = getelementptr inbounds i32, ptr %p, [[WORD]] %[[DELTA]]
21+
// CHECK: %[[TEMP:.+]] = getelementptr inbounds [4 x i8], ptr %p, [[WORD]] %[[DELTA]]
2222
// CHECK: ret ptr %[[TEMP]]
2323
p.sub(n)
2424
}
@@ -27,7 +27,7 @@ pub unsafe fn i32_sub(p: *const i32, n: usize) -> *const i32 {
2727
// CHECK-SAME: [[WORD:i[0-9]+]] noundef %d)
2828
#[no_mangle]
2929
pub unsafe fn i32_offset(p: *const i32, d: isize) -> *const i32 {
30-
// CHECK: %[[TEMP:.+]] = getelementptr inbounds i32, ptr %p, [[WORD]] %d
30+
// CHECK: %[[TEMP:.+]] = getelementptr inbounds [4 x i8], ptr %p, [[WORD]] %d
3131
// CHECK: ret ptr %[[TEMP]]
3232
p.offset(d)
3333
}

tests/codegen/simd/simd_arith_offset.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,16 @@ pub struct SimdConstPtr<T, const LANES: usize>([*const T; LANES]);
1818
#[repr(simd)]
1919
pub struct Simd<T, const LANES: usize>([T; LANES]);
2020

21-
// CHECK-LABEL: smoke
21+
// CHECK-LABEL: u8_offset
2222
#[no_mangle]
23-
pub fn smoke(ptrs: SimdConstPtr<u8, 8>, offsets: Simd<usize, 8>) -> SimdConstPtr<u8, 8> {
24-
// CHECK: getelementptr i8, <8 x ptr> %0, <8 x i64> %1
23+
pub fn u8_offset(ptrs: SimdConstPtr<u8, 8>, offsets: Simd<usize, 8>) -> SimdConstPtr<u8, 8> {
24+
// CHECK: getelementptr [1 x i8], <8 x ptr> %0, <8 x i64> %1
25+
unsafe { simd_arith_offset(ptrs, offsets) }
26+
}
27+
28+
// CHECK-LABEL: u64_offset
29+
#[no_mangle]
30+
pub fn u64_offset(ptrs: SimdConstPtr<u64, 8>, offsets: Simd<usize, 8>) -> SimdConstPtr<u64, 8> {
31+
// CHECK: getelementptr [8 x i8], <8 x ptr> %0, <8 x i64> %1
2532
unsafe { simd_arith_offset(ptrs, offsets) }
2633
}

tests/codegen/slice-iter-nonnull.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub fn slice_iter_next_back<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'
5454
#[no_mangle]
5555
pub fn slice_iter_new(slice: &[u32]) -> std::slice::Iter<'_, u32> {
5656
// CHECK-NOT: slice
57-
// CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1
57+
// CHECK: %[[END:.+]] = getelementptr inbounds [4 x i8]{{.+}} %slice.0{{.+}} %slice.1
5858
// CHECK-NOT: slice
5959
// CHECK: insertvalue {{.+}} ptr %slice.0, 0
6060
// CHECK-NOT: slice
@@ -69,7 +69,7 @@ pub fn slice_iter_new(slice: &[u32]) -> std::slice::Iter<'_, u32> {
6969
#[no_mangle]
7070
pub fn slice_iter_mut_new(slice: &mut [u32]) -> std::slice::IterMut<'_, u32> {
7171
// CHECK-NOT: slice
72-
// CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1
72+
// CHECK: %[[END:.+]] = getelementptr inbounds [4 x i8]{{.+}} %slice.0{{.+}} %slice.1
7373
// CHECK-NOT: slice
7474
// CHECK: insertvalue {{.+}} ptr %slice.0, 0
7575
// CHECK-NOT: slice

0 commit comments

Comments
 (0)