Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot compile to wasm with multivalue support #55136

Closed
dsyer opened this issue Apr 27, 2022 · 7 comments
Closed

Cannot compile to wasm with multivalue support #55136

dsyer opened this issue Apr 27, 2022 · 7 comments
Assignees
Labels

Comments

@dsyer
Copy link

dsyer commented Apr 27, 2022

Trying to use mpack.c with multivalue support. I have some code that uses mpack, but the error comes directly from there and doesn't seem to depend on what I do in my code:

$ emcc -mmultivalue -Xclang -target-abi -Xclang experimental-mv -Os -s STANDALONE_WASM=1 -Wl,--no-entry external/mpack.c -o foo.wasm
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: /nix/store/w2gkjafvdid2xsbipr7mjmn15921ghw8-emscripten-llvm-2.0.27/bin/clang -target wasm32-unknown-emscripten -DEMSCRIPTEN -fignore-exceptions -fno-inline-functions -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -D__EMSCRIPTEN_major__=2 -D__EMSCRIPTEN_minor__=0 -D__EMSCRIPTEN_tiny__=27 -D_LIBCPP_ABI_VERSION=2 -Dunix -D__unix -D__unix__ -Werror=implicit-function-declaration -Xclang -iwithsysroot/include/SDL --sysroot=/home/dsyer/.emscripten/cache/sysroot -resource-dir=/nix/store/w2gkjafvdid2xsbipr7mjmn15921ghw8-emscripten-llvm-2.0.27/lib/clang/13.0.0/ -idirafter/home/dsyer/.emscripten/cache/sysroot/include -iwithsysroot/include/c++/v1 -Xclang -iwithsysroot/include/compat -mmultivalue -Xclang -target-abi -Xclang experimental-mv -Os external/mpack.c -c -o /run/user/1000/emscripten_temp_p7qr3thm/mpack_0.o
1.      <eof> parser at end of file
2.      Code generation
3.      Running pass 'Function Pass Manager' on module 'external/mpack.c'.
4.      Running pass 'WebAssembly Register Stackify' on function '@mpack_parse_tag'
 #0 0x00007efc0aedbdb0 PrintStackTraceSignalHandler(void*) (//nix/store/qw6p9lrvfldqk2wzh4bnybsmnw4xc3hg-llvm-13.0.0-lib/lib/libLLVM-13.so+0xd29db0)
 #1 0x00007efc0aed9c3c llvm::sys::CleanupOnSignal(unsigned long) (//nix/store/qw6p9lrvfldqk2wzh4bnybsmnw4xc3hg-llvm-13.0.0-lib/lib/libLLVM-13.so+0xd27c3c)
 #2 0x00007efc0ade0ba8 CrashRecoverySignalHandler(int) (//nix/store/qw6p9lrvfldqk2wzh4bnybsmnw4xc3hg-llvm-13.0.0-lib/lib/libLLVM-13.so+0xc2eba8)
 #3 0x00007efc147ddee0 __restore_rt (/nix/store/wl60dr9p15rwf53gxz61ijgisc1zdjc7-glibc-2.33-59/lib/libpthread.so.0+0x12ee0)
 #4 0x00007efc0b23bdac llvm::LiveIntervals::HMEditor::handleMoveDown(llvm::LiveRange&) (//nix/store/qw6p9lrvfldqk2wzh4bnybsmnw4xc3hg-llvm-13.0.0-lib/lib/libLLVM-13.so+0x1089dac)
 #5 0x00007efc0b23ce13 llvm::LiveIntervals::HMEditor::updateAllRanges(llvm::MachineInstr*) (.isra.0) (//nix/store/qw6p9lrvfldqk2wzh4bnybsmnw4xc3hg-llvm-13.0.0-lib/lib/libLLVM-13.so+0x108ae13)
 #6 0x00007efc0b23d3e6 llvm::LiveIntervals::handleMove(llvm::MachineInstr&, bool) (//nix/store/qw6p9lrvfldqk2wzh4bnybsmnw4xc3hg-llvm-13.0.0-lib/lib/libLLVM-13.so+0x108b3e6)
 #7 0x00007efc0ddf4de8 moveForSingleUse(unsigned int, llvm::MachineOperand&, llvm::MachineInstr*, llvm::MachineBasicBlock&, llvm::MachineInstr*, llvm::LiveIntervals&, llvm::WebAssemblyFunctionInfo&, llvm::MachineRegisterInfo&) (//nix/store/qw6p9lrvfldqk2wzh4bnybsmnw4xc3hg-llvm-13.0.0-lib/lib/libLLVM-13.so+0x3c42de8)
 #8 0x00007efc0ddf8cbe (anonymous namespace)::WebAssemblyRegStackify::runOnMachineFunction(llvm::MachineFunction&) (//nix/store/qw6p9lrvfldqk2wzh4bnybsmnw4xc3hg-llvm-13.0.0-lib/lib/libLLVM-13.so+0x3c46cbe)
 #9 0x00007efc0b2f5264 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (//nix/store/qw6p9lrvfldqk2wzh4bnybsmnw4xc3hg-llvm-13.0.0-lib/lib/libLLVM-13.so+0x1143264)
#10 0x00007efc0b039b00 llvm::FPPassManager::runOnFunction(llvm::Function&) (//nix/store/qw6p9lrvfldqk2wzh4bnybsmnw4xc3hg-llvm-13.0.0-lib/lib/libLLVM-13.so+0xe87b00)
#11 0x00007efc0b039c6c llvm::FPPassManager::runOnModule(llvm::Module&) (//nix/store/qw6p9lrvfldqk2wzh4bnybsmnw4xc3hg-llvm-13.0.0-lib/lib/libLLVM-13.so+0xe87c6c)
#12 0x00007efc0b03b5f8 llvm::legacy::PassManagerImpl::run(llvm::Module&) (//nix/store/qw6p9lrvfldqk2wzh4bnybsmnw4xc3hg-llvm-13.0.0-lib/lib/libLLVM-13.so+0xe895f8)
#13 0x00007efc12861183 (anonymous namespace)::EmitAssemblyHelper::EmitAssemblyWithNewPassManager(clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream> >) (.constprop.0) (/nix/store/knla03zmbsd5qgmrn6lhhj78sjgqa2r0-clang-13.0.0-lib/lib/libclang-cpp.so.13+0x1c4b183)
#14 0x00007efc1286588c clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, std::unique_ptr<llvm::raw_pwrite_stream, std::default_delete<llvm::raw_pwrite_stream> >) (/nix/store/knla03zmbsd5qgmrn6lhhj78sjgqa2r0-clang-13.0.0-lib/lib/libclang-cpp.so.13+0x1c4f88c)
#15 0x00007efc12c155d2 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/nix/store/knla03zmbsd5qgmrn6lhhj78sjgqa2r0-clang-13.0.0-lib/lib/libclang-cpp.so.13+0x1fff5d2)
#16 0x00007efc1182ed09 clang::ParseAST(clang::Sema&, bool, bool) (/nix/store/knla03zmbsd5qgmrn6lhhj78sjgqa2r0-clang-13.0.0-lib/lib/libclang-cpp.so.13+0xc18d09)
#17 0x00007efc133d1cf9 clang::FrontendAction::Execute() (/nix/store/knla03zmbsd5qgmrn6lhhj78sjgqa2r0-clang-13.0.0-lib/lib/libclang-cpp.so.13+0x27bbcf9)
#18 0x00007efc1335cab9 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/nix/store/knla03zmbsd5qgmrn6lhhj78sjgqa2r0-clang-13.0.0-lib/lib/libclang-cpp.so.13+0x2746ab9)
#19 0x00007efc1345051f clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/nix/store/knla03zmbsd5qgmrn6lhhj78sjgqa2r0-clang-13.0.0-lib/lib/libclang-cpp.so.13+0x283a51f)
#20 0x00000000004164d0 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/nix/store/w2gkjafvdid2xsbipr7mjmn15921ghw8-emscripten-llvm-2.0.27/bin/clang+0x4164d0)
#21 0x00000000004138f9 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&) (/nix/store/w2gkjafvdid2xsbipr7mjmn15921ghw8-emscripten-llvm-2.0.27/bin/clang+0x4138f9)
#22 0x00007efc1301e1f5 void llvm::function_ref<void ()>::callback_fn<clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, bool*) const::'lambda'()>(long) (/nix/store/knla03zmbsd5qgmrn6lhhj78sjgqa2r0-clang-13.0.0-lib/lib/libclang-cpp.so.13+0x24081f5)
#23 0x00007efc0ade0cb3 llvm::CrashRecoveryContext::RunSafely(llvm::function_ref<void ()>) (//nix/store/qw6p9lrvfldqk2wzh4bnybsmnw4xc3hg-llvm-13.0.0-lib/lib/libLLVM-13.so+0xc2ecb3)
#24 0x00007efc1301e56c clang::driver::CC1Command::Execute(llvm::ArrayRef<llvm::Optional<llvm::StringRef> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, bool*) const (.part.0) (/nix/store/knla03zmbsd5qgmrn6lhhj78sjgqa2r0-clang-13.0.0-lib/lib/libclang-cpp.so.13+0x240856c)
#25 0x00007efc12ff1a47 clang::driver::Compilation::ExecuteCommand(clang::driver::Command const&, clang::driver::Command const*&) const (/nix/store/knla03zmbsd5qgmrn6lhhj78sjgqa2r0-clang-13.0.0-lib/lib/libclang-cpp.so.13+0x23dba47)
#26 0x00007efc12ff2459 clang::driver::Compilation::ExecuteJobs(clang::driver::JobList const&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*> >&) const (/nix/store/knla03zmbsd5qgmrn6lhhj78sjgqa2r0-clang-13.0.0-lib/lib/libclang-cpp.so.13+0x23dc459)
#27 0x00007efc13002281 clang::driver::Driver::ExecuteCompilation(clang::driver::Compilation&, llvm::SmallVectorImpl<std::pair<int, clang::driver::Command const*> >&) (/nix/store/knla03zmbsd5qgmrn6lhhj78sjgqa2r0-clang-13.0.0-lib/lib/libclang-cpp.so.13+0x23ec281)
#28 0x000000000041167d main (/nix/store/w2gkjafvdid2xsbipr7mjmn15921ghw8-emscripten-llvm-2.0.27/bin/clang+0x41167d)
#29 0x00007efc09ce2780 __libc_start_main (/nix/store/wl60dr9p15rwf53gxz61ijgisc1zdjc7-glibc-2.33-59/lib/libc.so.6+0x27780)
#30 0x000000000041327a _start (/nix/store/w2gkjafvdid2xsbipr7mjmn15921ghw8-emscripten-llvm-2.0.27/bin/clang+0x41327a)
clang-13: error: clang frontend command failed with exit code 139 (use -v to see invocation)
clang version 13.0.0
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /nix/store/w2gkjafvdid2xsbipr7mjmn15921ghw8-emscripten-llvm-2.0.27/bin
clang-13: note: diagnostic msg: 
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang-13: note: diagnostic msg: /run/user/1000/mpack-cd9f1f.c
clang-13: note: diagnostic msg: /run/user/1000/mpack-cd9f1f.sh
clang-13: note: diagnostic msg: 

********************
emcc: error: '/nix/store/w2gkjafvdid2xsbipr7mjmn15921ghw8-emscripten-llvm-2.0.27/bin/clang -target wasm32-unknown-emscripten -DEMSCRIPTEN -fignore-exceptions -fno-inline-functions -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -D__EMSCRIPTEN_major__=2 -D__EMSCRIPTEN_minor__=0 -D__EMSCRIPTEN_tiny__=27 -D_LIBCPP_ABI_VERSION=2 -Dunix -D__unix -D__unix__ -Werror=implicit-function-declaration -Xclang -iwithsysroot/include/SDL --sysroot=/home/dsyer/.emscripten/cache/sysroot -resource-dir=/nix/store/w2gkjafvdid2xsbipr7mjmn15921ghw8-emscripten-llvm-2.0.27/lib/clang/13.0.0/ -idirafter/home/dsyer/.emscripten/cache/sysroot/include -iwithsysroot/include/c++/v1 -Xclang -iwithsysroot/include/compat -mmultivalue -Xclang -target-abi -Xclang experimental-mv -Os external/mpack.c -c -o /run/user/1000/emscripten_temp_p7qr3thm/mpack_0.o' failed (returned 139)
@dsyer
Copy link
Author

dsyer commented Apr 27, 2022

Files from /run/user/1000/mpack-cd9f1f.*: mpack.zip

@llvmbot
Copy link
Collaborator

llvmbot commented Apr 27, 2022

@llvm/issue-subscribers-backend-webassembly

@tlively tlively self-assigned this Apr 28, 2022
@tlively tlively added the confirmed Verified by a second party label Apr 28, 2022
@tlively
Copy link
Collaborator

tlively commented Apr 28, 2022

I reduced the reproducer to this IR:

target triple = "wasm32-unknown-emscripten"

%i64_struct = type { i64 }
%pair = type { i32, %i64_struct }

declare %pair @return_struct() #0

define void @test() #1 {
  %p = tail call %pair @return_struct()
  %first = extractvalue %pair %p, 0
  %new_p = insertvalue %pair undef, i32 %first, 0
  %second = extractvalue %pair %p, 1
  %new_p2 = insertvalue %pair %new_p, %i64_struct %second, 1
  %new_first = extractvalue %pair %new_p2, 0
  %new_second = extractvalue %pair %new_p2, 1
  %inner = extractvalue %i64_struct %new_second, 0
  store i32 %new_first, i32* undef, align 8
  store i64 %inner, i64* null, align 8
  unreachable
}

attributes #0 = { readnone }
attributes #1 = { "target-features"="+multivalue" }

with this stack trace:

llc: /usr/local/google/home/tlively/code/llvm-project/llvm/lib/CodeGen/LiveIntervals.cpp:1197: void llvm::LiveIntervals::HMEditor::handleMoveDown(llvm::LiveRange &): Assertion `INext != E && "Must have following segment"' failed.
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
Stack dump:
0.      Program arguments: bin/llc repro.ll
1.      Running pass 'Function Pass Manager' on module 'repro.ll'.
2.      Running pass 'WebAssembly Register Stackify' on function '@test'
 #0 0x0000000001af83d3 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (bin/llc+0x1af83d3)
 #1 0x0000000001af608e llvm::sys::RunSignalHandlers() (bin/llc+0x1af608e)
 #2 0x0000000001af889a SignalHandler(int) Signals.cpp:0:0
 #3 0x00007fd2c7451200 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x13200)
 #4 0x00007fd2c6ed68a1 raise ./signal/../sysdeps/unix/sysv/linux/raise.c:50:1
 #5 0x00007fd2c6ec0546 abort ./stdlib/abort.c:81:7
 #6 0x00007fd2c6ec042f get_sysdep_segment_value ./intl/loadmsgcat.c:509:8
 #7 0x00007fd2c6ec042f _nl_load_domain ./intl/loadmsgcat.c:970:34
 #8 0x00007fd2c6ecf222 (/lib/x86_64-linux-gnu/libc.so.6+0x35222)
 #9 0x0000000000e4106c (bin/llc+0xe4106c)
#10 0x0000000000e4054d llvm::LiveIntervals::HMEditor::updateRange(llvm::LiveRange&, llvm::Register, llvm::LaneBitmask) (bin/llc+0xe4054d)
#11 0x0000000000e3e822 llvm::LiveIntervals::HMEditor::updateAllRanges(llvm::MachineInstr*) (bin/llc+0xe3e822)
#12 0x0000000000e3e322 llvm::LiveIntervals::handleMove(llvm::MachineInstr&, bool) (bin/llc+0xe3e322)
#13 0x0000000000a66463 (anonymous namespace)::WebAssemblyRegStackify::runOnMachineFunction(llvm::MachineFunction&) WebAssemblyRegStackify.cpp:0:0
#14 0x0000000000eebafe llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (bin/llc+0xeebafe)
#15 0x000000000135ede8 llvm::FPPassManager::runOnFunction(llvm::Function&) (bin/llc+0x135ede8)
#16 0x00000000013655a8 llvm::FPPassManager::runOnModule(llvm::Module&) (bin/llc+0x13655a8)
#17 0x000000000135f497 llvm::legacy::PassManagerImpl::run(llvm::Module&) (bin/llc+0x135f497)
#18 0x00000000006eaea1 main (bin/llc+0x6eaea1)
#19 0x00007fd2c6ec17fd __libc_start_main ./csu/../csu/libc-start.c:332:16
#20 0x00000000006e7f7a _start (bin/llc+0x6e7f7a)
Aborted

@Mrmaxmeier
Copy link

Hi,

I started looking into this, but don't have any experience with LLVM development so my methodology might be all over the place :)

The reproducer can be further reduced to this:
target triple = "wasm32-unknown-unknown"

%pair = type { i32, i64 }

declare %pair @return_struct() #0 readnone

define void @test() #0 {
  %p = call %pair @return_struct()
  %first = extractvalue %pair %p, 0
  %second = extractvalue %pair %p, 1
  store i32 %first, i32* undef, align 8
  store i64 %second, i64* null, align 8
  unreachable
}

attributes #0 = { "target-features"="+multivalue" }

To further minimize, I simplified the .mir from llc -stop-before="wasm-reg-stackify". While the undef store seems required for the LLVM-IR reproducer, the stackify pass also fails with similar stores in the MachineInsts-IR:

repro.mir
--- |
  ; ModuleID = 'repro-bad.ll'
  source_filename = "repro-bad.ll"
  target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
  target triple = "wasm32-unknown-unknown"
  
  %pair = type { i32, i64 }
  
  ; Function Attrs: readnone
  declare %pair @return_struct() #0
  
  ; // minimized from this:
  define void @test() #1 {
    %p = call %pair @return_struct()
    %first = extractvalue %pair %p, 0
    %second = extractvalue %pair %p, 1
    store i32 %first, i32* undef, align 8
    store i64 %second, i64* null, align 8
    unreachable
  }
  
  attributes #0 = { readnone "target-features"="+multivalue," }
  attributes #1 = { "target-features"="+multivalue," }
  
  !llvm.module.flags = !{!0}
  
  !0 = !{i32 1, !"wasm-feature-multivalue", i32 43}

...
---
name:            test
alignment:       1
exposesReturnsTwice: false
legalized:       false
regBankSelected: false
selected:        false
failedISel:      false
tracksRegLiveness: true
hasWinCFI:       false
callsEHReturn:   false
callsUnwindInit: false
hasEHCatchret:   false
hasEHScopes:     false
hasEHFunclets:   false
failsVerification: false
tracksDebugUserValues: false
registers:
  - { id: 0, class: i32, preferred-register: '' }
  - { id: 1, class: i32, preferred-register: '' }
  - { id: 2, class: i32, preferred-register: '' }
liveins:
  - { reg: '$arguments', virtual-reg: '' }
frameInfo:
  isFrameAddressTaken: false
  isReturnAddressTaken: false
  hasStackMap:     false
  hasPatchPoint:   false
  stackSize:       0
  offsetAdjustment: 0
  maxAlignment:    1
  adjustsStack:    false
  hasCalls:        true
  stackProtector:  ''
  functionContext: ''
  maxCallFrameSize: 0
  cvBytesOfCalleeSavedRegisters: 0
  hasOpaqueSPAdjustment: false
  hasVAStart:      false
  hasMustTailInVarArgFunc: false
  hasTailCall:     false
  localFrameSize:  0
  savePoint:       ''
  restorePoint:    ''
fixedStack:      []
stack:           []
callSites:       []
debugValueSubstitutions: []
constants:       []
machineFunctionInfo:
  params:          [  ]
  results:         [  ]
  isCFGStackified: false
  wasmEHFuncInfo:  {}
body:             |
  bb.0 (%ir-block.0):
    liveins: $arguments
  
    %0:i32 = CONST_I32 0, implicit-def dead $arguments
    %1:i32, %2:i32 = CALL @return_struct, implicit-def dead $arguments
    STORE_I32_A32 3, 0, %0, %2, implicit-def dead $arguments
    STORE_I32_A32 2, 0, %0, %1, implicit-def dead $arguments

...

(The issue can then be reproduced with llc -run-pass="wasm-reg-stackify" repro.mir)

The problem seem to be CanMove = true for this move:

16B	  %0:i32 = CONST_I32 0, implicit-def dead $arguments
32B	  %1:i32, %2:i32 = CALL @return_struct, implicit-def dead $arguments ---\
48B	  STORE_I32_A32 3, 0, %0:i32, %2:i32, implicit-def dead $arguments      |
                                                                        <-------/
64B	  STORE_I32_A32 2, 0, %0:i32, %1:i32, implicit-def dead $arguments

Intuitively (?) this should not be allowed, as %2 is used by the store at 48B -- prior to the move target position.
These kind of moves are rejected here, but the condition doesn't seem to apply:

// If any subsequent def is used prior to the current value by the same
// instruction in which the current value is used, we cannot
// stackify. Stackifying in this case would require that def moving below the
// current def in the stack, which cannot be achieved, even with locals.
for (const auto &SubsequentDef : drop_begin(DefI->defs())) {
for (const auto &PriorUse : UseI->uses()) {
if (&PriorUse == Use)
break;
if (PriorUse.isReg() && SubsequentDef.getReg() == PriorUse.getReg())
return false;
}
}

In this example, the def and use registers don't match, and the prior use is ignored. I'm not sure why the code tests for equal registers (how can any use be valid if the def is moved below?), but that's about as far as I got.

I applied this patch, and the testsuite seems fine, though there are unrelated failing tests that might be caused by -DLLVM_ENABLE_EXPENSIVE_CHECKS=True (?):

diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
index d3ad47147ac8..e016bacbd80f 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegStackify.cpp
@@ -337,11 +337,18 @@ static bool isSafeToMove(const MachineOperand *Def, const MachineOperand *Use,
   // instruction in which the current value is used, we cannot
   // stackify. Stackifying in this case would require that def moving below the
   // current def in the stack, which cannot be achieved, even with locals.
   for (const auto &SubsequentDef : drop_begin(DefI->defs())) {
     for (const auto &PriorUse : UseI->uses()) {
       if (&PriorUse == Use)
         break;
-      if (PriorUse.isReg() && SubsequentDef.getReg() == PriorUse.getReg())
+      if (PriorUse.isReg())
         return false;
     }
   }

Is this the correct way to run all relevant tests?

⋊> ~/_/_/llvm-project on main ⨯ ./build/bin/llvm-lit llvm/test/CodeGen/WebAssembly/ -q
********************
Failed Tests (2):
  LLVM :: CodeGen/WebAssembly/dbgvalue.ll
  LLVM :: CodeGen/WebAssembly/stackified-debug.ll

  Failed: 2

@tlively
Copy link
Collaborator

tlively commented Jun 27, 2022

Nice work! Here's the command I use to run all the Wasm tests from the entire project:

bin/llvm-lit -vv $(find ~/code/llvm-project/llvm/test -name WebAssembly -o -name wasm) ~/code/llvm-project/lld/test/wasm/*.{ll,test,s,yaml} ../llvm-project/clang/test/{CodeGen,CodeGenCXX,Preprocessor,Driver,Headers}/*wasm*.{c,cpp,ll,test} ../llvm-project/cross-project-tests/intrinsic-header-tests/*wasm*

But I would expect that your simpler test command would be sufficient for this particular issue. The -vv flag to llvm-lit will supply more details about how exactly the tests are failing.

My guess is that the tests are failing because the order of emitted instructions has changed with your patch. It looks like the intention of SubsequentDf.getReg() == PriorUse.getReg() is to check that the use and def do refer to the same virtual register, since according to the uses docs, uses "may include unrelated operands which are not register uses," although I don't know why that is.

IIUC, that block of code you identified is checking for situations like this:

%0, %1 = call foo
use %1, %0

Where the uses are all in the same instruction. We may need entirely new logic to fix the case in this bug where the uses are in two different instructions.

This move might be allowable, but only if we can then move the store at 48B past the call back to its current location (and not get into a loop of moving the call and the store past each other forever).

@aykevl
Copy link
Contributor

aykevl commented Jul 15, 2022

I have encountered the same issue. It is triggered in TinyGo when I tried to enable multivalue support.

Here is a Compiler Explorer reproducer: https://llvm.godbolt.org/z/W8KxTPz6n

Reproducer in IR:

source_filename = "main"
target datalayout = "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"
target triple = "wasm32-unknown-wasi"

declare { i32, i32 } @foo() #0

define i32 @crashing() #0 {
entry:
  %foo1 = call { i32, i32 } @foo()
  %foo2 = call { i32, i32 } @foo()
  %foo1_0 = extractvalue { i32, i32 } %foo2, 0
  %foo1_1 = extractvalue { i32, i32 } %foo2, 1
  %foo2_0 = extractvalue { i32, i32 } %foo1, 0
  %a = add i32 %foo2_0, %foo1_1
  %b = add i32 %a, %foo1_0
  ret i32 %b
}

attributes #0 = { "target-features"="+multivalue" }

@sparker-arm
Copy link
Contributor

Fixed in commit b303c0027ff7f3a9912d7690886b7b7b33ddb05f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants