Bug type: miscompilation
Component: ConstraintElimination
Bug location: llvm/lib/Transforms/Scalar/ConstraintElimination.cpp: State::addInfoForInductions
Issue title: [clang] Miscompile at O3 with SIGKILL
Labels: miscompilation
confirmed
llvm:transforms
Reported by: cardigan1008

When I compiled this code with O3, it triggered SIGKILL. With O0/1/2, it returned 0.

Bisected to https://github.com/llvm/llvm-project/commit/5b927130b0e15a442a6ed171f43a612e6a40bbcd, which was committed by @fhahn 

Compiler Explorer: https://godbolt.org/z/q9j75feYG

Code:
```c
int printf(const char *, ...);
int a, c, d;
int *b;
char e;
short f;
int g(int i) {
  if (i <= 0)
    return 1;
  int h = 0;
  for (; h < i - 1; h++) {
    for (; d - h - 1;)
      if (c)
        b[d] = e = 1;
    if (e)
      break;
  }
  return 0;
}
void j() { g(f); }
int main(int i, char *k[]) {
  j();
  while (0 < f)
    ;
  printf("%X\n", a);
}
```

Comments: author: dtcxzyw
body: Reproducer: https://alive2.llvm.org/ce/z/fLN5gw
```
; bin/opt -passes=constraint-elimination test.ll -S
define i1 @test(i16 %n) {
entry:
  %cond = icmp slt i16 %n, 1
  br i1 %cond, label %exit, label %loop.preheader

loop.preheader:
  %sub = add nsw i16 %n, -1
  %ext = zext nneg i16 %sub to i32
  br label %loop

loop:
  %indvar = phi i32 [ %indvar.inc, %loop.latch ], [ 0, %loop.preheader ]
  %12 = icmp eq i32 %indvar, %ext
  br i1 %12, label %exit, label %loop.latch

loop.latch:
  %indvar.inc = add nuw nsw i32 %indvar, 1
  br label %loop

exit:
  %cmp = icmp sgt i16 %n, 0
  ret i1 %cmp
}

```
I will post a fix later.


Fix patch:
commit 52361d0368b79841be12156bf03cf8c1851e5df7
Author: Yingwei Zheng <dtcxzyw2333@gmail.com>
Date:   Mon Nov 18 23:41:04 2024 +0800

    [ConstraintElim] Bail out on non-dedicated exits when adding exiting conditions (#116627)
    
    This patch bails out non-dedicated exits to avoid adding exiting
    conditions to invalid context.
    Closes https://github.com/llvm/llvm-project/issues/116553.

diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index d2e532d29d07..64433cb9216c 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -1034,9 +1034,9 @@ void State::addInfoForInductions(BasicBlock &BB) {
       DTN, CmpInst::ICMP_SLT, PN, B,
       ConditionTy(CmpInst::ICMP_SLE, StartValue, B)));
 
-  // Try to add condition from header to the exit blocks. When exiting either
-  // with EQ or NE in the header, we know that the induction value must be u<=
-  // B, as other exits may only exit earlier.
+  // Try to add condition from header to the dedicated exit blocks. When exiting
+  // either with EQ or NE in the header, we know that the induction value must
+  // be u<= B, as other exits may only exit earlier.
   assert(!StepOffset.isNegative() && "induction must be increasing");
   assert((Pred == CmpInst::ICMP_EQ || Pred == CmpInst::ICMP_NE) &&
          "unsupported predicate");
@@ -1044,8 +1044,11 @@ void State::addInfoForInductions(BasicBlock &BB) {
   SmallVector<BasicBlock *> ExitBBs;
   L->getExitBlocks(ExitBBs);
   for (BasicBlock *EB : ExitBBs) {
-    WorkList.emplace_back(FactOrCheck::getConditionFact(
-        DT.getNode(EB), CmpInst::ICMP_ULE, A, B, Precond));
+    // Bail out on non-dedicated exits.
+    if (DT.dominates(&BB, EB)) {
+      WorkList.emplace_back(FactOrCheck::getConditionFact(
+          DT.getNode(EB), CmpInst::ICMP_ULE, A, B, Precond));
+    }
   }
 }
 


Regression tests:
file: llvm/test/Transforms/ConstraintElimination/induction-condition-in-loop-exit.ll
commands: opt -p constraint-elimination -S %s
tests: test_name: test_non_dedicated_exit
test_body: define i1 @test_non_dedicated_exit(i16 %n) {
entry:
  %cond = icmp slt i16 %n, 1
  br i1 %cond, label %exit, label %loop.preheader

loop.preheader:                                   ; preds = %entry
  %sub = add nsw i16 %n, -1
  %ext = zext nneg i16 %sub to i32
  br label %loop

loop:                                             ; preds = %loop.latch, %loop.preheader
  %indvar = phi i32 [ %indvar.inc, %loop.latch ], [ 0, %loop.preheader ]
  %exitcond = icmp eq i32 %indvar, %ext
  br i1 %exitcond, label %exit, label %loop.latch

loop.latch:                                       ; preds = %loop
  %indvar.inc = add nuw nsw i32 %indvar, 1
  br label %loop

exit:                                             ; preds = %loop, %entry
  %cmp = icmp sgt i16 %n, 0
  ret i1 %cmp
}