Quuxplusone / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
https://p1144.godbolt.org/z/jf67zx5hq
Other
0 stars 2 forks source link

Null dereference in llvm::Operator::hasPoisonGeneratingFlags() #29

Open Quuxplusone opened 6 months ago

Quuxplusone commented 6 months ago

https://godbolt.org/z/ebebYdjof

long b(const char *);
int c(int d, const char *g, const char *a) {
  for (;;) {
    if (*g == 0)
      return 42;
    if (d < 10)
      return g - a + b(g);
    ++g;
    --d;
  }
}
void h() {
  static int e;
  static char f;
  e = c(e, "@", "");
  c(e, &f, &f);
  h();
}

Compile with clang++ -O2 and it ICEs. Interestingly, it ICEs only in C++, not in C. Started happening sometime after Clang 18. It looks like isGuaranteedNotToBeUndefOrPoison has been touched a lot in March 2024, so that's probably all it is.

Stack dump:
0.  Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/clang++ -gdwarf-4 -g -o /app/output.s -S --gcc-toolchain=/opt/compiler-explorer/gcc-snapshot -fcolor-diagnostics -fno-crash-diagnostics -O2 <source>
1.  <eof> parser at end of file
2.  Code generation
3.  Running pass 'Function Pass Manager' on module '<source>'.
4.  Running pass 'Loop Pass Manager' on function '@_Z1hv'
5.  Running pass 'Loop Strength Reduction' on basic block '%if.end.i2'
 #0 0x0000000003929c38 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3929c38)
 #1 0x000000000392791c llvm::sys::CleanupOnSignal(unsigned long) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x392791c)
 #2 0x000000000386dec8 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x00007fa042a42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
 #4 0x0000000000b16f52 llvm::Operator::hasPoisonGeneratingFlags() const (.cold) Operator.cpp:0:0
 #5 0x00000000032fc119 llvm::Operator::hasPoisonGeneratingFlagsOrMetadata() const (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x32fc119)
 #6 0x0000000002a997cd canCreateUndefOrPoison(llvm::Operator const*, UndefPoisonKind, bool) ValueTracking.cpp:0:0
 #7 0x0000000002aae633 isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind) ValueTracking.cpp:0:0
 #8 0x0000000002aae7c5 isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind) ValueTracking.cpp:0:0
 #9 0x0000000002aae307 isGuaranteedNotToBeUndefOrPoison(llvm::Value const*, llvm::AssumptionCache*, llvm::Instruction const*, llvm::DominatorTree const*, unsigned int, UndefPoisonKind) ValueTracking.cpp:0:0
#10 0x00000000029fb2ba void llvm::visitAll<(anonymous namespace)::SCEVPoisonCollector>(llvm::SCEV const*, (anonymous namespace)::SCEVPoisonCollector&) ScalarEvolution.cpp:0:0
#11 0x00000000029fb829 llvm::ScalarEvolution::getPoisonGeneratingValues(llvm::SmallPtrSetImpl<llvm::Value const*>&, llvm::SCEV const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x29fb829)
#12 0x00000000029fd133 llvm::ScalarEvolution::canReuseInstruction(llvm::SCEV const*, llvm::Instruction*, llvm::SmallVectorImpl<llvm::Instruction*>&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x29fd133)
#13 0x0000000003a7f310 llvm::SCEVExpander::FindValueInExprValueMap(llvm::SCEV const*, llvm::Instruction const*, llvm::SmallVectorImpl<llvm::Instruction*>&) (.part.0) ScalarEvolutionExpander.cpp:0:0
#14 0x0000000003a88a0a llvm::SCEVExpander::expand(llvm::SCEV const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3a88a0a)
#15 0x0000000003a88f3c llvm::SCEVExpander::expandCodeFor(llvm::SCEV const*, llvm::Type*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3a88f3c)
#16 0x00000000037695f7 (anonymous namespace)::LSRInstance::Expand((anonymous namespace)::LSRUse const&, (anonymous namespace)::LSRFixup const&, (anonymous namespace)::Formula const&, llvm::ilist_iterator_w_bits<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void, true>, false, false>, llvm::SmallVectorImpl<llvm::WeakTrackingVH>&) const (.constprop.0) LoopStrengthReduce.cpp:0:0
#17 0x0000000003780a26 (anonymous namespace)::LSRInstance::LSRInstance(llvm::Loop*, llvm::IVUsers&, llvm::ScalarEvolution&, llvm::DominatorTree&, llvm::LoopInfo&, llvm::TargetTransformInfo const&, llvm::AssumptionCache&, llvm::TargetLibraryInfo&, llvm::MemorySSAUpdater*) LoopStrengthReduce.cpp:0:0
#18 0x0000000003781ccf ReduceLoopStrength(llvm::Loop*, llvm::IVUsers&, llvm::ScalarEvolution&, llvm::DominatorTree&, llvm::LoopInfo&, llvm::TargetTransformInfo const&, llvm::AssumptionCache&, llvm::TargetLibraryInfo&, llvm::MemorySSA*) LoopStrengthReduce.cpp:0:0
#19 0x0000000003784f88 (anonymous namespace)::LoopStrengthReduce::runOnLoop(llvm::Loop*, llvm::LPPassManager&) LoopStrengthReduce.cpp:0:0
#20 0x000000000297e0db llvm::LPPassManager::runOnFunction(llvm::Function&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x297e0db)
#21 0x00000000032c2eb3 llvm::FPPassManager::runOnFunction(llvm::Function&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x32c2eb3)
#22 0x00000000032c30f1 llvm::FPPassManager::runOnModule(llvm::Module&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x32c30f1)
#23 0x00000000032c3955 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x32c3955)
#24 0x0000000003ba88ac (anonymous namespace)::EmitAssemblyHelper::EmitAssembly(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) BackendUtil.cpp:0:0
#25 0x0000000003ba8c3e 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*) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x3ba8c3e)
#26 0x00000000041d56dc clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x41d56dc)
#27 0x00000000061d6e0c clang::ParseAST(clang::Sema&, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/clang+++0x61d6e0c)
Quuxplusone commented 6 months ago

This looks like a plausible patch:

--- a/llvm/lib/IR/Operator.cpp
+++ b/llvm/lib/IR/Operator.cpp
@@ -19,7 +19,8 @@

 namespace llvm {
 bool Operator::hasPoisonGeneratingFlags() const {
-  switch (getOpcode()) {
+  unsigned opc = isa<Instruction>(this) ? getOpcode() : unsigned(-1);
+  switch (opc) {
   case Instruction::Add:
   case Instruction::Sub:
   case Instruction::Mul: