Bug type: crash
Component: LoopVectorize
Bug location: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp: LoopVectorizationCostModel::getInstructionCost
Issue title: [clang] Assertion failed in Vectorize
Labels: vectorizers
crash
Reported by: cardigan1008

In #105722 , we resolved the assertion failure in vectorization. However, I met this crash again with the following case:

```c
#include <stdint.h>
int a;
long b;
struct e {
  uint16_t f;
  uint64_t g;
  int32_t h
} static i = {65530};
void c(int d) {
  for (; a; a++)
    b *= d;
}
uint32_t j(struct e, uint16_t);
uint64_t k() { j(i, 0); }
uint32_t j(struct e, uint16_t) { c(i.f - 65528); }
```
I compiled it with -O2 flag and it crashed. But when I compiled with -O1/-O0, it worked.

The crash is: clang++: /root/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7359: llvm::VectorizationFactor llvm::LoopVectorizationPlanner::computeBestVF(): Assertion `(BestFactor.Width == LegacyVF.Width || planContainsAdditionalSimplifications(getPlanFor(BestFactor.Width), BestFactor.Width, CostCtx, OrigLoop, CM)) && " VPlan cost model and legacy cost model disagreed"' failed.

The details can be found here: https://godbolt.org/z/8x48xsKs6

Comments: author: fhahn
body: Thanks for the report @cardigan1008, should be fixed now

Fix patch:
commit 0a272d3a1703415abca42dc2e2cc2b57cb30734e
Author: Florian Hahn <flo@fhahn.com>
Date:   Thu Aug 29 12:08:27 2024 +0100

    [LV] Use SCEV to analyze second operand for cost query.
    
    Improve operand analysis using SCEV for cost purposes. This fixes a
    divergence between legacy and VPlan-based cost-modeling after
    533e6bbd0d34.
    
    Fixes https://github.com/llvm/llvm-project/issues/106248.

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 56f51e14a6eb..4cc75e2e7546 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -6529,6 +6529,10 @@ LoopVectorizationCostModel::getInstructionCost(Instruction *I,
     // Certain instructions can be cheaper to vectorize if they have a constant
     // second vector operand. One example of this are shifts on x86.
     Value *Op2 = I->getOperand(1);
+    if (!isa<Constant>(Op2) && PSE.getSE()->isSCEVable(Op2->getType()) &&
+        isa<SCEVConstant>(PSE.getSCEV(Op2))) {
+      Op2 = cast<SCEVConstant>(PSE.getSCEV(Op2))->getValue();
+    }
     auto Op2Info = TTI.getOperandInfo(Op2);
     if (Op2Info.Kind == TargetTransformInfo::OK_AnyValue &&
         Legal->isInvariant(Op2))


Regression tests:
file: llvm/test/Transforms/LoopVectorize/X86/cost-constant-known-via-scev.ll
commands: opt -p loop-vectorize -S %s
tests: test_name: test_foldable_live_in_via_scev
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 i64 @test_foldable_live_in_via_scev() {
entry:
  %conv = zext i16 -6 to i64
  %add = add nsw i64 %conv, -65528
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop ]
  %red = phi i64 [ 1, %entry ], [ %mul, %loop ]
  %mul = mul nsw i64 %red, %add
  %iv.next = add nsw i32 %iv, 1
  %ec = icmp eq i32 %iv.next, 100
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  %ret = phi i64 [ %mul, %loop ]
  ret i64 %ret
}