Skip to content

Commit 9aa7e6a

Browse files
authored
Merge pull request #4 from bytecodealliance/cfallin/use-op-predicates
Cleanup: use operator predicates in waffle rather than ad-hoc matches.
2 parents 3c85144 + bc037d9 commit 9aa7e6a

File tree

4 files changed

+24
-104
lines changed

4 files changed

+24
-104
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ edition = "2021"
99
exclude = ["/npm", "/ci"]
1010

1111
[dependencies]
12-
waffle = "0.1.0"
12+
waffle = "0.1.1"
1313
anyhow = "1.0"
1414
structopt = "0.3"
1515
log = "0.4"

src/constant_offsets.rs

Lines changed: 5 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
use fxhash::{FxHashMap, FxHashSet};
66
use std::collections::{BTreeMap, VecDeque};
77
use waffle::{
8-
cfg::CFGInfo, entity::PerEntity, pool::ListRef, Block, FunctionBody, MemoryArg, Operator,
9-
Terminator, Type, Value, ValueDef,
8+
cfg::CFGInfo, entity::PerEntity, pool::ListRef, Block, FunctionBody, Operator, Terminator,
9+
Type, Value, ValueDef,
1010
};
1111

1212
/// Dataflow analysis lattice: a value is either some original SSA
@@ -37,56 +37,6 @@ impl AbsValue {
3737
}
3838
}
3939

40-
fn is_load_or_store(op: &Operator) -> bool {
41-
match op {
42-
Operator::I32Load { .. }
43-
| Operator::I32Load8S { .. }
44-
| Operator::I32Load8U { .. }
45-
| Operator::I32Load16S { .. }
46-
| Operator::I32Load16U { .. }
47-
| Operator::I64Load { .. }
48-
| Operator::I64Load8S { .. }
49-
| Operator::I64Load8U { .. }
50-
| Operator::I64Load16S { .. }
51-
| Operator::I64Load16U { .. }
52-
| Operator::I64Load32S { .. }
53-
| Operator::I64Load32U { .. } => true,
54-
Operator::I32Store { .. }
55-
| Operator::I32Store8 { .. }
56-
| Operator::I32Store16 { .. }
57-
| Operator::I64Store { .. }
58-
| Operator::I64Store8 { .. }
59-
| Operator::I64Store16 { .. }
60-
| Operator::I64Store32 { .. } => true,
61-
_ => false,
62-
}
63-
}
64-
65-
fn update_load_or_store_memarg<F: Fn(&mut MemoryArg)>(op: &mut Operator, f: F) {
66-
match op {
67-
Operator::I32Load { memory }
68-
| Operator::I32Load8S { memory }
69-
| Operator::I32Load8U { memory }
70-
| Operator::I32Load16S { memory }
71-
| Operator::I32Load16U { memory }
72-
| Operator::I64Load { memory }
73-
| Operator::I64Load8S { memory }
74-
| Operator::I64Load8U { memory }
75-
| Operator::I64Load16S { memory }
76-
| Operator::I64Load16U { memory }
77-
| Operator::I64Load32S { memory }
78-
| Operator::I64Load32U { memory }
79-
| Operator::I32Store { memory }
80-
| Operator::I32Store8 { memory }
81-
| Operator::I32Store16 { memory }
82-
| Operator::I64Store { memory }
83-
| Operator::I64Store8 { memory }
84-
| Operator::I64Store16 { memory }
85-
| Operator::I64Store32 { memory } => f(memory),
86-
_ => {}
87-
}
88-
}
89-
9040
pub fn run(func: &mut FunctionBody, cfg: &CFGInfo) {
9141
waffle::passes::resolve_aliases::run(func);
9242
log::trace!(
@@ -235,7 +185,7 @@ pub fn run(func: &mut FunctionBody, cfg: &CFGInfo) {
235185
let mut used_as_addr = FxHashSet::default();
236186
for (_, def) in func.values.entries() {
237187
if let ValueDef::Operator(op, args, _) = def {
238-
if is_load_or_store(op) {
188+
if op.is_load() || op.is_store() {
239189
used_as_addr.insert(func.arg_pool[*args][0]);
240190
}
241191
}
@@ -311,7 +261,7 @@ pub fn run(func: &mut FunctionBody, cfg: &CFGInfo) {
311261

312262
// Handle loads/stores.
313263
if let ValueDef::Operator(op, args, tys) = &func.values[inst] {
314-
if is_load_or_store(op) {
264+
if op.is_load() || op.is_store() {
315265
let args = &func.arg_pool[*args];
316266
let tys = *tys;
317267
let addr = args[0];
@@ -327,7 +277,7 @@ pub fn run(func: &mut FunctionBody, cfg: &CFGInfo) {
327277
let offset = *min_offset_from.get(&base).unwrap();
328278
assert!(offset <= 0);
329279
let addend = (-offset) as u32;
330-
update_load_or_store_memarg(&mut op, |memory| {
280+
op.update_memory_arg(|memory| {
331281
memory.offset =
332282
memory.offset.wrapping_add(addend).wrapping_add(this_offset)
333283
});

src/dce.rs

Lines changed: 16 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
//! Dead-code elimination pass.
22
33
use fxhash::FxHashSet;
4-
use waffle::{cfg::CFGInfo, Block, FunctionBody, Operator, Terminator, Value, ValueDef};
4+
use waffle::{
5+
cfg::CFGInfo, Block, FunctionBody, Operator, SideEffect, Terminator, Value, ValueDef,
6+
};
57

68
fn op_can_be_removed(op: &Operator) -> bool {
79
// Pure ops, and also we allow loads and table.gets to be removed
@@ -11,53 +13,21 @@ fn op_can_be_removed(op: &Operator) -> bool {
1113
// unused (they technically have a read side-effect but really
1214
// should be considered pure).
1315
match op {
14-
Operator::I32Load { .. }
15-
| Operator::I32Load8S { .. }
16-
| Operator::I32Load8U { .. }
17-
| Operator::I32Load16S { .. }
18-
| Operator::I32Load16U { .. }
19-
| Operator::I64Load { .. }
20-
| Operator::I64Load8S { .. }
21-
| Operator::I64Load8U { .. }
22-
| Operator::I64Load16S { .. }
23-
| Operator::I64Load16U { .. }
24-
| Operator::I64Load32S { .. }
25-
| Operator::I64Load32U { .. }
26-
| Operator::V128Load { .. }
27-
| Operator::V128Load8x8S { .. }
28-
| Operator::V128Load8x8U { .. }
29-
| Operator::V128Load16x4S { .. }
30-
| Operator::V128Load16x4U { .. }
31-
| Operator::V128Load32x2S { .. }
32-
| Operator::V128Load32x2U { .. }
33-
| Operator::V128Load8Lane { .. }
34-
| Operator::V128Load8Splat { .. }
35-
| Operator::V128Load16Lane { .. }
36-
| Operator::V128Load16Splat { .. }
37-
| Operator::V128Load32Lane { .. }
38-
| Operator::V128Load32Splat { .. }
39-
| Operator::V128Load32Zero { .. }
40-
| Operator::V128Load64Lane { .. }
41-
| Operator::V128Load64Splat { .. }
42-
| Operator::V128Load64Zero { .. } => true,
43-
Operator::I32DivS
44-
| Operator::I32DivU
45-
| Operator::I32RemS
46-
| Operator::I32RemU
47-
| Operator::I64DivS
48-
| Operator::I64DivU
49-
| Operator::I64RemS
50-
| Operator::I64RemU => true,
51-
Operator::I32TruncF32S
52-
| Operator::I32TruncF32U
53-
| Operator::I32TruncF64S
54-
| Operator::I32TruncF64U
55-
| Operator::I64TruncF32S
56-
| Operator::I64TruncF32U
57-
| Operator::I64TruncF64S
58-
| Operator::I64TruncF64U => true,
16+
// If a load is unused, we can remove it because we're assuming
17+
// the program doesn't trap (so we don't need to preserve traps
18+
// due to out-of- bounds addresses).
19+
op if op.is_load() => true,
20+
// If the *only* side-effect is a possible trap, we can remove
21+
// the op if otherwise unused, because we're assuming the
22+
// program doesn't trap.
23+
op if op.effects() == &[SideEffect::Trap] => true,
24+
// `table.size` and `memory.size` technically access state
25+
// tracked via side-effects, but can otherwise be removed if
26+
// unused. Likewise for table element and global accesses.
5927
Operator::TableSize { .. } | Operator::MemorySize { .. } => true,
6028
Operator::GlobalGet { .. } | Operator::TableGet { .. } => true,
29+
// Finally, all pure ops (computation only, no accesses to
30+
// ambient state and no side-effects) can be removed if unused.
6131
op if op.is_pure() => true,
6232
_ => false,
6333
}

0 commit comments

Comments
 (0)