// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package ssa import ( "cmd/compile/internal/types" "fmt" "testing" ) const ( blockCount = 1000 passCount = 15000 ) type passFunc func(*Func) func BenchmarkDSEPass(b *testing.B) { benchFnPass(b, dse, blockCount, genFunction) } func BenchmarkDSEPassBlock(b *testing.B) { benchFnBlock(b, dse, genFunction) } func BenchmarkCSEPass(b *testing.B) { benchFnPass(b, cse, blockCount, genFunction) } func BenchmarkCSEPassBlock(b *testing.B) { benchFnBlock(b, cse, genFunction) } func BenchmarkDeadcodePass(b *testing.B) { benchFnPass(b, deadcode, blockCount, genFunction) } func BenchmarkDeadcodePassBlock(b *testing.B) { benchFnBlock(b, deadcode, genFunction) } func multi(f *Func) { cse(f) dse(f) deadcode(f) } func BenchmarkMultiPass(b *testing.B) { benchFnPass(b, multi, blockCount, genFunction) } func BenchmarkMultiPassBlock(b *testing.B) { benchFnBlock(b, multi, genFunction) } // benchFnPass runs passFunc b.N times across a single function. func benchFnPass(b *testing.B, fn passFunc, size int, bg blockGen) { b.ReportAllocs() c := testConfig(b) fun := c.Fun("entry", bg(size)...) CheckFunc(fun.f) b.ResetTimer() for i := 0; i < b.N; i++ { fn(fun.f) b.StopTimer() CheckFunc(fun.f) b.StartTimer() } } // benchFnPass runs passFunc across a function with b.N blocks. func benchFnBlock(b *testing.B, fn passFunc, bg blockGen) { b.ReportAllocs() c := testConfig(b) fun := c.Fun("entry", bg(b.N)...) CheckFunc(fun.f) b.ResetTimer() for i := 0; i < passCount; i++ { fn(fun.f) } b.StopTimer() } func genFunction(size int) []bloc { var blocs []bloc elemType := types.Types[types.TINT64] ptrType := elemType.PtrTo() valn := func(s string, m, n int) string { return fmt.Sprintf("%s%d-%d", s, m, n) } blocs = append(blocs, Bloc("entry", Valu(valn("store", 0, 4), OpInitMem, types.TypeMem, 0, nil), Valu("sb", OpSB, types.Types[types.TUINTPTR], 0, nil), Goto(blockn(1)), ), ) for i := 1; i < size+1; i++ { blocs = append(blocs, Bloc(blockn(i), Valu(valn("v", i, 0), OpConstBool, types.Types[types.TBOOL], 1, nil), Valu(valn("addr", i, 1), OpAddr, ptrType, 0, nil, "sb"), Valu(valn("addr", i, 2), OpAddr, ptrType, 0, nil, "sb"), Valu(valn("addr", i, 3), OpAddr, ptrType, 0, nil, "sb"), Valu(valn("zero", i, 1), OpZero, types.TypeMem, 8, elemType, valn("addr", i, 3), valn("store", i-1, 4)), Valu(valn("store", i, 1), OpStore, types.TypeMem, 0, elemType, valn("addr", i, 1), valn("v", i, 0), valn("zero", i, 1)), Valu(valn("store", i, 2), OpStore, types.TypeMem, 0, elemType, valn("addr", i, 2), valn("v", i, 0), valn("store", i, 1)), Valu(valn("store", i, 3), OpStore, types.TypeMem, 0, elemType, valn("addr", i, 1), valn("v", i, 0), valn("store", i, 2)), Valu(valn("store", i, 4), OpStore, types.TypeMem, 0, elemType, valn("addr", i, 3), valn("v", i, 0), valn("store", i, 3)), Goto(blockn(i+1)))) } blocs = append(blocs, Bloc(blockn(size+1), Goto("exit")), Bloc("exit", Exit("store0-4")), ) return blocs }