Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 7 additions & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,8 @@ jobs:
strategy:
matrix:
include:
- name: mingw-check
os: ubuntu-20.04-4core-16gb
env: {}
- name: mingw-check-tidy
os: ubuntu-20.04-4core-16gb
env: {}
- name: x86_64-gnu-llvm-16
env:
ENABLE_GCC_CODEGEN: "1"
os: ubuntu-20.04-16core-64gb
- name: x86_64-gnu-tools
os: ubuntu-20.04-16core-64gb
- name: dist-loongarch64-linux
os: ubuntu-20.04
env: {}
timeout-minutes: 600
runs-on: "${{ matrix.os }}"
Expand Down Expand Up @@ -271,22 +261,22 @@ jobs:
os: ubuntu-20.04-8core-32gb
env: {}
- name: mingw-check
os: ubuntu-20.04-4core-16gb
os: ubuntu-20.04
env: {}
- name: test-various
os: ubuntu-20.04-8core-32gb
env: {}
- name: x86_64-gnu
os: ubuntu-20.04-4core-16gb
os: ubuntu-20.04
env: {}
- name: x86_64-gnu-stable
env:
IMAGE: x86_64-gnu
RUST_CI_OVERRIDE_RELEASE_CHANNEL: stable
CI_ONLY_WHEN_CHANNEL: nightly
os: ubuntu-20.04-4core-16gb
os: ubuntu-20.04
- name: x86_64-gnu-aux
os: ubuntu-20.04-4core-16gb
os: ubuntu-20.04
env: {}
- name: x86_64-gnu-integration
env:
Expand All @@ -307,7 +297,7 @@ jobs:
RUST_BACKTRACE: 1
os: ubuntu-20.04-8core-32gb
- name: x86_64-gnu-nopt
os: ubuntu-20.04-4core-16gb
os: ubuntu-20.04
env: {}
- name: x86_64-gnu-tools
env:
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_middle/src/mir/terminator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,17 @@ impl SwitchTargets {
pub fn target_for_value(&self, value: u128) -> BasicBlock {
self.iter().find_map(|(v, t)| (v == value).then_some(t)).unwrap_or_else(|| self.otherwise())
}

/// Adds a new target to the switch. But You cannot add an already present value.
#[inline]
pub fn add_target(&mut self, value: u128, bb: BasicBlock) {
let value = Pu128(value);
if self.values.contains(&value) {
bug!("target value {:?} already present", value);
}
self.values.push(value);
self.targets.insert(self.targets.len() - 1, bb);
}
}

pub struct SwitchTargetsIter<'a> {
Expand Down
28 changes: 22 additions & 6 deletions compiler/rustc_mir_transform/src/uninhabited_enum_branching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
trace!("UninhabitedEnumBranching starting for {:?}", body.source);

let mut removable_switchs = Vec::new();
let mut otherwise_is_last_variant_switchs = Vec::new();

for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
trace!("processing block {:?}", bb);
Expand All @@ -92,8 +93,14 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
tcx.param_env_reveal_all_normalized(body.source.def_id()).and(discriminant_ty),
);

let allowed_variants = if let Ok(layout) = layout {
let mut allowed_variants = if let Ok(layout) = layout {
variant_discriminants(&layout, discriminant_ty, tcx)
} else if let Some(variant_range) = discriminant_ty.variant_range(tcx) {
variant_range
.map(|variant| {
discriminant_ty.discriminant_for_variant(tcx, variant).unwrap().val
})
.collect()
} else {
continue;
};
Expand All @@ -103,20 +110,29 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching {
let terminator = bb_data.terminator();
let TerminatorKind::SwitchInt { targets, .. } = &terminator.kind else { bug!() };

let mut reachable_count = 0;
for (index, (val, _)) in targets.iter().enumerate() {
if allowed_variants.contains(&val) {
reachable_count += 1;
} else {
if !allowed_variants.remove(&val) {
removable_switchs.push((bb, index));
}
}

if reachable_count == allowed_variants.len() {
if allowed_variants.is_empty() {
removable_switchs.push((bb, targets.iter().count()));
} else if allowed_variants.len() == 1 {
#[allow(rustc::potential_query_instability)]
let last_variant = *allowed_variants.iter().next().unwrap();
otherwise_is_last_variant_switchs.push((bb, last_variant));
}
}

for (bb, last_variant) in otherwise_is_last_variant_switchs {
let bb_data = &mut body.basic_blocks.as_mut()[bb];
let terminator = bb_data.terminator_mut();
let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind else { bug!() };
targets.add_target(last_variant, targets.otherwise());
removable_switchs.push((bb, targets.iter().count()));
}

if removable_switchs.is_empty() {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ ENV CC_loongarch64_unknown_linux_gnu=loongarch64-unknown-linux-gnu-gcc \
ENV HOSTS=loongarch64-unknown-linux-gnu

ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
ENV SCRIPT python3 ../x.py build src/tools/miri/cargo-miri --host $HOSTS --target $HOSTS
15 changes: 2 additions & 13 deletions src/ci/github-actions/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ x--expand-yaml-anchors--remove:
env: {}

- &job-linux-4c
os: ubuntu-20.04-4core-16gb
os: ubuntu-20.04
<<: *base-job

- &job-linux-8c
Expand Down Expand Up @@ -328,20 +328,9 @@ jobs:
strategy:
matrix:
include:
- name: mingw-check
<<: *job-linux-4c

- name: mingw-check-tidy
- name: dist-loongarch64-linux
<<: *job-linux-4c

- name: x86_64-gnu-llvm-16
env:
ENABLE_GCC_CODEGEN: "1"
<<: *job-linux-16c

- name: x86_64-gnu-tools
<<: *job-linux-16c

auto:
<<: *base-ci-job
name: auto - ${{ matrix.name }}
Expand Down
24 changes: 24 additions & 0 deletions tests/codegen/enum/uninhabited_enum_default_branch.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// compile-flags: -O

#![crate_type = "lib"]

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Int(u32);

const A: Int = Int(201);
const B: Int = Int(270);
const C: Int = Int(153);

// CHECK-LABEL: @foo
// CHECK-SAME: [[TMP0:%.*]])
// CHECK-NEXT: start:
// CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], -201
// CHECK-NEXT: [[OR_COND:%.*]] = icmp ult i32 [[TMP1]], 70
// CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 153
// CHECK-NEXT: [[SPEC_SELECT:%.*]] = or i1 [[OR_COND]], [[TMP2]]
// CHECK-NEXT: ret i1 [[SPEC_SELECT]]
#[no_mangle]
pub fn foo(x: Int) -> bool {
(x >= A && x <= B)
|| x == C
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
StorageLive(_6);
_6 = ((*_1).4: std::option::Option<usize>);
_7 = discriminant(_6);
switchInt(move _7) -> [1: bb4, otherwise: bb6];
switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9];
}

bb4: {
Expand Down Expand Up @@ -135,5 +135,9 @@
StorageDead(_6);
return;
}

bb9: {
unreachable;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
StorageLive(_6);
_6 = ((*_1).4: std::option::Option<usize>);
_7 = discriminant(_6);
switchInt(move _7) -> [1: bb4, otherwise: bb6];
switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9];
}

bb4: {
Expand Down Expand Up @@ -135,5 +135,9 @@
StorageDead(_6);
return;
}

bb9: {
unreachable;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
fn num_to_digit(_1: char) -> u32 {
debug num => _1;
let mut _0: u32;
let mut _5: std::option::Option<u32>;
let mut _5: bool;
let mut _6: std::option::Option<u32>;
scope 1 (inlined char::methods::<impl char>::is_digit) {
debug self => _1;
debug radix => const 8_u32;
Expand All @@ -15,15 +16,16 @@ fn num_to_digit(_1: char) -> u32 {
}
}
scope 3 (inlined #[track_caller] Option::<u32>::unwrap) {
debug self => _5;
let mut _6: isize;
let mut _7: !;
debug self => _6;
let mut _7: isize;
let mut _8: !;
scope 4 {
debug val => _0;
}
}

bb0: {
StorageLive(_5);
StorageLive(_3);
StorageLive(_2);
_2 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> [return: bb1, unwind unreachable];
Expand All @@ -33,45 +35,59 @@ fn num_to_digit(_1: char) -> u32 {
_3 = &_2;
StorageLive(_4);
_4 = discriminant(_2);
StorageDead(_3);
StorageDead(_2);
switchInt(move _4) -> [1: bb2, otherwise: bb7];
switchInt(move _4) -> [1: bb2, 0: bb3, otherwise: bb11];
}

bb2: {
StorageDead(_4);
StorageLive(_5);
_5 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb3, unwind unreachable];
_5 = const true;
goto -> bb4;
}

bb3: {
StorageLive(_6);
_6 = discriminant(_5);
switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb6];
_5 = const false;
goto -> bb4;
}

bb4: {
_7 = option::unwrap_failed() -> unwind unreachable;
StorageDead(_4);
StorageDead(_3);
StorageDead(_2);
switchInt(move _5) -> [0: bb5, otherwise: bb6];
}

bb5: {
_0 = move ((_5 as Some).0: u32);
StorageDead(_6);
StorageDead(_5);
goto -> bb8;
_0 = const 0_u32;
goto -> bb10;
}

bb6: {
unreachable;
StorageLive(_6);
_6 = char::methods::<impl char>::to_digit(move _1, const 8_u32) -> [return: bb7, unwind unreachable];
}

bb7: {
StorageDead(_4);
_0 = const 0_u32;
goto -> bb8;
StorageLive(_7);
_7 = discriminant(_6);
switchInt(move _7) -> [0: bb8, 1: bb9, otherwise: bb11];
}

bb8: {
_8 = option::unwrap_failed() -> unwind unreachable;
}

bb9: {
_0 = move ((_6 as Some).0: u32);
StorageDead(_7);
StorageDead(_6);
goto -> bb10;
}

bb10: {
StorageDead(_5);
return;
}

bb11: {
unreachable;
}
}
Loading