Skip to content

Commit 69ae423

Browse files
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.
1 parent 4ce3749 commit 69ae423

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
@@ -478,6 +478,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
478478
bx: &mut Builder<'a, 'll, 'tcx>,
479479
load: &'ll Value,
480480
scalar: abi::Scalar,
481+
layout: TyAndLayout<'tcx>,
482+
offset: Size,
481483
) {
482484
if !scalar.is_always_valid(bx) {
483485
bx.noundef_metadata(load);
@@ -489,10 +491,18 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
489491
bx.range_metadata(load, scalar.valid_range);
490492
}
491493
}
492-
abi::Pointer if !scalar.valid_range.contains(0) => {
493-
bx.nonnull_metadata(load);
494+
abi::Pointer => {
495+
if !scalar.valid_range.contains(0) {
496+
bx.nonnull_metadata(load);
497+
}
498+
499+
if let Some(pointee) = layout.pointee_info_at(bx, offset) {
500+
if let Some(_) = pointee.safe {
501+
bx.align_metadata(load, pointee.align);
502+
}
503+
}
494504
}
495-
_ => {}
505+
abi::F32 | abi::F64 => {}
496506
}
497507
}
498508

@@ -510,7 +520,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
510520
let llval = const_llval.unwrap_or_else(|| {
511521
let load = self.load(place.layout.llvm_type(self), place.llval, place.align);
512522
if let abi::Abi::Scalar(scalar) = place.layout.abi {
513-
scalar_load_metadata(self, load, scalar);
523+
scalar_load_metadata(self, load, scalar, place.layout, Size::ZERO);
514524
}
515525
load
516526
});
@@ -519,17 +529,17 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
519529
let b_offset = a.value.size(self).align_to(b.value.align(self).abi);
520530
let pair_ty = place.layout.llvm_type(self);
521531

522-
let mut load = |i, scalar: abi::Scalar, align| {
532+
let mut load = |i, scalar: abi::Scalar, layout, align, offset| {
523533
let llptr = self.struct_gep(pair_ty, place.llval, i as u64);
524534
let llty = place.layout.scalar_pair_element_llvm_type(self, i, false);
525535
let load = self.load(llty, llptr, align);
526-
scalar_load_metadata(self, load, scalar);
536+
scalar_load_metadata(self, load, scalar, layout, offset);
527537
self.to_immediate_scalar(load, scalar)
528538
};
529539

530540
OperandValue::Pair(
531-
load(0, a, place.align),
532-
load(1, b, place.align.restrict_for_offset(b_offset)),
541+
load(0, a, place.layout, place.align, Size::ZERO),
542+
load(1, b, place.layout, place.align.restrict_for_offset(b_offset), b_offset),
533543
)
534544
} else {
535545
OperandValue::Ref(place.llval, None, place.align)
@@ -1219,6 +1229,18 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
12191229
}
12201230
}
12211231

1232+
fn align_metadata(&mut self, load: &'ll Value, align: Align) {
1233+
unsafe {
1234+
let v = [self.cx.const_u64(align.bytes())];
1235+
1236+
llvm::LLVMSetMetadata(
1237+
load,
1238+
llvm::MD_align as c_uint,
1239+
llvm::LLVMMDNodeInContext(self.cx.llcx, v.as_ptr(), v.len() as c_uint),
1240+
);
1241+
}
1242+
}
1243+
12221244
fn noundef_metadata(&mut self, load: &'ll Value) {
12231245
unsafe {
12241246
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*, %Align16** %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)