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

[WebAssembly] stacksave leads machine code verification failure after wasm-replace-phys-regs #62235

Closed
kateinoigakukun opened this issue Apr 19, 2023 · 1 comment · Fixed by #68133

Comments

@kateinoigakukun
Copy link
Member

kateinoigakukun commented Apr 19, 2023

LLVM version: llvmorg-16.0.0

Minimum reproducible code:

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"

define weak_odr swiftcc { i32, i8 } @x(i1 %0) {
entry:
  br i1 %0, label %.thread51, label %.lr.ph.i30

.thread51:                                        ; preds = %entry
  %spsave253 = tail call i8* @llvm.stacksave()
  br label %.loopexit

.lr.ph.i30:                                       ; preds = %.lr.ph.i30, %entry
  br i1 %0, label %.loopexit, label %.lr.ph.i30

.loopexit:                                        ; preds = %.lr.ph.i30, %.thread51
  %spsave254.ph = phi i8* [ %spsave253, %.thread51 ], [ null, %.lr.ph.i30 ]
  tail call void @llvm.stackrestore(i8* %spsave254.ph)
  unreachable
}

; Function Attrs: nocallback nofree nosync nounwind willreturn
declare i8* @llvm.stacksave() #0

; Function Attrs: nocallback nofree nosync nounwind willreturn
declare void @llvm.stackrestore(i8*) #0

attributes #0 = { nocallback nofree nosync nounwind willreturn }
$ llc test.ll -stop-after wasm-replace-phys-regs -o - -verify-machineinstrs
# Machine code for function x: NoPHIs, TracksLiveness, TiedOpsRewritten
Function Live Ins: $arguments

bb.0.entry:
  successors: %bb.1(0x00000000), %bb.2(0x80000000); %bb.1(0.00%), %bb.2(100.00%)
  liveins: $arguments
  %3:i32 = ARGUMENT_i32 1, implicit $arguments
  dead %2:i32 = ARGUMENT_i32 0, implicit $arguments
  %4:i32 = CONST_I32 1, implicit-def dead $arguments
  %5:i32 = AND_I32 %3:i32, %4:i32, implicit-def dead $arguments
  BR_UNLESS %bb.2, %5:i32, implicit-def $arguments

bb.1..thread51:
; predecessors: %bb.0

  %10:i32 = COPY_I32 %11:i32, implicit-def $arguments
  %11:i32 = COPY_I32 %10:i32, implicit-def $arguments
  UNREACHABLE implicit-def dead $arguments

bb.2..lr.ph.i30:
; predecessors: %bb.2, %bb.0
  successors: %bb.3(0x00000000), %bb.2(0x80000000); %bb.3(0.00%), %bb.2(100.00%)

  BR_UNLESS %bb.2, %5:i32, implicit-def dead $arguments

bb.3:
; predecessors: %bb.2

  %10:i32 = CONST_I32 0, implicit-def dead $arguments
  %11:i32 = COPY_I32 %10:i32, implicit-def $arguments
  UNREACHABLE implicit-def dead $arguments

# End machine code for function x.

*** Bad machine code: Virtual register defs don't dominate all uses. ***
- function:    x
- v. register: %11
LLVM ERROR: Found 1 machine code errors.
Stack trace
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.      Program arguments: /home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc Swift.x.wasm32-unknown-wasi.reduced.ll
1.      Running pass 'Function Pass Manager' on module 'Swift.x.wasm32-unknown-wasi.reduced.ll'.
2.      Running pass 'Live Interval Analysis' on function '@x'
 #0 0x0000000001e019d3 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x1e019d3)
 #1 0x0000000001dff6fe llvm::sys::RunSignalHandlers() (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x1dff6fe)
 #2 0x0000000001e01e9f SignalHandler(int) Signals.cpp:0:0
 #3 0x00007f6a7e2c3420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #4 0x00007f6a7dd5600b raise /build/glibc-SzIz7B/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #5 0x00007f6a7dd35859 abort /build/glibc-SzIz7B/glibc-2.31/stdlib/abort.c:81:7
 #6 0x0000000001d7e6b0 llvm::report_fatal_error(llvm::Twine const&, bool) (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x1d7e6b0)
 #7 0x000000000127f7a6 (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x127f7a6)
 #8 0x00000000011004aa llvm::LiveRangeCalc::findReachingDefs(llvm::LiveRange&, llvm::MachineBasicBlock&, llvm::SlotIndex, unsigned int, llvm::ArrayRef<llvm::SlotIndex>) (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x11004aa)
 #9 0x00000000010ff7f7 llvm::LiveRangeCalc::extend(llvm::LiveRange&, llvm::SlotIndex, unsigned int, llvm::ArrayRef<llvm::SlotIndex>) (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x10ff7f7)
#10 0x000000000110321a llvm::LiveIntervalCalc::extendToUses(llvm::LiveRange&, llvm::Register, llvm::LaneBitmask, llvm::LiveInterval*) (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x110321a)
#11 0x0000000001102ec0 llvm::LiveIntervalCalc::calculate(llvm::LiveInterval&, bool) (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x1102ec0)
#12 0x00000000010ead22 llvm::LiveIntervals::computeVirtRegInterval(llvm::LiveInterval&) (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x10ead22)
#13 0x00000000010e9824 llvm::LiveIntervals::computeVirtRegs() (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x10e9824)
#14 0x00000000010e95f2 llvm::LiveIntervals::runOnMachineFunction(llvm::MachineFunction&) (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x10e95f2)
#15 0x00000000011a4641 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x11a4641)
#16 0x000000000165c868 llvm::FPPassManager::runOnFunction(llvm::Function&) (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x165c868)
#17 0x0000000001664f41 llvm::FPPassManager::runOnModule(llvm::Module&) (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x1664f41)
#18 0x000000000165d034 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x165d034)
#19 0x00000000006e3a7d compileModule(char**, llvm::LLVMContext&) llc.cpp:0:0
#20 0x00000000006e144d main (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x6e144d)
#21 0x00007f6a7dd37083 __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:342:3
#22 0x00000000006e07ae _start (/home/katei/ghq/work.katei.dev/swiftwasm-source/host-build/Ninja-ReleaseAssert/llvm-linux-x86_64/bin/llc+0x6e07ae)

It looks like $sp32 read by stacksave is replaced with a virtual reg by wasm-replace-phys-regs, but it results in violating the domination principle for virtual registers.

Result of `-stop-before=wasm-replace-phys-regs`
  bb.0.entry:
    successors: %bb.1(0x00000000), %bb.2(0x80000000)
    liveins: $arguments

    %3:i32 = ARGUMENT_i32 1, implicit $arguments
    dead %2:i32 = ARGUMENT_i32 0, implicit $arguments
    %4:i32 = CONST_I32 1, implicit-def dead $arguments
    %5:i32 = AND_I32 %3, %4, implicit-def dead $arguments
    BR_UNLESS %bb.2, %5, implicit-def $arguments

  bb.1..thread51:
    %10:i32 = COPY_I32 $sp32, implicit-def $arguments
    $sp32 = COPY_I32 %10, implicit-def $arguments
    UNREACHABLE implicit-def dead $arguments

  bb.2..lr.ph.i30:
    successors: %bb.3(0x00000000), %bb.2(0x80000000)

    BR_UNLESS %bb.2, %5, implicit-def dead $arguments

  bb.3:
    %10:i32 = CONST_I32 0, implicit-def dead $arguments
    $sp32 = COPY_I32 %10, implicit-def $arguments
    UNREACHABLE implicit-def dead $arguments

I'm not sure the stacksave / stackrestore are supported on WebAssembly target or not 🤷 But it seems that it somehow succeeds with LLVM 14: https://godbolt.org/z/7Mx45GqK6

@llvmbot
Copy link
Collaborator

llvmbot commented Apr 19, 2023

@llvm/issue-subscribers-backend-webassembly

@kateinoigakukun kateinoigakukun changed the title WebAssembly: stacksave leads machine code verification failure after wasm-replace-phys-regs [WebAssembly] stacksave leads machine code verification failure after wasm-replace-phys-regs Apr 19, 2023
kateinoigakukun added a commit to kateinoigakukun/swift that referenced this issue Sep 14, 2023
The LLVM backend generates bad code for some code using `llvm.stacksave`
intrinsics. This patch works around the issue by avoiding such code
generation. See llvm/llvm-project#62235
dschuff pushed a commit that referenced this issue Oct 3, 2023
Usually `llvm.stacksave/stackrestore` are used together with `alloca`
but they can appear without it (e.g. `alloca` can be optimized away).
WebAssembly's function local physical user sp register, which is
referenced by `llvm.stacksave` is created while frame lowering and
replaced with virtual register.
However the sp register was not created when `llvm.stacksave` is used
without `alloca`, and it led MIR verification failure about
use-before-def of sp virtual register.

Resolves #62235
kateinoigakukun added a commit to swiftlang/llvm-project that referenced this issue Oct 9, 2023
Usually `llvm.stacksave/stackrestore` are used together with `alloca`
but they can appear without it (e.g. `alloca` can be optimized away).
WebAssembly's function local physical user sp register, which is
referenced by `llvm.stacksave` is created while frame lowering and
replaced with virtual register.
However the sp register was not created when `llvm.stacksave` is used
without `alloca`, and it led MIR verification failure about
use-before-def of sp virtual register.

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

Successfully merging a pull request may close this issue.

2 participants