diff --git a/tests/mir-opt/gvn_const_eval_polymorphic.no_optimize.GVN.diff b/tests/mir-opt/gvn_const_eval_polymorphic.no_optimize.GVN.diff new file mode 100644 index 0000000000000..a91561ba304b8 --- /dev/null +++ b/tests/mir-opt/gvn_const_eval_polymorphic.no_optimize.GVN.diff @@ -0,0 +1,12 @@ +- // MIR for `no_optimize` before GVN ++ // MIR for `no_optimize` after GVN + + fn no_optimize() -> bool { + let mut _0: bool; + + bb0: { + _0 = Eq(const no_optimize::::{constant#0}, const no_optimize::::{constant#1}); + return; + } + } + diff --git a/tests/mir-opt/gvn_const_eval_polymorphic.optimize_false.GVN.diff b/tests/mir-opt/gvn_const_eval_polymorphic.optimize_false.GVN.diff new file mode 100644 index 0000000000000..bdfa2987b23cd --- /dev/null +++ b/tests/mir-opt/gvn_const_eval_polymorphic.optimize_false.GVN.diff @@ -0,0 +1,13 @@ +- // MIR for `optimize_false` before GVN ++ // MIR for `optimize_false` after GVN + + fn optimize_false() -> bool { + let mut _0: bool; + + bb0: { +- _0 = Eq(const optimize_false::::{constant#0}, const optimize_false::::{constant#1}); ++ _0 = const false; + return; + } + } + diff --git a/tests/mir-opt/gvn_const_eval_polymorphic.optimize_true.GVN.diff b/tests/mir-opt/gvn_const_eval_polymorphic.optimize_true.GVN.diff new file mode 100644 index 0000000000000..dc337d43fb04d --- /dev/null +++ b/tests/mir-opt/gvn_const_eval_polymorphic.optimize_true.GVN.diff @@ -0,0 +1,13 @@ +- // MIR for `optimize_true` before GVN ++ // MIR for `optimize_true` after GVN + + fn optimize_true() -> bool { + let mut _0: bool; + + bb0: { +- _0 = Eq(const optimize_true::::{constant#0}, const optimize_true::::{constant#1}); ++ _0 = const true; + return; + } + } + diff --git a/tests/mir-opt/gvn_const_eval_polymorphic.rs b/tests/mir-opt/gvn_const_eval_polymorphic.rs new file mode 100644 index 0000000000000..7320ad947ff2e --- /dev/null +++ b/tests/mir-opt/gvn_const_eval_polymorphic.rs @@ -0,0 +1,57 @@ +//@ test-mir-pass: GVN +//@ compile-flags: --crate-type lib + +//! Regressions test for a mis-optimization where some functions +//! (`type_id` / `type_name` / `needs_drop`) could be evaluated in +//! a generic context, even though their value depends on some type +//! parameter `T`. +//! +//! In particular, `type_name_of_val(&generic::)` was incorrectly +//! evaluated to the string "crate_name::generic::", and +//! `no_optimize` was incorrectly optimized to `false`. + +#![feature(const_type_name)] + +fn generic() {} + +const fn type_name_contains_i32(_: &T) -> bool { + let pattern = b"i32"; + let name = std::any::type_name::().as_bytes(); + let mut i = 0; + 'outer: while i < name.len() - pattern.len() + 1 { + let mut j = 0; + while j < pattern.len() { + if name[i + j] != pattern[j] { + i += 1; + continue 'outer; + } + j += 1; + } + return true; + } + false +} + +// EMIT_MIR gvn_const_eval_polymorphic.optimize_true.GVN.diff +fn optimize_true() -> bool { + // CHECK-LABEL: fn optimize_true( + // CHECK: _0 = const true; + // CHECK-NEXT: return; + (const { type_name_contains_i32(&generic::) }) == const { true } +} + +// EMIT_MIR gvn_const_eval_polymorphic.optimize_false.GVN.diff +fn optimize_false() -> bool { + // CHECK-LABEL: fn optimize_false( + // CHECK: _0 = const false; + // CHECK-NEXT: return; + (const { type_name_contains_i32(&generic::) }) == const { true } +} + +// EMIT_MIR gvn_const_eval_polymorphic.no_optimize.GVN.diff +fn no_optimize() -> bool { + // CHECK-LABEL: fn no_optimize( + // CHECK: _0 = Eq(const no_optimize::::{constant#0}, const no_optimize::::{constant#1}); + // CHECK-NEXT: return; + (const { type_name_contains_i32(&generic::) }) == const { true } +} diff --git a/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff b/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff deleted file mode 100644 index 2f83f54d2afdb..0000000000000 --- a/tests/mir-opt/gvn_type_id_polymorphic.cursed_is_i32.GVN.diff +++ /dev/null @@ -1,12 +0,0 @@ -- // MIR for `cursed_is_i32` before GVN -+ // MIR for `cursed_is_i32` after GVN - - fn cursed_is_i32() -> bool { - let mut _0: bool; - - bb0: { - _0 = Eq(const cursed_is_i32::::{constant#0}, const cursed_is_i32::::{constant#1}); - return; - } - } - diff --git a/tests/mir-opt/gvn_type_id_polymorphic.rs b/tests/mir-opt/gvn_type_id_polymorphic.rs deleted file mode 100644 index 39bc5c24ecc68..0000000000000 --- a/tests/mir-opt/gvn_type_id_polymorphic.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ test-mir-pass: GVN -//@ compile-flags: -C opt-level=2 - -#![feature(core_intrinsics)] - -fn generic() {} - -const fn type_id_of_val(_: &T) -> u128 { - std::intrinsics::type_id::() -} - -// EMIT_MIR gvn_type_id_polymorphic.cursed_is_i32.GVN.diff -fn cursed_is_i32() -> bool { - // CHECK-LABEL: fn cursed_is_i32( - // CHECK: _0 = Eq(const cursed_is_i32::::{constant#0}, const cursed_is_i32::::{constant#1}); - // CHECK-NEXT: return; - (const { type_id_of_val(&generic::) } == const { type_id_of_val(&generic::) }) -} - -fn main() { - dbg!(cursed_is_i32::()); -}