Bug type: crash
Component: LoopVectorize
Bug location: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp: LoopVectorizationCostModel::setCostBasedWideningDecision
Issue title: [LV]VPlan cost model and legacy cost model disagreed
Labels: vectorizers
crash-on-valid
Reported by: alexey-bataev

https://godbolt.org/z/o9sPfa35r
@fhahn 
Maybe related to https://github.com/llvm/llvm-project/commit/7defb0a4a35817ee7accb310d99912152a542ec2

Comments: author: alexey-bataev
body: Ping!
author: fhahn
body: It's not related to https://github.com/llvm/llvm-project/commit/7defb0a4a35817ee7accb310d99912152a542ec2, but will fix soon

Fix patch:
commit d3afa171ee236dfef4b7cd4b4dd0b0fb165a48cc
Author: Florian Hahn <flo@fhahn.com>
Date:   Wed Feb 11 20:52:07 2026 +0000

    [LV] Don't scalarize loads that need predication in legacy CM.
    
    The legacy cost model tries to scalarize loads that are used as
    pointers. Skip if the load would need predicating when scalarized,
    because that would incur very high costs, see useEmulatedMaskMemRefHack.
    
    Fixes https://github.com/llvm/llvm-project/issues/180780.

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 164d74f1a440..9b2641c2b9bb 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -5883,9 +5883,9 @@ void LoopVectorizationCostModel::setCostBasedWideningDecision(ElementCount VF) {
       // if the loaded register is involved in an address computation, it is
       // instead changed here when we know this is the case.
       InstWidening Decision = getWideningDecision(I, VF);
-      if (Decision == CM_Widen || Decision == CM_Widen_Reverse ||
-          (!isPredicatedInst(I) && !Legal->isUniformMemOp(*I, VF) &&
-           Decision == CM_Scalarize)) {
+      if (!isPredicatedInst(I) &&
+          (Decision == CM_Widen || Decision == CM_Widen_Reverse ||
+           (!Legal->isUniformMemOp(*I, VF) && Decision == CM_Scalarize))) {
         // Scalarize a widened load of address or update the cost of a scalar
         // load of an address.
         setWideningDecision(


Regression tests:
file: llvm/test/Transforms/LoopVectorize/X86/cost-model.ll
commands: opt < %s -passes=loop-vectorize -mtriple=x86_64-apple-macosx10.8.0 -mcpu=corei7-avx -S
tests: test_name: known_deref_load_tail_folding
test_body: target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.8.0"

@src.arr = external global [15 x double]
@dst.arr.a = external global [10 x double]
@dst.arr.b = external global [15 x double]

define void @known_deref_load_tail_folding() #0 {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 1, %entry ], [ %iv.next, %loop ]
  %gep.src = getelementptr double, ptr @src.arr, i64 %iv
  %val = load double, ptr %gep.src, align 8
  %cmp = fcmp oeq double %val, 0.000000e+00
  %dst.select = select i1 %cmp, ptr @dst.arr.a, ptr @dst.arr.b
  store double 0.000000e+00, ptr %dst.select, align 8
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv.next, 12
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

attributes #0 = { "target-cpu"="haswell" }