Skip to content

Commit

Permalink
cmd/compile: fix bit length intrinsic for 16/8 bits on GOAMD64=v3
Browse files Browse the repository at this point in the history
Upper bits of registers for uint8/uint16 are junk. Make sure we
mask those off before using LZCNT (leading zeros count).

Fixes #52681

Change-Id: I0ca9e62f23bcb1f6ad2a787fa9895322afaa2533
Reviewed-on: https://go-review.googlesource.com/c/go/+/403815
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
Auto-Submit: Keith Randall <khr@google.com>
  • Loading branch information
randall77 authored and gopherbot committed May 3, 2022
1 parent 8a5845e commit 5a103ca
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 5 deletions.
4 changes: 3 additions & 1 deletion src/cmd/compile/internal/ssa/gen/AMD64.rules
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@
(BitLen8 x) && buildcfg.GOAMD64 < 3 => (BSRL (LEAL1 <typ.UInt32> [1] (MOVBQZX <typ.UInt32> x) (MOVBQZX <typ.UInt32> x)))
(BitLen64 <t> x) && buildcfg.GOAMD64 >= 3 => (NEGQ (ADDQconst <t> [-64] (LZCNTQ x)))
// Use 64-bit version to allow const-fold remove unnecessary arithmetic.
(BitLen(32|16|8) <t> x) && buildcfg.GOAMD64 >= 3 => (NEGQ (ADDQconst <t> [-32] (LZCNTL x)))
(BitLen32 <t> x) && buildcfg.GOAMD64 >= 3 => (NEGQ (ADDQconst <t> [-32] (LZCNTL x)))
(BitLen16 <t> x) && buildcfg.GOAMD64 >= 3 => (NEGQ (ADDQconst <t> [-32] (LZCNTL (MOVWQZX <x.Type> x))))
(BitLen8 <t> x) && buildcfg.GOAMD64 >= 3 => (NEGQ (ADDQconst <t> [-32] (LZCNTL (MOVBQZX <x.Type> x))))

(Bswap(64|32) ...) => (BSWAP(Q|L) ...)

Expand Down
12 changes: 8 additions & 4 deletions src/cmd/compile/internal/ssa/rewriteAMD64.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 62 additions & 0 deletions src/cmd/compile/internal/test/intrinsics_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2022 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 test

import (
"math/bits"
"testing"
)

func TestBitLen64(t *testing.T) {
for i := 0; i <= 64; i++ {
got := bits.Len64(1 << i)
want := i + 1
if want == 65 {
want = 0
}
if got != want {
t.Errorf("Len64(1<<%d) = %d, want %d", i, got, want)
}
}
}

func TestBitLen32(t *testing.T) {
for i := 0; i <= 32; i++ {
got := bits.Len32(1 << i)
want := i + 1
if want == 33 {
want = 0
}
if got != want {
t.Errorf("Len32(1<<%d) = %d, want %d", i, got, want)
}
}
}

func TestBitLen16(t *testing.T) {
for i := 0; i <= 16; i++ {
got := bits.Len16(1 << i)
want := i + 1
if want == 17 {
want = 0
}
if got != want {
t.Errorf("Len16(1<<%d) = %d, want %d", i, got, want)
}
}
}

func TestBitLen8(t *testing.T) {
for i := 0; i <= 8; i++ {
got := bits.Len8(1 << i)
want := i + 1
if want == 9 {
want = 0
}
if got != want {
t.Errorf("Len8(1<<%d) = %d, want %d", i, got, want)
}
}
}

0 comments on commit 5a103ca

Please sign in to comment.