]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: test non-constant shifts
authorKeith Randall <khr@golang.org>
Tue, 31 May 2016 20:48:29 +0000 (13:48 -0700)
committerKeith Randall <khr@golang.org>
Wed, 1 Jun 2016 00:06:00 +0000 (00:06 +0000)
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: Todd Neal <todd@tneal.org>
src/cmd/compile/internal/gc/shift_test.go

index cb6be777a7fb18d5d4c307e6a8f7e95b11860083..ce2eedf1521d9d9af087b8e7adfc5901261a3785 100644 (file)
@@ -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)
+                               }
+                       }
+               }
+       }
+}