[llvm] [SimplifyCFG] When only one case value is missing, replace default with that case (PR #76669)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 1 02:19:23 PST 2024


================
@@ -5609,10 +5612,30 @@ static bool eliminateDeadSwitchCases(SwitchInst *SI, DomTreeUpdater *DTU,
       Known.getBitWidth() - (Known.Zero | Known.One).popcount();
   assert(NumUnknownBits <= Known.getBitWidth());
   if (HasDefault && DeadCases.empty() &&
-      NumUnknownBits < 64 /* avoid overflow */ &&
-      SI->getNumCases() == (1ULL << NumUnknownBits)) {
-    createUnreachableSwitchDefault(SI, DTU);
-    return true;
+      NumUnknownBits < 64 /* avoid overflow */) {
+    uint64_t AllNumCases = 1ULL << NumUnknownBits;
+    if (SI->getNumCases() == AllNumCases) {
+      createUnreachableSwitchDefault(SI, DTU);
+      return true;
+    }
+    // When only one case value is missing, replace default with that case.
+    if (SI->getNumCases() == AllNumCases - 1) {
+      uint64_t MissingCaseVal = 0;
+      for (const auto &Case : SI->cases())
+        MissingCaseVal ^= Case.getCaseValue()->getValue().getLimitedValue();
+      for (uint64_t I = 0; I < AllNumCases; I++)
+        MissingCaseVal ^= I;
----------------
dtcxzyw wrote:

I don't think the approach to find the missing case value is correct.
An example:
```
%val = and i32 %a, 1
%shl = shl nuw i32 %val, 2
%caseval = or disjoint %shl, 11
switch i32 %x, label %default [
i32 11, label %case0
; i32 15, label %case1 ; Missing case val
]
```
```
NumUnknownBits = 1
AllNumCases = 2
MissingCaseVal = 11 ^ 1 = 10 != 15
```
For other cases with `NumUnknownBits > 1`, your approach just happens to produce the right result because `(0 ^ 1 ^ ... ^ (2^k - 1)) = 0` when `k > 1`.

```suggestion
      assert(NumUnknownBits > 1 && "Should be canonicalized to a branch");
```


https://github.com/llvm/llvm-project/pull/76669


More information about the llvm-commits mailing list