Skip to content

Commit

Permalink
Enable GVN for AggregateKind::RawPtr
Browse files Browse the repository at this point in the history
  • Loading branch information
scottmcm committed May 12, 2024
1 parent ee97564 commit b4bbd3a
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 3 deletions.
19 changes: 16 additions & 3 deletions compiler/rustc_mir_transform/src/gvn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ enum AggregateTy<'tcx> {
Array,
Tuple,
Def(DefId, ty::GenericArgsRef<'tcx>),
/// Starting from `*const ()` and `usize` can give you any slice type,
/// so we just record the full type of the pointer here.
RawPtr { pointer_ty: Ty<'tcx> },
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -385,6 +388,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
AggregateTy::Def(def_id, args) => {
self.tcx.type_of(def_id).instantiate(self.tcx, args)
}
AggregateTy::RawPtr { pointer_ty } => pointer_ty,
};
let variant = if ty.is_enum() { Some(variant) } else { None };
let ty = self.ecx.layout_of(ty).ok()?;
Expand All @@ -399,7 +403,13 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
};
for (field_index, op) in fields.into_iter().enumerate() {
let field_dest = self.ecx.project_field(&variant_dest, field_index).ok()?;
self.ecx.copy_op(op, &field_dest).ok()?;
if let AggregateTy::RawPtr { .. } = kind && field_index == 0 {
// The pointer field might be any thin pointer type,
// so avoid ICEing for a type mismatch.
self.ecx.copy_op_allow_transmute(op, &field_dest).ok()?;
} else {
self.ecx.copy_op(op, &field_dest).ok()?;
}
}
self.ecx.write_discriminant(variant.unwrap_or(FIRST_VARIANT), &dest).ok()?;
self.ecx
Expand Down Expand Up @@ -927,8 +937,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
}
// Do not track unions.
AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
// FIXME: Do the extra work to GVN `from_raw_parts`
AggregateKind::RawPtr(..) => return None,
AggregateKind::RawPtr(pointee_ty, mtbl) => {
assert_eq!(fields.len(), 2);
let pointer_ty = Ty::new_ptr(self.tcx, pointee_ty, mtbl);
(AggregateTy::RawPtr { pointer_ty }, FIRST_VARIANT)
}
};

let fields: Option<Vec<_>> = fields
Expand Down
12 changes: 12 additions & 0 deletions tests/mir-opt/gvn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,16 @@ fn non_freeze<T: Copy>(x: T) {
)
}

// Check that we can const-prop into `from_raw_parts`
fn slice_index(x: &[i32]) -> *const [i32] {
// CHECK-LABEL: fn slice_index(
// CHECK: _0 = *const [i32] from
// CHECK-SAME: const 123_usize);
let ptr = x.as_ptr();
let len = 123;
std::intrinsics::aggregate_raw_ptr(ptr, len)
}

fn main() {
subexpression_elimination(2, 4, 5);
wrap_unwrap(5);
Expand All @@ -805,6 +815,7 @@ fn main() {
wide_ptr_integer();
borrowed(5);
non_freeze(5);
slice_index(&[1]);
}

#[inline(never)]
Expand Down Expand Up @@ -838,3 +849,4 @@ fn identity<T>(x: T) -> T {
// EMIT_MIR gvn.wide_ptr_integer.GVN.diff
// EMIT_MIR gvn.borrowed.GVN.diff
// EMIT_MIR gvn.non_freeze.GVN.diff
// EMIT_MIR gvn.slice_index.GVN.diff
48 changes: 48 additions & 0 deletions tests/mir-opt/gvn.slice_index.GVN.panic-abort.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
- // MIR for `slice_index` before GVN
+ // MIR for `slice_index` after GVN

fn slice_index(_1: &[i32]) -> *const [i32] {
debug x => _1;
let mut _0: *const [i32];
let _2: *const i32;
let mut _3: &[i32];
let mut _5: *const i32;
let mut _6: usize;
scope 1 {
debug ptr => _2;
let _4: usize;
scope 2 {
debug len => _4;
}
}

bb0: {
- StorageLive(_2);
+ nop;
StorageLive(_3);
_3 = &(*_1);
_2 = core::slice::<impl [i32]>::as_ptr(move _3) -> [return: bb1, unwind unreachable];
}

bb1: {
StorageDead(_3);
- StorageLive(_4);
+ nop;
_4 = const 123_usize;
StorageLive(_5);
_5 = _2;
StorageLive(_6);
- _6 = _4;
- _0 = *const [i32] from (move _5, move _6);
+ _6 = const 123_usize;
+ _0 = *const [i32] from (_2, const 123_usize);
StorageDead(_6);
StorageDead(_5);
- StorageDead(_4);
- StorageDead(_2);
+ nop;
+ nop;
return;
}
}

48 changes: 48 additions & 0 deletions tests/mir-opt/gvn.slice_index.GVN.panic-unwind.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
- // MIR for `slice_index` before GVN
+ // MIR for `slice_index` after GVN

fn slice_index(_1: &[i32]) -> *const [i32] {
debug x => _1;
let mut _0: *const [i32];
let _2: *const i32;
let mut _3: &[i32];
let mut _5: *const i32;
let mut _6: usize;
scope 1 {
debug ptr => _2;
let _4: usize;
scope 2 {
debug len => _4;
}
}

bb0: {
- StorageLive(_2);
+ nop;
StorageLive(_3);
_3 = &(*_1);
_2 = core::slice::<impl [i32]>::as_ptr(move _3) -> [return: bb1, unwind continue];
}

bb1: {
StorageDead(_3);
- StorageLive(_4);
+ nop;
_4 = const 123_usize;
StorageLive(_5);
_5 = _2;
StorageLive(_6);
- _6 = _4;
- _0 = *const [i32] from (move _5, move _6);
+ _6 = const 123_usize;
+ _0 = *const [i32] from (_2, const 123_usize);
StorageDead(_6);
StorageDead(_5);
- StorageDead(_4);
- StorageDead(_2);
+ nop;
+ nop;
return;
}
}

0 comments on commit b4bbd3a

Please sign in to comment.