Skip to content

Commit f67692a

Browse files
committed
Expand to a call to compare_bytes instead
1 parent f2018e8 commit f67692a

File tree

9 files changed

+177
-37
lines changed

9 files changed

+177
-37
lines changed

compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, GenericArg, MetaItem, Mutability, Safety};
1+
use rustc_ast::{
2+
BinOpKind, BlockCheckMode, BorrowKind, Expr, ExprKind, GenericArg, MetaItem, MutTy, Mutability,
3+
Safety, TyKind, UnsafeSource,
4+
};
25
use rustc_expand::base::{Annotatable, ExtCtxt};
36
use rustc_span::{Ident, Span, kw, sym};
47
use thin_vec::thin_vec;
@@ -189,20 +192,44 @@ fn get_substructure_equality_expr(
189192
span,
190193
true,
191194
cx.std_path(&[sym::intrinsics, sym::can_compare_bitwise]),
192-
vec![GenericArg::Type(self_ty)],
195+
vec![GenericArg::Type(self_ty.clone())],
193196
));
194197
let cond = cx.expr_call(span, path, thin_vec![]);
195198

196199
let [_self, rhs] = &substructure.selflike_args[..] else {
197200
cx.dcx().span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`");
198201
};
199202

200-
// Construct intrinsics::compare_bitwise(self, other)
201-
let compare_bitwise = cx.std_path(&[sym::intrinsics, sym::compare_bitwise]);
202-
let call_compare_bitwise =
203-
cx.expr_call_global(span, compare_bitwise, thin_vec![cx.expr_self(span), rhs.clone()]);
203+
// Construct intrinsics::compare_bitwise(
204+
// self as *const Self as *const u8,
205+
// other as *const Self as *const u8,
206+
//
207+
// );
208+
let self_ptr_ty = cx.ty(span, TyKind::Ptr(MutTy { ty: self_ty, mutbl: Mutability::Not }));
209+
let u8_ty = cx.ty_ident(span, Ident::with_dummy_span(sym::u8));
210+
let u8_ptr_ty = cx.ty(span, TyKind::Ptr(MutTy { ty: u8_ty, mutbl: Mutability::Not }));
204211

205-
cx.expr_if(span, cond, call_compare_bitwise, Some(field_comparison))
212+
let self_ptr = cx.expr_cast(span, cx.expr_self(span), self_ptr_ty.clone());
213+
let self_ptr_u8 = cx.expr_cast(span, self_ptr, u8_ptr_ty.clone());
214+
215+
let other_ptr = cx.expr_cast(span, rhs.clone(), self_ptr_ty);
216+
let other_ptr_u8 = cx.expr_cast(span, other_ptr, u8_ptr_ty);
217+
218+
let size_of_val = cx.std_path(&[sym::intrinsics, sym::size_of_val]);
219+
let size = cx.expr_call_global(span, size_of_val, thin_vec![cx.expr_self(span)]);
220+
221+
let compare_bytes = cx.std_path(&[sym::intrinsics, sym::compare_bytes]);
222+
223+
let call_compare_bytes =
224+
cx.expr_call_global(span, compare_bytes, thin_vec![self_ptr_u8, other_ptr_u8, size]);
225+
226+
let mut call = cx.block_expr(call_compare_bytes);
227+
call.rules = BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated);
228+
let call = cx.expr_block(call);
229+
230+
let is_eq = cx.expr_binary(span, BinOpKind::Eq, call, cx.expr_i32(span, 0));
231+
232+
cx.expr_if(span, cond, is_eq, Some(field_comparison))
206233
} else {
207234
field_comparison
208235
}

compiler/rustc_expand/src/build.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,11 @@ impl<'a> ExtCtxt<'a> {
394394
let pathexpr = self.expr_path(self.path_global(sp, fn_path));
395395
self.expr_call(sp, pathexpr, args)
396396
}
397+
398+
pub fn expr_cast(&self, span: Span, src: Box<Expr>, ty: Box<ast::Ty>) -> Box<Expr> {
399+
self.expr(span, ast::ExprKind::Cast(src, ty))
400+
}
401+
397402
pub fn expr_block(&self, b: Box<ast::Block>) -> Box<ast::Expr> {
398403
self.expr(b.span, ast::ExprKind::Block(b, None))
399404
}
@@ -445,6 +450,12 @@ impl<'a> ExtCtxt<'a> {
445450
self.expr(span, ast::ExprKind::Lit(lit))
446451
}
447452

453+
pub fn expr_i32(&self, span: Span, n: u32) -> Box<ast::Expr> {
454+
let suffix = Some(ast::IntTy::I32.name());
455+
let lit = token::Lit::new(token::Integer, sym::integer(n), suffix);
456+
self.expr(span, ast::ExprKind::Lit(lit))
457+
}
458+
448459
pub fn expr_bool(&self, span: Span, value: bool) -> Box<ast::Expr> {
449460
let lit = token::Lit::new(token::Bool, if value { kw::True } else { kw::False }, None);
450461
self.expr(span, ast::ExprKind::Lit(lit))

library/core/src/intrinsics/mod.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2585,21 +2585,6 @@ pub const unsafe fn typed_swap_nonoverlapping<T>(x: *mut T, y: *mut T) {
25852585
#[rustc_intrinsic_const_stable_indirect]
25862586
pub const fn can_compare_bitwise<T: ?Sized>() -> bool;
25872587

2588-
#[rustc_nounwind]
2589-
#[inline]
2590-
#[rustc_intrinsic]
2591-
#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
2592-
#[miri::intrinsic_fallback_is_spec]
2593-
pub const fn compare_bitwise<T: ?Sized>(a: &T, b: &T) -> bool {
2594-
// SAFETY: These pointers were originally references to the same memory.
2595-
unsafe {
2596-
let len = size_of_val(a);
2597-
let a = ptr::from_ref(a).cast::<u8>();
2598-
let b = ptr::from_ref(b).cast::<u8>();
2599-
compare_bytes(a, b, len) == 0
2600-
}
2601-
}
2602-
26032588
/// Returns whether we should perform some UB-checking at runtime. This eventually evaluates to
26042589
/// `cfg!(ub_checks)`, but behaves different from `cfg!` when mixing crates built with different
26052590
/// flags: if the crate has UB checks enabled or carries the `#[rustc_preserve_ub_checks]`

tests/mir-opt/pre-codegen/derived_partialeq.cmp_no_padding.PreCodegen.after.mir

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,45 @@ fn cmp_no_padding(_1: &NoPadding, _2: &NoPadding) -> bool {
66
let mut _0: bool;
77
scope 1 (inlined std::cmp::impls::<impl PartialEq for &NoPadding>::eq) {
88
scope 2 (inlined <NoPadding as PartialEq>::eq) {
9+
let mut _3: *const NoPadding;
10+
let mut _4: *const u8;
11+
let mut _5: *const NoPadding;
12+
let mut _6: *const u8;
13+
let mut _7: *const NoPadding;
14+
let mut _8: usize;
15+
let mut _9: i32;
916
}
1017
}
1118

1219
bb0: {
13-
_0 = compare_bitwise::<NoPadding>(move _1, move _2) -> [return: bb1, unwind unreachable];
20+
StorageLive(_9);
21+
StorageLive(_4);
22+
StorageLive(_3);
23+
_3 = &raw const (*_1);
24+
_4 = copy _3 as *const u8 (PtrToPtr);
25+
StorageDead(_3);
26+
StorageLive(_6);
27+
StorageLive(_5);
28+
_5 = &raw const (*_2);
29+
_6 = copy _5 as *const u8 (PtrToPtr);
30+
StorageDead(_5);
31+
StorageLive(_8);
32+
StorageLive(_7);
33+
_7 = &raw const (*_1);
34+
_8 = std::intrinsics::size_of_val::<NoPadding>(move _7) -> [return: bb1, unwind unreachable];
1435
}
1536

1637
bb1: {
38+
StorageDead(_7);
39+
_9 = compare_bytes(move _4, move _6, move _8) -> [return: bb2, unwind unreachable];
40+
}
41+
42+
bb2: {
43+
StorageDead(_8);
44+
StorageDead(_6);
45+
StorageDead(_4);
46+
_0 = Eq(move _9, const 0_i32);
47+
StorageDead(_9);
1748
return;
1849
}
1950
}

tests/mir-opt/pre-codegen/derived_partialeq.cmp_no_padding_after_opt.PreCodegen.after.mir

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,45 @@ fn cmp_no_padding_after_opt(_1: &NoPaddingAfterOpt, _2: &NoPaddingAfterOpt) -> b
66
let mut _0: bool;
77
scope 1 (inlined std::cmp::impls::<impl PartialEq for &NoPaddingAfterOpt>::eq) {
88
scope 2 (inlined <NoPaddingAfterOpt as PartialEq>::eq) {
9+
let mut _3: *const NoPaddingAfterOpt;
10+
let mut _4: *const u8;
11+
let mut _5: *const NoPaddingAfterOpt;
12+
let mut _6: *const u8;
13+
let mut _7: *const NoPaddingAfterOpt;
14+
let mut _8: usize;
15+
let mut _9: i32;
916
}
1017
}
1118

1219
bb0: {
13-
_0 = compare_bitwise::<NoPaddingAfterOpt>(move _1, move _2) -> [return: bb1, unwind unreachable];
20+
StorageLive(_9);
21+
StorageLive(_4);
22+
StorageLive(_3);
23+
_3 = &raw const (*_1);
24+
_4 = copy _3 as *const u8 (PtrToPtr);
25+
StorageDead(_3);
26+
StorageLive(_6);
27+
StorageLive(_5);
28+
_5 = &raw const (*_2);
29+
_6 = copy _5 as *const u8 (PtrToPtr);
30+
StorageDead(_5);
31+
StorageLive(_8);
32+
StorageLive(_7);
33+
_7 = &raw const (*_1);
34+
_8 = std::intrinsics::size_of_val::<NoPaddingAfterOpt>(move _7) -> [return: bb1, unwind unreachable];
1435
}
1536

1637
bb1: {
38+
StorageDead(_7);
39+
_9 = compare_bytes(move _4, move _6, move _8) -> [return: bb2, unwind unreachable];
40+
}
41+
42+
bb2: {
43+
StorageDead(_8);
44+
StorageDead(_6);
45+
StorageDead(_4);
46+
_0 = Eq(move _9, const 0_i32);
47+
StorageDead(_9);
1748
return;
1849
}
1950
}

tests/mir-opt/pre-codegen/derived_partialeq.cmp_no_padding_array.PreCodegen.after.mir

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ fn cmp_no_padding_array(_1: &NoPaddingArray, _2: &NoPaddingArray) -> bool {
66
let mut _0: bool;
77
scope 1 (inlined std::cmp::impls::<impl PartialEq for &NoPaddingArray>::eq) {
88
scope 2 (inlined <NoPaddingArray as PartialEq>::eq) {
9+
let mut _3: *const NoPaddingArray;
10+
let mut _4: *const u8;
11+
let mut _5: *const NoPaddingArray;
12+
let mut _6: *const u8;
13+
let mut _7: *const NoPaddingArray;
14+
let mut _8: usize;
15+
let mut _9: i32;
916
scope 3 (inlined array::equality::<impl PartialEq for [u16; 2]>::eq) {
1017
scope 4 (inlined <u16 as array::equality::SpecArrayEq<u16, 2>>::spec_eq) {
1118
}
@@ -14,10 +21,34 @@ fn cmp_no_padding_array(_1: &NoPaddingArray, _2: &NoPaddingArray) -> bool {
1421
}
1522

1623
bb0: {
17-
_0 = compare_bitwise::<NoPaddingArray>(move _1, move _2) -> [return: bb1, unwind unreachable];
24+
StorageLive(_9);
25+
StorageLive(_4);
26+
StorageLive(_3);
27+
_3 = &raw const (*_1);
28+
_4 = copy _3 as *const u8 (PtrToPtr);
29+
StorageDead(_3);
30+
StorageLive(_6);
31+
StorageLive(_5);
32+
_5 = &raw const (*_2);
33+
_6 = copy _5 as *const u8 (PtrToPtr);
34+
StorageDead(_5);
35+
StorageLive(_8);
36+
StorageLive(_7);
37+
_7 = &raw const (*_1);
38+
_8 = std::intrinsics::size_of_val::<NoPaddingArray>(move _7) -> [return: bb1, unwind unreachable];
1839
}
1940

2041
bb1: {
42+
StorageDead(_7);
43+
_9 = compare_bytes(move _4, move _6, move _8) -> [return: bb2, unwind unreachable];
44+
}
45+
46+
bb2: {
47+
StorageDead(_8);
48+
StorageDead(_6);
49+
StorageDead(_4);
50+
_0 = Eq(move _9, const 0_i32);
51+
StorageDead(_9);
2152
return;
2253
}
2354
}

tests/mir-opt/pre-codegen/derived_partialeq.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub struct NoPadding {
1010

1111
// CHECK-LABEL: fn cmp_no_padding(
1212
fn cmp_no_padding(a: &NoPadding, b: &NoPadding) -> bool {
13-
// CHECK: compare_bitwise::<NoPadding>(
13+
// CHECK: compare_bytes(
1414
a == b
1515
}
1616
// EMIT_MIR derived_partialeq.cmp_no_padding.PreCodegen.after.mir
@@ -23,7 +23,7 @@ pub struct NoPaddingArray {
2323

2424
// CHECK-LABEL: fn cmp_no_padding_array(
2525
fn cmp_no_padding_array(a: &NoPaddingArray, b: &NoPaddingArray) -> bool {
26-
// CHECK: compare_bitwise::<NoPaddingArray>(
26+
// CHECK: compare_bytes(
2727
a == b
2828
}
2929
// EMIT_MIR derived_partialeq.cmp_no_padding_array.PreCodegen.after.mir
@@ -37,7 +37,7 @@ pub struct NoPaddingAfterOpt {
3737

3838
// CHECK-LABEL: fn cmp_no_padding_after_opt(
3939
fn cmp_no_padding_after_opt(a: &NoPaddingAfterOpt, b: &NoPaddingAfterOpt) -> bool {
40-
// CHECK: compare_bitwise::<NoPaddingAfterOpt>(
40+
// CHECK: compare_bytes(
4141
a == b
4242
}
4343
// EMIT_MIR derived_partialeq.cmp_no_padding_after_opt.PreCodegen.after.mir
@@ -50,7 +50,7 @@ pub struct HasPadding {
5050

5151
// CHECK-LABEL: fn cmp_has_padding(
5252
fn cmp_has_padding(a: &HasPadding, b: &HasPadding) -> bool {
53-
// CHECK-NOT: compare_bitwise
53+
// CHECK-NOT: compare_bytes(
5454
a == b
5555
}
5656
// EMIT_MIR derived_partialeq.cmp_has_padding.PreCodegen.after.mir
@@ -63,7 +63,7 @@ pub struct HasFloat {
6363

6464
// CHECK-LABEL: fn cmp_has_float(
6565
fn cmp_has_float(a: &HasFloat, b: &HasFloat) -> bool {
66-
// CHECK-NOT: compare_bitwise
66+
// CHECK-NOT: compare_bytes(
6767
a == b
6868
}
6969
// EMIT_MIR derived_partialeq.cmp_has_float.PreCodegen.after.mir

tests/ui/deriving/deriving-all-codegen.stdout

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,11 @@ impl ::core::cmp::PartialEq for Point {
136136
#[inline]
137137
fn eq(&self, other: &Point) -> bool {
138138
if ::core::intrinsics::can_compare_bitwise::<Self>() {
139-
::core::intrinsics::compare_bitwise(self, other)
139+
(unsafe {
140+
::core::intrinsics::compare_bytes(self as *const Self as
141+
*const u8, other as *const Self as *const u8,
142+
::core::intrinsics::size_of_val(self))
143+
}) == 0i32
140144
} else { self.x == other.x && self.y == other.y }
141145
}
142146
}
@@ -226,7 +230,11 @@ impl ::core::cmp::PartialEq for PackedPoint {
226230
#[inline]
227231
fn eq(&self, other: &PackedPoint) -> bool {
228232
if ::core::intrinsics::can_compare_bitwise::<Self>() {
229-
::core::intrinsics::compare_bitwise(self, other)
233+
(unsafe {
234+
::core::intrinsics::compare_bytes(self as *const Self as
235+
*const u8, other as *const Self as *const u8,
236+
::core::intrinsics::size_of_val(self))
237+
}) == 0i32
230238
} else {
231239
({ self.x }) == ({ other.x }) && ({ self.y }) == ({ other.y })
232240
}
@@ -490,7 +498,11 @@ impl ::core::cmp::PartialEq for Big {
490498
#[inline]
491499
fn eq(&self, other: &Big) -> bool {
492500
if ::core::intrinsics::can_compare_bitwise::<Self>() {
493-
::core::intrinsics::compare_bitwise(self, other)
501+
(unsafe {
502+
::core::intrinsics::compare_bytes(self as *const Self as
503+
*const u8, other as *const Self as *const u8,
504+
::core::intrinsics::size_of_val(self))
505+
}) == 0i32
494506
} else {
495507
self.b1 == other.b1 && self.b2 == other.b2 && self.b3 == other.b3
496508
&& self.b4 == other.b4 && self.b5 == other.b5 &&
@@ -613,7 +625,11 @@ impl ::core::cmp::PartialEq for Reorder {
613625
#[inline]
614626
fn eq(&self, other: &Reorder) -> bool {
615627
if ::core::intrinsics::can_compare_bitwise::<Self>() {
616-
::core::intrinsics::compare_bitwise(self, other)
628+
(unsafe {
629+
::core::intrinsics::compare_bytes(self as *const Self as
630+
*const u8, other as *const Self as *const u8,
631+
::core::intrinsics::size_of_val(self))
632+
}) == 0i32
617633
} else {
618634
self.b2 == other.b2 && self.b4 == other.b4 && self.b5 == other.b5
619635
&& self.b6 == other.b6 && self.b7 == other.b7 &&
@@ -859,7 +875,11 @@ impl<T: ::core::cmp::PartialEq + Trait, U: ::core::cmp::PartialEq>
859875
#[inline]
860876
fn eq(&self, other: &Generic<T, U>) -> bool {
861877
if ::core::intrinsics::can_compare_bitwise::<Self>() {
862-
::core::intrinsics::compare_bitwise(self, other)
878+
(unsafe {
879+
::core::intrinsics::compare_bytes(self as *const Self as
880+
*const u8, other as *const Self as *const u8,
881+
::core::intrinsics::size_of_val(self))
882+
}) == 0i32
863883
} else {
864884
self.t == other.t && self.ta == other.ta && self.u == other.u
865885
}
@@ -983,7 +1003,11 @@ impl<T: ::core::cmp::PartialEq + ::core::marker::Copy + Trait,
9831003
#[inline]
9841004
fn eq(&self, other: &PackedGeneric<T, U>) -> bool {
9851005
if ::core::intrinsics::can_compare_bitwise::<Self>() {
986-
::core::intrinsics::compare_bitwise(self, other)
1006+
(unsafe {
1007+
::core::intrinsics::compare_bytes(self as *const Self as
1008+
*const u8, other as *const Self as *const u8,
1009+
::core::intrinsics::size_of_val(self))
1010+
}) == 0i32
9871011
} else {
9881012
({ self.0 }) == ({ other.0 }) && ({ self.1 }) == ({ other.1 }) &&
9891013
({ self.2 }) == ({ other.2 })

tests/ui/stats/macro-stats.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ macro-stats Macro Name Uses Lines Avg Lines B
44
macro-stats -----------------------------------------------------------------------------------
55
macro-stats #[derive(Clone)] 8 67 8.4 1_879 234.9
66
macro-stats #[derive(PartialOrd)] 1 17 17.0 675 675.0
7+
macro-stats #[derive(PartialEq)] 1 15 15.0 604 604.0
78
macro-stats #[derive(Hash)] 2 17 8.5 577 288.5
89
macro-stats q! 1 26 26.0 519 519.0
910
macro-stats #[derive(Ord)] 1 15 15.0 503 503.0
1011
macro-stats #[derive(Default)] 2 16 8.0 403 201.5
11-
macro-stats #[derive(PartialEq)] 1 11 11.0 402 402.0
1212
macro-stats #[derive(Eq)] 1 11 11.0 325 325.0
1313
macro-stats #[derive(Debug)] 1 8 8.0 277 277.0
1414
macro-stats #[derive(Copy)] 1 2 2.0 61 61.0

0 commit comments

Comments
 (0)