Bug type: miscompilation
Component: InstructionSimplify
Bug location: llvm/lib/Analysis/InstructionSimplify.cpp: simplifyWithOpReplaced
Issue title: [InstCombine] Miscompilation which simplifies a use of a multi-use freeze
Labels: miscompilation
llvm:instcombine
Reported by: dtcxzyw

Reduced test case: https://alive2.llvm.org/ce/z/_JyUGw
```
define i8 @func78(i1 %0, i8 %1) {
  %3 = zext i1 %0 to i8
  %4 = shl i8 %3, %1
  %5 = freeze i8 %4
  %6 = select i1 %0, i8 0, i8 %5
  %7 = call i8 @llvm.fshr.i8(i8 0, i8 %5, i8 %6)
  ret i8 %7
}
```

```
----------------------------------------
define i8 @func78(i1 %#0, i8 %#1) {
#2:
  %#3 = zext i1 %#0 to i8
  %#4 = shl i8 %#3, %#1
  %#5 = freeze i8 %#4
  %#6 = select i1 %#0, i8 0, i8 %#5
  %#7 = fshr i8 0, i8 %#5, i8 %#6
  ret i8 %#7
}
=>
define i8 @func78(i1 %#0, i8 %#1) nofree noundef willreturn memory(none) {
#2:
  %#3 = zext i1 %#0 to i8
  %#4 = shl nuw i8 %#3, %#1
  %#5 = freeze i8 %#4
  ret i8 %#5
}
Transformation doesn't verify!

ERROR: Value mismatch

Example:
i1 %#0 = #x0 (0)
i8 %#1 = #x08 (8)

Source:
i8 %#3 = #x00 (0)
i8 %#4 = poison
i8 %#5 = #x00 (0)
i8 %#6 = #x00 (0)
i8 %#7 = #x00 (0)

Target:
i8 %#3 = #x00 (0)
i8 %#4 = poison
i8 %#5 = #x9d (157, -99)
Source value: #x00 (0)
Target value: #x9d (157, -99)

Summary:
  0 correct transformations
  1 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors
```


Fix patch:
commit d085b42cbbefe79a41113abcd2b1e1f2a203acef
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Wed May 8 10:04:09 2024 +0800

    [InstSimplify] Do not simplify freeze in `simplifyWithOpReplaced` (#91215)
    
    See the LangRef:
    > All uses of a value returned by the same ‘freeze’ instruction are
    guaranteed to always observe the same value, while different ‘freeze’
    instructions may yield different values.
    
    It is incorrect to replace freezes with the simplified value.
    
    Proof:
    https://alive2.llvm.org/ce/z/3Dn9Cd
    https://alive2.llvm.org/ce/z/Qyh5h6
    
    Fixes https://github.com/llvm/llvm-project/issues/91178

diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 4061dae83c10..37a7259a5cd0 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4312,6 +4312,10 @@ static Value *simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
   if (match(I, m_Intrinsic<Intrinsic::is_constant>()))
     return nullptr;
 
+  // Don't simplify freeze.
+  if (isa<FreezeInst>(I))
+    return nullptr;
+
   // Replace Op with RepOp in instruction operands.
   SmallVector<Value *, 8> NewOps;
   bool AnyReplaced = false;


Regression tests:
file: llvm/test/Transforms/InstCombine/icmp.ll
commands: opt < %s -passes=instcombine -S
tests: test_name: icmp_freeze_sext
test_body: target datalayout = "e-p:64:64:64-p1:16:16:16-p2:32:32:32-p3:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"

define i1 @icmp_freeze_sext(i16 %x, i16 %y) {
  %cmp1 = icmp uge i16 %x, %y
  %ext = sext i1 %cmp1 to i16
  %ext.fr = freeze i16 %ext
  %cmp2 = icmp uge i16 %ext.fr, %y
  ret i1 %cmp2
}

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

define i8 @test_replace_freeze_oneuse(i1 %x, i8 %y) {
  %ext = zext i1 %x to i8
  %shl = shl nuw i8 %ext, %y
  %shl.fr = freeze i8 %shl
  %sel = select i1 %x, i8 0, i8 %shl.fr
  ret i8 %sel
}

test_name: sequence_select_with_same_cond_extra_use
test_body: target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32-p3:64:64:64"

declare void @use32(i32)

define i32 @sequence_select_with_same_cond_extra_use(i1 %c1, i1 %c2) {
  %s1 = select i1 %c1, i32 23, i32 45
  call void @use32(i32 %s1)
  %s2 = select i1 %c2, i32 666, i32 %s1
  %s3 = select i1 %c1, i32 789, i32 %s2
  ret i32 %s3
}

test_name: test_replace_freeze_multiuse
test_body: target datalayout = "e-p:64:64-p1:16:16-p2:32:32:32-p3:64:64:64"

define i8 @test_replace_freeze_multiuse(i1 %x, i8 %y) {
  %ext = zext i1 %x to i8
  %shl = shl nuw i8 %ext, %y
  %shl.fr = freeze i8 %shl
  %sel = select i1 %x, i8 0, i8 %shl.fr
  %add = add i8 %shl.fr, %sel
  ret i8 %add
}