From ad3ce6afab30fb68cfcda40a1910b87279795c5a Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Wed, 21 Apr 2021 08:01:30 +0200 Subject: pkg/compiler: optimize array[const] representation Represent array[const[X, int8], N] as string["XX...X"]. This replaces potentially huge number of: NONFAILING(*(uint8_t*)0x2000126c = 0); NONFAILING(*(uint8_t*)0x2000126d = 0); NONFAILING(*(uint8_t*)0x2000126e = 0); with a single memcpy. In one reproducer we had 3991 such lines. Also replace memcpy's with memset's when possible. Update #1070 --- pkg/compiler/types.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'pkg/compiler') diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go index b2c8c3204..038a05f24 100644 --- a/pkg/compiler/types.go +++ b/pkg/compiler/types.go @@ -4,6 +4,8 @@ package compiler import ( + "bytes" + "encoding/binary" "fmt" "sort" "strconv" @@ -249,6 +251,28 @@ var typeArray = &typeDesc{ RangeEnd: end, } } + if ct, ok := elemType.(*prog.ConstType); ok && + (ct.ArgFormat == prog.FormatNative || ct.ArgFormat == prog.FormatBigEndian) && + kind == prog.ArrayRangeLen && begin == end { + // Special case: const string takes less space in C programs. + base.TypeSize = begin * ct.Size() + base.TypeAlign = ct.TypeAlign + val := make([]byte, 8) + if ct.ArgFormat == prog.FormatBigEndian { + binary.BigEndian.PutUint64(val, ct.Val) + val = val[8-ct.Size():] + } else { + binary.LittleEndian.PutUint64(val, ct.Val) + val = val[:ct.Size()] + } + val = bytes.Repeat(val, int(begin)) + return &prog.BufferType{ + TypeCommon: base.TypeCommon, + Kind: prog.BufferString, + Values: []string{string(val)}, + NoZ: true, + } + } // TypeSize is assigned later in layoutArray. base.TypeAlign = elemType.Alignment() return &prog.ArrayType{ -- cgit mrf-deployment