Source file src/cmd/compile/internal/ssarewrite/rewriteppc64/ppc64_helpers.go

     1  // Copyright 2015 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 rewriteppc64
     6  
     7  import (
     8  	"math/bits"
     9  
    10  	"cmd/compile/internal/ssa"
    11  )
    12  
    13  func getPPC64ShiftMaskLength(v int64) int64 {
    14  	return int64(bits.Len64(uint64(v)))
    15  }
    16  
    17  // Test if this mask is a valid, contiguous bitmask which can be
    18  // represented by a RLWNM mask and also clears the upper 32 bits
    19  // of the register.
    20  func isPPC64WordRotateMaskNonWrapping(v64 int64) bool {
    21  	// Isolate rightmost 1 (if none 0) and add.
    22  	v := uint32(v64)
    23  	vp := (v & -v) + v
    24  	return (v&vp == 0) && v != 0 && uint64(uint32(v64)) == uint64(v64)
    25  }
    26  
    27  // isU16Bit reports whether n can be represented as an unsigned 16 bit integer.
    28  func isU16Bit(n int64) bool {
    29  	return n == int64(uint16(n))
    30  }
    31  
    32  // Test if RLWINM feeding into an ANDconst can be merged. Return the encoded RLWINM constant,
    33  // or 0 if they cannot be merged.
    34  func mergePPC64AndRlwinm(mask uint32, rlw int64) int64 {
    35  	r, _, _, mask_rlw := ssa.DecodePPC64RotateMask(rlw)
    36  	mask_out := (mask_rlw & uint64(mask))
    37  
    38  	// Verify the result is still a valid bitmask of <= 32 bits.
    39  	if !ssa.IsPPC64WordRotateMask(int64(mask_out)) {
    40  		return 0
    41  	}
    42  	return ssa.EncodePPC64RotateMask(r, int64(mask_out), 32)
    43  }
    44  
    45  // Combine (ANDconst [m] (SLDconst [s])) into (RLWINM [y]) or return 0
    46  func mergePPC64AndSldi(m, s int64) int64 {
    47  	mask := -1 << s & m
    48  
    49  	// Verify the rotate and mask result only uses the lower 32 bits.
    50  	rv := bits.RotateLeft64(0xFFFFFFFF00000000, int(s))
    51  	if rv&uint64(mask) != 0 {
    52  		return 0
    53  	}
    54  	if !isPPC64WordRotateMaskNonWrapping(mask) {
    55  		return 0
    56  	}
    57  	return ssa.EncodePPC64RotateMask(s&31, mask, 32)
    58  }
    59  
    60  // Combine (ANDconst [m] (SRDconst [s])) into (RLWINM [y]) or return 0
    61  func mergePPC64AndSrdi(m, s int64) int64 {
    62  	mask := ssa.MergePPC64RShiftMask(m, s, 64)
    63  
    64  	// Verify the rotate and mask result only uses the lower 32 bits.
    65  	rv := bits.RotateLeft64(0xFFFFFFFF00000000, -int(s))
    66  	if rv&uint64(mask) != 0 {
    67  		return 0
    68  	}
    69  	if !isPPC64WordRotateMaskNonWrapping(mask) {
    70  		return 0
    71  	}
    72  	return ssa.EncodePPC64RotateMask((32-s)&31, mask, 32)
    73  }
    74  
    75  // Test if a doubleword shift right feeding into a CLRLSLDI can be merged into RLWINM.
    76  // Return the encoded RLWINM constant, or 0 if they cannot be merged.
    77  func mergePPC64ClrlsldiSrd(sld, srd int64) int64 {
    78  	mask_1 := uint64(0xFFFFFFFFFFFFFFFF) >> uint(srd)
    79  	// for CLRLSLDI, it's more convenient to think of it as a mask left bits then rotate left.
    80  	mask_2 := uint64(0xFFFFFFFFFFFFFFFF) >> uint(ssa.GetPPC64Shiftmb(sld))
    81  
    82  	// Rewrite mask to apply after the final left shift.
    83  	mask_3 := (mask_1 & mask_2) << uint(ssa.GetPPC64Shiftsh(sld))
    84  
    85  	r_1 := 64 - srd
    86  	r_2 := ssa.GetPPC64Shiftsh(sld)
    87  	r_3 := (r_1 + r_2) & 63 // This can wrap.
    88  
    89  	if uint64(uint32(mask_3)) != mask_3 || mask_3 == 0 {
    90  		return 0
    91  	}
    92  	// This combine only works when selecting and shifting the lower 32 bits.
    93  	v1 := bits.RotateLeft64(0xFFFFFFFF00000000, int(r_3))
    94  	if v1&mask_3 != 0 {
    95  		return 0
    96  	}
    97  	return ssa.EncodePPC64RotateMask(r_3&31, int64(mask_3), 32)
    98  }
    99  
   100  // Test if RLWINM opcode rlw clears the upper 32 bits of the
   101  // result. Return rlw if it does, 0 otherwise.
   102  func mergePPC64MovwzregRlwinm(rlw int64) int64 {
   103  	_, mb, me, _ := ssa.DecodePPC64RotateMask(rlw)
   104  	if mb > me {
   105  		return 0
   106  	}
   107  	return rlw
   108  }
   109  
   110  // Test if AND feeding into an ANDconst can be merged. Return the encoded RLWINM constant,
   111  // or 0 if they cannot be merged.
   112  func mergePPC64RlwinmAnd(rlw int64, mask uint32) int64 {
   113  	r, _, _, mask_rlw := ssa.DecodePPC64RotateMask(rlw)
   114  
   115  	// Rotate the input mask, combine with the rlwnm mask, and test if it is still a valid rlwinm mask.
   116  	r_mask := bits.RotateLeft32(mask, int(r))
   117  
   118  	mask_out := (mask_rlw & uint64(r_mask))
   119  
   120  	// Verify the result is still a valid bitmask of <= 32 bits.
   121  	if !ssa.IsPPC64WordRotateMask(int64(mask_out)) {
   122  		return 0
   123  	}
   124  	return ssa.EncodePPC64RotateMask(r, int64(mask_out), 32)
   125  }
   126  
   127  // Test if RLWINM feeding into SRDconst can be merged. Return the encoded RLIWNM constant,
   128  // or 0 if they cannot be merged.
   129  func mergePPC64SldiRlwinm(sldi, rlw int64) int64 {
   130  	r_1, mb, me, mask_1 := ssa.DecodePPC64RotateMask(rlw)
   131  	if mb > me || mb < sldi {
   132  		// Wrapping masks cannot be merged as the upper 32 bits are effectively undefined in this case.
   133  		// Likewise, if mb is less than the shift amount, it cannot be merged.
   134  		return 0
   135  	}
   136  	// combine the masks, and adjust for the final left shift.
   137  	mask_3 := mask_1 << sldi
   138  	r_3 := (r_1 + sldi) & 31 // This can wrap.
   139  
   140  	// Verify the result is still a valid bitmask of <= 32 bits.
   141  	if uint64(uint32(mask_3)) != mask_3 {
   142  		return 0
   143  	}
   144  	return ssa.EncodePPC64RotateMask(r_3, int64(mask_3), 32)
   145  }
   146  
   147  // Convenience function to rotate a 32 bit constant value by another constant.
   148  func rotateLeft32(v, rotate int64) int64 {
   149  	return int64(bits.RotateLeft32(uint32(v), int(rotate)))
   150  }
   151  

View as plain text