Source file src/cmd/compile/internal/ssacompile/prove_test.go

     1  // Copyright 2025 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ssacompile
     6  
     7  import (
     8  	"math"
     9  	"math/bits"
    10  	"testing"
    11  
    12  	"cmd/compile/internal/ssa"
    13  )
    14  
    15  func testLimitUnaryOpSigned8(t *testing.T, opName string, initLimit ssa.Limit, op func(l ssa.Limit, bitsize uint) ssa.Limit, opImpl func(int8) int8) {
    16  	for min := math.MinInt8; min <= math.MaxInt8; min++ {
    17  		for max := min; max <= math.MaxInt8; max++ {
    18  			realSmallest, realBiggest := int8(math.MaxInt8), int8(math.MinInt8)
    19  			for i := min; i <= max; i++ {
    20  				result := opImpl(int8(i))
    21  				if result < realSmallest {
    22  					realSmallest = result
    23  				}
    24  				if result > realBiggest {
    25  					realBiggest = result
    26  				}
    27  			}
    28  
    29  			l := ssa.Limit{Min: int64(min), Max: int64(max), Umin: 0, Umax: math.MaxUint64}
    30  			l = op(l, 8)
    31  			l = l.Intersect(initLimit) // We assume this is gonna be used by newLimit which is seeded by the op size already.
    32  
    33  			if l.Min != int64(realSmallest) || l.Max != int64(realBiggest) {
    34  				t.Errorf("%s(%d..%d) = %d..%d; want %d..%d", opName, min, max, l.Min, l.Max, realSmallest, realBiggest)
    35  			}
    36  		}
    37  	}
    38  }
    39  
    40  func testLimitUnaryOpUnsigned8(t *testing.T, opName string, initLimit ssa.Limit, op func(l ssa.Limit, bitsize uint) ssa.Limit, opImpl func(uint8) uint8) {
    41  	for min := 0; min <= math.MaxUint8; min++ {
    42  		for max := min; max <= math.MaxUint8; max++ {
    43  			realSmallest, realBiggest := uint8(math.MaxUint8), uint8(0)
    44  			for i := min; i <= max; i++ {
    45  				result := opImpl(uint8(i))
    46  				if result < realSmallest {
    47  					realSmallest = result
    48  				}
    49  				if result > realBiggest {
    50  					realBiggest = result
    51  				}
    52  			}
    53  
    54  			l := ssa.Limit{Min: math.MinInt64, Max: math.MaxInt64, Umin: uint64(min), Umax: uint64(max)}
    55  			l = op(l, 8)
    56  			l = l.Intersect(initLimit) // We assume this is gonna be used by newLimit which is seeded by the op size already.
    57  
    58  			if l.Umin != uint64(realSmallest) || l.Umax != uint64(realBiggest) {
    59  				t.Errorf("%s(%d..%d) = %d..%d; want %d..%d", opName, min, max, l.Umin, l.Umax, realSmallest, realBiggest)
    60  			}
    61  		}
    62  	}
    63  }
    64  
    65  func TestLimitNegSigned(t *testing.T) {
    66  	testLimitUnaryOpSigned8(t, "neg", ssa.NoLimitForBitsize(8), ssa.Limit.Neg, func(x int8) int8 { return -x })
    67  }
    68  func TestLimitNegUnsigned(t *testing.T) {
    69  	testLimitUnaryOpUnsigned8(t, "neg", ssa.NoLimitForBitsize(8), ssa.Limit.Neg, func(x uint8) uint8 { return -x })
    70  }
    71  
    72  func TestLimitComSigned(t *testing.T) {
    73  	testLimitUnaryOpSigned8(t, "com", ssa.NoLimitForBitsize(8), ssa.Limit.Com, func(x int8) int8 { return ^x })
    74  }
    75  func TestLimitComUnsigned(t *testing.T) {
    76  	testLimitUnaryOpUnsigned8(t, "com", ssa.NoLimitForBitsize(8), ssa.Limit.Com, func(x uint8) uint8 { return ^x })
    77  }
    78  
    79  func TestLimitCtzUnsigned(t *testing.T) {
    80  	testLimitUnaryOpUnsigned8(t, "ctz", ssa.Limit{Min: -128, Max: 127, Umin: 0, Umax: 8}, ssa.Limit.Ctz, func(x uint8) uint8 { return uint8(bits.TrailingZeros8(x)) })
    81  }
    82  
    83  func TestLimitBitlenUnsigned(t *testing.T) {
    84  	testLimitUnaryOpUnsigned8(t, "bitlen", ssa.Limit{Min: -128, Max: 127, Umin: 0, Umax: 8}, ssa.Limit.Bitlen, func(x uint8) uint8 { return uint8(bits.Len8(x)) })
    85  }
    86  
    87  func TestLimitPopcountUnsigned(t *testing.T) {
    88  	testLimitUnaryOpUnsigned8(t, "popcount", ssa.Limit{Min: -128, Max: 127, Umin: 0, Umax: 8}, ssa.Limit.Popcount, func(x uint8) uint8 { return uint8(bits.OnesCount8(x)) })
    89  }
    90  
    91  func TestConvertIntWithBitsize(t *testing.T) {
    92  	if got := ssa.ConvertIntWithBitsize[int64, uint64](255, 8); got != -1 {
    93  		t.Errorf("convertIntWithBitsize(255, 8) = %d; want -1", got)
    94  	}
    95  	if got := ssa.ConvertIntWithBitsize[uint64, int64](-1, 8); got != 255 {
    96  		t.Errorf("convertIntWithBitsize(-1, 8) = %d; want 255", got)
    97  	}
    98  
    99  	if got := ssa.ConvertIntWithBitsize[int64, uint64](127, 8); got != 127 {
   100  		t.Errorf("convertIntWithBitsize(127, 8) = %d; want 127", got)
   101  	}
   102  	if got := ssa.ConvertIntWithBitsize[uint64, int64](127, 8); got != 127 {
   103  		t.Errorf("convertIntWithBitsize(127, 8) = %d; want 127", got)
   104  	}
   105  }
   106  

View as plain text