diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 7f907bc630b2f..4c41068f2d85b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -7,7 +7,6 @@ use rustc_abi::{ }; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; -use rustc_data_structures::packed::Pu128; use rustc_hir::attrs::AttributeKind; use rustc_hir::attrs::lang_items::LangItem; use rustc_lint_defs::builtin::TAIL_CALL_TRACK_CALLER; @@ -454,39 +453,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let cmp = bx.icmp(IntPredicate::IntEQ, discr_value, llval); bx.cond_br_with_expect(cmp, lltarget, llotherwise, expect); } - } else if target_iter.len() == 2 - && self.mir[targets.otherwise()].is_empty_unreachable() - && targets.all_values().contains(&Pu128(0)) - && targets.all_values().contains(&Pu128(1)) - { - // This is the really common case for `bool`, `Option`, etc. - // By using `trunc nuw` we communicate that other values are - // impossible without needing `switch` or `assume`s. - let true_bb = targets.target_for_value(1); - let false_bb = targets.target_for_value(0); - let true_ll = helper.llbb_with_cleanup(self, true_bb); - let false_ll = helper.llbb_with_cleanup(self, false_bb); - - let expected_cond_value = if self.cx.sess().opts.optimize == OptLevel::No { - None - } else { - match (self.cold_blocks[true_bb], self.cold_blocks[false_bb]) { - // Same coldness, no expectation - (true, true) | (false, false) => None, - // Different coldness, expect the non-cold one - (true, false) => Some(false), - (false, true) => Some(true), - } - }; - - let bool_ty = bx.tcx().types.bool; - let cond = if switch_ty == bool_ty { - discr_value - } else { - let bool_llty = bx.immediate_backend_type(bx.layout_of(bool_ty)); - bx.unchecked_utrunc(discr_value, bool_llty) - }; - bx.cond_br_with_expect(cond, true_ll, false_ll, expected_cond_value); } else if self.cx.sess().opts.optimize == OptLevel::No && target_iter.len() == 2 && self.mir[targets.otherwise()].is_empty_unreachable() diff --git a/tests/codegen-llvm/enum/enum-two-variants-match.rs b/tests/codegen-llvm/enum/enum-two-variants-match.rs deleted file mode 100644 index a083bb00422c7..0000000000000 --- a/tests/codegen-llvm/enum/enum-two-variants-match.rs +++ /dev/null @@ -1,130 +0,0 @@ -//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -//@ only-64bit (because these discriminants are isize) - -#![crate_type = "lib"] - -// This directly tests what we emit for these matches, rather than what happens -// after optimization, so it doesn't need to worry about extra flags on the -// instructions and is less susceptible to being broken on LLVM updates. - -// CHECK-LABEL: @option_match -#[no_mangle] -pub fn option_match(x: Option) -> u16 { - // CHECK-NOT: %x = alloca - // CHECK: %[[OUT:.+]] = alloca [2 x i8] - // CHECK-NOT: %x = alloca - - // CHECK: %[[DISCR:.+]] = zext i32 %x.0 to i64 - // CHECK: %[[COND:.+]] = trunc nuw i64 %[[DISCR]] to i1 - // CHECK: br i1 %[[COND]], label %[[TRUE:[a-z0-9]+]], label %[[FALSE:[a-z0-9]+]] - - // CHECK: [[TRUE]]: - // CHECK: store i16 13, ptr %[[OUT]] - - // CHECK: [[FALSE]]: - // CHECK: store i16 42, ptr %[[OUT]] - - // CHECK: %[[RET:.+]] = load i16, ptr %[[OUT]] - // CHECK: ret i16 %[[RET]] - match x { - Some(_) => 13, - None => 42, - } -} - -// CHECK-LABEL: @result_match -#[no_mangle] -pub fn result_match(x: Result) -> u16 { - // CHECK-NOT: %x = alloca - // CHECK: %[[OUT:.+]] = alloca [2 x i8] - // CHECK-NOT: %x = alloca - - // CHECK: %[[COND:.+]] = trunc nuw i64 %x.0 to i1 - // CHECK: br i1 %[[COND]], label %[[TRUE:[a-z0-9]+]], label %[[FALSE:[a-z0-9]+]] - - // CHECK: [[TRUE]]: - // CHECK: store i16 13, ptr %[[OUT]] - - // CHECK: [[FALSE]]: - // CHECK: store i16 42, ptr %[[OUT]] - - // CHECK: %[[RET:.+]] = load i16, ptr %[[OUT]] - // CHECK: ret i16 %[[RET]] - match x { - Err(_) => 13, - Ok(_) => 42, - } -} - -// CHECK-LABEL: @option_bool_match( -#[no_mangle] -pub fn option_bool_match(x: Option) -> char { - // CHECK: %[[RAW:.+]] = load i8, ptr %x - // CHECK: %[[IS_NONE:.+]] = icmp eq i8 %[[RAW]], 2 - // CHECK: %[[OPT_DISCR:.+]] = select i1 %[[IS_NONE]], i64 0, i64 1 - // CHECK: %[[OPT_DISCR_T:.+]] = trunc nuw i64 %[[OPT_DISCR]] to i1 - // CHECK: br i1 %[[OPT_DISCR_T]], label %[[BB_SOME:.+]], label %[[BB_NONE:.+]] - - // CHECK: [[BB_SOME]]: - // CHECK: %[[FIELD:.+]] = load i8, ptr %x - // CHECK: %[[FIELD_T:.+]] = trunc nuw i8 %[[FIELD]] to i1 - // CHECK: br i1 %[[FIELD_T]] - match x { - None => 'n', - Some(false) => 'f', - Some(true) => 't', - } -} - -use std::cmp::Ordering::{self, *}; -// CHECK-LABEL: @option_ordering_match( -#[no_mangle] -pub fn option_ordering_match(x: Option) -> char { - // CHECK: %[[RAW:.+]] = load i8, ptr %x - // CHECK: %[[IS_NONE:.+]] = icmp eq i8 %[[RAW]], -2 - // CHECK: %[[OPT_DISCR:.+]] = select i1 %[[IS_NONE]], i64 0, i64 1 - // CHECK: %[[OPT_DISCR_T:.+]] = trunc nuw i64 %[[OPT_DISCR]] to i1 - // CHECK: br i1 %[[OPT_DISCR_T]], label %[[BB_SOME:.+]], label %[[BB_NONE:.+]] - - // CHECK: [[BB_SOME]]: - // CHECK: %[[FIELD:.+]] = load i8, ptr %x - // CHECK: switch i8 %[[FIELD]], label %[[UNREACHABLE:.+]] [ - // CHECK-NEXT: i8 -1, label - // CHECK-NEXT: i8 0, label - // CHECK-NEXT: i8 1, label - // CHECK-NEXT: ] - - // CHECK: [[UNREACHABLE]]: - // CHECK-NEXT: unreachable - match x { - None => '?', - Some(Less) => '<', - Some(Equal) => '=', - Some(Greater) => '>', - } -} - -// CHECK-LABEL: @option_nonzero_match( -#[no_mangle] -pub fn option_nonzero_match(x: Option>) -> u16 { - // CHECK: %[[OUT:.+]] = alloca [2 x i8] - - // CHECK: %[[IS_NONE:.+]] = icmp eq i16 %x, 0 - // CHECK: %[[OPT_DISCR:.+]] = select i1 %[[IS_NONE]], i64 0, i64 1 - // CHECK: %[[OPT_DISCR_T:.+]] = trunc nuw i64 %[[OPT_DISCR]] to i1 - // CHECK: br i1 %[[OPT_DISCR_T]], label %[[BB_SOME:.+]], label %[[BB_NONE:.+]] - - // CHECK: [[BB_SOME]]: - // CHECK: store i16 987, ptr %[[OUT]] - - // CHECK: [[BB_NONE]]: - // CHECK: store i16 123, ptr %[[OUT]] - - // CHECK: %[[RET:.+]] = load i16, ptr %[[OUT]] - // CHECK: ret i16 %[[RET]] - - match x { - None => 123, - Some(_) => 987, - } -} diff --git a/tests/codegen-llvm/try_question_mark_nop.rs b/tests/codegen-llvm/try_question_mark_nop.rs deleted file mode 100644 index a09fa0a49019d..0000000000000 --- a/tests/codegen-llvm/try_question_mark_nop.rs +++ /dev/null @@ -1,232 +0,0 @@ -//@ compile-flags: -Copt-level=3 -Z merge-functions=disabled -//@ edition: 2021 -//@ only-x86_64 - -#![crate_type = "lib"] -#![feature(try_blocks)] - -use std::ops::ControlFlow::{self, Break, Continue}; -use std::ptr::NonNull; - -// CHECK-LABEL: @option_nop_match_32 -#[no_mangle] -pub fn option_nop_match_32(x: Option) -> Option { - // CHECK: start: - // CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i32 %0 to i1 - - // CHECK-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i32 %1, i32 undef - // CHECK-NEXT: [[REG2:%.*]] = insertvalue { i32, i32 } poison, i32 %0, 0 - // CHECK-NEXT: [[REG3:%.*]] = insertvalue { i32, i32 } [[REG2]], i32 [[SELECT]], 1 - - // CHECK-NEXT: ret { i32, i32 } [[REG3]] - match x { - Some(x) => Some(x), - None => None, - } -} - -// CHECK-LABEL: @option_nop_traits_32 -#[no_mangle] -pub fn option_nop_traits_32(x: Option) -> Option { - // CHECK: start: - // CHECK-NEXT: %[[IS_SOME:.+]] = trunc nuw i32 %0 to i1 - // CHECK-NEXT: select i1 %[[IS_SOME]], i32 %1, i32 undef - // CHECK-NEXT: insertvalue { i32, i32 } - // CHECK-NEXT: insertvalue { i32, i32 } - // CHECK-NEXT: ret { i32, i32 } - try { x? } -} - -// CHECK-LABEL: @result_nop_match_32 -#[no_mangle] -pub fn result_nop_match_32(x: Result) -> Result { - // CHECK: start: - // CHECK-NEXT: insertvalue { i32, i32 } - // CHECK-NEXT: insertvalue { i32, i32 } - // CHECK-NEXT: ret { i32, i32 } - match x { - Ok(x) => Ok(x), - Err(x) => Err(x), - } -} - -// CHECK-LABEL: @result_nop_traits_32 -#[no_mangle] -pub fn result_nop_traits_32(x: Result) -> Result { - // CHECK: start: - // CHECK-NEXT: insertvalue { i32, i32 } - // CHECK-NEXT: insertvalue { i32, i32 } - // CHECK-NEXT: ret { i32, i32 } - try { x? } -} - -// CHECK-LABEL: @control_flow_nop_match_32 -#[no_mangle] -pub fn control_flow_nop_match_32(x: ControlFlow) -> ControlFlow { - // CHECK: start: - // CHECK-NEXT: insertvalue { i32, i32 } - // CHECK-NEXT: insertvalue { i32, i32 } - // CHECK-NEXT: ret { i32, i32 } - match x { - Continue(x) => Continue(x), - Break(x) => Break(x), - } -} - -// CHECK-LABEL: @control_flow_nop_traits_32 -#[no_mangle] -pub fn control_flow_nop_traits_32(x: ControlFlow) -> ControlFlow { - // CHECK: start: - // CHECK-NEXT: insertvalue { i32, i32 } - // CHECK-NEXT: insertvalue { i32, i32 } - // CHECK-NEXT: ret { i32, i32 } - try { x? } -} - -// CHECK-LABEL: @option_nop_match_64 -#[no_mangle] -pub fn option_nop_match_64(x: Option) -> Option { - // CHECK: start: - // CHECK-NEXT: [[TRUNC:%.*]] = trunc nuw i64 %0 to i1 - - // CHECK-NEXT: [[SELECT:%.*]] = select i1 [[TRUNC]], i64 %1, i64 undef - // CHECK-NEXT: [[REG2:%.*]] = insertvalue { i64, i64 } poison, i64 %0, 0 - // CHECK-NEXT: [[REG3:%.*]] = insertvalue { i64, i64 } [[REG2]], i64 [[SELECT]], 1 - - // CHECK-NEXT: ret { i64, i64 } [[REG3]] - match x { - Some(x) => Some(x), - None => None, - } -} - -// CHECK-LABEL: @option_nop_traits_64 -#[no_mangle] -pub fn option_nop_traits_64(x: Option) -> Option { - // CHECK: start: - // CHECK-NEXT: %[[TRUNC:[0-9]+]] = trunc nuw i64 %0 to i1 - // CHECK-NEXT: %[[SEL:\.[0-9]+]] = select i1 %[[TRUNC]], i64 %1, i64 undef - // CHECK-NEXT: insertvalue { i64, i64 } - // CHECK-NEXT: insertvalue { i64, i64 } - // CHECK-NEXT: ret { i64, i64 } - try { x? } -} - -// CHECK-LABEL: @result_nop_match_64 -#[no_mangle] -pub fn result_nop_match_64(x: Result) -> Result { - // CHECK: start: - // CHECK-NEXT: insertvalue { i64, i64 } - // CHECK-NEXT: insertvalue { i64, i64 } - // CHECK-NEXT: ret { i64, i64 } - match x { - Ok(x) => Ok(x), - Err(x) => Err(x), - } -} - -// CHECK-LABEL: @result_nop_traits_64 -#[no_mangle] -pub fn result_nop_traits_64(x: Result) -> Result { - // CHECK: start: - // CHECK-NEXT: insertvalue { i64, i64 } - // CHECK-NEXT: insertvalue { i64, i64 } - // CHECK-NEXT: ret { i64, i64 } - try { x? } -} - -// CHECK-LABEL: @control_flow_nop_match_64 -#[no_mangle] -pub fn control_flow_nop_match_64(x: ControlFlow) -> ControlFlow { - // CHECK: start: - // CHECK-NEXT: insertvalue { i64, i64 } - // CHECK-NEXT: insertvalue { i64, i64 } - // CHECK-NEXT: ret { i64, i64 } - match x { - Continue(x) => Continue(x), - Break(x) => Break(x), - } -} - -// CHECK-LABEL: @control_flow_nop_traits_64 -#[no_mangle] -pub fn control_flow_nop_traits_64(x: ControlFlow) -> ControlFlow { - // CHECK: start: - // CHECK-NEXT: insertvalue { i64, i64 } - // CHECK-NEXT: insertvalue { i64, i64 } - // CHECK-NEXT: ret { i64, i64 } - try { x? } -} - -// CHECK-LABEL: @result_nop_match_128 -#[no_mangle] -pub fn result_nop_match_128(x: Result) -> Result { - // CHECK: start: - // CHECK-NEXT: store i128 - // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 - // CHECK-NEXT: store i128 - // CHECK-NEXT: ret void - match x { - Ok(x) => Ok(x), - Err(x) => Err(x), - } -} - -// CHECK-LABEL: @result_nop_traits_128 -#[no_mangle] -pub fn result_nop_traits_128(x: Result) -> Result { - // CHECK: start: - // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 - // CHECK-NEXT: store i128 - // CHECK-NEXT: store i128 - // CHECK-NEXT: ret void - try { x? } -} - -// CHECK-LABEL: @control_flow_nop_match_128 -#[no_mangle] -pub fn control_flow_nop_match_128(x: ControlFlow) -> ControlFlow { - // CHECK: start: - // CHECK-NEXT: store i128 - // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 - // CHECK-NEXT: store i128 - // CHECK-NEXT: ret void - match x { - Continue(x) => Continue(x), - Break(x) => Break(x), - } -} - -// CHECK-LABEL: @control_flow_nop_traits_128 -#[no_mangle] -pub fn control_flow_nop_traits_128(x: ControlFlow) -> ControlFlow { - // CHECK: start: - // CHECK-NEXT: getelementptr inbounds {{(nuw )?}}i8 - // CHECK-NEXT: store i128 - // CHECK-NEXT: store i128 - // CHECK-NEXT: ret void - try { x? } -} - -// CHECK-LABEL: @result_nop_match_ptr -#[no_mangle] -pub fn result_nop_match_ptr(x: Result>) -> Result> { - // CHECK: start: - // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } - // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } - // CHECK-NEXT: ret - match x { - Ok(x) => Ok(x), - Err(x) => Err(x), - } -} - -// CHECK-LABEL: @result_nop_traits_ptr -#[no_mangle] -pub fn result_nop_traits_ptr(x: Result>) -> Result> { - // CHECK: start: - // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } - // CHECK-NEXT: insertvalue { i{{[0-9]+}}, ptr } - // CHECK-NEXT: ret - try { x? } -}