llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.48k stars 11.77k forks source link

[18 regression] [x86_64] SDValue llvm::SelectionDAG::getNode(unsigned int, const SDLoc &, SDVTList, ArrayRef<SDValue>, const SDNodeFlags): Assertion `Op.getOpcode() != ISD::DELETED_NODE && "Operand is DELETED_NODE!"' failed. #82431

Closed berolinux closed 3 months ago

berolinux commented 7 months ago

When building the reduced test case in this bug report with AMD specific optimizations (-target-cpu znver1, -target-cpu znver2 etc.), clang 18 crashes with an assertion error.

$ clang -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -target-cpu znver1 -O -x c test.c
clang: /builddir/build/BUILD/llvm-project-release-18.x/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:9845: SDValue llvm::SelectionDAG::getNode(unsigned int, const SDLoc &, SDVTList, ArrayRef<SDValue>, const SDNodeFlags): Assertion `Op.getOpcode() != ISD::DELETED_NODE && "Operand is DELETED_NODE!"' 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: clang -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -target-cpu znver1 -O -x c test.c
1.      <eof> parser at end of file
2.      Code generation
3.      Running pass 'Function Pass Manager' on module 'test.c'.
4.      Running pass 'X86 DAG->DAG Instruction Selection' on function '@d'
 #0 0x0000ffff9d700510 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/lib64/libLLVM-18.so+0x4300510)
 #1 0x0000ffff9d6ff084 llvm::sys::RunSignalHandlers() (/lib64/libLLVM-18.so+0x42ff084)
 #2 0x0000ffff9d6ffd3c (/lib64/libLLVM-18.so+0x42ffd3c)
 #3 0x0000ffffa6fa37bc (linux-vdso.so.1+0x7bc)
 #4 0x0000ffffa6dee458 (/lib64/libc.so.6+0x8e458)
 #5 0x0000ffffa6da457c raise (/lib64/libc.so.6+0x4457c)
 #6 0x0000ffffa6d90280 abort (/lib64/libc.so.6+0x30280)
 #7 0x0000ffffa6d9dd04 (/lib64/libc.so.6+0x3dd04)
 #8 0x0000ffffa6d9dd7c (/lib64/libc.so.6+0x3dd7c)
 #9 0x0000ffff9e327848 llvm::SelectionDAG::getNode(unsigned int, llvm::SDLoc const&, llvm::SDVTList, llvm::ArrayRef<llvm::SDValue>, llvm::SDNodeFlags) (/lib64/libLLVM-18.so+0x4f27848)
#10 0x0000ffff9e37dd68 llvm::SelectionDAGISel::Select_INLINEASM(llvm::SDNode*) (/lib64/libLLVM-18.so+0x4f7dd68)
#11 0x0000ffffa15162b0 (/lib64/libLLVM-18.so+0x81162b0)
#12 0x0000ffff9e37b8f4 llvm::SelectionDAGISel::DoInstructionSelection() (/lib64/libLLVM-18.so+0x4f7b8f4)
#13 0x0000ffff9e375b58 llvm::SelectionDAGISel::CodeGenAndEmitDAG() (/lib64/libLLVM-18.so+0x4f75b58)
#14 0x0000ffff9e37313c llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/lib64/libLLVM-18.so+0x4f7313c)
#15 0x0000ffff9e36f670 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (/lib64/libLLVM-18.so+0x4f6f670)
#16 0x0000ffffa150c408 (/lib64/libLLVM-18.so+0x810c408)
#17 0x0000ffff9dd0bc50 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/lib64/libLLVM-18.so+0x490bc50)
#18 0x0000ffff9d988408 llvm::FPPassManager::runOnFunction(llvm::Function&) (/lib64/libLLVM-18.so+0x4588408)
#19 0x0000ffff9d993e64 llvm::FPPassManager::runOnModule(llvm::Module&) (/lib64/libLLVM-18.so+0x4593e64)
#20 0x0000ffff9d98d040 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/lib64/libLLVM-18.so+0x458d040)
#21 0x0000ffffa5370130 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*) (/lib64/libclang-cpp.so.18+0x2b70130)
#22 0x0000ffffa5773ae4 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/lib64/libclang-cpp.so.18+0x2f73ae4)
#23 0x0000ffffa3ea841c clang::ParseAST(clang::Sema&, bool, bool) (/lib64/libclang-cpp.so.18+0x16a841c)
#24 0x0000ffffa61ea008 clang::FrontendAction::Execute() (/lib64/libclang-cpp.so.18+0x39ea008)
#25 0x0000ffffa616a698 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/lib64/libclang-cpp.so.18+0x396a698)
#26 0x0000ffffa6264c50 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/lib64/libclang-cpp.so.18+0x3a64c50)
#27 0x0000aaaaade950d8 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/usr/bin/clang-18+0x250d8)
#28 0x0000aaaaade91824 (/usr/bin/clang-18+0x21824)
#29 0x0000aaaaade9011c clang_main(int, char**, llvm::ToolContext const&) (/usr/bin/clang-18+0x2011c)
#30 0x0000aaaaade9de50 main (/usr/bin/clang-18+0x2de50)
#31 0x0000ffffa6d90944 (/lib64/libc.so.6+0x30944)
#32 0x0000ffffa6d90a18 __libc_start_main (/lib64/libc.so.6+0x30a18)
#33 0x0000aaaaade8dd30 _start (/usr/bin/clang-18+0x1dd30)
Aborted (core dumped)

Reduced test case:

struct {
  long a[1];
} b;
char c();
void d() { asm("" : "+m"(b.a[1 + (c() & 1)])); }

The test case is extracted from the Linux kernel.

llvmbot commented 7 months ago

@llvm/issue-subscribers-backend-x86

Author: Bernhard Rosenkraenzer (berolinux)

When building the reduced test case in this bug report with AMD specific optimizations (`-target-cpu znver1`, `-target-cpu znver2` etc.), clang 18 crashes with an assertion error. ``` $ clang -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -target-cpu znver1 -O -x c test.c clang: /builddir/build/BUILD/llvm-project-release-18.x/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:9845: SDValue llvm::SelectionDAG::getNode(unsigned int, const SDLoc &, SDVTList, ArrayRef<SDValue>, const SDNodeFlags): Assertion `Op.getOpcode() != ISD::DELETED_NODE && "Operand is DELETED_NODE!"' 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: clang -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -target-cpu znver1 -O -x c test.c 1. <eof> parser at end of file 2. Code generation 3. Running pass 'Function Pass Manager' on module 'test.c'. 4. Running pass 'X86 DAG->DAG Instruction Selection' on function '@d' #0 0x0000ffff9d700510 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/lib64/libLLVM-18.so+0x4300510) #1 0x0000ffff9d6ff084 llvm::sys::RunSignalHandlers() (/lib64/libLLVM-18.so+0x42ff084) #2 0x0000ffff9d6ffd3c (/lib64/libLLVM-18.so+0x42ffd3c) #3 0x0000ffffa6fa37bc (linux-vdso.so.1+0x7bc) #4 0x0000ffffa6dee458 (/lib64/libc.so.6+0x8e458) #5 0x0000ffffa6da457c raise (/lib64/libc.so.6+0x4457c) #6 0x0000ffffa6d90280 abort (/lib64/libc.so.6+0x30280) #7 0x0000ffffa6d9dd04 (/lib64/libc.so.6+0x3dd04) #8 0x0000ffffa6d9dd7c (/lib64/libc.so.6+0x3dd7c) #9 0x0000ffff9e327848 llvm::SelectionDAG::getNode(unsigned int, llvm::SDLoc const&, llvm::SDVTList, llvm::ArrayRef<llvm::SDValue>, llvm::SDNodeFlags) (/lib64/libLLVM-18.so+0x4f27848) #10 0x0000ffff9e37dd68 llvm::SelectionDAGISel::Select_INLINEASM(llvm::SDNode*) (/lib64/libLLVM-18.so+0x4f7dd68) #11 0x0000ffffa15162b0 (/lib64/libLLVM-18.so+0x81162b0) #12 0x0000ffff9e37b8f4 llvm::SelectionDAGISel::DoInstructionSelection() (/lib64/libLLVM-18.so+0x4f7b8f4) #13 0x0000ffff9e375b58 llvm::SelectionDAGISel::CodeGenAndEmitDAG() (/lib64/libLLVM-18.so+0x4f75b58) #14 0x0000ffff9e37313c llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/lib64/libLLVM-18.so+0x4f7313c) #15 0x0000ffff9e36f670 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (/lib64/libLLVM-18.so+0x4f6f670) #16 0x0000ffffa150c408 (/lib64/libLLVM-18.so+0x810c408) #17 0x0000ffff9dd0bc50 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/lib64/libLLVM-18.so+0x490bc50) #18 0x0000ffff9d988408 llvm::FPPassManager::runOnFunction(llvm::Function&) (/lib64/libLLVM-18.so+0x4588408) #19 0x0000ffff9d993e64 llvm::FPPassManager::runOnModule(llvm::Module&) (/lib64/libLLVM-18.so+0x4593e64) #20 0x0000ffff9d98d040 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/lib64/libLLVM-18.so+0x458d040) #21 0x0000ffffa5370130 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*) (/lib64/libclang-cpp.so.18+0x2b70130) #22 0x0000ffffa5773ae4 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/lib64/libclang-cpp.so.18+0x2f73ae4) #23 0x0000ffffa3ea841c clang::ParseAST(clang::Sema&, bool, bool) (/lib64/libclang-cpp.so.18+0x16a841c) #24 0x0000ffffa61ea008 clang::FrontendAction::Execute() (/lib64/libclang-cpp.so.18+0x39ea008) #25 0x0000ffffa616a698 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/lib64/libclang-cpp.so.18+0x396a698) #26 0x0000ffffa6264c50 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/lib64/libclang-cpp.so.18+0x3a64c50) #27 0x0000aaaaade950d8 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/usr/bin/clang-18+0x250d8) #28 0x0000aaaaade91824 (/usr/bin/clang-18+0x21824) #29 0x0000aaaaade9011c clang_main(int, char**, llvm::ToolContext const&) (/usr/bin/clang-18+0x2011c) #30 0x0000aaaaade9de50 main (/usr/bin/clang-18+0x2de50) #31 0x0000ffffa6d90944 (/lib64/libc.so.6+0x30944) #32 0x0000ffffa6d90a18 __libc_start_main (/lib64/libc.so.6+0x30a18) #33 0x0000aaaaade8dd30 _start (/usr/bin/clang-18+0x1dd30) Aborted (core dumped) ``` Reduced test case: ```c struct { long a[1]; } b; char c(); void d() { asm("" : "+m"(b.a[1 + (c() & 1)])); } ``` The test case is extracted from the Linux kernel.
RKSimon commented 7 months ago

This doesn't seem to be AMD related:

%struct.anon.12 = type { [1 x i32] }
@"?b@@3U<unnamed-type-b>@@A" = external dso_local global %struct.anon.12, align 4

define dso_local void @"?d@@YAXXZ"() local_unnamed_addr #0 {
entry:
  %call = tail call noundef i8 @"?c@@YADXZ"()
  %0 = and i8 %call, 1
  %narrow = add nuw nsw i8 %0, 1
  %idxprom = zext nneg i8 %narrow to i64
  %arrayidx = getelementptr inbounds [1 x i32], ptr @"?b@@3U<unnamed-type-b>@@A", i64 0, i64 %idxprom
  tail call void asm "", "=*m,*m,~{dirflag},~{fpsr},~{flags}"(ptr nonnull elementtype(i32) %arrayidx, ptr nonnull elementtype(i32) %arrayidx) #1
  ret void
}
declare dso_local i8 @"?c@@YADXZ"() local_unnamed_addr #0
berolinux commented 7 months ago

This doesn't seem to be AMD related:

Indeed, the reduced test case fails even without -target-cpu znver1. -target-cpu znver1 is required to reproduce it with the "big test case" ("compile the Linux kernel's ipv6_input.c"). Apparently optimizing for a different x86 subtarget optimizes something away. I didn't re-check options after reducing the test case initially.

RicoAfoat commented 7 months ago

The assertion fails because a SDNode whose PersistentId is 39 is builded to work as a builder method parameter and then quickly deleted before it is used to call the builder method.

// llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
void SelectionDAGISel::Select_INLINEASM(SDNode *N) {
  SDLoc DL(N);

  std::vector<SDValue> Ops(N->op_begin(), N->op_end());
  SelectInlineAsmMemoryOperands(Ops, DL); // t39 is builded and deleted here, but it remains in Ops

  const EVT VTs[] = {MVT::Other, MVT::Glue};
  SDValue New = CurDAG->getNode(N->getOpcode(), DL, VTs, Ops);// t39 is a DELETED_NODE, assertion fails in builder
  New->setNodeId(-1);
  ReplaceUses(N, New.getNode());
  CurDAG->RemoveDeadNode(N);
}

To be precise, I tried -triple riscv64-unknown-elf and -triple armv7a-none-eabi, clang terminate with no assertion failure.

So it might be a bug only in x86.

It seems like ReplaceAllUsesWith is called to early, before t39 is used to construct a new inline asm node.

// llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
SDValue X86DAGToDAGISel::matchIndexRecursively(SDValue N,
                                               X86ISelAddressMode &AM,
                                               unsigned Depth) {
  ...
  if (Opc == ISD::ZERO_EXTEND && !VT.isVector() && N.hasOneUse()) {
    ...
    if (((SrcOpc == ISD::ADD && Src->getFlags().hasNoUnsignedWrap()) ||
         CurDAG->isADDLike(Src)) &&
        Src.hasOneUse()) {
      if (CurDAG->isBaseWithConstantOffset(Src)) {
        ...
        if (!foldOffsetIntoAddress(Offset * AM.Scale, AM)) {
          ...
          CurDAG->ReplaceAllUsesWith(N, ExtAdd); //t39 is abolished here, but later it will be used as 
          CurDAG->RemoveDeadNode(N.getNode());// parameters to call a builder method.
          return Res ? Res : ExtSrc;
        }
      }
    }
  }
 ...
  return N;
}
RKSimon commented 7 months ago

We'll let 1e6627ecef42fa8e36dae71589fc17d3adbd18aa brew for a few days and then cherry pick

berolinux commented 7 months ago

I can confirm that https://github.com/llvm/llvm-project/commit/1e6627ecef42fa8e36dae71589fc17d3adbd18aa applied on top of the 18 release branch fixes the particular test case, but I can still reproduce the error on the original unreduced code (Linux kernel ip6_input.c built with -march=znver1). Building a new test case...

berolinux commented 7 months ago
enum { a, b, c, d, e } f[];
int g;
void h() {
  asm("" : "+m"(f[e + ((g >> 4) & 3)]));
}
$ clang -march=znver1 -O -o /dev/null -c bug82431.c
bug82431.c:1:24: warning: tentative array definition assumed to have one element
    1 | enum { a, b, c, d, e } f[];
      |                        ^
clang: /builddir/build/BUILD/llvm-project-release-18.x/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:9845: SDValue llvm::SelectionDAG::getNode(unsigned int, const SDLoc &, SDVTList, ArrayRef<SDValue>, const SDNodeFlags): Assertion `Op.getOpcode() != ISD::DELETED_NODE && "Operand is DELETED_NODE!"' 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: clang -march=znver1 -O -o /dev/null -c bug82431.c
1.      <eof> parser at end of file
2.      Code generation
3.      Running pass 'Function Pass Manager' on module 'bug82431.c'.
4.      Running pass 'X86 DAG->DAG Instruction Selection' on function '@h'
 #0 0x00007f5d2c99bbf6 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/usr/lib64/libLLVM.so.18.1+0x459bbf6)
 #1 0x00007f5d2c99a86a llvm::sys::RunSignalHandlers() (/usr/lib64/libLLVM.so.18.1+0x459a86a)
 #2 0x00007f5d2c8b244e (/usr/lib64/libLLVM.so.18.1+0x44b244e)
 #3 0x00007f5d27e53690 (/usr/lib64/libc.so.6+0x3f690)
 #4 0x00007f5d27ea2edc (/usr/lib64/libc.so.6+0x8eedc)
 #5 0x00007f5d27e535e2 raise (/usr/lib64/libc.so.6+0x3f5e2)
 #6 0x00007f5d27e3c4ad abort (/usr/lib64/libc.so.6+0x284ad)
 #7 0x00007f5d27e3c3d5 (/usr/lib64/libc.so.6+0x283d5)
 #8 0x00007f5d27e4c052 (/usr/lib64/libc.so.6+0x38052)
 #9 0x00007f5d2d6bf1c4 llvm::SelectionDAG::getNode(unsigned int, llvm::SDLoc const&, llvm::SDVTList, llvm::ArrayRef<llvm::SDValue>, llvm::SDNodeFlags) (/usr/lib64/libLLVM.so.18.1+0x52bf1c4)
#10 0x00007f5d2d717d4a llvm::SelectionDAGISel::Select_INLINEASM(llvm::SDNode*) (/usr/lib64/libLLVM.so.18.1+0x5317d4a)
#11 0x00007f5d30ce857c (/usr/lib64/libLLVM.so.18.1+0x88e857c)
#12 0x00007f5d2d715678 llvm::SelectionDAGISel::DoInstructionSelection() (/usr/lib64/libLLVM.so.18.1+0x5315678)
#13 0x00007f5d2d70e9af llvm::SelectionDAGISel::CodeGenAndEmitDAG() (/usr/lib64/libLLVM.so.18.1+0x530e9af)
#14 0x00007f5d2d70b234 llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/usr/lib64/libLLVM.so.18.1+0x530b234)
#15 0x00007f5d2d70746f llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (/usr/lib64/libLLVM.so.18.1+0x530746f)
#16 0x00007f5d30cdad92 (/usr/lib64/libLLVM.so.18.1+0x88dad92)
#17 0x00007f5d2cffc64c llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/usr/lib64/libLLVM.so.18.1+0x4bfc64c)
#18 0x00007f5d2cc3dd93 llvm::FPPassManager::runOnFunction(llvm::Function&) (/usr/lib64/libLLVM.so.18.1+0x483dd93)
#19 0x00007f5d2cc4a154 llvm::FPPassManager::runOnModule(llvm::Module&) (/usr/lib64/libLLVM.so.18.1+0x484a154)
#20 0x00007f5d2cc42c7b llvm::legacy::PassManagerImpl::run(llvm::Module&) (/usr/lib64/libLLVM.so.18.1+0x4842c7b)
#21 0x00007f5d34d8c820 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*) (/usr/lib64/libclang-cpp.so.18.1+0x2d8c820)
#22 0x00007f5d3521ae3f clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/usr/lib64/libclang-cpp.so.18.1+0x321ae3f)
#23 0x00007f5d33845a66 clang::ParseAST(clang::Sema&, bool, bool) (/usr/lib64/libclang-cpp.so.18.1+0x1845a66)
#24 0x00007f5d35d82fdb clang::FrontendAction::Execute() (/usr/lib64/libclang-cpp.so.18.1+0x3d82fdb)
#25 0x00007f5d35ce7289 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/usr/lib64/libclang-cpp.so.18.1+0x3ce7289)
#26 0x00007f5d35e0253a clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/usr/lib64/libclang-cpp.so.18.1+0x3e0253a)
#27 0x0000560a13365056 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/usr/bin/clang-18+0x17056)
#28 0x0000560a13360d0f (/usr/bin/clang-18+0x12d0f)
#29 0x00007f5d358c2afb (/usr/lib64/libclang-cpp.so.18.1+0x38c2afb)
#30 0x00007f5d2c8b26b3 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (/usr/lib64/libLLVM.so.18.1+0x44b26b3)
#31 0x00007f5d358c29e3 clang::driver::CC1Command::Execute(llvm::ArrayRef<std::optional<llvm::StringRef>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, bool*) const (/usr/lib64/libclang-cpp.so.18.1+0x38c29e3)
#32 0x00007f5d3587b657 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&, bool) const (/usr/lib64/libclang-cpp.so.18.1+0x387b657)
#33 0x00007f5d3587bb6e clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&, bool) const (/usr/lib64/libclang-cpp.so.18.1+0x387bb6e)
#34 0x00007f5d358be0af clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*>>&) (/usr/lib64/libclang-cpp.so.18.1+0x38be0af)
#35 0x0000560a13360285 clang_main(int, char**, llvm::ToolContext const&) (/usr/bin/clang-18+0x12285)
#36 0x0000560a1336ff56 main (/usr/bin/clang-18+0x21f56)
#37 0x00007f5d27e3dc0a (/usr/lib64/libc.so.6+0x29c0a)
#38 0x00007f5d27e3dcc5 __libc_start_main (/usr/lib64/libc.so.6+0x29cc5)
#39 0x0000560a1335ce91 _start (/usr/bin/clang-18+0xee91)
berolinux commented 7 months ago
target triple = "x86_64-pc-linux-gnu"

@g = dso_local local_unnamed_addr global i32 0, align 4
@f = dso_local global [1 x i32] zeroinitializer, align 4

define dso_local void @h() local_unnamed_addr #0 {
entry:
  %0 = load i32, ptr @g, align 4, !tbaa !0
  %shr = lshr i32 %0, 4
  %and = and i32 %shr, 3
  %add = or disjoint i32 %and, 4
  %idxprom = zext nneg i32 %add to i64
  %arrayidx = getelementptr inbounds [0 x i32], ptr @f, i64 0, i64 %idxprom
  tail call void asm "", "=*m,*m,~{dirflag},~{fpsr},~{flags}"(ptr nonnull elementtype(i32) %arrayidx, ptr nonnull elementtype(i32) %arrayidx) #1, !srcloc !2
  ret void
}

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

!0 = !{!"omnipotent char", !1, i64 0}
!1 = !{!"Simple C/C++ TBAA"}
!2 = !{i64 54}
RicoAfoat commented 7 months ago

I can confirm that 1e6627e applied on top of the 18 release branch fixes the particular test case, but I can still reproduce the error on the original unreduced code (Linux kernel ip6_input.c built with -march=znver1). Building a new test case...

Sorry but I couldn't reproduce this on commit Add support for x87 registers on GISel register selection (#83528) on main branch or on manually patched release/18.x branch(I manually added my patch locally and built again). Could you please give me more information so that I can reproduce it locally?

Here's what my bash displayed:

(base) r1c0@RicoLaptop:~/llvm-project$ cat ./mine_test/test.c
enum { a, b, c, d, e } f[];
int g;
void h() {
  asm("" : "+m"(f[e + ((g >> 4) & 3)]));
}(base) r1c0@RicoLaptop:~/llvm-project$ ./build/bin/clang -march=znver1 -O -o /dev/null -c ./mine_test/test.c
./mine_test/test.c:1:24: warning: tentative array definition assumed to have one element
    1 | enum { a, b, c, d, e } f[];
      |                        ^
1 warning generated.
(base) r1c0@RicoLaptop:~/llvm-project$ 
KyunLFA commented 7 months ago

Can confirm that on my Zen4 machine

enum { a, b, c, d, e } f[];
int g;
void h() {
  asm("" : "+m"(f[e + ((g >> 4) & 3)]));
}

produces:

bug.c:1:24: warning: tentative array definition assumed to have one element
    1 | enum { a, b, c, d, e } f[];
      |                        ^
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/13.2.1/../../../../include/c++/13.2.1/bits/stl_vector.h:1125: reference std::vector<llvm::SUnit>::operator[](size_type) [_Tp = llvm::SUnit, _Alloc = std::allocator<llvm::SUnit>]: Assertion '__n < this->size()' 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: clang -march=znver1 -O -o /dev/null -c bug.c
1.  <eof> parser at end of file
2.  Code generation
3.  Running pass 'Function Pass Manager' on module 'bug.c'.
4.  Running pass 'X86 DAG->DAG Instruction Selection' on function '@h'
 #0 0x00007f27b4388bd9 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/usr/bin/../lib/libLLVM.so.19.0+0x2f88bd9)
 #1 0x00007f27b4387a20 llvm::sys::RunSignalHandlers() (/usr/bin/../lib/libLLVM.so.19.0+0x2f87a20)
 #2 0x00007f27b428aa01 (/usr/bin/../lib/libLLVM.so.19.0+0x2e8aa01)
 #3 0x00007f27b0c420f0 (/usr/bin/../lib/libc.so.6+0x420f0)
 #4 0x00007f27b0ca053b pthread_kill (/usr/bin/../lib/libc.so.6+0xa053b)
 #5 0x00007f27b0c42048 raise (/usr/bin/../lib/libc.so.6+0x42048)
 #6 0x00007f27b0c24478 abort (/usr/bin/../lib/libc.so.6+0x24478)
 #7 0x00007f27b10ee472 (/usr/bin/../lib/libstdc++.so.6+0xee472)
 #8 0x00007f27b4fe6805 (/usr/bin/../lib/libLLVM.so.19.0+0x3be6805)
 #9 0x00007f27b4fcffd2 (/usr/bin/../lib/libLLVM.so.19.0+0x3bcffd2)
#10 0x00007f27b50bf681 llvm::SelectionDAGISel::CodeGenAndEmitDAG() (/usr/bin/../lib/libLLVM.so.19.0+0x3cbf681)
#11 0x00007f27b50be1cd llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/usr/bin/../lib/libLLVM.so.19.0+0x3cbe1cd)
#12 0x00007f27b50bb02f llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (/usr/bin/../lib/libLLVM.so.19.0+0x3cbb02f)
#13 0x00007f27b6fb55cc (/usr/bin/../lib/libLLVM.so.19.0+0x5bb55cc)
#14 0x00007f27b49e4721 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/usr/bin/../lib/libLLVM.so.19.0+0x35e4721)
#15 0x00007f27b45e7c7d llvm::FPPassManager::runOnFunction(llvm::Function&) (/usr/bin/../lib/libLLVM.so.19.0+0x31e7c7d)
#16 0x00007f27b45f5e93 llvm::FPPassManager::runOnModule(llvm::Module&) (/usr/bin/../lib/libLLVM.so.19.0+0x31f5e93)
#17 0x00007f27b45ee156 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/usr/bin/../lib/libLLVM.so.19.0+0x31ee156)
#18 0x00007f27bb936d62 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*) (/usr/bin/../lib/libclang-cpp.so.19.0+0x2f36d62)
#19 0x00007f27bbdf30c5 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/usr/bin/../lib/libclang-cpp.so.19.0+0x33f30c5)
#20 0x00007f27ba16fa59 clang::ParseAST(clang::Sema&, bool, bool) (/usr/bin/../lib/libclang-cpp.so.19.0+0x176fa59)
#21 0x00007f27bce12888 clang::FrontendAction::Execute() (/usr/bin/../lib/libclang-cpp.so.19.0+0x4412888)
#22 0x00007f27bcd69b30 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/usr/bin/../lib/libclang-cpp.so.19.0+0x4369b30)
#23 0x00007f27bceac923 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/usr/bin/../lib/libclang-cpp.so.19.0+0x44ac923)
#24 0x00005dbe1f730621 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/usr/bin/clang-19+0x16621)
#25 0x00005dbe1f72c062 (/usr/bin/clang-19+0x12062)
#26 0x00007f27bc84dd79 clang::driver::CC1Command::setEnvironment(llvm::ArrayRef<char const*>) (/usr/bin/../lib/libclang-cpp.so.19.0+0x3e4dd79)
clang: error: clang frontend command failed with exit code 134 (use -v to see invocation)
clang version 19.0.0 (/home/smol/.cache/paru/clone/llvm-git/llvm-project a6382de3999280ef7bf8bb63750686cdad889cd5)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
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/bug-c93a43.c
clang: note: diagnostic msg: /tmp/bug-c93a43.sh
clang: note: diagnostic msg: 

********************

On LLVM main a6382de39992: AMDGPU: Refactor mfma hazard handling [NFC] (#84276) (7th March 9:09 UTC).

and the kernel build still produces:

/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/13.2.1/../../../../include/c++/13.2.1/bits/stl_vector.h:1125: reference std::vector<llvm::SUnit>::operator[](size_type) [_Tp = llvm::SUnit, _Alloc = std::allocator<llvm::SUnit>]: Assertion '__n < this->size()' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.  Program arguments: ld.lld -m elf_x86_64 --lto-O3 --lto-CGO3 --threads=24 -mllvm -import-instr-limit=5 -z noexecstack -r -o vmlinux.o -T .tmp_initcalls.lds --whole-archive vmlinux.a --no-whole-archive --start-group --end-group
1.  Running pass 'Function Pass Manager' on module 'ld-temp.o'.
2.  Running pass 'X86 DAG->DAG Instruction Selection' on function '@ip6_rcv_core'
 #0 0x00007b1497388bd9 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/usr/bin/../lib/libLLVM.so.19.0+0x2f88bd9)
 #1 0x00007b1497387a20 llvm::sys::RunSignalHandlers() (/usr/bin/../lib/libLLVM.so.19.0+0x2f87a20)
 #2 0x00007b14973885ab (/usr/bin/../lib/libLLVM.so.19.0+0x2f885ab)
 #3 0x00007b1493c420f0 (/usr/bin/../lib/libc.so.6+0x420f0)
 #4 0x00007b1493ca053b pthread_kill (/usr/bin/../lib/libc.so.6+0xa053b)
 #5 0x00007b1493c42048 raise (/usr/bin/../lib/libc.so.6+0x42048)
 #6 0x00007b1493c24478 abort (/usr/bin/../lib/libc.so.6+0x24478)
 #7 0x00007b14940ee472 (/usr/bin/../lib/libstdc++.so.6+0xee472)
 #8 0x00007b1497fe6805 (/usr/bin/../lib/libLLVM.so.19.0+0x3be6805)
 #9 0x00007b1497fcffd2 (/usr/bin/../lib/libLLVM.so.19.0+0x3bcffd2)
#10 0x00007b14980bf681 llvm::SelectionDAGISel::CodeGenAndEmitDAG() (/usr/bin/../lib/libLLVM.so.19.0+0x3cbf681)
#11 0x00007b14980be1cd llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/usr/bin/../lib/libLLVM.so.19.0+0x3cbe1cd)
#12 0x00007b14980bb02f llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (/usr/bin/../lib/libLLVM.so.19.0+0x3cbb02f)
#13 0x00007b1499fb55cc (/usr/bin/../lib/libLLVM.so.19.0+0x5bb55cc)
#14 0x00007b14979e4721 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/usr/bin/../lib/libLLVM.so.19.0+0x35e4721)
#15 0x00007b14975e7c7d llvm::FPPassManager::runOnFunction(llvm::Function&) (/usr/bin/../lib/libLLVM.so.19.0+0x31e7c7d)
#16 0x00007b14975f5e93 llvm::FPPassManager::runOnModule(llvm::Module&) (/usr/bin/../lib/libLLVM.so.19.0+0x31f5e93)
#17 0x00007b14975ee156 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/usr/bin/../lib/libLLVM.so.19.0+0x31ee156)
#18 0x00007b149959b75b (/usr/bin/../lib/libLLVM.so.19.0+0x519b75b)
#19 0x00007b149959a34a llvm::lto::backend(llvm::lto::Config const&, std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>, unsigned int, llvm::Module&, llvm::ModuleSummaryIndex&) (/usr/bin/../lib/libLLVM.so.19.0+0x519a34a)
#20 0x00007b14995881a0 llvm::lto::LTO::runRegularLTO(std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>) (/usr/bin/../lib/libLLVM.so.19.0+0x51881a0)
#21 0x00007b14995876d1 llvm::lto::LTO::run(std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>, std::function<llvm::Expected<std::function<llvm::Expected<std::unique_ptr<llvm::CachedFileStream, std::default_delete<llvm::CachedFileStream>>> (unsigned int, llvm::Twine const&)>> (unsigned int, llvm::StringRef, llvm::Twine const&)>) (/usr/bin/../lib/libLLVM.so.19.0+0x51876d1)
#22 0x000056a91565f7c2 lld::elf::BitcodeCompiler::compile() (/usr/bin/lld+0x3897c2)
#23 0x000056a91555e05d lld::elf::LinkerDriver::link(llvm::opt::InputArgList&) (/usr/bin/lld+0x28805d)
#24 0x000056a91554ba17 lld::elf::LinkerDriver::linkerMain(llvm::ArrayRef<char const*>) (/usr/bin/lld+0x275a17)
#25 0x000056a9155488f1 lld::elf::link(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, bool, bool) (/usr/bin/lld+0x2728f1)
#26 0x000056a91544c9ba lld::unsafeLldMain(llvm::ArrayRef<char const*>, llvm::raw_ostream&, llvm::raw_ostream&, llvm::ArrayRef<lld::DriverDef>, bool) (/usr/bin/lld+0x1769ba)
#27 0x000056a91544c023 lld_main(int, char**, llvm::ToolContext const&) (/usr/bin/lld+0x176023)
#28 0x000056a91544c269 main (/usr/bin/lld+0x176269)
#29 0x00007b1493c25fd0 (/usr/bin/../lib/libc.so.6+0x25fd0)
#30 0x00007b1493c2608a __libc_start_main (/usr/bin/../lib/libc.so.6+0x2608a)
#31 0x000056a915449a05 _start (/usr/bin/lld+0x173a05)
make[2]: *** [scripts/Makefile.vmlinux_o:62: vmlinux.o] Error 134
make[1]: *** [/home/smol/Downloads/thenew/6.8/src/linux/Makefile:1302: vmlinux_o] Error 2
make: *** [Makefile:240: __sub-make] Error 2
KyunLFA commented 7 months ago

Cannot reproduce anymore on LLVM main 5d59fa90ce225814739d9b51ba37e1cca9204cad!

Could it be a bug affecting certain build configurations/FLAGS of LLVM? I changed my LLVM build's C[XX]FLAGS to only "-O3 -march=znver4 -pipe"... Can you try using less FLAGS, @berolinux ?

Update: Surely enough, rebuilding with my default FLAGS makes the error crop up again. I will try to disable LTO and see if that is the root cause (bad LTO breaking the compiler)

Update 2: Not LTO.

KyunLFA commented 7 months ago

I'm almost nailing it down exactly. It's, almost funnily obvious in hindsight, but CXXFLAGS=" -Wp,-D_GLIBCXX_ASSERTIONS" is playing a huge roll in the bug (when LLVM was compiled with it). Right now, with CFLAGS="-v -march=znver4 -O3 -pipe -fno-plt" CXXFLAGS="$CFLAGS -Wp,-D_GLIBCXX_ASSERTIONS" LDFLAGS="-fuse-ld=lld -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now" used to build LLVM, I have the test case here FAILING (when before it passed without GLIBCXX_ASSERTIONS) and ip6_input.c PASSING, both with the same llvm 19 main.

KyunLFA commented 7 months ago

Hi. I'm glad to say I finally tracked it down to a tee. It is indeed, -Wp,-D_GLIBCXX_ASSERTIONS, or at the very least, it's required to expose the underlying bug.

Steps to reproduce:

  1. Build LLVM 18 or later with CXXFLAGS containing -Wp,-D_GLIBCXX_ASSERTIONS. Install or add to path.
  2. Build the test case above from berolinux with said compiler. It should fail.
  3. Build the Linux kernel FROM SCRATCH with the same compiler. Now, I don't know why, but using an existing .config, or using anything left over (potentially) will NOT trigger the bug (at least, it was the case for me, leading to the assumption above that ip6_input.c was passing. Now, you don't need to build the whole kernel. Just doing: KCFLAGS=' -march=znver1 -mtune=znver1 -v' KCPPFLAGS=' -march=znver1 -mtune=znver1 -v' LLVM=1 make net/ipv6/ip6_input.o in the source tree is enough, as long you're working clean with no previous .config (use make xconfig or another config generator). ip6_input.c should also fail.
  4. Repeat steps above with LLVM >17 WITHOUT GLIBCXX_ASSERTIONS. Both cases should pass.

I hope this helps.

Update: On LLVM 18.1.1, the bug persists even with the patch, so disregard the "18 or later" and ">17", it must be 19 main.

RicoAfoat commented 7 months ago

Hi. I'm glad to say I finally tracked it down to a tee. It is indeed, -Wp,-D_GLIBCXX_ASSERTIONS, or at the very least, it's required to expose the underlying bug.

Steps to reproduce:

  1. Build LLVM 18 or later with CXXFLAGS containing -Wp,-D_GLIBCXX_ASSERTIONS. Install or add to path.
  2. Build the test case above from berolinux with said compiler. It should fail.
  3. Build the Linux kernel FROM SCRATCH with the same compiler. Now, I don't know why, but using an existing .config, or using anything left over (potentially) will NOT trigger the bug (at least, it was the case for me, leading to the assumption above that ip6_input.c was passing. Now, you don't need to build the whole kernel. Just doing: KCFLAGS=' -march=znver1 -mtune=znver1 -v' KCPPFLAGS=' -march=znver1 -mtune=znver1 -v' LLVM=1 make net/ipv6/ip6_input.o in the source tree is enough, as long you're working clean with no previous .config (use make xconfig or another config generator). ip6_input.c should also fail.
  4. Repeat steps above with LLVM >17 WITHOUT GLIBCXX_ASSERTIONS. Both cases should pass.

I hope this helps.

Update: On LLVM 18.1.1, the bug persists even with the patch, so disregard the "18 or later" and ">17", it must be 19 main.

Thanks a lot @KyunLFA.

@RKSimon

Similar problem.

(all functions mentioned here are located in llvm/lib/Target/X86/X86ISelDAGToDAG.cpp)

SDNode whose PersistentID is 52, created here:

bool X86DAGToDAGISel::matchAddressRecursively(SDValue N, X86ISelAddressMode &AM,
                                              unsigned Depth) {
  ...
  switch (N.getOpcode()) {
  case ISD::ZERO_EXTEND: 
    if (Src.getOpcode() == ISD::ADD || Src.getOpcode() == ISD::OR)
      if (SDValue Index = matchIndexRecursively(N, AM, Depth + 1))// created here
        if (Index != N) {
          AM.IndexReg = Index;
          return false;
        }
  }

After entering the vector, replaced here

bool X86DAGToDAGISel::matchAddressRecursively(SDValue N, X86ISelAddressMode &AM,
                                              unsigned Depth) {
  ...
  switch (N.getOpcode()) {
  case ISD::ZERO_EXTEND: 
    ...
    if (Src.getOpcode() == ISD::SRL && !Mask.isAllOnes()) {
      // Try to fold the mask and shift into an extract and scale.
      if (!foldMaskAndShiftToExtract(*CurDAG, N, Mask.getZExtValue(), Src,
                                     Src.getOperand(0), AM))
        return false;

      // Try to fold the mask and shift directly into the scale.
      if (!foldMaskAndShiftToScale(*CurDAG, N, Mask.getZExtValue(), Src,
                                   Src.getOperand(0), AM))
        return false;

      // Try to fold the mask and shift into BEXTR and scale.
      if (!foldMaskedShiftToBEXTR(*CurDAG, N, Mask.getZExtValue(), Src,
                                  Src.getOperand(0), AM, *Subtarget))// replaced here
        return false;
    }
  }

Then this SDNode causes the assertion failure just like previous problem.

RKSimon commented 7 months ago

@RicoAfoat do you intend to look at this or should I?

RicoAfoat commented 7 months ago

@RicoAfoat do you intend to look at this or should I?

Trying

mgorny commented 2 months ago

If anyone wanted to backport this to 18.x, note you'll also need e975ff0a223e79842b693e0ec4d3cac87963869a along with these two commits.

In other words, the complete backport sequence is:

  1. 1e6627ecef42fa8e36dae71589fc17d3adbd18aa
  2. e975ff0a223e79842b693e0ec4d3cac87963869a
  3. 46505b3cbfc5f48f28431b9141085c5d71ddf1c4

The middle one hits some merge conflicts on the test but I've resolved them by preserving the 'old' expectations.