Skip to content

Commit 62ff2bc

Browse files
committed
Auto merge of rust-lang#94159 - erikdesjardins:align-load, r=nikic
Add !align metadata on loads of &/&mut/Box Note that this refers to the alignment of what the loaded value points to, _not_ the alignment of the loaded value itself. r? `@ghost` (blocked on rust-lang#94158)
2 parents 65f6d33 + a381aef commit 62ff2bc

File tree

3 files changed

+67
-16
lines changed

3 files changed

+67
-16
lines changed

compiler/rustc_codegen_llvm/src/builder.rs

+30-8
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
477477
bx: &mut Builder<'a, 'll, 'tcx>,
478478
load: &'ll Value,
479479
scalar: abi::Scalar,
480+
layout: TyAndLayout<'tcx>,
481+
offset: Size,
480482
) {
481483
if !scalar.is_always_valid(bx) {
482484
bx.noundef_metadata(load);
@@ -488,10 +490,18 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
488490
bx.range_metadata(load, scalar.valid_range);
489491
}
490492
}
491-
abi::Pointer if !scalar.valid_range.contains(0) => {
492-
bx.nonnull_metadata(load);
493+
abi::Pointer => {
494+
if !scalar.valid_range.contains(0) {
495+
bx.nonnull_metadata(load);
496+
}
497+
498+
if let Some(pointee) = layout.pointee_info_at(bx, offset) {
499+
if let Some(_) = pointee.safe {
500+
bx.align_metadata(load, pointee.align);
501+
}
502+
}
493503
}
494-
_ => {}
504+
abi::F32 | abi::F64 => {}
495505
}
496506
}
497507

@@ -509,7 +519,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
509519
let llval = const_llval.unwrap_or_else(|| {
510520
let load = self.load(place.layout.llvm_type(self), place.llval, place.align);
511521
if let abi::Abi::Scalar(scalar) = place.layout.abi {
512-
scalar_load_metadata(self, load, scalar);
522+
scalar_load_metadata(self, load, scalar, place.layout, Size::ZERO);
513523
}
514524
load
515525
});
@@ -518,17 +528,17 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
518528
let b_offset = a.value.size(self).align_to(b.value.align(self).abi);
519529
let pair_ty = place.layout.llvm_type(self);
520530

521-
let mut load = |i, scalar: abi::Scalar, align| {
531+
let mut load = |i, scalar: abi::Scalar, layout, align, offset| {
522532
let llptr = self.struct_gep(pair_ty, place.llval, i as u64);
523533
let llty = place.layout.scalar_pair_element_llvm_type(self, i, false);
524534
let load = self.load(llty, llptr, align);
525-
scalar_load_metadata(self, load, scalar);
535+
scalar_load_metadata(self, load, scalar, layout, offset);
526536
self.to_immediate_scalar(load, scalar)
527537
};
528538

529539
OperandValue::Pair(
530-
load(0, a, place.align),
531-
load(1, b, place.align.restrict_for_offset(b_offset)),
540+
load(0, a, place.layout, place.align, Size::ZERO),
541+
load(1, b, place.layout, place.align.restrict_for_offset(b_offset), b_offset),
532542
)
533543
} else {
534544
OperandValue::Ref(place.llval, None, place.align)
@@ -1208,6 +1218,18 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
12081218
}
12091219
}
12101220

1221+
fn align_metadata(&mut self, load: &'ll Value, align: Align) {
1222+
unsafe {
1223+
let v = [self.cx.const_u64(align.bytes())];
1224+
1225+
llvm::LLVMSetMetadata(
1226+
load,
1227+
llvm::MD_align as c_uint,
1228+
llvm::LLVMMDNodeInContext(self.cx.llcx, v.as_ptr(), v.len() as c_uint),
1229+
);
1230+
}
1231+
}
1232+
12111233
fn noundef_metadata(&mut self, load: &'ll Value) {
12121234
unsafe {
12131235
llvm::LLVMSetMetadata(

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ pub enum MetadataType {
441441
MD_nontemporal = 9,
442442
MD_mem_parallel_loop_access = 10,
443443
MD_nonnull = 11,
444+
MD_align = 17,
444445
MD_type = 19,
445446
MD_noundef = 29,
446447
}

src/test/codegen/loads.rs

+36-8
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,47 @@ pub enum MyBool {
1818
False,
1919
}
2020

21+
#[repr(align(16))]
22+
pub struct Align16(u128);
23+
24+
// CHECK: @ptr_alignment_helper({}** {{.*}}align [[PTR_ALIGNMENT:[0-9]+]]
25+
#[no_mangle]
26+
pub fn ptr_alignment_helper(x: &&()) {}
27+
2128
// CHECK-LABEL: @load_ref
2229
#[no_mangle]
2330
pub fn load_ref<'a>(x: &&'a i32) -> &'a i32 {
24-
// Alignment of a reference itself is target dependent, so just match any alignment:
25-
// the main thing we care about here is !nonnull and !noundef.
26-
// CHECK: load i32*, i32** %x, align {{[0-9]+}}, !nonnull !{{[0-9]+}}, !noundef !{{[0-9]+}}
31+
// CHECK: load i32*, i32** %x, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META:[0-9]+]], !noundef !{{[0-9]+}}
32+
*x
33+
}
34+
35+
// CHECK-LABEL: @load_ref_higher_alignment
36+
#[no_mangle]
37+
pub fn load_ref_higher_alignment<'a>(x: &&'a Align16) -> &'a Align16 {
38+
// CHECK: load {{%Align16|i128}}*, {{%Align16|i128}}** %x, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_16_META:[0-9]+]], !noundef !{{[0-9]+}}
39+
*x
40+
}
41+
42+
// CHECK-LABEL: @load_scalar_pair
43+
#[no_mangle]
44+
pub fn load_scalar_pair<'a>(x: &(&'a i32, &'a Align16)) -> (&'a i32, &'a Align16) {
45+
// CHECK: load i32*, i32** %{{.+}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META]], !noundef !{{[0-9]+}}
46+
// CHECK: load i64*, i64** %{{.+}}, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_16_META]], !noundef !{{[0-9]+}}
47+
*x
48+
}
49+
50+
// CHECK-LABEL: @load_raw_pointer
51+
#[no_mangle]
52+
pub fn load_raw_pointer<'a>(x: &*const i32) -> *const i32 {
53+
// loaded raw pointer should not have !nonnull, !align, or !noundef metadata
54+
// CHECK: load i32*, i32** %x, align [[PTR_ALIGNMENT]]{{$}}
2755
*x
2856
}
2957

3058
// CHECK-LABEL: @load_box
3159
#[no_mangle]
3260
pub fn load_box<'a>(x: Box<Box<i32>>) -> Box<i32> {
33-
// Alignment of a box itself is target dependent, so just match any alignment:
34-
// the main thing we care about here is !nonnull and !noundef.
35-
// CHECK: load i32*, i32** %x, align {{[0-9]+}}, !nonnull !{{[0-9]+}}, !noundef !{{[0-9]+}}
61+
// CHECK: load i32*, i32** %x, align [[PTR_ALIGNMENT]], !nonnull !{{[0-9]+}}, !align ![[ALIGN_4_META]], !noundef !{{[0-9]+}}
3662
*x
3763
}
3864

@@ -120,5 +146,7 @@ pub fn small_struct_alignment(x: Bytes) -> Bytes {
120146
x
121147
}
122148

123-
// CHECK: ![[BOOL_RANGE]] = !{i8 0, i8 2}
124-
// CHECK: ![[NONZEROU16_RANGE]] = !{i16 1, i16 0}
149+
// CHECK-DAG: ![[BOOL_RANGE]] = !{i8 0, i8 2}
150+
// CHECK-DAG: ![[NONZEROU16_RANGE]] = !{i16 1, i16 0}
151+
// CHECK-DAG: ![[ALIGN_4_META]] = !{i64 4}
152+
// CHECK-DAG: ![[ALIGN_16_META]] = !{i64 16}

0 commit comments

Comments
 (0)