Bug type: crash
Component: LoopVectorize
Bug location: llvm/lib/Transforms/Vectorize/LoopVectorize.cpp: LoopVectorizationCostModel::getInterleaveGroupCost
llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp: VPInterleaveRecipe::computeCost
Issue title: [clang] Assertion in `llvm::LoopVectorizationPlanner::computeBestVF()`
Labels: vectorizers
crash
Reported by: bcornille

When building the METIS (v5.1.0) library (GKLib) an assertion is thrown during LoopVectorize. This error was introduced within the past few days (see git sha of broken and working versions below).

#### Error:
```shell
clang: /mnt/thera/cicd/actions_work/ActionsRunner/ActionsRunner/trunk_repos/llvm-project/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp:7457: llvm::VectorizationFactor llvm::LoopVectorizationPlanner::computeBestVF(): Assertion `(BestFactor.Width == LegacyVF.Width || planContainsAdditionalSimplifications(getPlanFor(BestFactor.Width), CostCtx, OrigLoop)) && " VPlan cost model and legacy cost model disagreed"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: /share/contrib-modules/Core/llvm/2024-10-16/bin/clang -I/home/bcornill/libraries/metis-5.1.0/GKlib/. -I/home/bcornill/libraries/metis-5.1.0/GKlib/test -DLINUX -D_FILE_OFFSET_BITS=64 -DNDEBUG -DNDEBUG2 -DHAVE_EXECINFO_H -DHAVE_GETLINE -O3 -MD -MT CMakeFiles/GKlib.dir/blas.c.o -MF CMakeFiles/GKlib.dir/blas.c.o.d -o CMakeFiles/GKlib.dir/blas.c.o -c /home/bcornill/libraries/metis-5.1.0/GKlib/blas.c
1.      <eof> parser at end of file
2.      Optimizer
3.      Running pass "function<eager-inv>(float2int,lower-constant-intrinsics,chr,loop(loop-rotate<header-duplication;no-prepare-for-lto>,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>,infer-alignment,loop-load-elim,instcombine<max-iterations=1;no-verify-fixpoint>,simplifycfg<bonus-inst-threshold=1;forward-switch-cond;switch-range-to-icmp;switch-to-lookup;no-keep-loops;hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,slp-vectorizer,vector-combine,instcombine<max-iterations=1;no-verify-fixpoint>,loop-unroll<O3>,transform-warning,sroa<preserve-cfg>,infer-alignment,instcombine<max-iterations=1;no-verify-fixpoint>,loop-mssa(licm<allowspeculation>),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,tailcallelim,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;speculate-unpredictables>)" on module "/home/bcornill/libraries/metis-5.1.0/GKlib/blas.c"
4.      Running pass "loop-vectorize<no-interleave-forced-only;no-vectorize-forced-only;>" on function "gk_dargmax_n"
 #0 0x00007fa15911cc8b llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libLLVMSupport.so.20.0git+0x1c2c8b)
 #1 0x00007fa15911a664 llvm::sys::CleanupOnSignal(unsigned long) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libLLVMSupport.so.20.0git+0x1c0664)
 #2 0x00007fa1590227f8 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x00007fa1615e0dd0 __restore_rt sigaction.c:0:0
 #4 0x00007fa15821e70f raise (/lib64/libc.so.6+0x3770f)
 #5 0x00007fa158208b25 abort (/lib64/libc.so.6+0x21b25)
 #6 0x00007fa1582089f9 _nl_load_domain.cold.0 loadmsgcat.c:0:0
 #7 0x00007fa158216cc6 .annobin___GI___assert_fail.end assert.c:0:0
 #8 0x00007fa15db3af1b llvm::LoopVectorizationPlanner::computeBestVF() (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libLLVMVectorize.so.20.0git+0xb5f1b)
 #9 0x00007fa15db52d46 llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libLLVMVectorize.so.20.0git+0xcdd46)
#10 0x00007fa15db55ed1 llvm::LoopVectorizePass::runImpl(llvm::Function&) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libLLVMVectorize.so.20.0git+0xd0ed1)
#11 0x00007fa15db56517 llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libLLVMVectorize.so.20.0git+0xd1517)
#12 0x00007fa155d90a9e llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/../lib/libLLVMPasses.so.20.0git+0x76a9e)
#13 0x00007fa15998eab7 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libLLVMCore.so.20.0git+0x323ab7)
#14 0x00007fa16434e17e llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libLLVMX86CodeGen.so.20.0git+0xa917e)
#15 0x00007fa15998ce55 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libLLVMCore.so.20.0git+0x321e55)
#16 0x00007fa16434e56e llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libLLVMX86CodeGen.so.20.0git+0xa956e)
#17 0x00007fa15998d9bc llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libLLVMCore.so.20.0git+0x3229bc)
#18 0x00007fa15faab288 (anonymous namespace)::EmitAssemblyHelper::RunOptimizationPipeline(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>&, std::unique_ptr<llvm::ToolOutputFile, std::default_delete<llvm::ToolOutputFile>>&, clang::BackendConsumer*) BackendUtil.cpp:0:0
#19 0x00007fa15faaeb9c clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libclangCodeGen.so.20.0git+0x111b9c)
#20 0x00007fa15ffdd293 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libclangCodeGen.so.20.0git+0x640293)
#21 0x00007fa150c5592c clang::ParseAST(clang::Sema&, bool, bool) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/../lib/libclangParse.so.20.0git+0x3c92c)
#22 0x00007fa15d75dee9 clang::FrontendAction::Execute() (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libclangFrontend.so.20.0git+0x138ee9)
#23 0x00007fa15d6ceb05 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libclangFrontend.so.20.0git+0xa9b05)
#24 0x00007fa1613cad83 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libclangFrontendTool.so.20.0git+0x4d83)
#25 0x00000000004141c7 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/share/contrib-modules/Core/llvm/2024-10-16/bin/clang+0x4141c7)
#26 0x000000000040b96a ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
#27 0x00007fa15d135049 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const::'lambda'()>(long) Job.cpp:0:0
#28 0x00007fa159022cb4 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libLLVMSupport.so.20.0git+0xc8cb4)
#29 0x00007fa15d13589e clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (.part.0) Job.cpp:0:0
#30 0x00007fa15d0f22fc clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libclangDriver.so.20.0git+0x922fc)
#31 0x00007fa15d0f33fd clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libclangDriver.so.20.0git+0x933fd)
#32 0x00007fa15d1039c4 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/../lib/libclangDriver.so.20.0git+0xa39c4)
#33 0x0000000000410b5b clang_main(int, char**, llvm::ToolContext const&) (/share/contrib-modules/Core/llvm/2024-10-16/bin/clang+0x410b5b)
#34 0x000000000040b074 main (/share/contrib-modules/Core/llvm/2024-10-16/bin/clang+0x40b074)
#35 0x00007fa15820a6a3 __libc_start_main (/lib64/libc.so.6+0x236a3)
#36 0x000000000040b0be _start (/share/contrib-modules/Core/llvm/2024-10-16/bin/clang+0x40b0be)
clang: error: clang frontend command failed with exit code 134 (use -v to see invocation)
clang version 20.0.0git (https://github.com/llvm/llvm-project ae68d532f810e217c747b10b26aeea3bb84c3844)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin
Build config: +assertions
Configuration file: /share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/clang.cfg
clang: note: diagnostic msg:
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang: note: diagnostic msg: /tmp/blas-9fe25d.c
clang: note: diagnostic msg: /tmp/blas-9fe25d.sh
clang: note: diagnostic msg:

********************
```
#### Reproducer:
[gklib-blas.tar.gz](https://github.com/user-attachments/files/17437550/gklib-blas.tar.gz)

#### Broken Versions:
```shell
>> clang --version
clang version 20.0.0git (https://github.com/llvm/llvm-project ae68d532f810e217c747b10b26aeea3bb84c3844)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin
Build config: +assertions
Configuration file: /share/contrib-modules/Core/llvm/2024-10-16_20.0-0/bin/clang.cfg

>> clang --version
clang version 20.0.0git (https://github.com/llvm/llvm-project af90e7c5161de9a36af768dd5c9d73464e0eed64)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /share/contrib-modules/Core/llvm/2024-10-18_20.0-0/bin
Build config: +assertions
Configuration file: /share/contrib-modules/Core/llvm/2024-10-18_20.0-0/bin/clang.cfg
```

#### Working version:
```shell
>> clang --version
clang version 20.0.0git (https://github.com/llvm/llvm-project 48deb3568eb2452ff385b04b8f71c34121f47387)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /share/contrib-modules/Core/llvm/2024-10-13_20.0-0/bin
Build config: +assertions
Configuration file: /share/contrib-modules/Core/llvm/2024-10-13_20.0-0/bin/clang.cfg
```

Comments: author: fhahn
body: Thanks, taking a look!

Fix patch:
commit 2a6b09e0d3d3c1a05d3d5165202a6e68900974b1
Author: Florian Hahn <flo@fhahn.com>
Date:   Fri Oct 18 19:12:39 2024 -0700

    [LV] Use type from InsertPos for cost computation of interleave groups.
    
    Previously the legacy cost model would pick the type for the cost
    computation depending on the order of the members in the input IR.
    This is incompatible with the VPlan-based cost model (independent of
    original IR order) and also doesn't match code-gen, which uses the type
    of the insert position.
    
    Update the legacy cost model to use the type (and address space) from
    the Group's insert position.
    
    This brings the legacy cost model in line with the legacy cost model and
    fixes a divergence between both models.
    
    Note that the X86 cost model seems to assign different costs to groups
    with i64 and double types. Added a TODO to check.
    
    Fixes https://github.com/llvm/llvm-project/issues/112922.

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
index 857efbdf687c..ce0903b838aa 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
@@ -5738,14 +5738,15 @@ LoopVectorizationCostModel::getGatherScatterCost(Instruction *I,
 InstructionCost
 LoopVectorizationCostModel::getInterleaveGroupCost(Instruction *I,
                                                    ElementCount VF) {
-  Type *ValTy = getLoadStoreType(I);
-  auto *VectorTy = cast<VectorType>(ToVectorTy(ValTy, VF));
-  unsigned AS = getLoadStoreAddressSpace(I);
-  enum TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
-
   const auto *Group = getInterleavedAccessGroup(I);
   assert(Group && "Fail to get an interleaved access group.");
 
+  Instruction *InsertPos = Group->getInsertPos();
+  Type *ValTy = getLoadStoreType(InsertPos);
+  auto *VectorTy = cast<VectorType>(ToVectorTy(ValTy, VF));
+  unsigned AS = getLoadStoreAddressSpace(InsertPos);
+  enum TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
+
   unsigned InterleaveFactor = Group->getFactor();
   auto *WideVecTy = VectorType::get(ValTy, VF * InterleaveFactor);
 
@@ -5760,8 +5761,9 @@ LoopVectorizationCostModel::getInterleaveGroupCost(Instruction *I,
       (Group->requiresScalarEpilogue() && !isScalarEpilogueAllowed()) ||
       (isa<StoreInst>(I) && (Group->getNumMembers() < Group->getFactor()));
   InstructionCost Cost = TTI.getInterleavedMemoryOpCost(
-      I->getOpcode(), WideVecTy, Group->getFactor(), Indices, Group->getAlign(),
-      AS, CostKind, Legal->isMaskRequired(I), UseMaskForGaps);
+      InsertPos->getOpcode(), WideVecTy, Group->getFactor(), Indices,
+      Group->getAlign(), AS, CostKind, Legal->isMaskRequired(I),
+      UseMaskForGaps);
 
   if (Group->isReverse()) {
     // TODO: Add support for reversed masked interleaved access.
diff --git a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
index f4a1f58debba..41f13cc2d9a9 100644
--- a/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
+++ b/llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
@@ -2958,11 +2958,20 @@ void VPInterleaveRecipe::print(raw_ostream &O, const Twine &Indent,
 
 InstructionCost VPInterleaveRecipe::computeCost(ElementCount VF,
                                                 VPCostContext &Ctx) const {
-  Instruction *I = getInsertPos();
+  Instruction *InsertPos = getInsertPos();
+  // Find the VPValue index of the interleave group. We need to skip gaps.
+  unsigned InsertPosIdx = 0;
+  for (unsigned Idx = 0; IG->getFactor(); ++Idx)
+    if (auto *Member = IG->getMember(Idx)) {
+      if (Member == InsertPos)
+        break;
+      InsertPosIdx++;
+    }
   Type *ValTy = Ctx.Types.inferScalarType(
-      getNumDefinedValues() > 0 ? getVPValue(0) : getStoredValues()[0]);
+      getNumDefinedValues() > 0 ? getVPValue(InsertPosIdx)
+                                : getStoredValues()[InsertPosIdx]);
   auto *VectorTy = cast<VectorType>(ToVectorTy(ValTy, VF));
-  unsigned AS = getLoadStoreAddressSpace(I);
+  unsigned AS = getLoadStoreAddressSpace(InsertPos);
   enum TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
 
   unsigned InterleaveFactor = IG->getFactor();
@@ -2976,8 +2985,8 @@ InstructionCost VPInterleaveRecipe::computeCost(ElementCount VF,
 
   // Calculate the cost of the whole interleaved group.
   InstructionCost Cost = Ctx.TTI.getInterleavedMemoryOpCost(
-      I->getOpcode(), WideVecTy, IG->getFactor(), Indices, IG->getAlign(), AS,
-      CostKind, getMask(), NeedsMaskForGaps);
+      InsertPos->getOpcode(), WideVecTy, IG->getFactor(), Indices,
+      IG->getAlign(), AS, CostKind, getMask(), NeedsMaskForGaps);
 
   if (!IG->isReverse())
     return Cost;


Regression tests:
file: llvm/test/Transforms/LoopVectorize/X86/interleave-cost.ll
commands: opt -p loop-vectorize -S %s
tests: test_name: geps_feeding_interleave_groups_with_reuse
test_body: target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.15.0"

define void @geps_feeding_interleave_groups_with_reuse(ptr %arg, i64 %arg1, ptr %arg2) #0 {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %shl.iv.5 = shl i64 %iv, 5
  %gep.1 = getelementptr i8, ptr %arg, i64 %shl.iv.5
  %add.5 = or disjoint i64 %shl.iv.5, 16
  %gep.2 = getelementptr i8, ptr %arg, i64 %add.5
  %shl.iv.4 = shl i64 %iv, 4
  %gep.3 = getelementptr i8, ptr %arg2, i64 %shl.iv.4
  %l.1 = load float, ptr %gep.1, align 4
  %l.2 = load float, ptr %gep.2, align 4
  %add.1 = fadd float %l.1, %l.2
  %mul.1 = fmul float %add.1, 0.000000e+00
  store float %mul.1, ptr %gep.3, align 4
  %gep.4 = getelementptr i8, ptr %gep.1, i64 4
  %l.3 = load float, ptr %gep.4, align 4
  %gep.5 = getelementptr i8, ptr %gep.2, i64 4
  %l.4 = load float, ptr %gep.5, align 4
  %add.2 = fadd float %l.3, %l.4
  %mul.2 = fmul float %add.2, 0.000000e+00
  %gep.6 = getelementptr i8, ptr %gep.3, i64 4
  store float %mul.2, ptr %gep.6, align 4
  %gep.7 = getelementptr i8, ptr %gep.1, i64 8
  %l.5 = load float, ptr %gep.7, align 4
  %gep.8 = getelementptr i8, ptr %gep.2, i64 8
  %l.6 = load float, ptr %gep.8, align 4
  %add.3 = fadd float %l.5, %l.6
  %mul.3 = fmul float %add.3, 0.000000e+00
  %gep.9 = getelementptr i8, ptr %gep.3, i64 8
  store float %mul.3, ptr %gep.9, align 4
  %i27 = getelementptr i8, ptr %gep.1, i64 12
  %l.7 = load float, ptr %i27, align 4
  %gep.10 = getelementptr i8, ptr %gep.2, i64 12
  %l.8 = load float, ptr %gep.10, align 4
  %add.4 = fadd float %l.7, %l.8
  %mul.4 = fmul float %add.4, 0.000000e+00
  %gep.11 = getelementptr i8, ptr %gep.3, i64 12
  store float %mul.4, ptr %gep.11, align 4
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv, %arg1
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

attributes #0 = { "target-features"="+sse4.2" }

test_name: geps_feeding_interleave_groups_with_reuse2
test_body: target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.15.0"

define void @geps_feeding_interleave_groups_with_reuse2(ptr %A, ptr %B, i64 %N) #0 {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next.7, %loop ]
  %shr.1 = lshr exact i64 %iv, 1
  %gep.B = getelementptr nusw i32, ptr %B, i64 %shr.1
  %l = load i32, ptr %gep.B, align 4
  %gep.A = getelementptr i32, ptr %A, i64 %iv
  store i32 %l, ptr %gep.A, align 4
  %iv.next = or disjoint i64 %iv, 1
  %gep.A.1 = getelementptr i32, ptr %A, i64 %iv.next
  store i32 0, ptr %gep.A.1, align 4
  %iv.next.1 = or disjoint i64 %iv, 2
  %shr.2 = lshr exact i64 %iv.next.1, 1
  %gep.B.2 = getelementptr i32, ptr %B, i64 %shr.2
  %0 = load i32, ptr %gep.B.2, align 4
  %gep.A.2 = getelementptr i32, ptr %A, i64 %iv.next.1
  store i32 %0, ptr %gep.A.2, align 4
  %iv.next.2 = or disjoint i64 %iv, 3
  %gep.A.3 = getelementptr i32, ptr %A, i64 %iv.next.2
  store i32 0, ptr %gep.A.3, align 4
  %iv.next.3 = or disjoint i64 %iv, 4
  %gep.B.4 = getelementptr i32, ptr %B, i64 %iv
  %1 = load i32, ptr %gep.B.4, align 4
  %gep.A.4 = getelementptr i32, ptr %A, i64 %iv.next.3
  store i32 %1, ptr %gep.A.4, align 4
  %iv.next.4 = or disjoint i64 %iv, 5
  %gep.A.5 = getelementptr i32, ptr %A, i64 %iv.next.4
  store i32 0, ptr %gep.A.5, align 4
  %iv.next.5 = or disjoint i64 %iv, 6
  %gep.A.6 = getelementptr i32, ptr %A, i64 %iv.next.5
  store i32 0, ptr %gep.A.6, align 4
  %iv.next.6 = or disjoint i64 %iv, 7
  %gep.A.7 = getelementptr i32, ptr %A, i64 %iv.next.6
  store i32 0, ptr %gep.A.7, align 4
  %iv.next.7 = add nuw nsw i64 %iv, 8
  %ec = icmp eq i64 %iv, %N
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

attributes #0 = { "min-legal-vector-width"="0" "target-cpu"="cascadelake" }

test_name: interleave_store_double_i64_2
test_body: target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.15.0"

define void @interleave_store_double_i64_2(ptr %dst) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %gep.1 = getelementptr { i64, double }, ptr %dst, i64 %iv, i32 1
  store double 0.000000e+00, ptr %gep.1, align 8
  %gep.0 = getelementptr { i64, double }, ptr %dst, i64 %iv
  store i64 %iv, ptr %gep.0, align 8
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv, 1
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

test_name: interleave_store_i64_double
test_body: target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.15.0"

define void @interleave_store_i64_double(ptr %dst) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %gep.0 = getelementptr { double, i64 }, ptr %dst, i64 %iv
  store double 0.000000e+00, ptr %gep.0, align 8
  %gep.1 = getelementptr { double, i64 }, ptr %dst, i64 %iv, i32 1
  store i64 %iv, ptr %gep.1, align 8
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv, 1
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

test_name: test_free_instructions_feeding_geps_for_interleave_groups
test_body: target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.15.0"

define void @test_free_instructions_feeding_geps_for_interleave_groups(ptr noalias %p.invar, ptr noalias %dst.1, ptr noalias %dst.2) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %l.0 = load float, ptr %p.invar, align 4
  %iv.mul = shl i64 %iv, 2
  %gep.dst.19 = getelementptr float, ptr %dst.1, i64 %iv.mul
  store float %l.0, ptr %gep.dst.19, align 4
  %l.1 = load float, ptr %p.invar, align 4
  %add.1 = or disjoint i64 %iv.mul, 1
  %gep.dst.119 = getelementptr float, ptr %dst.1, i64 %add.1
  store float %l.1, ptr %gep.dst.119, align 4
  %add.2 = or disjoint i64 %iv.mul, 2
  %gep.dst.129 = getelementptr float, ptr %dst.1, i64 %add.2
  store float 0.000000e+00, ptr %gep.dst.129, align 4
  %add.3 = or disjoint i64 %iv.mul, 3
  %gep.dst.140 = getelementptr float, ptr %dst.1, i64 %add.3
  store float 0.000000e+00, ptr %gep.dst.140, align 4
  %l.2 = load float, ptr %p.invar, align 4
  %gep.dst.247 = getelementptr float, ptr %dst.2, i64 %iv.mul
  store float %l.2, ptr %gep.dst.247, align 4
  %gep.dst.255 = getelementptr float, ptr %dst.2, i64 %add.1
  store float 0.000000e+00, ptr %gep.dst.255, align 4
  %gep.dst.265 = getelementptr float, ptr %dst.2, i64 %add.2
  store float 0.000000e+00, ptr %gep.dst.265, align 4
  %gep.dst.276 = getelementptr float, ptr %dst.2, i64 %add.3
  store float 0.000000e+00, ptr %gep.dst.276, align 4
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv.next, 0
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

test_name: interleave_store_double_i64
test_body: target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.15.0"

define void @interleave_store_double_i64(ptr %dst) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %gep.1 = getelementptr { double, i64 }, ptr %dst, i64 %iv, i32 1
  store i64 %iv, ptr %gep.1, align 8
  %gep.0 = getelementptr { double, i64 }, ptr %dst, i64 %iv
  store double 0.000000e+00, ptr %gep.0, align 8
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv, 1
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}

test_name: interleave_store_i64_double_2
test_body: target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.15.0"

define void @interleave_store_i64_double_2(ptr %dst) {
entry:
  br label %loop

loop:                                             ; preds = %loop, %entry
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
  %gep.0 = getelementptr { i64, double }, ptr %dst, i64 %iv
  store i64 %iv, ptr %gep.0, align 8
  %gep.1 = getelementptr { i64, double }, ptr %dst, i64 %iv, i32 1
  store double 0.000000e+00, ptr %gep.1, align 8
  %iv.next = add i64 %iv, 1
  %ec = icmp eq i64 %iv, 1
  br i1 %ec, label %exit, label %loop

exit:                                             ; preds = %loop
  ret void
}