Bug type: miscompilation
Component: LoopVectorize
Bug location: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp: LoopVectorizationCostModel::getInstructionCost
VPRecipeBuilder::tryToWiden
Issue title: [clang] Miscompilation at -O3
Labels: miscompilation
vectorizers
Reported by: cardigan1008

This code prints 15 at -O3, but prints 5 at -O0/1/2:
```c
int printf(const char *, ...);
static int a[] = {4294967295, 5};
int b, c;
int main() {
  a[1] = b = 5;
  unsigned d = -13;
  for (; d >= 8; d = a[0] + d + 6) {
    int *e = &b;
    *e = a[0] - -1 + b;
  }
  a[c];
  printf("%d\n", b);
}
```

Compiler Explorer: https://godbolt.org/z/4xdPqcjPb

Bisected to https://github.com/llvm/llvm-project/commit/6d6eea92e36c301e34a7ec11b2a40e3080f79f53, which was committed by @fhahn 

Comments: author: hstk30-hw
body: Don't ignore the warning.

```
<source>:2:19: warning: implicit conversion from 'long' to 'int' changes value from 4294967294 to -2 [-Wconstant-conversion]
    2 | static int a[] = {4294967294, 5};
      |                  ~^~~~~~~~~~
```
author: antoniofrighetto
body: Please leave the issue opened, as it's implementation-defined behaviour, not undefined behaviour.
author: antoniofrighetto
body: Reduced to:
```llvm
target triple = "x86_64-unknown-linux-gnu"

define noundef i32 @src() {
entry:
  br label %for.body

for.body:                                         ; preds = %entry, %for.body
  %d.06 = phi i32 [ -13, %entry ], [ %add2.reass, %for.body ]
  %add45 = phi i32 [ 5, %entry ], [ %add, %for.body ]
  %add = add i32 0, %add45
  %add2.reass = add i32 %d.06, 5
  %cmp = icmp ugt i32 %add2.reass, 7
  br i1 %cmp, label %for.body, label %for.end

for.end:                                          ; preds = %for.body
  ret i32 %add
}
```

@fhahn I think the issue fundamentally here lies in the fact that we are incorrectly widening the constant 5 (retrieved from SCEV) to `<5, 5, 5, 5>`, when in fact it should be `<5, 0, 0, 0>` (VPlan value: `WIDEN-REDUCTION-PHI ir<%add45> = phi ir<5>`). The VPBasicBlock for the miscompiled basic block is the following one:
```
vector.body:
  EMIT vp<%4> = CANONICAL-INDUCTION ir<0>, vp<%7>
  WIDEN-INDUCTION %d.06 = phi -13, %add2.reass, ir<5>, vp<%0>
  WIDEN-REDUCTION-PHI ir<%add45> = phi ir<5>
  EMIT vp<%5> = WIDEN-CANONICAL-INDUCTION vp<%4>
  EMIT vp<%6> = icmp ule vp<%5>, vp<%3>
```
I'm not that familiar with VPlan, though I feel like that either we are not taking into account the active lane, or we should have not emitted a widen instruction in the first place.

(Godbolt: https://llvm.godbolt.org/z/4Wz46ceh1)
author: antoniofrighetto
body: @fhahn Would you be willing to have a look at it? Happy to help with any additional triage, if needed.
author: fhahn
body: Yep let me take a look!

Fix patch:
commit 30f3752e54fa7cd595a434a985efbe9a7abe9b65
Author: Florian Hahn <flo@fhahn.com>
Date:   Mon Feb 3 17:01:02 2025 +0000

    [VPlan] Only use SCEV for live-ins in tryToWiden. (#125436)
    
    Replacing a recipe with a live-in may not be correct in all cases,
    e.g. when replacing recipes involving header-phi recipes, like
    reductions.
    
    For now, only use SCEV to simplify live-ins.
    
    More powerful input simplification can be built in top of
    https://github.com/llvm/llvm-project/pull/124432 in the future.
    
    
    Fixes https://github.com/llvm/llvm-project/issues/119173.
    Fixes https://github.com/llvm/llvm-project/issues/125374.
    
    PR: https://github.com/llvm/llvm-project/pull/125436

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index cbb9960959f2..ce66350669d5 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -6637,8 +6637,10 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I,
     // fold away.  We can generalize this for all operations using the notion
     // of neutral elements.  (TODO)
     if (I->getOpcode() == Instruction::Mul &&
-        (PSE.getSCEV(I->getOperand(0))->isOne() ||
-         PSE.getSCEV(I->getOperand(1))->isOne()))
+        ((TheLoop->isLoopInvariant(I->getOperand(0)) &&
+          PSE.getSCEV(I->getOperand(0))->isOne()) ||
+         (TheLoop->isLoopInvariant(I->getOperand(1)) &&
+          PSE.getSCEV(I->getOperand(1))->isOne())))
       return 0;
 
     // Detect reduction patterns
@@ -8588,6 +8590,8 @@ VPWidenRecipe *VPRecipeBuilder::tryToWiden(Instruction *I,
       // to replace operands with constants.
       ScalarEvolution &SE = *PSE.getSE();
       auto GetConstantViaSCEV = [this, &SE](VPValue *Op) {
+        if (!Op->isLiveIn())
+          return Op;
         Value *V = Op->getUnderlyingValue();
         if (isa<Constant>(V) || !SE.isSCEVable(V->getType()))
           return Op;


Regression tests:
file: llvm/test/Transforms/LoopVectorize/AArch64/mul-simplification.ll
commands: opt -p loop-vectorize -S %s
tests: test_name: mul_select_operand_known_1_via_scev
test_body: target triple = "arm64-apple-macosx"

define i64 @mul_select_operand_known_1_via_scev() {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %red = phi i64 [ 12, %entry ], [ %red.next, %loop ]
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
  %0 = and i32 %iv, 1
  %cmp1.i = icmp eq i32 %0, 0
  %narrow.i = select i1 %cmp1.i, i32 1, i32 %iv
  %mul = zext nneg i32 %narrow.i to i64
  %red.next = mul nsw i64 %red, %mul
  %iv.next = add nuw nsw i32 %iv, 1
  %ec = icmp eq i32 %iv, 1
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  %res = phi i64 [ %red.next, %loop ]
  ret i64 %res
}

additional_args: -src-unroll=4 -tgt-unroll=4
test_name: pr125374
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"

define i32 @main() {
entry:
  br label %for.body.i.i

for.body.i.i:                                     ; preds = %for.body.i.i, %entry
  %indvars.iv.i.i = phi i64 [ 0, %entry ], [ %indvars.iv.next.i.i, %for.body.i.i ]
  %conv678.i.i = phi i8 [ 1, %entry ], [ %add.i.i.i, %for.body.i.i ]
  %add.i.i.i = add i8 0, %conv678.i.i
  %indvars.iv.next.i.i = add i64 %indvars.iv.i.i, 1
  %exitcond.not.i.i = icmp eq i64 %indvars.iv.i.i, 1
  br i1 %exitcond.not.i.i, label %o.exit, label %for.body.i.i

o.exit:                                           ; preds = %for.body.i.i
  %conv6.i.i = zext i8 %add.i.i.i to i32
  ret i32 %conv6.i.i
}

additional_args: -src-unroll=2 -tgt-unroll=2