about summary refs log tree commit diff
path: root/tests/codegen
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-03-08 07:18:17 +0000
committerbors <bors@rust-lang.org>2024-03-08 07:18:17 +0000
commit14fbc3c00525b41a3a3ee2c90e9ab6fd3b05274f (patch)
tree81cec2387610314e63c2468b5c3a2d1b797b6529 /tests/codegen
parent9fb91aa2e70bfcc1c0adaad79711f0321ea81ece (diff)
parent2884230df2bdf6ff23d51808f5e2f270dfbe0d3a (diff)
downloadrust-14fbc3c00525b41a3a3ee2c90e9ab6fd3b05274f.tar.gz
rust-14fbc3c00525b41a3a3ee2c90e9ab6fd3b05274f.zip
Auto merge of #120268 - DianQK:otherwise_is_last_variant_switchs, r=oli-obk
Replace the default branch with an unreachable branch If it is the last variant

Fixes #119520. Fixes #110097.

LLVM currently has limited ability to eliminate dead branches in switches, even with the patch of https://github.com/llvm/llvm-project/issues/73446.

The main reasons are as follows:

- Additional costs are required to calculate the range of values, and there exist many scenarios that cannot be analyzed accurately.
- Matching values by bitwise calculation cannot handle odd branches, nor can it handle values like `-1, 0, 1`. See [SimplifyCFG.cpp#L5424](https://github.com/llvm/llvm-project/blob/llvmorg-17.0.6/llvm/lib/Transforms/Utils/SimplifyCFG.cpp#L5424) and https://llvm.godbolt.org/z/qYMqhvMa8
- The current range information is continuous, even if the metadata for the range is submitted. See [ConstantRange.cpp#L1869-L1870](https://github.com/llvm/llvm-project/blob/llvmorg-17.0.6/llvm/lib/IR/ConstantRange.cpp#L1869-L1870).
- The metadata of the range may be lost in passes such as SROA. See https://rust.godbolt.org/z/e7f87vKMK.

Although we can make improvements, I think it would be more appropriate to put this issue to rustc first. After all, we can easily know the possible values.

Note that we've currently found a slow compilation problem in the presence of unreachable branches. See
https://github.com/llvm/llvm-project/issues/78578.

r? compiler
Diffstat (limited to 'tests/codegen')
-rw-r--r--tests/codegen/enum/uninhabited_enum_default_branch.rs24
1 files changed, 24 insertions, 0 deletions
diff --git a/tests/codegen/enum/uninhabited_enum_default_branch.rs b/tests/codegen/enum/uninhabited_enum_default_branch.rs
new file mode 100644
index 00000000000..5f318f18dec
--- /dev/null
+++ b/tests/codegen/enum/uninhabited_enum_default_branch.rs
@@ -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:    icmp ult i32 [[TMP1]], 70
+// CHECK-NEXT:    icmp eq i32 [[TMP0]], 153
+// CHECK-NEXT:    [[SPEC_SELECT:%.*]] = or i1
+// CHECK-NEXT:    ret i1 [[SPEC_SELECT]]
+#[no_mangle]
+pub fn foo(x: Int) -> bool {
+    (x >= A && x <= B)
+        || x == C
+}