for _, a := range v.Args {
if a.Block == b && a.Type.IsMemory() {
storeUse.add(a.ID)
- if v.Op != OpStore {
+ if v.Op != OpStore && v.Op != OpZero {
// CALL, DUFFCOPY, etc. are both
// reads and writes.
loadUse.add(a.ID)
// Clear all shadowed addresses.
shadowed.clear()
}
- if v.Op == OpStore {
+ if v.Op == OpStore || v.Op == OpZero {
if shadowed.contains(v.Args[0].ID) {
// Modify store into a copy
- v.Op = OpCopy
+ if v.Op == OpStore {
+ // store addr value mem
+ v.SetArgs1(v.Args[2])
+ } else {
+ // zero addr mem
+ sz := v.Args[0].Type.Elem().Size()
+ if v.AuxInt != sz {
+ f.Fatalf("mismatched zero/store sizes: %d and %d [%s]",
+ v.AuxInt, sz, v.LongString())
+ }
+ v.SetArgs1(v.Args[1])
+ }
v.Aux = nil
- v.SetArgs1(v.Args[2])
+ v.AuxInt = 0
+ v.Op = OpCopy
} else {
shadowed.add(v.Args[0].ID)
}
package ssa
-import (
- "testing"
-)
+import "testing"
func TestDeadStore(t *testing.T) {
c := testConfig(t)
Valu("v", OpConstBool, TypeBool, 0, true),
Valu("addr1", OpAddr, ptrType, 0, nil, "sb"),
Valu("addr2", OpAddr, ptrType, 0, nil, "sb"),
- Valu("store1", OpStore, TypeMem, 0, nil, "addr1", "v", "start"),
+ Valu("addr3", OpAddr, ptrType, 0, nil, "sb"),
+ Valu("zero1", OpZero, TypeMem, 8, nil, "addr3", "start"),
+ Valu("store1", OpStore, TypeMem, 0, nil, "addr1", "v", "zero1"),
Valu("store2", OpStore, TypeMem, 0, nil, "addr2", "v", "store1"),
Valu("store3", OpStore, TypeMem, 0, nil, "addr1", "v", "store2"),
+ Valu("store4", OpStore, TypeMem, 0, nil, "addr3", "v", "store3"),
Goto("exit")),
Bloc("exit",
Exit("store3")))
dse(fun.f)
CheckFunc(fun.f)
- v := fun.values["store1"]
- if v.Op != OpCopy {
+ v1 := fun.values["store1"]
+ if v1.Op != OpCopy {
t.Errorf("dead store not removed")
}
+
+ v2 := fun.values["zero1"]
+ if v2.Op != OpCopy {
+ t.Errorf("dead store (zero) not removed")
+ }
}
func TestDeadStorePhi(t *testing.T) {
// make sure we don't get into an infinite loop with phi values.