Skip to content

Commit 0f9f2dc

Browse files
authored
GlobalStructInference: Optimize globals too (#6674)
This is achieved by simply replacing the Literal with PossibleConstantValues, which supports both Literals and Globals.
1 parent b377b6f commit 0f9f2dc

File tree

2 files changed

+61
-11
lines changed

2 files changed

+61
-11
lines changed

src/passes/GlobalStructInference.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050

5151
#include "ir/find_all.h"
5252
#include "ir/module-utils.h"
53-
#include "ir/properties.h"
53+
#include "ir/possible-constant.h"
5454
#include "ir/subtypes.h"
5555
#include "ir/utils.h"
5656
#include "pass.h"
@@ -300,24 +300,23 @@ struct GlobalStructInference : public Pass {
300300

301301
// Find the constant values and which globals correspond to them.
302302
// TODO: SmallVectors?
303-
std::vector<Literal> values;
303+
std::vector<PossibleConstantValues> values;
304304
std::vector<std::vector<Name>> globalsForValue;
305305

306306
// Check if the relevant fields contain constants.
307307
auto fieldType = field.type;
308308
for (Index i = 0; i < globals.size(); i++) {
309309
Name global = globals[i];
310310
auto* structNew = wasm.getGlobal(global)->init->cast<StructNew>();
311-
Literal value;
311+
PossibleConstantValues value;
312312
if (structNew->isWithDefault()) {
313-
value = Literal::makeZero(fieldType);
313+
value.note(Literal::makeZero(fieldType));
314314
} else {
315-
auto* init = structNew->operands[fieldIndex];
316-
if (!Properties::isConstantExpression(init)) {
317-
// Non-constant; give up entirely.
315+
value.note(structNew->operands[fieldIndex], wasm);
316+
if (!value.isConstant()) {
317+
// Give up entirely.
318318
return;
319319
}
320-
value = Properties::getLiteral(init);
321320
}
322321

323322
// Process the current value, comparing it against the previous.
@@ -346,7 +345,7 @@ struct GlobalStructInference : public Pass {
346345
// otherwise return the value.
347346
replaceCurrent(builder.makeSequence(
348347
builder.makeDrop(builder.makeRefAs(RefAsNonNull, curr->ref)),
349-
builder.makeConstantExpression(values[0])));
348+
values[0].makeExpression(wasm)));
350349
return;
351350
}
352351
assert(values.size() == 2);
@@ -373,8 +372,8 @@ struct GlobalStructInference : public Pass {
373372
builder.makeRefEq(builder.makeRefAs(RefAsNonNull, curr->ref),
374373
builder.makeGlobalGet(
375374
checkGlobal, wasm.getGlobal(checkGlobal)->type)),
376-
builder.makeConstantExpression(values[0]),
377-
builder.makeConstantExpression(values[1])));
375+
values[0].makeExpression(wasm),
376+
values[1].makeExpression(wasm)));
378377
}
379378

380379
void visitFunction(Function* func) {

test/lit/passes/gsi.wast

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,3 +1437,54 @@
14371437
)
14381438
)
14391439
)
1440+
1441+
;; Test that we can optimize global.get operations on immutable globals.
1442+
(module
1443+
;; CHECK: (type $struct (struct (field i32)))
1444+
(type $struct (struct i32))
1445+
1446+
;; CHECK: (type $1 (func (param (ref null $struct))))
1447+
1448+
;; CHECK: (global $one i32 (i32.const 1))
1449+
(global $one i32 (i32.const 1))
1450+
1451+
;; CHECK: (global $two i32 (i32.const 2))
1452+
(global $two i32 (i32.const 2))
1453+
1454+
;; CHECK: (global $global1 (ref $struct) (struct.new $struct
1455+
;; CHECK-NEXT: (global.get $one)
1456+
;; CHECK-NEXT: ))
1457+
(global $global1 (ref $struct) (struct.new $struct
1458+
(global.get $one)
1459+
))
1460+
1461+
;; CHECK: (global $global2 (ref $struct) (struct.new $struct
1462+
;; CHECK-NEXT: (global.get $two)
1463+
;; CHECK-NEXT: ))
1464+
(global $global2 (ref $struct) (struct.new $struct
1465+
(global.get $two)
1466+
))
1467+
1468+
;; CHECK: (func $test (type $1) (param $struct (ref null $struct))
1469+
;; CHECK-NEXT: (drop
1470+
;; CHECK-NEXT: (select
1471+
;; CHECK-NEXT: (global.get $one)
1472+
;; CHECK-NEXT: (global.get $two)
1473+
;; CHECK-NEXT: (ref.eq
1474+
;; CHECK-NEXT: (ref.as_non_null
1475+
;; CHECK-NEXT: (local.get $struct)
1476+
;; CHECK-NEXT: )
1477+
;; CHECK-NEXT: (global.get $global1)
1478+
;; CHECK-NEXT: )
1479+
;; CHECK-NEXT: )
1480+
;; CHECK-NEXT: )
1481+
;; CHECK-NEXT: )
1482+
(func $test (param $struct (ref null $struct))
1483+
;; The get here will read one of the two globals, so we can use a select.
1484+
(drop
1485+
(struct.get $struct 0
1486+
(local.get $struct)
1487+
)
1488+
)
1489+
)
1490+
)

0 commit comments

Comments
 (0)