Commit e1061222 authored by Keith Randall's avatar Keith Randall

cmd/compile: test non-constant shifts

Test all the weird shifts, like int8 shifted right by uint16.
Increases coverage for shift lowerings in AMD64.rules.

Change-Id: I066fe6ad6bfc05253a8d6a2ee17ff244d3a7652e
Reviewed-on: https://go-review.googlesource.com/23585
Run-TryBot: Todd Neal <todd@tneal.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarTodd Neal <todd@tneal.org>
parent 3d81d4ad
......@@ -4,7 +4,10 @@
package gc
import "testing"
import (
"reflect"
"testing"
)
// Tests shifts of zero.
......@@ -905,3 +908,124 @@ func TestShiftLargeCombine3(t *testing.T) {
t.Errorf("shift overflow mishandled")
}
}
func TestShiftGeneric(t *testing.T) {
for _, test := range [...]struct {
valueWidth int
signed bool
shiftWidth int
left bool
f interface{}
}{
{64, true, 64, true, func(n int64, s uint64) int64 { return n << s }},
{64, true, 64, false, func(n int64, s uint64) int64 { return n >> s }},
{64, false, 64, false, func(n uint64, s uint64) uint64 { return n >> s }},
{64, true, 32, true, func(n int64, s uint32) int64 { return n << s }},
{64, true, 32, false, func(n int64, s uint32) int64 { return n >> s }},
{64, false, 32, false, func(n uint64, s uint32) uint64 { return n >> s }},
{64, true, 16, true, func(n int64, s uint16) int64 { return n << s }},
{64, true, 16, false, func(n int64, s uint16) int64 { return n >> s }},
{64, false, 16, false, func(n uint64, s uint16) uint64 { return n >> s }},
{64, true, 8, true, func(n int64, s uint8) int64 { return n << s }},
{64, true, 8, false, func(n int64, s uint8) int64 { return n >> s }},
{64, false, 8, false, func(n uint64, s uint8) uint64 { return n >> s }},
{32, true, 64, true, func(n int32, s uint64) int32 { return n << s }},
{32, true, 64, false, func(n int32, s uint64) int32 { return n >> s }},
{32, false, 64, false, func(n uint32, s uint64) uint32 { return n >> s }},
{32, true, 32, true, func(n int32, s uint32) int32 { return n << s }},
{32, true, 32, false, func(n int32, s uint32) int32 { return n >> s }},
{32, false, 32, false, func(n uint32, s uint32) uint32 { return n >> s }},
{32, true, 16, true, func(n int32, s uint16) int32 { return n << s }},
{32, true, 16, false, func(n int32, s uint16) int32 { return n >> s }},
{32, false, 16, false, func(n uint32, s uint16) uint32 { return n >> s }},
{32, true, 8, true, func(n int32, s uint8) int32 { return n << s }},
{32, true, 8, false, func(n int32, s uint8) int32 { return n >> s }},
{32, false, 8, false, func(n uint32, s uint8) uint32 { return n >> s }},
{16, true, 64, true, func(n int16, s uint64) int16 { return n << s }},
{16, true, 64, false, func(n int16, s uint64) int16 { return n >> s }},
{16, false, 64, false, func(n uint16, s uint64) uint16 { return n >> s }},
{16, true, 32, true, func(n int16, s uint32) int16 { return n << s }},
{16, true, 32, false, func(n int16, s uint32) int16 { return n >> s }},
{16, false, 32, false, func(n uint16, s uint32) uint16 { return n >> s }},
{16, true, 16, true, func(n int16, s uint16) int16 { return n << s }},
{16, true, 16, false, func(n int16, s uint16) int16 { return n >> s }},
{16, false, 16, false, func(n uint16, s uint16) uint16 { return n >> s }},
{16, true, 8, true, func(n int16, s uint8) int16 { return n << s }},
{16, true, 8, false, func(n int16, s uint8) int16 { return n >> s }},
{16, false, 8, false, func(n uint16, s uint8) uint16 { return n >> s }},
{8, true, 64, true, func(n int8, s uint64) int8 { return n << s }},
{8, true, 64, false, func(n int8, s uint64) int8 { return n >> s }},
{8, false, 64, false, func(n uint8, s uint64) uint8 { return n >> s }},
{8, true, 32, true, func(n int8, s uint32) int8 { return n << s }},
{8, true, 32, false, func(n int8, s uint32) int8 { return n >> s }},
{8, false, 32, false, func(n uint8, s uint32) uint8 { return n >> s }},
{8, true, 16, true, func(n int8, s uint16) int8 { return n << s }},
{8, true, 16, false, func(n int8, s uint16) int8 { return n >> s }},
{8, false, 16, false, func(n uint8, s uint16) uint8 { return n >> s }},
{8, true, 8, true, func(n int8, s uint8) int8 { return n << s }},
{8, true, 8, false, func(n int8, s uint8) int8 { return n >> s }},
{8, false, 8, false, func(n uint8, s uint8) uint8 { return n >> s }},
} {
fv := reflect.ValueOf(test.f)
var args [2]reflect.Value
for i := 0; i < test.valueWidth; i++ {
// Build value to be shifted.
var n int64 = 1
for j := 0; j < i; j++ {
n <<= 1
}
args[0] = reflect.ValueOf(n).Convert(fv.Type().In(0))
for s := 0; s <= test.shiftWidth; s++ {
args[1] = reflect.ValueOf(s).Convert(fv.Type().In(1))
// Compute desired result. We're testing variable shifts
// assuming constant shifts are correct.
r := n
var op string
switch {
case test.left:
op = "<<"
for j := 0; j < s; j++ {
r <<= 1
}
switch test.valueWidth {
case 32:
r = int64(int32(r))
case 16:
r = int64(int16(r))
case 8:
r = int64(int8(r))
}
case test.signed:
op = ">>"
switch test.valueWidth {
case 32:
r = int64(int32(r))
case 16:
r = int64(int16(r))
case 8:
r = int64(int8(r))
}
for j := 0; j < s; j++ {
r >>= 1
}
default:
op = ">>>"
for j := 0; j < s; j++ {
r = int64(uint64(r) >> 1)
}
}
// Call function.
res := fv.Call(args[:])[0].Convert(reflect.ValueOf(r).Type())
if res.Int() != r {
t.Errorf("%s%dx%d(%x,%x)=%x, want %x", op, test.valueWidth, test.shiftWidth, n, s, res.Int(), r)
}
}
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment