Bug type: crash
Component: LoopVectorize
Bug location: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp: LoopVectorizationCostModel::collectLoopUniforms
Issue title: [LoopVectorize] Assertion `WideningDecision != CM_Unknown && "Widening decision should be ready at this moment"' failed.
Labels: vectorizers
crash-on-valid
Reported by: patrick-rivos

Reduced LLVM IR:
```llvm ir
; ModuleID = 'reduced.bc'
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define i32 @main(i64 %indvars.iv.i) #0 {
entry:
  br label %for.body6.i

for.body6.i:                                      ; preds = %for.inc34.i, %entry
  %indvars.iv.i1 = phi i64 [ 0, %entry ], [ %indvars.iv.next.i, %for.inc34.i ]
  br i1 false, label %for.body6.i.for.inc34.i_crit_edge, label %for.cond7.preheader.i

for.body6.i.for.inc34.i_crit_edge:                ; preds = %for.body6.i
  br label %for.inc34.i

for.cond7.preheader.i:                            ; preds = %for.body6.i
  %arrayidx30.i = getelementptr [0 x i16], ptr null, i64 0, i64 %indvars.iv.i
  store i16 0, ptr %arrayidx30.i, align 2
  br label %for.inc34.i

for.body19.1.i:                                   ; preds = %for.body19.1.i
  store i16 0, ptr %arrayidx30.i, align 2
  br label %for.body19.1.i

for.inc34.i:                                      ; preds = %for.cond7.preheader.i, %for.body6.i.for.inc34.i_crit_edge
  %indvars.iv.next.i = add i64 %indvars.iv.i1, 1
  %exitcond.not.i = icmp eq i64 %indvars.iv.next.i, 0
  br i1 %exitcond.not.i, label %q.exit, label %for.body6.i

q.exit:                                           ; preds = %for.inc34.i
  ret i32 0
}

attributes #0 = { "target-features"="+64bit,+a,+c,+d,+f,+m,+relax,+v,+zicsr,+zifencei,+zmmul,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl256b,+zvl32b,+zvl64b,-b,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zacas,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smepmp,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zaamo,-zabha,-zalrsc,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl16384b,-zvl2048b,-zvl32768b,-zvl4096b,-zvl512b,-zvl65536b,-zvl8192b" }
```

Backtrace:
```
> /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt -passes="loop-vectorize" -S reduced.ll
opt: /scratch/tc-testing/tc-compiler-fuzz-trunk/llvm/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:3631: llvm::LoopVectorizationCostModel::collectLoopUniforms(llvm::ElementCount)::<lambda(llvm::Instruction*, llvm::ElementCount)>: Assertion `WideningDecision != CM_Unknown && "Widening decision should be ready at this moment"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt -passes=loop-vectorize -S reduced.ll
1.      Running pass "function(loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>)" on module "reduced.ll"
2.      Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "main"
 #0 0x000059f80448a570 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2f4f570)
 #1 0x000059f80448798f llvm::sys::RunSignalHandlers() (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2f4c98f)
 #2 0x000059f804487ae5 SignalHandler(int) Signals.cpp:0:0
 #3 0x0000795355842520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x00007953558969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x00007953558969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x00007953558969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x0000795355842476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x00007953558287f3 abort ./stdlib/abort.c:81:7
 #9 0x000079535582871b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x0000795355839e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#11 0x000059f80347d610 llvm::LoopVectorizationCostModel::collectLoopUniforms(llvm::ElementCount) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1f42610)
#12 0x000059f80348fa77 llvm::LoopVectorizationPlanner::plan(llvm::ElementCount, unsigned int) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1f54a77)
#13 0x000059f803491b83 llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1f56b83)
#14 0x000059f803494de1 llvm::LoopVectorizePass::runImpl(llvm::Function&, llvm::ScalarEvolution&, llvm::LoopInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::BlockFrequencyInfo*, llvm::TargetLibraryInfo*, llvm::DemandedBits&, llvm::AssumptionCache&, llvm::LoopAccessInfoManager&, llvm::OptimizationRemarkEmitter&, llvm::ProfileSummaryInfo*) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1f59de1)
#15 0x000059f803495497 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x1f5a497)
#16 0x000059f8022ff336 llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0xdc4336)
#17 0x000059f8042a17ff llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2d667ff)
#18 0x000059f8023024c6 llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0xdc74c6)
#19 0x000059f8042a057b llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2d6557b)
#20 0x000059f8022fe7c6 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0xdc37c6)
#21 0x000059f80429e5dd llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x2d635dd)
#22 0x000059f801b38c36 llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef<llvm::PassPlugin>, llvm::ArrayRef<std::function<void (llvm::PassBuilder&)>>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool) (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x5fdc36)
#23 0x000059f801b2a881 optMain (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x5ef881)
#24 0x0000795355829d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#25 0x0000795355829e40 call_init ./csu/../csu/libc-start.c:128:20
#26 0x0000795355829e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#27 0x000059f801b206c5 _start (/scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt+0x5e56c5)
zsh: IOT instruction (core dumped)  /scratch/tc-testing/tc-compiler-fuzz-trunk/build-gcv/build-llvm-linux/bin/opt
```

Found via fuzzer.


Fix patch:
commit 2ab910c08c4ed43d6fd9eb2ef9b3ff52e0293cf9
Author: Florian Hahn <flo@fhahn.com>
Date:   Tue Aug 13 09:23:44 2024 +0100

    [LV] Check pointer user are in loop when checking for uniform pointers.
    
    Widening decisions are not set for users outside the loop. Avoid
    crashing by only calling isVectorizedMemAccessUse for users in the loop.
    
    Fixes https://github.com/llvm/llvm-project/issues/102934.

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 5547116133e8..0d1262fa1872 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -3705,7 +3705,8 @@ void LoopVectorizationCostModel::collectLoopUniforms(ElementCount VF) {
     auto *I = cast<Instruction>(V);
     auto UsersAreMemAccesses =
       llvm::all_of(I->users(), [&](User *U) -> bool {
-        return isVectorizedMemAccessUse(cast<Instruction>(U), V);
+        auto *UI = cast<Instruction>(U);
+        return TheLoop->contains(UI) && isVectorizedMemAccessUse(UI, V);
       });
     if (UsersAreMemAccesses)
       addToWorklistIfAllowed(I);


Regression tests:
file: llvm/test/Transforms/LoopVectorize/X86/gep-use-outside-loop.ll
commands: opt -p loop-vectorize -mtriple=x86_64-apple-macosx -mcpu=skylake-avx512 -force-vector-width=4 -force-vector-interleave=1 -S %s
tests: test_name: gep_use_outside_loop
test_body: define void @gep_use_outside_loop(ptr noalias %dst, ptr %src) {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep.dst = getelementptr i16, ptr %dst, i64 %iv
  %gep.src = getelementptr i16, ptr %src, i64 %iv
  %l = load i16, ptr %gep.src, align 2
  %c = icmp eq i16 %l, 10
  br i1 %c, label %loop.latch, label %then

then:                                             ; preds = %loop.header
  store i16 0, ptr %gep.dst, align 2
  br label %loop.latch

loop.latch:                                       ; preds = %then, %loop.header
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv.next, 99
  br i1 %ec, label %exit, label %loop.header

exit:                                             ; preds = %loop.latch
  store i16 0, ptr %gep.dst, align 2
  ret void
}

test_name: gep_use_in_dead_block
test_body: define void @gep_use_in_dead_block(ptr noalias %dst, ptr %src) {
entry:
  br label %loop.header

loop.header:                                      ; preds = %loop.latch, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %gep.src = getelementptr i16, ptr %src, i64 %iv
  %l = load i16, ptr %gep.src, align 2
  %c = icmp eq i16 %l, 10
  br i1 %c, label %loop.latch, label %then

then:                                             ; preds = %loop.header
  %gep.dst = getelementptr i16, ptr %dst, i64 %iv
  store i16 0, ptr %gep.dst, align 2
  br label %loop.latch

dead:                                             ; preds = %dead
  store i16 0, ptr %gep.dst, align 2
  br label %dead

loop.latch:                                       ; preds = %then, %loop.header
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv.next, 99
  br i1 %ec, label %exit, label %loop.header

exit:                                             ; preds = %loop.latch
  ret void
}