From 1a5ff413c0cb96f14922fad905ce621d78859690 Mon Sep 17 00:00:00 2001 From: Bryce Kahle Date: Wed, 4 May 2022 10:19:17 +0000 Subject: [PATCH] internal: hard code endianness This results in a reduction of the instructions necessary for endian-related operations. The wall clock time difference for a single call is miniscule (picoseconds). An example, with the ByteOrder.Uint32 function: Runtime instructions: https://godbolt.org/z/7vW1Pfnso Buildtime instructions: https://godbolt.org/z/baxW1Wb7W The function call on amd64 changes from: MOVQ "".NativeEndian(SB), CX MOVQ "".NativeEndian+8(SB), DX MOVQ 64(CX), CX MOVQ AX, BX MOVL $4, DI MOVQ DX, AX MOVQ CX, DX MOVQ DI, CX CALL DX to XCHGL AX, AX The difference on arm64 is equivalent, but uses different specific instructions. --- internal/endian.go | 29 ----------------------------- internal/endian_be.go | 13 +++++++++++++ internal/endian_le.go | 13 +++++++++++++ 3 files changed, 26 insertions(+), 29 deletions(-) delete mode 100644 internal/endian.go create mode 100644 internal/endian_be.go create mode 100644 internal/endian_le.go diff --git a/internal/endian.go b/internal/endian.go deleted file mode 100644 index 6ae99fcd5..000000000 --- a/internal/endian.go +++ /dev/null @@ -1,29 +0,0 @@ -package internal - -import ( - "encoding/binary" - "unsafe" -) - -// NativeEndian is set to either binary.BigEndian or binary.LittleEndian, -// depending on the host's endianness. -var NativeEndian binary.ByteOrder - -// Clang is set to either "el" or "eb" depending on the host's endianness. -var ClangEndian string - -func init() { - if isBigEndian() { - NativeEndian = binary.BigEndian - ClangEndian = "eb" - } else { - NativeEndian = binary.LittleEndian - ClangEndian = "el" - } -} - -func isBigEndian() (ret bool) { - i := int(0x1) - bs := (*[int(unsafe.Sizeof(i))]byte)(unsafe.Pointer(&i)) - return bs[0] == 0 -} diff --git a/internal/endian_be.go b/internal/endian_be.go new file mode 100644 index 000000000..ad33cda85 --- /dev/null +++ b/internal/endian_be.go @@ -0,0 +1,13 @@ +//go:build armbe || arm64be || mips || mips64 || mips64p32 || ppc64 || s390 || s390x || sparc || sparc64 +// +build armbe arm64be mips mips64 mips64p32 ppc64 s390 s390x sparc sparc64 + +package internal + +import "encoding/binary" + +// NativeEndian is set to either binary.BigEndian or binary.LittleEndian, +// depending on the host's endianness. +var NativeEndian binary.ByteOrder = binary.BigEndian + +// ClangEndian is set to either "el" or "eb" depending on the host's endianness. +const ClangEndian = "eb" diff --git a/internal/endian_le.go b/internal/endian_le.go new file mode 100644 index 000000000..41a68224c --- /dev/null +++ b/internal/endian_le.go @@ -0,0 +1,13 @@ +//go:build 386 || amd64 || amd64p32 || arm || arm64 || mipsle || mips64le || mips64p32le || ppc64le || riscv64 +// +build 386 amd64 amd64p32 arm arm64 mipsle mips64le mips64p32le ppc64le riscv64 + +package internal + +import "encoding/binary" + +// NativeEndian is set to either binary.BigEndian or binary.LittleEndian, +// depending on the host's endianness. +var NativeEndian binary.ByteOrder = binary.LittleEndian + +// ClangEndian is set to either "el" or "eb" depending on the host's endianness. +const ClangEndian = "el"