Bug type: miscompilation
Component: ValueTracking
Bug location: llvm/lib/Analysis/ValueTracking.cpp: breakSelfRecursivePHI
computeKnownBitsFromOperator
Issue title: wrong code at -O1 and above on x86_64-linux-gnu
Labels: miscompilation
llvm:analysis
Reported by: zhendongsu

It appears to be a recent regression from 19.1.0. 

Compiler Explorer: https://godbolt.org/z/haMfGoo6h

```
[548] % clangtk -v
clang version 20.0.0git (https://github.com/llvm/llvm-project.git ddd2f57b29661f21308eec0400fa92a6d075b0c6)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/home/suz/suz-local/software/local/clang-trunk/bin
Build config: +assertions
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Candidate multilib: .;@m64
Selected multilib: .;@m64
Found CUDA installation: /usr/local/cuda, version 12.1
[549] % 
[549] % clangtk -O1 small.c
[550] % ./a.out
Aborted
[551] % 
[551] % cat small.c
int printf(const char *, ...);
unsigned a;
int b, c = 1;
int main() {
  int d;
  a = -1;
  if (a < 1)
    goto e;
  d = c;
  if (d) {
  e:;
  }
  if (!d)
    __builtin_abort();
  if (b)
    goto e;
  return 0;
}
```

Comments: author: zhendongsu
body: Another likely related test:
```
[552] % clangtk -v
clang version 20.0.0git (https://github.com/llvm/llvm-project.git ddd2f57b29661f21308eec0400fa92a6d075b0c6)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /local/home/suz/suz-local/software/local/clang-trunk/bin
Build config: +assertions
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/12
Candidate multilib: .;@m64
Selected multilib: .;@m64
Found CUDA installation: /usr/local/cuda, version 12.1
[553] % 
[553] % clangtk -O0 small.c
[554] % ./a.out
[555] % 
[555] % clangtk -O1 small.c
[556] % timeout -s 9 5 ./a.out
Killed
[557] % cat small.c
int a, b;
int main() {
  {
    int c;
    if (a && 0)
      goto d;
  }
  int e = -~b;
  if (e) {
  d:;
  }
  while (!e)
    goto d;
  return 0;
}
```
author: antoniofrighetto
body: Reduced to:

```llvm
; opt -p instcombine small.ll
define i32 @small(i32 noundef %0) {
  %2 = xor i32 %0, 1
  %3 = sub i32 0, %2
  %4 = icmp ne i32 %3, 0
  br i1 %4, label %5, label %6

5:                                                ; preds = %6, %1
  %.0 = phi i32 [ %.1, %6 ], [ %3, %1 ]
  br label %6

6:                                                ; preds = %5, %1
  %.1 = phi i32 [ %.0, %5 ], [ 0, %1 ]
  %7 = icmp ne i32 %.1, 0
  %8 = xor i1 %7, true
  br i1 %8, label %5, label %9

9:                                                ; preds = %6
  ret i32 0
}
```
author: goldsteinn
body: Fix at: https://github.com/llvm/llvm-project/pull/124481

Fix patch:
commit c2fba023475fddb893eac29dc9f34dfbdb221cd5
Author: goldsteinn <35538541+goldsteinn@users.noreply.github.com>
Date:   Tue Jan 28 15:54:00 2025 -0600

    [ValueTracking] Fix bug of using wrong condition for deducing KnownBits (#124481)
    
    - **[ValueTracking] Add test for issue 124275**
    - **[ValueTracking] Fix bug of using wrong condition for deducing
    KnownBits**
    
    Fixes https://github.com/llvm/llvm-project/issues/124275
    
    Bug was introduced by https://github.com/llvm/llvm-project/pull/114689
    
    Now that computeKnownBits supports breaking out of recursive Phi
    nodes, `IncValue` can be an operand of a different Phi than `P`. This
    breaks the previous assumptions we had when using the possibly
    condition at `CxtI` to constrain `IncValue`.

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index eba728c7c8c3..b63a0a07f7de 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -593,11 +593,14 @@ static bool cmpExcludesZero(CmpInst::Predicate Pred, const Value *RHS) {
 }
 
 static void breakSelfRecursivePHI(const Use *U, const PHINode *PHI,
-                                  Value *&ValOut, Instruction *&CtxIOut) {
+                                  Value *&ValOut, Instruction *&CtxIOut,
+                                  const PHINode **PhiOut = nullptr) {
   ValOut = U->get();
   if (ValOut == PHI)
     return;
   CtxIOut = PHI->getIncomingBlock(*U)->getTerminator();
+  if (PhiOut)
+    *PhiOut = PHI;
   Value *V;
   // If the Use is a select of this phi, compute analysis on other arm to break
   // recursion.
@@ -610,11 +613,13 @@ static void breakSelfRecursivePHI(const Use *U, const PHINode *PHI,
   // incoming value to break recursion.
   // TODO: We could handle any number of incoming edges as long as we only have
   // two unique values.
-  else if (auto *IncPhi = dyn_cast<PHINode>(ValOut);
-           IncPhi && IncPhi->getNumIncomingValues() == 2) {
+  if (auto *IncPhi = dyn_cast<PHINode>(ValOut);
+      IncPhi && IncPhi->getNumIncomingValues() == 2) {
     for (int Idx = 0; Idx < 2; ++Idx) {
       if (IncPhi->getIncomingValue(Idx) == PHI) {
         ValOut = IncPhi->getIncomingValue(1 - Idx);
+        if (PhiOut)
+          *PhiOut = IncPhi;
         CtxIOut = IncPhi->getIncomingBlock(1 - Idx)->getTerminator();
         break;
       }
@@ -1673,8 +1678,9 @@ static void computeKnownBitsFromOperator(const Operator *I,
       Known.One.setAllBits();
       for (const Use &U : P->operands()) {
         Value *IncValue;
+        const PHINode *CxtPhi;
         Instruction *CxtI;
-        breakSelfRecursivePHI(&U, P, IncValue, CxtI);
+        breakSelfRecursivePHI(&U, P, IncValue, CxtI, &CxtPhi);
         // Skip direct self references.
         if (IncValue == P)
           continue;
@@ -1705,9 +1711,10 @@ static void computeKnownBitsFromOperator(const Operator *I,
                     m_Br(m_c_ICmp(Pred, m_Specific(IncValue), m_APInt(RHSC)),
                          m_BasicBlock(TrueSucc), m_BasicBlock(FalseSucc)))) {
             // Check for cases of duplicate successors.
-            if ((TrueSucc == P->getParent()) != (FalseSucc == P->getParent())) {
+            if ((TrueSucc == CxtPhi->getParent()) !=
+                (FalseSucc == CxtPhi->getParent())) {
               // If we're using the false successor, invert the predicate.
-              if (FalseSucc == P->getParent())
+              if (FalseSucc == CxtPhi->getParent())
                 Pred = CmpInst::getInversePredicate(Pred);
               // Get the knownbits implied by the incoming phi condition.
               auto CR = ConstantRange::makeExactICmpRegion(Pred, *RHSC);


Regression tests:
file: llvm/test/Analysis/ValueTracking/phi-known-bits.ll
commands: opt -O1 < %s -S
tests: test_name: issue_124275_wrong_br_direction
test_body: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@c = dso_local global i32 1, align 4
@a = dso_local global i32 0, align 4
@b = dso_local global i32 0, align 4

define dso_local i32 @main() #0 {
entry:
  %retval = alloca i32, align 4
  %d = alloca i32, align 4
  store i32 0, ptr %retval, align 4
  store i32 -1, ptr @a, align 4
  %0 = load i32, ptr @a, align 4
  %cmp = icmp ult i32 %0, 1
  br i1 %cmp, label %if.then, label %if.end

if.then:
  br label %e

if.end:
  %1 = load i32, ptr @c, align 4
  store i32 %1, ptr %d, align 4
  %2 = load i32, ptr %d, align 4
  %tobool = icmp ne i32 %2, 0
  br i1 %tobool, label %if.then1, label %if.end2

if.then1:
  br label %e

e:
  br label %if.end2

if.end2:
  %3 = load i32, ptr %d, align 4
  %tobool3 = icmp ne i32 %3, 0
  br i1 %tobool3, label %if.end5, label %if.then4

if.then4:
  unreachable

if.end5:
  %4 = load i32, ptr @b, align 4
  %tobool6 = icmp ne i32 %4, 0
  br i1 %tobool6, label %if.then7, label %if.end8

if.then7:
  br label %e

if.end8:
  ret i32 0
}

attributes #0 = { noinline nounwind uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }

!llvm.module.flags = !{!0, !1, !2, !3, !4, !5}
!llvm.ident = !{!6}

!0 = !{i32 7, !"Dwarf Version", i32 4}
!1 = !{i32 1, !"wchar_size", i32 4}
!2 = !{i32 8, !"PIC Level", i32 2}
!3 = !{i32 7, !"PIE Level", i32 2}
!4 = !{i32 7, !"uwtable", i32 2}
!5 = !{i32 7, !"frame-pointer", i32 2}
!6 = !{!"clang version 21.0.0git (https://github.com/llvm/llvm-project.git 5c3c0a8cec9205efba78583bd0b8a646270968a1)"}

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