From 2ca0f0d0c60ef86e6e8f761378599e04e67baa6e Mon Sep 17 00:00:00 2001 From: Jaden Weiss Date: Sat, 22 Feb 2020 18:15:45 -0500 Subject: [PATCH] compiler/llvmutil: move constant pointer packs into constant globals This adds an optimization to EmitPointerPack when all values are constants. The values are stored in a constant global instead of on the heap. This eliminates a heap allocation, and can reduce binary size. --- compiler/llvmutil/wordpack.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/compiler/llvmutil/wordpack.go b/compiler/llvmutil/wordpack.go index 0c1c951f..55666a43 100644 --- a/compiler/llvmutil/wordpack.go +++ b/compiler/llvmutil/wordpack.go @@ -12,6 +12,7 @@ import ( // EmitPointerPack packs the list of values into a single pointer value using // bitcasts, or else allocates a value on the heap if it cannot be packed in the // pointer value directly. It returns the pointer with the packed data. +// If the values are all constants, they are be stored in a constant global and deduplicated. func EmitPointerPack(builder llvm.Builder, mod llvm.Module, config *compileopts.Config, values []llvm.Value) llvm.Value { ctx := mod.Context() targetData := llvm.NewTargetData(mod.DataLayout()) @@ -42,6 +43,27 @@ func EmitPointerPack(builder llvm.Builder, mod llvm.Module, config *compileopts. // it in an alloca first for bitcasting (store+bitcast+load). packedAlloc, _, _ = CreateTemporaryAlloca(builder, mod, packedType, "") } else { + // Check if the values are all constants. + constant := true + for _, v := range values { + if !v.IsConstant() { + constant = false + break + } + } + + if constant { + // The data is known at compile time, so store it in a constant global. + // The global address is marked as unnamed, which allows LLVM to merge duplicates. + funcName := builder.GetInsertBlock().Parent().Name() + global := llvm.AddGlobal(mod, packedType, funcName+"$pack") + global.SetInitializer(ctx.ConstStruct(values, false)) + global.SetGlobalConstant(true) + global.SetUnnamedAddr(true) + global.SetLinkage(llvm.PrivateLinkage) + return llvm.ConstBitCast(global, i8ptrType) + } + // Packed data is bigger than a pointer, so allocate it on the heap. sizeValue := llvm.ConstInt(uintptrType, size, false) alloc := mod.NamedFunction("runtime.alloc")