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] WebAssemblyDebugValueManager cannot handle DBG_VALUE_LISTs #49705

Open
aheejin opened this issue May 16, 2021 · 3 comments
Open
Labels
backend:WebAssembly bugzilla Issues migrated from bugzilla confirmed Verified by a second party

Comments

@aheejin
Copy link
Member

aheejin commented May 16, 2021

Bugzilla Link 50361
Version trunk
OS All
CC @aardappel,@dschuff

Extended Description

WebAssemblyDebugValueManager class
(https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/WebAssembly/WebAssemblyDebugValueManager.cpp)
was created when there was no DBG_VALUE_LIST instruction, so it assumes all
debug value instructions are DBG_VALUEs, each of which can have at most a single
register operand. WebAssemblyDebugValueManager groups a register def with its
corresponding DBG_VALUEs that refer to the def.

  1. When a reg def moves, we can't move DBG_VALUE_LISTs like DBG_VALUEs.

With DBG_VALUE_LIST instruction this relationship does not hold anymore.
DBG_VALUE_LIST can contain multiple register operands and a complex expression
describing the relationship between those operands. So when moving an
instruction that defines a register, we can move DBG_VALUEs referring to that
def but can't safely do the same thing with DBG_VALUE_LISTs. For example, see
the pseudocode below:

%0 = ...
DBG_VALUE %0, ...
%1 = ...
...
%2 = ADD %1, %2

When we move %0 right before %2, we can move the DBG_VALUE with it:

%1 = ...
...
%0 = ...
DBG_VALUE %0, ...
%2 = ADD %1, %2

But if it is a DBG_VALUE_LIST, there can be multiple register operands that
aren't supposed to be moved:

%0 = ...
DBG_VALUE_LIST ... %0, %1, ...
%1 = ...
...
%2 = ADD %1, %2

When we move %0 right before %2, we can't move the DBG_VALUE_LIST in the same
way, because it changes the meaning of the DBG_VALUE_LIST:

%1 = ...
...
%0 = ...
DBG_VALUE_LIST ... %0, %1, ... ;; Error. %1's value changed by new def
%2 = ADD %1, %2

But currently WebAssemblyDebugValueManager moves all DBG_VALUE_LISTs around
in the same way, which should be fixed.


  1. We can't copy DBG_VALUE_LISTs in a brute-force manner as we do for
    DBG_VALUEs.

A single DBG_VALUE_LIST instruction can contain any number of register
operands. In real world code I have seen a DBG_VALUE_LIST with dozens of them.

In WebAssemblyRegisterStackify, when we create a tee.local for a reg def, one
reg def becomes three reg defs, which is well illustrated in this comment:

/// A multiple-use def in the same block with no intervening memory or register
/// dependencies; move the def down, nest it with the current instruction, and
/// insert a tee to satisfy the rest of the uses. As an illustration, rewrite
/// this:
///
/// Reg = INST ... // Def
/// INST ..., Reg, ... // Insert
/// INST ..., Reg, ...
/// INST ..., Reg, ...
///
/// to this:
///
/// DefReg = INST ... // Def (to become the new Insert)
/// TeeReg, Reg = TEE_... DefReg
/// INST ..., TeeReg, ... // Insert
/// INST ..., Reg, ...
/// INST ..., Reg, ...

(In the old code, there's one def 'Reg', but in the new code, there are three
with the same value: 'Reg', 'DefReg', and 'TeeReg')

And when a def becomes three defs, each corresponding DBG_VALUE is copied
twice so there will be three copies of it. But if a DBG_VALUE_LIST contains
dozens of registers and each of them gets tee'd, the DBG_VALUE_LIST can be
copied exponentially. For example, if a DBG_VALUE_LIST contains %0, %1, and
%2, after %0 is tee'd, the instruction has 3 copies. And after %1 is tee'd, each
of 3 copies becomes 3 copies, so there will be 9 copies. And after %2 is tee'd
there will be 27 copies.

This way, in real world code, I have seen a BB with ~100 instruction (including
DBG_VALUEs and DBG_VALUE_LISTs) becomes several million instructions,
effectively stalling the compilation process. It will look like
infinite-looping.


To fix both bugs, we should come up with a way so that it can handle
DBG_VALUE_LISTs correctly and efficiently. In the meantime, I am planning to
nullify those DBG_VALUE_LIST instructions to make them appear as "optimized
out", which is at least correct.

@aheejin
Copy link
Member Author

aheejin commented May 17, 2021

DBG_VALUE_LISTs are converted to DBG_VALUE $noregin WebAssemblyDebugValueManager by this commit: 6e1c1da

This is a temporary fix to make things at least correct and not explode, so I'll keep this bug open.

@aheejin
Copy link
Member Author

aheejin commented May 30, 2021

The previous patch turned out to be error-prone to use, so I added WebAssemblyNullifyDebugValueLists pass for the interim measure: a64ebb8

This pass converts all DBG_VALUE_LISTs into DBG_VALUE $noregs and runs before all WebAssembly backend passes.

@aheejin
Copy link
Member Author

aheejin commented Jun 1, 2021

There seem to be patches that tries to curb the excessive number of operands in DBG_VALUE_LISTs in the upstream, probably due to a similar reason we observed:
https://reviews.llvm.org/D101373
https://reviews.llvm.org/D103162

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 11, 2021
@llvmbot llvmbot added the confirmed Verified by a second party label Jan 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:WebAssembly bugzilla Issues migrated from bugzilla confirmed Verified by a second party
Projects
None yet
Development

No branches or pull requests

2 participants