Bug type: miscompilation
Component: ConstraintElimination
Bug location: llvm/lib/Transforms/Scalar/ConstraintElimination.cpp: checkAndReplaceCmp
Issue title: [ConstraintElim] Miscompilation with cmp intrinsic
Labels: miscompilation
llvm:transforms
Reported by: dtcxzyw

Reproducer: https://alive2.llvm.org/ce/z/Tvz2NA
```
; bin/opt -passes=constraint-elimination test.ll -S
define void @h(ptr %p) {
entry:
  br label %for.cond

for.cond:                                         ; preds = %for.cond1, %entry
  %storemerge = phi i32 [ 0, %entry ], [ 1, %for.cond1 ]
  %cmp = icmp eq i32 %storemerge, 0
  br i1 %cmp, label %for.cond1, label %for.end6

for.cond1:                                        ; preds = %for.cond, %for.body3
  %i.0 = phi i32 [ %inc, %for.body3 ], [ 0, %for.cond ]
  %cmp2 = icmp ult i32 %i.0, 3
  br i1 %cmp2, label %for.body3, label %for.cond

for.body3:                                        ; preds = %for.cond1
  %sub.i = tail call range(i32 -1, 2) i32 @llvm.scmp.i32.i32(i32 1, i32 %storemerge)
  store i32 %sub.i, ptr %p, align 4
  %inc = add nuw nsw i32 %i.0, 1
  br label %for.cond1

for.end6:
  ret void
}
```

```
define void @h(ptr %p) {
entry:
  br label %for.cond

for.cond:                                         ; preds = %for.cond1, %entry
  %storemerge = phi i32 [ 0, %entry ], [ 1, %for.cond1 ]
  %cmp = icmp eq i32 %storemerge, 0
  br i1 %cmp, label %for.cond1, label %for.end6

for.cond1:                                        ; preds = %for.body3, %for.cond
  %i.0 = phi i32 [ %inc, %for.body3 ], [ 0, %for.cond ]
  %cmp2 = icmp ult i32 %i.0, 3
  br i1 %cmp2, label %for.body3, label %for.cond

for.body3:                                        ; preds = %for.cond1
  store i32 0, ptr %p, align 4
  %inc = add nuw nsw i32 %i.0, 1
  br label %for.cond1

for.end6:                                         ; preds = %for.cond
  ret void
}
```

The result of scmp should be 1 instead of 0.

Reduced C reproducer:
```
#include <stdio.h>
#include <stdint.h>

int builtin_scmp(int d, int e) { return (d > e) - (d < e); }
int32_t f = 0;
int64_t g = 0;
void h() {
  for (f = 0; f <= 0; f++) {
    int i;
    for (i = 0; i < 3; i++)
      g = builtin_scmp(1, f);
  }
}
int main() {
  h();
  printf("%d\n", (int)g);
  return 0;
}
```

I will post a fix later.



Fix patch:
commit 3ff9d92aae0945daa85ec6f85f05a3aeaaa9f962
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Fri Aug 23 16:06:00 2024 +0800

    [ConstraintElim] Fix miscompilation caused by PR97974 (#105790)
    
    Fixes https://github.com/llvm/llvm-project/issues/105785.
    
    (cherry picked from commit 85b6aac7c25f9d2a976a76045ace1e7afebb5965)

diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index c31173879af1..37022104d0a9 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -1464,7 +1464,7 @@ static bool checkAndReplaceCmp(CmpIntrinsic *I, ConstraintInfo &Info,
     ToRemove.push_back(I);
     return true;
   }
-  if (checkCondition(ICmpInst::ICMP_EQ, LHS, RHS, I, Info)) {
+  if (checkCondition(ICmpInst::ICMP_EQ, LHS, RHS, I, Info).value_or(false)) {
     I->replaceAllUsesWith(ConstantInt::get(I->getType(), 0));
     ToRemove.push_back(I);
     return true;


Regression tests:
file: llvm/test/Transforms/ConstraintElimination/pr105785.ll
commands: opt -passes=constraint-elimination -S %s
tests: test_name: pr105785
test_body: define void @pr105785(ptr %p) {
entry:
  br label %for.cond

for.cond:                                         ; preds = %for.cond1, %entry
  %for.ind = phi i32 [ 0, %entry ], [ 1, %for.cond1 ]
  %cmp = icmp eq i32 %for.ind, 0
  br i1 %cmp, label %for.cond1, label %for.end6

for.cond1:                                        ; preds = %for.body3, %for.cond
  %for.ind2 = phi i32 [ %inc, %for.body3 ], [ 0, %for.cond ]
  %cmp2 = icmp ult i32 %for.ind2, 3
  br i1 %cmp2, label %for.body3, label %for.cond

for.body3:                                        ; preds = %for.cond1
  %scmp = call i32 @llvm.scmp.i32.i32(i32 %for.ind, i32 1)
  store i32 %scmp, ptr %p, align 4
  %inc = add nuw nsw i32 %for.ind2, 1
  br label %for.cond1

for.end6:                                         ; preds = %for.cond
  ret void
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.scmp.i32.i32(i32, i32) #0

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

additional_args: -src-unroll=4 -tgt-unroll=4