2016-02-10 00:27:33 +01:00
|
|
|
package ssa
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"testing"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestFuseEliminatesOneBranch(t *testing.T) {
|
|
|
|
|
ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr"} // dummy for testing
|
|
|
|
|
c := NewConfig("amd64", DummyFrontend{t}, nil, true)
|
|
|
|
|
fun := Fun(c, "entry",
|
|
|
|
|
Bloc("entry",
|
|
|
|
|
Valu("mem", OpInitMem, TypeMem, 0, nil),
|
|
|
|
|
Valu("sb", OpSB, TypeInvalid, 0, nil),
|
|
|
|
|
Goto("checkPtr")),
|
|
|
|
|
Bloc("checkPtr",
|
|
|
|
|
Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
|
|
|
|
|
Valu("nilptr", OpConstNil, ptrType, 0, nil, "sb"),
|
|
|
|
|
Valu("bool1", OpNeqPtr, TypeBool, 0, nil, "ptr1", "nilptr"),
|
|
|
|
|
If("bool1", "then", "exit")),
|
|
|
|
|
Bloc("then",
|
|
|
|
|
Goto("exit")),
|
|
|
|
|
Bloc("exit",
|
|
|
|
|
Exit("mem")))
|
|
|
|
|
|
|
|
|
|
CheckFunc(fun.f)
|
|
|
|
|
fuse(fun.f)
|
|
|
|
|
|
|
|
|
|
for _, b := range fun.f.Blocks {
|
|
|
|
|
if b == fun.blocks["then"] && b.Kind != BlockInvalid {
|
|
|
|
|
t.Errorf("then was not eliminated, but should have")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestFuseEliminatesBothBranches(t *testing.T) {
|
|
|
|
|
ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr"} // dummy for testing
|
|
|
|
|
c := NewConfig("amd64", DummyFrontend{t}, nil, true)
|
|
|
|
|
fun := Fun(c, "entry",
|
|
|
|
|
Bloc("entry",
|
|
|
|
|
Valu("mem", OpInitMem, TypeMem, 0, nil),
|
|
|
|
|
Valu("sb", OpSB, TypeInvalid, 0, nil),
|
|
|
|
|
Goto("checkPtr")),
|
|
|
|
|
Bloc("checkPtr",
|
|
|
|
|
Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
|
|
|
|
|
Valu("nilptr", OpConstNil, ptrType, 0, nil, "sb"),
|
|
|
|
|
Valu("bool1", OpNeqPtr, TypeBool, 0, nil, "ptr1", "nilptr"),
|
|
|
|
|
If("bool1", "then", "else")),
|
|
|
|
|
Bloc("then",
|
|
|
|
|
Goto("exit")),
|
|
|
|
|
Bloc("else",
|
|
|
|
|
Goto("exit")),
|
|
|
|
|
Bloc("exit",
|
|
|
|
|
Exit("mem")))
|
|
|
|
|
|
|
|
|
|
CheckFunc(fun.f)
|
|
|
|
|
fuse(fun.f)
|
|
|
|
|
|
|
|
|
|
for _, b := range fun.f.Blocks {
|
|
|
|
|
if b == fun.blocks["then"] && b.Kind != BlockInvalid {
|
|
|
|
|
t.Errorf("then was not eliminated, but should have")
|
|
|
|
|
}
|
|
|
|
|
if b == fun.blocks["else"] && b.Kind != BlockInvalid {
|
|
|
|
|
t.Errorf("then was not eliminated, but should have")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-17 17:21:53 +01:00
|
|
|
func TestFuseHandlesPhis(t *testing.T) {
|
|
|
|
|
ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr"} // dummy for testing
|
|
|
|
|
c := NewConfig("amd64", DummyFrontend{t}, nil, true)
|
|
|
|
|
fun := Fun(c, "entry",
|
|
|
|
|
Bloc("entry",
|
|
|
|
|
Valu("mem", OpInitMem, TypeMem, 0, nil),
|
|
|
|
|
Valu("sb", OpSB, TypeInvalid, 0, nil),
|
|
|
|
|
Goto("checkPtr")),
|
|
|
|
|
Bloc("checkPtr",
|
|
|
|
|
Valu("ptr1", OpLoad, ptrType, 0, nil, "sb", "mem"),
|
|
|
|
|
Valu("nilptr", OpConstNil, ptrType, 0, nil, "sb"),
|
|
|
|
|
Valu("bool1", OpNeqPtr, TypeBool, 0, nil, "ptr1", "nilptr"),
|
|
|
|
|
If("bool1", "then", "else")),
|
|
|
|
|
Bloc("then",
|
|
|
|
|
Goto("exit")),
|
|
|
|
|
Bloc("else",
|
|
|
|
|
Goto("exit")),
|
|
|
|
|
Bloc("exit",
|
|
|
|
|
Valu("phi", OpPhi, ptrType, 0, nil, "ptr1", "ptr1"),
|
|
|
|
|
Exit("mem")))
|
|
|
|
|
|
|
|
|
|
CheckFunc(fun.f)
|
|
|
|
|
fuse(fun.f)
|
|
|
|
|
|
|
|
|
|
for _, b := range fun.f.Blocks {
|
|
|
|
|
if b == fun.blocks["then"] && b.Kind != BlockInvalid {
|
|
|
|
|
t.Errorf("then was not eliminated, but should have")
|
|
|
|
|
}
|
|
|
|
|
if b == fun.blocks["else"] && b.Kind != BlockInvalid {
|
|
|
|
|
t.Errorf("then was not eliminated, but should have")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-10 00:27:33 +01:00
|
|
|
func TestFuseEliminatesEmptyBlocks(t *testing.T) {
|
|
|
|
|
c := NewConfig("amd64", DummyFrontend{t}, nil, true)
|
|
|
|
|
fun := Fun(c, "entry",
|
|
|
|
|
Bloc("entry",
|
|
|
|
|
Valu("mem", OpInitMem, TypeMem, 0, nil),
|
|
|
|
|
Valu("sb", OpSB, TypeInvalid, 0, nil),
|
|
|
|
|
Goto("z0")),
|
|
|
|
|
Bloc("z1",
|
|
|
|
|
Goto("z2")),
|
|
|
|
|
Bloc("z3",
|
|
|
|
|
Goto("exit")),
|
|
|
|
|
Bloc("z2",
|
|
|
|
|
Goto("z3")),
|
|
|
|
|
Bloc("z0",
|
|
|
|
|
Goto("z1")),
|
|
|
|
|
Bloc("exit",
|
|
|
|
|
Exit("mem"),
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
CheckFunc(fun.f)
|
|
|
|
|
fuse(fun.f)
|
|
|
|
|
|
|
|
|
|
for k, b := range fun.blocks {
|
|
|
|
|
if k[:1] == "z" && b.Kind != BlockInvalid {
|
|
|
|
|
t.Errorf("%s was not eliminated, but should have", k)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|