Skip to content

Commit

Permalink
[Outlining] Changing stringify values to 32-bit (WebAssembly#5832)
Browse files Browse the repository at this point in the history
The LLVM suffix tree expects to be provided with a vector of 32-bit unsigned integers. This PR makes it easier to integrate our wasm program string with the suffix tree.

Because the range of possible values is reduced from 2^64 to 2^32, a signed integer was added to manage the next separator value and ensure we're using every possible negative number.
  • Loading branch information
ashleynh authored Jul 21, 2023
1 parent 84af348 commit e2f5d79
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 51 deletions.
5 changes: 3 additions & 2 deletions src/passes/hash-stringify-walker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ bool StringifyEquator::operator()(Expression* lhs, Expression* rhs) const {
void HashStringifyWalker::addUniqueSymbol() {
// Use a negative value to distinguish symbols for separators from symbols
// for Expressions
hashString.push_back((uint64_t)-nextVal);
nextVal++;
assert((uint32_t)nextSeparatorVal >= nextVal);
hashString.push_back((uint32_t)nextSeparatorVal);
nextSeparatorVal--;
}

void HashStringifyWalker::visitExpression(Expression* curr) {
Expand Down
11 changes: 7 additions & 4 deletions src/passes/stringify-walker.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,17 +113,20 @@ struct StringifyEquator {

struct HashStringifyWalker : public StringifyWalker<HashStringifyWalker> {
// After calling walkModule, this vector contains the result of encoding a
// wasm module as a string of uint64_t values. Each value represents either an
// wasm module as a string of uint32_t values. Each value represents either an
// Expression or a separator to mark the end of control flow.
std::vector<uint64_t> hashString;
std::vector<uint32_t> hashString;
// A monotonic counter used to ensure that unique expressions in the
// module are assigned a unique value in the hashString
uint64_t nextVal = 0;
uint32_t nextVal = 0;
// A monotonic counter used to ensure that each separator in the
// module is assigned a unique value in the hashString
int32_t nextSeparatorVal = -1;
// Contains a mapping of expression pointer to value to ensure we
// use the same value for matching expressions. A custom hasher and
// equator is provided in order to separate out evaluation of the if-condition
// when evaluating if expressions.
std::unordered_map<Expression*, uint64_t, StringifyHasher, StringifyEquator>
std::unordered_map<Expression*, uint32_t, StringifyHasher, StringifyEquator>
exprToCounter;

void addUniqueSymbol();
Expand Down
90 changes: 45 additions & 45 deletions test/gtest/stringify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,51 +168,51 @@ TEST_F(StringifyTest, Stringify) {
stringify.walkModule(&wasm);

EXPECT_EQ(stringify.hashString,
(std::vector<uint64_t>{
(std::vector<uint32_t>{
0, // function block evaluated as a whole
(uint64_t)-1, // separate function block from function contents
2, // block_a evaluated as a whole
3, // block_b evaluated as a whole
4, // block_c evaluated as a whole
2, // block_d has the same contents as block_a
4, // block_e has the same contents as block_c
5, // block_f evaluated as a whole
(uint64_t)-6, // separate blocks from block contents
7, // i32.const 20
8, // drop, all drops will be the same symbol
9, // i32.const 10
8, // drop
(uint64_t)-10, // separate block_a contents
11, // i32.const 0, if condition
12, // block_b's if evaluated as a whole
8, // drop
(uint64_t)-13, // separate block_b contents
14, // i32.const 1, if condition
15, // block_c's if evaluated as a whole
8, // drop
(uint64_t)-16, // separate block_c contents
7, // i32.const 20
8, // drop
9, // i32.const 10
8, // drop
(uint64_t)-17, // separate block_d contents
14, // i32.const 1, if condition
15, // block_e if evaluated as a whole
8, // drop
(uint64_t)-18, // separate block_e contents
11, // i32.const 0, if condition
15, // block_f's if evaluated as a whole
8, // drop
(uint64_t)-19, // separate block_f contents
20, // i32.const 40
(uint64_t)-21, // separate block_b if-true
22, // i32.const 5
(uint64_t)-23, // separate block_b if-false
24, // i32.const 30
(uint64_t)-25, // separate block_c if-true
24, // i32.const 30
(uint64_t)-26, // separate block_e if-true
24, // i32.const 30
(uint64_t)-27 // separate block_f if-true
(uint32_t)-1, // separate function block from function contents
1, // block_a evaluated as a whole
2, // block_b evaluated as a whole
3, // block_c evaluated as a whole
1, // block_d has the same contents as block_a
3, // block_e has the same contents as block_c
4, // block_f evaluated as a whole
(uint32_t)-2, // separate blocks from block contents
5, // i32.const 20
6, // drop, all drops will be the same symbol
7, // i32.const 10
6, // drop
(uint32_t)-3, // separate block_a contents
8, // i32.const 0, if condition
9, // block_b's if evaluated as a whole
6, // drop
(uint32_t)-4, // separate block_b contents
10, // i32.const 1, if condition
11, // block_c's if evaluated as a whole
6, // drop
(uint32_t)-5, // separate block_c contents
5, // i32.const 20
6, // drop
7, // i32.const 10
6, // drop
(uint32_t)-6, // separate block_d contents
10, // i32.const 1, if condition
11, // block_e if evaluated as a whole
6, // drop
(uint32_t)-7, // separate block_e contents
8, // i32.const 0, if condition
11, // block_f's if evaluated as a whole
6, // drop
(uint32_t)-8, // separate block_f contents
12, // i32.const 40
(uint32_t)-9, // separate block_b if-true
13, // i32.const 5
(uint32_t)-10, // separate block_b if-false
14, // i32.const 30
(uint32_t)-11, // separate block_c if-true
14, // i32.const 30
(uint32_t)-12, // separate block_e if-true
14, // i32.const 30
(uint32_t)-13 // separate block_f if-true
}));
}

0 comments on commit e2f5d79

Please sign in to comment.