From 52199f4a14c20cda8c2c33227b5a1d5b593c2934 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Fri, 12 Oct 2018 17:00:39 +0200 Subject: [PATCH] compiler: eliminate created but never used maps --- compiler/optimizer.go | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/compiler/optimizer.go b/compiler/optimizer.go index 0c4f998d..394a0978 100644 --- a/compiler/optimizer.go +++ b/compiler/optimizer.go @@ -37,6 +37,7 @@ func (c *Compiler) Optimize(optLevel, sizeLevel int, inlinerThreshold uint) { goPasses.Run(c.mod) // Run Go-specific optimization passes. + c.OptimizeMaps() c.OptimizeStringToBytes() c.OptimizeAllocs() c.Verify() @@ -49,6 +50,44 @@ func (c *Compiler) Optimize(optLevel, sizeLevel int, inlinerThreshold uint) { modPasses.Run(c.mod) } +// Eliminate created but not used maps. +// +// In the future, this should statically allocate created but never modified +// maps. This has not yet been implemented, however. +func (c *Compiler) OptimizeMaps() { + hashmapMake := c.mod.NamedFunction("runtime.hashmapMake") + if hashmapMake.IsNil() { + // nothing to optimize + return + } + + hashmapBinarySet := c.mod.NamedFunction("runtime.hashmapBinarySet") + hashmapStringSet := c.mod.NamedFunction("runtime.hashmapStringSet") + + for _, makeInst := range getUses(hashmapMake) { + updateInsts := []llvm.Value{} + unknownUses := false // are there any uses other than setting a value? + + for _, use := range getUses(makeInst) { + switch use.CalledValue() { + case hashmapBinarySet, hashmapStringSet: + updateInsts = append(updateInsts, use) + default: + unknownUses = true + } + } + + if !unknownUses { + // This map can be entirely removed, as it is only created but never + // used. + for _, inst := range updateInsts { + inst.EraseFromParentAsInstruction() + } + makeInst.EraseFromParentAsInstruction() + } + } +} + // Transform runtime.stringToBytes(...) calls into const []byte slices whenever // possible. This optimizes the following pattern: // w.Write([]byte("foo"))