(= e (PointsToExpr state p)) indicates that at program point state, p points to e.
I also re-organized the memory bril tests. Previously, mem_simple_redundant_load actually was an example of store forwarding, so I moved it to mem_simple_store_forwarding, and added an actual test for redundant load elimination in its place.
Example optimization
Optimizes the following bril, containing two loads:
@main(cond: bool) {
one: int = const 1;
p: ptr<int> = alloc one;
br cond .t .f;
.t:
two: int = const 2;
store p two;
jmp .done;
.f:
three: int = const 3;
store p three;
.done:
load1: int = load p;
load2: int = load p;
print load2;
free p;
ret;
}
To (just one load!):
@main(v0: bool) {
v1_: int = const 1;
v2_: ptr<int> = alloc v1_;
br v0 .v3_ .v4_;
.v3_:
v5_: int = const 2;
store v2_ v5_;
v6_: ptr<int> = id v2_;
jmp .v7_;
.v4_:
v8_: int = const 3;
store v2_ v8_;
v6_: ptr<int> = id v2_;
.v7_:
v9_: int = load v2_;
print v9_;
free v2_;
}
Note that this test makes it unknown what value is written via the cond arg; otherwise, store forwarding usually subsumes redundant load elimination.
Summary
Eliminate loads for which we already have the value from a prior load.
We perform this mainly by beefing up
PointsToExpr
:(= e (PointsToExpr state p))
indicates that at program pointstate
,p
points toe
.I also re-organized the memory bril tests. Previously,
mem_simple_redundant_load
actually was an example of store forwarding, so I moved it tomem_simple_store_forwarding
, and added an actual test for redundant load elimination in its place.Example optimization
Optimizes the following bril, containing two loads:
To (just one load!):
Note that this test makes it unknown what value is written via the
cond
arg; otherwise, store forwarding usually subsumes redundant load elimination.