Skip to content

Commit 07fb5ee

Browse files
committed
Adjust the threshold to look at the ABI, not just the size
1 parent 6444f24 commit 07fb5ee

File tree

2 files changed

+36
-12
lines changed

2 files changed

+36
-12
lines changed

compiler/rustc_codegen_llvm/src/intrinsic.rs

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -297,28 +297,40 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
297297
}
298298

299299
sym::raw_eq => {
300+
use abi::Abi::*;
300301
let tp_ty = substs.type_at(0);
301-
let (size, align) = self.size_and_align_of(tp_ty);
302+
let layout = self.layout_of(tp_ty).layout;
303+
let use_integer_compare = match layout.abi {
304+
Scalar(_) | ScalarPair(_, _) => true,
305+
Uninhabited | Vector { .. } => false,
306+
Aggregate { .. } => {
307+
// For rusty ABIs, small aggregates are actually passed
308+
// as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
309+
// so we re-use that same threshold here.
310+
layout.size <= self.data_layout().pointer_size * 2
311+
}
312+
};
313+
302314
let a = args[0].immediate();
303315
let b = args[1].immediate();
304-
if size.bytes() == 0 {
316+
if layout.size.bytes() == 0 {
305317
self.const_bool(true)
306-
} else if size > self.data_layout().pointer_size * 4 {
318+
} else if use_integer_compare {
319+
let integer_ty = self.type_ix(layout.size.bits());
320+
let ptr_ty = self.type_ptr_to(integer_ty);
321+
let a_ptr = self.bitcast(a, ptr_ty);
322+
let a_val = self.load(a_ptr, layout.align.abi);
323+
let b_ptr = self.bitcast(b, ptr_ty);
324+
let b_val = self.load(b_ptr, layout.align.abi);
325+
self.icmp(IntPredicate::IntEQ, a_val, b_val)
326+
} else {
307327
let i8p_ty = self.type_i8p();
308328
let a_ptr = self.bitcast(a, i8p_ty);
309329
let b_ptr = self.bitcast(b, i8p_ty);
310-
let n = self.const_usize(size.bytes());
330+
let n = self.const_usize(layout.size.bytes());
311331
let llfn = self.get_intrinsic("memcmp");
312332
let cmp = self.call(llfn, &[a_ptr, b_ptr, n], None);
313333
self.icmp(IntPredicate::IntEQ, cmp, self.const_i32(0))
314-
} else {
315-
let integer_ty = self.type_ix(size.bits());
316-
let ptr_ty = self.type_ptr_to(integer_ty);
317-
let a_ptr = self.bitcast(a, ptr_ty);
318-
let a_val = self.load(a_ptr, align);
319-
let b_ptr = self.bitcast(b, ptr_ty);
320-
let b_val = self.load(b_ptr, align);
321-
self.icmp(IntPredicate::IntEQ, a_val, b_val)
322334
}
323335
}
324336

src/test/codegen/array-equality.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ pub fn array_eq_ref(a: &[u16; 6], b: &[u16; 6]) -> bool {
2323
a == b
2424
}
2525

26+
// CHECK-LABEL: @array_eq_value_still_passed_by_pointer
27+
#[no_mangle]
28+
pub fn array_eq_value_still_passed_by_pointer(a: [u16; 9], b: [u16; 9]) -> bool {
29+
// CHECK-NEXT: start:
30+
// CHECK-NEXT: bitcast
31+
// CHECK-NEXT: bitcast
32+
// CHECK-NEXT: %[[CMP:.+]] = tail call i32 @{{bcmp|memcmp}}(i8* nonnull dereferenceable(18) %{{.+}}, i8* nonnull dereferenceable(18) %{{.+}}, i64 18)
33+
// CHECK-NEXT: %[[EQ:.+]] = icmp eq i32 %[[CMP]], 0
34+
// CHECK-NEXT: ret i1 %[[EQ]]
35+
a == b
36+
}
37+
2638
// CHECK-LABEL: @array_eq_long
2739
#[no_mangle]
2840
pub fn array_eq_long(a: &[u16; 1234], b: &[u16; 1234]) -> bool {

0 commit comments

Comments
 (0)