about summary refs log tree commit diff
diff options
context:
space:
mode:
authorScott McMurray <scottmcm@users.noreply.github.com>2021-05-30 18:04:07 -0700
committerScott McMurray <scottmcm@users.noreply.github.com>2021-07-08 14:55:57 -0700
commit12163534a94b24a8a754fffe6e601904c2c6f31f (patch)
treeef831ef9e1424d02ea23d9b7df94b1f7279183f8
parentb63b2f1e426016b24a9e552faf17f20f421f5034 (diff)
downloadrust-12163534a94b24a8a754fffe6e601904c2c6f31f.tar.gz
rust-12163534a94b24a8a754fffe6e601904c2c6f31f.zip
Implement the raw_eq intrinsic in codegen_cranelift
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs39
-rw-r--r--compiler/rustc_codegen_cranelift/src/value_and_place.rs6
2 files changed, 45 insertions, 0 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 52896fc7127..3e658cb1211 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -1115,6 +1115,45 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
             );
             ret.write_cvalue(fx, CValue::by_val(res, ret.layout()));
         };
+
+        raw_eq, <T>(v lhs_ref, v rhs_ref) {
+            fn type_by_size(size: Size) -> Option<Type> {
+                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/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
index 171f39805f8..b6f5f5707fb 100644
--- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs
+++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs
@@ -437,6 +437,12 @@ impl<'tcx> CPlace<'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)
                 }