Skip to content

Commit

Permalink
Auto merge of rust-lang#122325 - erikdesjardins:array, r=<try>
Browse files Browse the repository at this point in the history
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`
  • Loading branch information
bors committed Mar 11, 2024
2 parents c69fda7 + 379de30 commit 7ba692d
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 19 deletions.
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2378,7 +2378,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
}
let offsets = args[1].immediate();

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

if name == sym::simd_saturating_add || name == sym::simd_saturating_sub {
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let layout = bx.layout_of(ty);
let ptr = args[0].immediate();
let offset = args[1].immediate();
bx.gep(bx.backend_type(layout), ptr, &[offset])
let elem_sized_type = bx.type_array(bx.type_i8(), layout.size.bytes());
bx.gep(elem_sized_type, ptr, &[offset])
}
sym::copy => {
copy_intrinsic(
Expand Down
7 changes: 2 additions & 5 deletions compiler/rustc_codegen_ssa/src/mir/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,12 +356,9 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
layout.size
};

let elem_sized_type = bx.type_array(bx.type_i8(), layout.size.bytes());
PlaceRef {
llval: bx.inbounds_gep(
bx.cx().backend_type(self.layout),
self.llval,
&[bx.cx().const_usize(0), llindex],
),
llval: bx.inbounds_gep(elem_sized_type, self.llval, &[llindex]),
llextra: None,
layout,
align: self.align.restrict_for_offset(offset),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_ssa/src/mir/rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -862,8 +862,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// so offsetting a pointer to ZST is a noop.
lhs
} else {
let llty = bx.cx().backend_type(pointee_layout);
bx.inbounds_gep(llty, lhs, &[rhs])
let elem_sized_type = bx.type_array(bx.type_i8(), pointee_layout.size.bytes());
bx.inbounds_gep(elem_sized_type, lhs, &[rhs])
}
}
mir::BinOp::Shl => common::build_masked_lshift(bx, lhs, rhs),
Expand Down
33 changes: 33 additions & 0 deletions tests/codegen/intrinsics/arith_offset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//@ compile-flags: -O

#![crate_type = "lib"]
#![feature(core_intrinsics)]

use std::intrinsics::arith_offset;

// CHECK-LABEL: ptr @arith_offset_zst
// CHECK-SAME: (ptr noundef{{.*}} %p, [[SIZE:i[0-9]+]] noundef %d)
#[no_mangle]
pub unsafe fn arith_offset_zst(p: *const (), d: isize) -> *const () {
// CHECK-NOT: getelementptr
// CHECK: ret ptr %p
arith_offset(p, d)
}

// CHECK-LABEL: ptr @arith_offset_u32
// CHECK-SAME: (ptr noundef{{.*}} %p, [[SIZE]] noundef %d)
#[no_mangle]
pub unsafe fn arith_offset_u32(p: *const u32, d: isize) -> *const u32 {
// CHECK: %[[R:.*]] = getelementptr [4 x i8], ptr %p, [[SIZE]] %d
// CHECK-NEXT: ret ptr %[[R]]
arith_offset(p, d)
}

// CHECK-LABEL: ptr @arith_offset_u64
// CHECK-SAME: (ptr noundef{{.*}} %p, [[SIZE]] noundef %d)
#[no_mangle]
pub unsafe fn arith_offset_u64(p: *const u64, d: isize) -> *const u64 {
// CHECK: %[[R:.*]] = getelementptr [8 x i8], ptr %p, [[SIZE]] %d
// CHECK-NEXT: ret ptr %[[R]]
arith_offset(p, d)
}
4 changes: 2 additions & 2 deletions tests/codegen/intrinsics/offset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub unsafe fn offset_zst(p: *const (), d: usize) -> *const () {
// CHECK-SAME: (ptr noundef %p, [[SIZE]] noundef %d)
#[no_mangle]
pub unsafe fn offset_isize(p: *const u32, d: isize) -> *const u32 {
// CHECK: %[[R:.*]] = getelementptr inbounds i32, ptr %p, [[SIZE]] %d
// CHECK: %[[R:.*]] = getelementptr inbounds [4 x i8], ptr %p, [[SIZE]] %d
// CHECK-NEXT: ret ptr %[[R]]
offset(p, d)
}
Expand All @@ -27,7 +27,7 @@ pub unsafe fn offset_isize(p: *const u32, d: isize) -> *const u32 {
// CHECK-SAME: (ptr noundef %p, [[SIZE]] noundef %d)
#[no_mangle]
pub unsafe fn offset_usize(p: *const u64, d: usize) -> *const u64 {
// CHECK: %[[R:.*]] = getelementptr inbounds i64, ptr %p, [[SIZE]] %d
// CHECK: %[[R:.*]] = getelementptr inbounds [8 x i8], ptr %p, [[SIZE]] %d
// CHECK-NEXT: ret ptr %[[R]]
offset(p, d)
}
6 changes: 3 additions & 3 deletions tests/codegen/ptr-arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// CHECK-SAME: [[WORD:i[0-9]+]] noundef %n)
#[no_mangle]
pub unsafe fn i32_add(p: *const i32, n: usize) -> *const i32 {
// CHECK: %[[TEMP:.+]] = getelementptr inbounds i32, ptr %p, [[WORD]] %n
// CHECK: %[[TEMP:.+]] = getelementptr inbounds [4 x i8], ptr %p, [[WORD]] %n
// CHECK: ret ptr %[[TEMP]]
p.add(n)
}
Expand All @@ -18,7 +18,7 @@ pub unsafe fn i32_add(p: *const i32, n: usize) -> *const i32 {
#[no_mangle]
pub unsafe fn i32_sub(p: *const i32, n: usize) -> *const i32 {
// CHECK: %[[DELTA:.+]] = sub nsw [[WORD]] 0, %n
// CHECK: %[[TEMP:.+]] = getelementptr inbounds i32, ptr %p, [[WORD]] %[[DELTA]]
// CHECK: %[[TEMP:.+]] = getelementptr inbounds [4 x i8], ptr %p, [[WORD]] %[[DELTA]]
// CHECK: ret ptr %[[TEMP]]
p.sub(n)
}
Expand All @@ -27,7 +27,7 @@ pub unsafe fn i32_sub(p: *const i32, n: usize) -> *const i32 {
// CHECK-SAME: [[WORD:i[0-9]+]] noundef %d)
#[no_mangle]
pub unsafe fn i32_offset(p: *const i32, d: isize) -> *const i32 {
// CHECK: %[[TEMP:.+]] = getelementptr inbounds i32, ptr %p, [[WORD]] %d
// CHECK: %[[TEMP:.+]] = getelementptr inbounds [4 x i8], ptr %p, [[WORD]] %d
// CHECK: ret ptr %[[TEMP]]
p.offset(d)
}
13 changes: 10 additions & 3 deletions tests/codegen/simd/simd_arith_offset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,16 @@ pub struct SimdConstPtr<T, const LANES: usize>([*const T; LANES]);
#[repr(simd)]
pub struct Simd<T, const LANES: usize>([T; LANES]);

// CHECK-LABEL: smoke
// CHECK-LABEL: u8_offset
#[no_mangle]
pub fn smoke(ptrs: SimdConstPtr<u8, 8>, offsets: Simd<usize, 8>) -> SimdConstPtr<u8, 8> {
// CHECK: getelementptr i8, <8 x ptr> %0, <8 x i64> %1
pub fn u8_offset(ptrs: SimdConstPtr<u8, 8>, offsets: Simd<usize, 8>) -> SimdConstPtr<u8, 8> {
// CHECK: getelementptr [1 x i8], <8 x ptr> %0, <8 x i64> %1
unsafe { simd_arith_offset(ptrs, offsets) }
}

// CHECK-LABEL: u64_offset
#[no_mangle]
pub fn u64_offset(ptrs: SimdConstPtr<u64, 8>, offsets: Simd<usize, 8>) -> SimdConstPtr<u64, 8> {
// CHECK: getelementptr [8 x i8], <8 x ptr> %0, <8 x i64> %1
unsafe { simd_arith_offset(ptrs, offsets) }
}
4 changes: 2 additions & 2 deletions tests/codegen/slice-iter-nonnull.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub fn slice_iter_next_back<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'
#[no_mangle]
pub fn slice_iter_new(slice: &[u32]) -> std::slice::Iter<'_, u32> {
// CHECK-NOT: slice
// CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1
// CHECK: %[[END:.+]] = getelementptr inbounds [4 x i8]{{.+}} %slice.0{{.+}} %slice.1
// CHECK-NOT: slice
// CHECK: insertvalue {{.+}} ptr %slice.0, 0
// CHECK-NOT: slice
Expand All @@ -69,7 +69,7 @@ pub fn slice_iter_new(slice: &[u32]) -> std::slice::Iter<'_, u32> {
#[no_mangle]
pub fn slice_iter_mut_new(slice: &mut [u32]) -> std::slice::IterMut<'_, u32> {
// CHECK-NOT: slice
// CHECK: %[[END:.+]] = getelementptr inbounds i32{{.+}} %slice.0{{.+}} %slice.1
// CHECK: %[[END:.+]] = getelementptr inbounds [4 x i8]{{.+}} %slice.0{{.+}} %slice.1
// CHECK-NOT: slice
// CHECK: insertvalue {{.+}} ptr %slice.0, 0
// CHECK-NOT: slice
Expand Down

0 comments on commit 7ba692d

Please sign in to comment.