Bug type: crash
Component: InstCombine
Bug location: llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp: InstCombinerImpl::foldSelectInstWithICmp
Issue title: LLVM ERROR while InstCombine
Labels: llvm:instcombine
crash-on-valid
Reported by: ParkHanbum

```
$ bllvm0/bin/clang --version
clang version 18.0.0git (git@github.com:ParkHanbum/llvm-project.git a9f39ff2b628e38826d5b95c1e8ae3cb7c692de9)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/m/bllvm0/bin
```
my clang version.

IR that caused the error
```
define i32 @no_trans_select_xor_eq0_xor_and(i32 %x, i32 %y) {
; CHECK-LABEL: @no_trans_select_xor_eq0_xor_and(
; CHECK-NEXT:    [[XOR:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT:    [[XOR0:%.*]] = icmp eq i32 [[XOR]], 0
; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X]], [[Y]]
; CHECK-NEXT:    [[COND:%.*]] = select i1 [[XOR0]], i32 [[XOR]], i32 [[AND]]
; CHECK-NEXT:    ret i32 [[COND]]
;
  %xor = xor i32 %x, %y
  %xor0 = icmp eq i32 %xor, 0
  %and = and i32 %x, %y
  %cond = select i1 %xor0, i32 %xor, i32 %and
  ret i32 %cond
}
```

and Debug message :
```
$ bllvm0/bin/opt -passes=instcombine temp.ll -debug
INSTCOMBINE ITERATION #1 on no_trans_select_xor_eq0_xor_and
ADD:   ret i32 %cond
ADD:   %cond = select i1 %xor0, i32 %xor, i32 %and
ADD:   %and = and i32 %x, %y
ADD:   %xor0 = icmp eq i32 %xor, 0
ADD:   %xor = xor i32 %x, %y
IC: Visiting:   %xor = xor i32 %x, %y
IC: Visiting:   %xor0 = icmp eq i32 %xor, 0
IC: Visiting:   %and = and i32 %x, %y
IC: Visiting:   %cond = select i1 %xor0, i32 %xor, i32 %and
IC: Mod =   %cond = select i1 %xor0, i32 %xor, i32 %and
    New =   %cond = select i1 %xor0, i32 0, i32 %and
ADD:   %cond = select i1 %xor0, i32 0, i32 %and
IC: Visiting:   %cond = select i1 %xor0, i32 0, i32 %and
IC: Visiting:   ret i32 %cond


INSTCOMBINE ITERATION #2 on no_trans_select_xor_eq0_xor_and
ADD:   ret i32 %cond
ADD:   %cond = select i1 %xor0, i32 0, i32 %and
ADD:   %and = and i32 %x, %y
ADD:   %xor0 = icmp eq i32 %xor, 0
ADD:   %xor = xor i32 %x, %y
IC: Visiting:   %xor = xor i32 %x, %y
IC: Visiting:   %xor0 = icmp eq i32 %xor, 0
IC: Old =   %xor0 = icmp eq i32 %xor, 0
    New =   <badref> = icmp eq i32 %x, %y
ADD:   %xor0 = icmp eq i32 %x, %y
IC: ERASE   %1 = icmp eq i32 %xor, 0
ADD DEFERRED:   %xor = xor i32 %x, %y
IC: ERASE   %xor = xor i32 %x, %y
IC: Visiting:   %xor0 = icmp eq i32 %x, %y
IC: Visiting:   %and = and i32 %x, %y
IC: Visiting:   %cond = select i1 %xor0, i32 0, i32 %and
IC: Visiting:   ret i32 %cond
LLVM ERROR: Instruction Combining did not reach a fixpoint after 1 iterations

```

If time isn't tight, I'd like to take on this issue.



Comments: author: nikic
body: The problem is likely that https://github.com/llvm/llvm-project/blob/084f1c2ee074a5ac8186ea4b5b181b48bf4621b6/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp#L1704-L1714 calls setOperand() instead of replaceOperand().
author: ParkHanbum
body: @nikic can I try this?
author: nikic
body: Sure.

Fix patch:
commit 66eedd1dd370d22ddf994540c20848618d64d1a6
Author: hanbeom <kese111@gmail.com>
Date:   Thu Jan 11 17:34:30 2024 +0900

    [InstCombine] Fix worklist management in select fold (#77738)
    
    `InstCombine` uses `Worklist` to manage change history. `setOperand`,
    which was previously used to change the `Select` Instruction, does not,
    so it is `run` twice, which causes an `LLVM ERROR`.
    
    This problem is resolved by changing `setOperand` to `replaceOperand` as
    the change history will be registered in the Worklist.
    
    Fixes #77553.

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index ab55f235920a..21bfc91148bf 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1704,11 +1704,11 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
   if (CmpRHS != CmpLHS && isa<Constant>(CmpRHS) && !isa<Constant>(CmpLHS)) {
     if (CmpLHS == TrueVal && Pred == ICmpInst::ICMP_EQ) {
       // Transform (X == C) ? X : Y -> (X == C) ? C : Y
-      SI.setOperand(1, CmpRHS);
+      replaceOperand(SI, 1, CmpRHS);
       Changed = true;
     } else if (CmpLHS == FalseVal && Pred == ICmpInst::ICMP_NE) {
       // Transform (X != C) ? Y : X -> (X != C) ? Y : C
-      SI.setOperand(2, CmpRHS);
+      replaceOperand(SI, 2, CmpRHS);
       Changed = true;
     }
   }


Regression tests:
file: llvm/test/Transforms/InstCombine/select.ll
commands: opt < %s -passes=instcombine -S
tests: test_name: src_select_xxory_eq0_xorxy_y
test_body: target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32-p3:64:64:64"

define i32 @src_select_xxory_eq0_xorxy_y(i32 %x, i32 %y) {
  %xor = xor i32 %x, %y
  %xor0 = icmp eq i32 %xor, 0
  %cond = select i1 %xor0, i32 %xor, i32 %y
  ret i32 %cond
}