| // 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() | |
| } | |
| } | |
| // benchFnBlock 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 | |
| } |