diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index dd3f39eceadb6..1fd9f9e811671 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -1000,8 +1000,10 @@ impl<'ll> CodegenCx<'ll, '_> { ifn!("llvm.is.constant.i64", fn(t_i64) -> i1); ifn!("llvm.is.constant.i128", fn(t_i128) -> i1); ifn!("llvm.is.constant.isize", fn(t_isize) -> i1); + ifn!("llvm.is.constant.f16", fn(t_f16) -> i1); ifn!("llvm.is.constant.f32", fn(t_f32) -> i1); ifn!("llvm.is.constant.f64", fn(t_f64) -> i1); + ifn!("llvm.is.constant.f128", fn(t_f128) -> i1); ifn!("llvm.is.constant.ptr", fn(ptr) -> i1); ifn!("llvm.expect.i1", fn(i1, i1) -> i1); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index f5558723d11bf..abfe38d4c0cc6 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -192,14 +192,22 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { } sym::is_val_statically_known => { let intrinsic_type = args[0].layout.immediate_llvm_type(self.cx); - match self.type_kind(intrinsic_type) { - TypeKind::Pointer | TypeKind::Integer | TypeKind::Float | TypeKind::Double => { - self.call_intrinsic( - &format!("llvm.is.constant.{:?}", intrinsic_type), - &[args[0].immediate()], - ) + let kind = self.type_kind(intrinsic_type); + let intrinsic_name = match kind { + TypeKind::Pointer | TypeKind::Integer => { + Some(format!("llvm.is.constant.{intrinsic_type:?}")) } - _ => self.const_bool(false), + // LLVM float types' intrinsic names differ from their type names. + TypeKind::Half => Some(format!("llvm.is.constant.f16")), + TypeKind::Float => Some(format!("llvm.is.constant.f32")), + TypeKind::Double => Some(format!("llvm.is.constant.f64")), + TypeKind::FP128 => Some(format!("llvm.is.constant.f128")), + _ => None, + }; + if let Some(intrinsic_name) = intrinsic_name { + self.call_intrinsic(&intrinsic_name, &[args[0].immediate()]) + } else { + self.const_bool(false) } } sym::unlikely => self diff --git a/tests/codegen/is_val_statically_known.rs b/tests/codegen/is_val_statically_known.rs index 6af4f353a481c..fe432d3bcc4de 100644 --- a/tests/codegen/is_val_statically_known.rs +++ b/tests/codegen/is_val_statically_known.rs @@ -1,6 +1,7 @@ //@ compile-flags: --crate-type=lib -Zmerge-functions=disabled -O #![feature(core_intrinsics)] +#![feature(f16, f128)] use std::intrinsics::is_val_statically_known; @@ -49,7 +50,7 @@ pub fn _bool_false(b: bool) -> i32 { #[inline] pub fn _iref(a: &u8) -> i32 { - if unsafe { is_val_statically_known(a) } { 5 } else { 4 } + if is_val_statically_known(a) { 5 } else { 4 } } // CHECK-LABEL: @_iref_borrow( @@ -68,7 +69,7 @@ pub fn _iref_arg(a: &u8) -> i32 { #[inline] pub fn _slice_ref(a: &[u8]) -> i32 { - if unsafe { is_val_statically_known(a) } { 7 } else { 6 } + if is_val_statically_known(a) { 7 } else { 6 } } // CHECK-LABEL: @_slice_ref_borrow( @@ -84,3 +85,79 @@ pub fn _slice_ref_arg(a: &[u8]) -> i32 { // CHECK: ret i32 6 _slice_ref(a) } + +#[inline] +pub fn _f16(a: f16) -> i32 { + if is_val_statically_known(a) { 1 } else { 0 } +} + +// CHECK-LABEL: @_f16_true( +#[no_mangle] +pub fn _f16_true() -> i32 { + // CHECK: ret i32 1 + _f16(1.0) +} + +// CHECK-LABEL: @_f16_false( +#[no_mangle] +pub fn _f16_false(a: f16) -> i32 { + // CHECK: ret i32 0 + _f16(a) +} + +#[inline] +pub fn _f32(a: f32) -> i32 { + if is_val_statically_known(a) { 1 } else { 0 } +} + +// CHECK-LABEL: @_f32_true( +#[no_mangle] +pub fn _f32_true() -> i32 { + // CHECK: ret i32 1 + _f32(1.0) +} + +// CHECK-LABEL: @_f32_false( +#[no_mangle] +pub fn _f32_false(a: f32) -> i32 { + // CHECK: ret i32 0 + _f32(a) +} + +#[inline] +pub fn _f64(a: f64) -> i32 { + if is_val_statically_known(a) { 1 } else { 0 } +} + +// CHECK-LABEL: @_f64_true( +#[no_mangle] +pub fn _f64_true() -> i32 { + // CHECK: ret i32 1 + _f64(1.0) +} + +// CHECK-LABEL: @_f64_false( +#[no_mangle] +pub fn _f64_false(a: f64) -> i32 { + // CHECK: ret i32 0 + _f64(a) +} + +#[inline] +pub fn _f128(a: f128) -> i32 { + if is_val_statically_known(a) { 1 } else { 0 } +} + +// CHECK-LABEL: @_f128_true( +#[no_mangle] +pub fn _f128_true() -> i32 { + // CHECK: ret i32 1 + _f128(1.0) +} + +// CHECK-LABEL: @_f128_false( +#[no_mangle] +pub fn _f128_false(a: f128) -> i32 { + // CHECK: ret i32 0 + _f128(a) +}