Bug type: crash
Component: LoopVectorize
Bug location: llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h: createOr
createSelect
llvm/lib/Transforms/Vectorize/VPlan.h: GEPFlagsTy
VPInstruction
VPRecipeWithIRFlags
Issue title: [LoopVectorize] Assertion `OpType == OperationType::DisjointOp && "recipe cannot have a disjoing flag"' failed.
Labels: vectorizers
crash
Reported by: patrick-rivos

Reduced LLVM IR:
``` llvm ir
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

define i32 @main() #0 {
entry:
  br label %for.body300.us.us.i

for.body300.us.us.i:                              ; preds = %if.end559.us.us.i, %entry
  br label %for.body326.us.us.i

for.body326.us.us.i:                              ; preds = %if.end559.us.us.i, %for.body300.us.us.i
  %indvars.iv18 = phi i64 [ 0, %for.body300.us.us.i ], [ %indvars.iv.next19, %if.end559.us.us.i ]
  br i1 false, label %cond.end339.us.us.i, label %cond.end354.us.us.i

cond.end339.us.us.i:                              ; preds = %for.body326.us.us.i
  br i1 false, label %cond.end339.us.us.i.if.then357.us.us.i_crit_edge, label %cond.end339.us.us.i.cond.end354.us.us.i_crit_edge

cond.end339.us.us.i.cond.end354.us.us.i_crit_edge: ; preds = %cond.end339.us.us.i
  br label %cond.end354.us.us.i

cond.end339.us.us.i.if.then357.us.us.i_crit_edge: ; preds = %cond.end339.us.us.i
  br label %if.then357.us.us.i

cond.end354.us.us.i:                              ; preds = %cond.end339.us.us.i.cond.end354.us.us.i_crit_edge, %for.body326.us.us.i
  br i1 false, label %cond.end354.us.us.i.if.then357.us.us.i_crit_edge, label %if.end559.us.us.i

cond.end354.us.us.i.if.then357.us.us.i_crit_edge: ; preds = %cond.end354.us.us.i
  br label %if.then357.us.us.i

if.then357.us.us.i:                               ; preds = %cond.end354.us.us.i.if.then357.us.us.i_crit_edge, %cond.end339.us.us.i.if.then357.us.us.i_crit_edge
  %.pre1143.i7 = phi i64 [ poison, %cond.end339.us.us.i.if.then357.us.us.i_crit_edge ], [ %indvars.iv18, %cond.end354.us.us.i.if.then357.us.us.i_crit_edge ]
  %arrayidx429.us.us.i = getelementptr [14 x i16], ptr null, i64 0, i64 %.pre1143.i7
  store i16 0, ptr %arrayidx429.us.us.i, align 2
  br label %if.end559.us.us.i

if.end559.us.us.i:                                ; preds = %if.then357.us.us.i, %cond.end354.us.us.i
  %indvars.iv.next19 = add i64 %indvars.iv18, 1
  %0 = trunc i64 %indvars.iv18 to i32
  %cmp323.us.us.i = icmp slt i32 %0, 1
  br i1 %cmp323.us.us.i, label %for.body326.us.us.i, label %for.body300.us.us.i
}

attributes #0 = { "target-features"="+64bit,+a,+c,+d,+f,+m,+relax,+v,+zicsr,+zifencei,+zve32f,+zve32x,+zve64d,+zve64f,+zve64x,+zvl128b,+zvl256b,+zvl32b,+zvl64b,-e,-experimental-smmpm,-experimental-smnpm,-experimental-ssnpm,-experimental-sspm,-experimental-ssqosid,-experimental-supm,-experimental-zaamo,-experimental-zabha,-experimental-zalasr,-experimental-zalrsc,-experimental-zcmop,-experimental-zfbfmin,-experimental-zicfilp,-experimental-zicfiss,-experimental-zimop,-experimental-ztso,-experimental-zvfbfmin,-experimental-zvfbfwma,-h,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smepmp,-ssaia,-ssccptr,-sscofpmf,-sscounterenw,-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,-za128rs,-za64rs,-zacas,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmp,-zcmt,-zdinx,-zfa,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zihintntl,-zihintpause,-zihpm,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-zmmul,-zvbb,-zvbc,-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:
```
opt: /scratch/tc-testing/tc-apr-2/llvm/llvm/lib/Transforms/Vectorize/VPlan.h:1131: bool llvm::VPRecipeWithIRFlags::isDisjoint() const: Assertion `OpType == OperationType::DisjointOp && "recipe cannot have a disjoing flag"' 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-apr-2/build-rv64gcv/build-llvm-linux/bin/opt reduced.ll --passes=loop-vectorize
 #0 0x00005bd204995b60 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x2d84b60)
 #1 0x00005bd204992f6f llvm::sys::RunSignalHandlers() (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x2d81f6f)
 #2 0x00005bd2049930c5 SignalHandler(int) Signals.cpp:0:0
 #3 0x000076eef1a42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x000076eef1a969fc __pthread_kill_implementation ./nptl/pthread_kill.c:44:76
 #5 0x000076eef1a969fc __pthread_kill_internal ./nptl/pthread_kill.c:78:10
 #6 0x000076eef1a969fc pthread_kill ./nptl/pthread_kill.c:89:10
 #7 0x000076eef1a42476 gsignal ./signal/../sysdeps/posix/raise.c:27:6
 #8 0x000076eef1a287f3 abort ./stdlib/abort.c:81:7
 #9 0x000076eef1a2871b _nl_load_domain ./intl/loadmsgcat.c:1177:9
#10 0x000076eef1a39e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#11 0x00005bd203b25ea2 llvm::VPlanTransforms::dropPoisonGeneratingRecipes(llvm::VPlan&, llvm::function_ref<bool (llvm::BasicBlock*)>)::'lambda'(llvm::VPRecipeBase*)::operator()(llvm::VPRecipeBase*) const VPlanTransforms.cpp:0:0
#12 0x00005bd203b2c77d llvm::VPlanTransforms::dropPoisonGeneratingRecipes(llvm::VPlan&, llvm::function_ref<bool (llvm::BasicBlock*)>) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x1f1b77d)
#13 0x00005bd203a05435 llvm::LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(llvm::VFRange&) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x1df4435)
#14 0x00005bd203a05c9e llvm::LoopVectorizationPlanner::buildVPlansWithVPRecipes(llvm::ElementCount, llvm::ElementCount) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x1df4c9e)
#15 0x00005bd203a0c319 llvm::LoopVectorizationPlanner::plan(llvm::ElementCount, unsigned int) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x1dfb319)
#16 0x00005bd203a0f8a9 llvm::LoopVectorizePass::processLoop(llvm::Loop*) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x1dfe8a9)
#17 0x00005bd203a1273e 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-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x1e0173e)
#18 0x00005bd203a1388d llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x1e0288d)
#19 0x00005bd20291a276 llvm::detail::PassModel<llvm::Function, llvm::LoopVectorizePass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0xd09276)
#20 0x00005bd2047bc141 llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x2bab141)
#21 0x00005bd202911bd6 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-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0xd00bd6)
#22 0x00005bd2047bae3b llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x2ba9e3b)
#23 0x00005bd202919dc6 llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0xd08dc6)
#24 0x00005bd2047b8cb1 llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x2ba7cb1)
#25 0x00005bd202193ce5 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-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x582ce5)
#26 0x00005bd202186316 optMain (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x575316)
#27 0x000076eef1a29d90 __libc_start_call_main ./csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#28 0x000076eef1a29e40 call_init ./csu/../csu/libc-start.c:128:20
#29 0x000076eef1a29e40 __libc_start_main ./csu/../csu/libc-start.c:379:5
#30 0x00005bd20217bf95 _start (/scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt+0x56af95)
zsh: IOT instruction (core dumped)  /scratch/tc-testing/tc-apr-2/build-rv64gcv/build-llvm-linux/bin/opt reduced.l
```

Godbolt: https://godbolt.org/z/jj39h3z7M

Minor spelling nit: `disjoing -> disjoint`

Found via fuzzer.

Likely caused/exposed by https://github.com/llvm/llvm-project/commit/6ef829941b38f7e8a28c4cba1ff25cd0ae9f7d3d https://github.com/llvm/llvm-project/pull/83821 @fhahn 


Fix patch:
commit 6261c53c6f9c82bfca5df2ed5917876d748ed079
Author: Florian Hahn <flo@fhahn.com>
Date:   Tue Apr 2 21:48:35 2024 +0100

    [VPlan] Make sure OR VPInstructions are treated as disjoint ops.
    
    Make sure that VPInstructions with OR opcodes are properly registered as
    disjoint ops.
    
    Fixes https://github.com/llvm/llvm-project/issues/87378.

diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h
index 5d03b66b0ce3..ebca2d855a46 100644
--- a/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h
+++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationPlanner.h
@@ -175,7 +175,10 @@ public:
 
   VPValue *createOr(VPValue *LHS, VPValue *RHS, DebugLoc DL = {},
                     const Twine &Name = "") {
-    return createInstruction(Instruction::BinaryOps::Or, {LHS, RHS}, DL, Name);
+
+    return tryInsertInstruction(new VPInstruction(
+        Instruction::BinaryOps::Or, {LHS, RHS},
+        VPRecipeWithIRFlags::DisjointFlagsTy(false), DL, Name));
   }
 
   VPValue *createSelect(VPValue *Cond, VPValue *TrueVal, VPValue *FalseVal,
diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h
index 3baca43f7276..707a826ecdc2 100644
--- a/llvm/lib/Transforms/Vectorize/VPlan.h
+++ b/llvm/lib/Transforms/Vectorize/VPlan.h
@@ -913,6 +913,11 @@ public:
     WrapFlagsTy(bool HasNUW, bool HasNSW) : HasNUW(HasNUW), HasNSW(HasNSW) {}
   };
 
+  struct DisjointFlagsTy {
+    char IsDisjoint : 1;
+    DisjointFlagsTy(bool IsDisjoint) : IsDisjoint(IsDisjoint) {}
+  };
+
 protected:
   struct GEPFlagsTy {
     char IsInBounds : 1;
@@ -920,9 +925,6 @@ protected:
   };
 
 private:
-  struct DisjointFlagsTy {
-    char IsDisjoint : 1;
-  };
   struct ExactFlagsTy {
     char IsExact : 1;
   };
@@ -1016,6 +1018,12 @@ public:
       : VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::FPMathOp),
         FMFs(FMFs) {}
 
+  template <typename IterT>
+  VPRecipeWithIRFlags(const unsigned char SC, IterT Operands,
+                      DisjointFlagsTy DisjointFlags, DebugLoc DL = {})
+      : VPSingleDefRecipe(SC, Operands, DL), OpType(OperationType::DisjointOp),
+        DisjointFlags(DisjointFlags) {}
+
 protected:
   template <typename IterT>
   VPRecipeWithIRFlags(const unsigned char SC, IterT Operands,
@@ -1221,6 +1229,14 @@ public:
       : VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, WrapFlags, DL),
         Opcode(Opcode), Name(Name.str()) {}
 
+  VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands,
+                DisjointFlagsTy DisjointFlag, DebugLoc DL = {},
+                const Twine &Name = "")
+      : VPRecipeWithIRFlags(VPDef::VPInstructionSC, Operands, DisjointFlag, DL),
+        Opcode(Opcode), Name(Name.str()) {
+    assert(Opcode == Instruction::Or && "only OR opcodes can be disjoint");
+  }
+
   VPInstruction(unsigned Opcode, std::initializer_list<VPValue *> Operands,
                 FastMathFlags FMFs, DebugLoc DL = {}, const Twine &Name = "");
 


Regression tests:
file: llvm/test/Transforms/LoopVectorize/pr87378-vpinstruction-or-drop-poison-generating-flags.ll
commands: opt -p loop-vectorize -mattr="+v" -S %s
tests: test_name: <module>
test_body: 
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "riscv64-unknown-linux-gnu"

; Test case for https://github.com/llvm/llvm-project/issues/87378.
define void @pr87378_vpinstruction_or_drop_poison_generating_flags(ptr %arg, i64 %a, i64 %b, i64 %c) {
;
entry:
  br label %loop.header

loop.header:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %c.1 = icmp ule i64 %iv, %a
  br i1 %c.1, label %then.1, label %else.1

then.1:
  %c.2 = icmp ule i64 %iv, %b
  br i1 %c.2, label %else.1, label %merge

else.1:
  %c.3 = icmp ule i64 %iv, %c
  br i1 %c.3, label %then.2, label %loop.latch

then.2:
  br label %merge

merge:
  %idx = phi i64 [ poison, %then.1 ], [ %iv, %then.2 ]
  %getelementptr = getelementptr i16, ptr %arg, i64 %idx
  store i16 0, ptr %getelementptr, align 2
  br label %loop.latch

loop.latch:
  %iv.next = add i64 %iv, 1
  %icmp = icmp eq i64 %iv, 1000
  br i1 %icmp, label %exit, label %loop.header

exit:
  ret void
}
;.
;.