diff --git a/src/intrinsics/mod.rs b/src/intrinsics/mod.rs index 52896fc7127..3e658cb1211 100644 --- a/src/intrinsics/mod.rs +++ b/src/intrinsics/mod.rs @@ -1115,6 +1115,45 @@ fn swap(bcx: &mut FunctionBuilder<'_>, v: Value) -> Value { ); ret.write_cvalue(fx, CValue::by_val(res, ret.layout())); }; + + raw_eq, (v lhs_ref, v rhs_ref) { + fn type_by_size(size: Size) -> Option { + Some(match size.bits() { + 8 => types::I8, + 16 => types::I16, + 32 => types::I32, + 64 => types::I64, + 128 => types::I128, + _ => return None, + }) + } + + let size = fx.layout_of(T).layout.size; + let is_eq_value = + if size == Size::ZERO { + // No bytes means they're trivially equal + fx.bcx.ins().bconst(types::B1, true) + } else if let Some(clty) = type_by_size(size) { + // Can't use `trusted` for these loads; they could be unaligned. + let mut flags = MemFlags::new(); + flags.set_notrap(); + let lhs_val = fx.bcx.ins().load(clty, flags, lhs_ref, 0); + let rhs_val = fx.bcx.ins().load(clty, flags, rhs_ref, 0); + fx.bcx.ins().icmp(IntCC::Equal, lhs_val, rhs_val) + } else { + // Just call `memcmp` (like slices do in core) when the + // size is too large or it's not a power-of-two. + let ptr_ty = pointer_ty(fx.tcx); + let signed_bytes = i64::try_from(size.bytes()).unwrap(); + let bytes_val = fx.bcx.ins().iconst(ptr_ty, signed_bytes); + let params = vec![AbiParam::new(ptr_ty); 3]; + let returns = vec![AbiParam::new(types::I32)]; + let args = &[lhs_ref, rhs_ref, bytes_val]; + let cmp = fx.lib_call("memcmp", params, returns, args)[0]; + fx.bcx.ins().icmp_imm(IntCC::Equal, cmp, 0) + }; + ret.write_cvalue(fx, CValue::by_val(is_eq_value, ret.layout())); + }; } if let Some((_, dest)) = destination { diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 171f39805f8..b6f5f5707fb 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -437,6 +437,12 @@ fn transmute_value<'tcx>( | (types::F32, types::I32) | (types::I64, types::F64) | (types::F64, types::I64) => fx.bcx.ins().bitcast(dst_ty, data), + + // Widen an abstract SSA boolean to something that can be stored in memory + (types::B1, types::I8 | types::I16 | types::I32 | types::I64 | types::I128) => { + fx.bcx.ins().bint(dst_ty, data) + } + _ if src_ty.is_vector() && dst_ty.is_vector() => { fx.bcx.ins().raw_bitcast(dst_ty, data) }