Bug type: crash
Component: LowerSwitch
Bug location: llvm/lib/Transforms/Utils/LowerSwitch.cpp: NewLeafBlock
Issue title: LLVM ERROR: Broken function found after pass "LowerSwitchPass", compilation aborted!
Labels: crash-on-valid
llvm:transforms
Reported by: mikaelholmen

llvm commit: 4cc6d0f4dfb26d
Reproduce with:
```opt -passes="lower-switch" -verify-each bbi-95731.ll -o /dev/null```
Result:
```
PHINode should have one entry for each predecessor of its parent basic block!
  %tmp = phi i3 [ 0, %LeafBlock ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ]
LLVM ERROR: Broken function found after pass "LowerSwitchPass", compilation aborted!
```
If we look at what lower-switch actually produces (-print-after-all) we see
```
; *** IR Dump After LowerSwitchPass on v_257_0 ***
define void @v_257_0(i3 %0) {
bb.0:
  br label %LeafBlock

LeafBlock:                                        ; preds = %bb.0
  %.off = add i3 %0, 2
  %SwitchLeaf = icmp ule i3 %.off, -4
  br i1 %SwitchLeaf, label %bb.1, label %bb.2

bb.1:                                             ; preds = %LeafBlock
  %tmp = phi i3 [ 0, %LeafBlock ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ]
  br label %bb.2

bb.2:                                             ; preds = %LeafBlock, %bb.1
  ret void
}
PHINode should have one entry for each predecessor of its parent basic block!
  %tmp = phi i3 [ 0, %LeafBlock ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ]
```
So it has removed the switch instruction but it only updated one of the five phi operands for %bb.0.
The input looked like
```
define void @v_257_0(i3 %0) {
bb.0:
  switch i3 %0, label %bb.2 [
    i3 -1, label %bb.1
    i3 -2, label %bb.1
    i3 2, label %bb.1
    i3 1, label %bb.1
    i3 0, label %bb.1
  ]

bb.1:                                             ; preds = %bb.0, %bb.0, %bb.0, %bb.0, %bb.0
  %tmp = phi i3 [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ]
  br label %bb.2

bb.2:                                             ; preds = %bb.1, %bb.0
  ret void
}
```
So there is one phi operand for each of the values that makes it jump from %bb.0 to %bb.1 and lower-switch only updated one of them when it changed things.
[bbi-95731.ll.gz](https://github.com/llvm/llvm-project/files/15414163/bbi-95731.ll.gz)


Comments: author: mikaelholmen
body: This starts happening with 1db51d8eb2d
```
[Transform] Rewrite LowerSwitch using APInt

This rewrite fixes https://github.com/llvm/llvm-project/issues/59316.

Previously LowerSwitch uses int64_t, which will crash on case branches using integers with more than 64 bits.
Using APInt fixes this problem. This patch also includes a test

Reviewed By: RKSimon

Differential Revision: https://reviews.llvm.org/D140747
```
author: DataCorrupted
body: I am taking a look. Some initial thoughts:

- https://github.com/llvm/llvm-project/commit/1db51d8eb2d220a4f0000555ada310990098cf5b didn't attempt to change how it optimizes the switch. Maybe we forgot to change the API in that optimization.
- `i3` is playing a role here: if you switch it to `i32`, [it'll pass](https://godbolt.org/z/c5Yveb8Kf). 
author: DataCorrupted
body: I found the problem. Fixing it now. Will push a patch shortly

Fix patch:
commit 67aec0cd62d607b4e5b7198769be061454ce67b3
Author: Peter Rong <peterrong96@gmail.com>
Date:   Mon May 27 10:58:22 2024 -0700

    [LowerSwitch] Use unsigned integer for range comparison (#93237)
    
    Commit 1db51d8eb2 switched from int64_t to `APInt` to prevent high precision integer overflow.
    However, when comparing the "range" of switch cases, we should switch to unsigned integer to prevent overflow.
    This patch fixes https://github.com/llvm/llvm-project/issues/93152.
    Some test cases are added.
    
    Signed-off-by: Peter Rong <PeterRong96@gmail.com>

diff --git a/llvm/lib/Transforms/Utils/LowerSwitch.cpp b/llvm/lib/Transforms/Utils/LowerSwitch.cpp
index f5921e5ccb09..f4ef6d02abf0 100644
--- a/llvm/lib/Transforms/Utils/LowerSwitch.cpp
+++ b/llvm/lib/Transforms/Utils/LowerSwitch.cpp
@@ -208,7 +208,7 @@ BasicBlock *NewLeafBlock(CaseRange &Leaf, Value *Val, ConstantInt *LowerBound,
     PHINode *PN = cast<PHINode>(I);
     // Remove all but one incoming entries from the cluster
     APInt Range = Leaf.High->getValue() - Leaf.Low->getValue();
-    for (APInt j(Range.getBitWidth(), 0, true); j.slt(Range); ++j) {
+    for (APInt j(Range.getBitWidth(), 0, false); j.ult(Range); ++j) {
       PN->removeIncomingValue(OrigBlock);
     }
 


Regression tests:
file: llvm/test/Transforms/LowerSwitch/93152.ll
commands: opt < %s -passes=lower-switch -S
tests: test_name: <module>
test_body: define void @i3_range_4(i3 %0) {
;
bb.0:
  switch i3 %0, label %bb.2 [
  i3 -1, label %bb.1
  i3 -2, label %bb.1
  i3 2, label %bb.1
  i3 1, label %bb.1
  i3 0, label %bb.1
  ]

bb.1:                                             ; preds = %bb.0, %bb.0, %bb.0, %bb.0, %bb.0
  %tmp = phi i3 [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ]
  br label %bb.2

bb.2:                                             ; preds = %bb.1, %bb.0
  ret void
}

define void @i3_range_6(i3 %0) {
;
bb.0:
  switch i3 %0, label %bb.2 [
  i3 -1, label %bb.1
  i3 -2, label %bb.1
  i3 -3, label %bb.1
  i3 3, label %bb.1
  i3 2, label %bb.1
  i3 1, label %bb.1
  i3 0, label %bb.1
  ]

bb.1:                                             ; preds = %bb.0, %bb.0, %bb.0, %bb.0, %bb.0
  %tmp = phi i3 [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ]
  br label %bb.2

bb.2:                                             ; preds = %bb.1, %bb.0
  ret void
}


define void @i3_range_7(i3 %0) {
;
bb.0:
  switch i3 %0, label %bb.2 [
  i3 -1, label %bb.1
  i3 -2, label %bb.1
  i3 -3, label %bb.1
  i3 -4, label %bb.1
  i3 3, label %bb.1
  i3 2, label %bb.1
  i3 1, label %bb.1
  i3 0, label %bb.1
  ]

bb.1:                                             ; preds = %bb.0, %bb.0, %bb.0, %bb.0, %bb.0
  %tmp = phi i3 [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ], [ 0, %bb.0 ]
  br label %bb.2

bb.2:                                             ; preds = %bb.1, %bb.0
  ret void
}