Source file src/cmd/compile/internal/ssa/rewrite/generic/generic_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 generic
     6  
     7  import (
     8  	"fmt"
     9  	"math"
    10  	"math/bits"
    11  	"strings"
    12  
    13  	"cmd/compile/internal/base"
    14  	"cmd/compile/internal/ir"
    15  	"cmd/compile/internal/reflectdata"
    16  	"cmd/compile/internal/rttype"
    17  	"cmd/compile/internal/ssa"
    18  	"cmd/compile/internal/ssa/ssaop"
    19  	"cmd/compile/internal/typecheck"
    20  	"cmd/compile/internal/types"
    21  	"cmd/internal/obj"
    22  	"cmd/internal/objabi"
    23  )
    24  
    25  func addToSub(op ssaop.Op) ssaop.Op {
    26  	switch op {
    27  	case ssaop.OpAdd64:
    28  		return ssaop.OpSub64
    29  	case ssaop.OpAdd32:
    30  		return ssaop.OpSub32
    31  	case ssaop.OpAdd16:
    32  		return ssaop.OpSub16
    33  	case ssaop.OpAdd8:
    34  		return ssaop.OpSub8
    35  	default:
    36  		panic(fmt.Sprintf("unexpected op %v", op))
    37  	}
    38  }
    39  
    40  func bitsAdd64(x, y, carry int64) (r struct{ sum, carry int64 }) {
    41  	s, c := bits.Add64(uint64(x), uint64(y), uint64(carry))
    42  	r.sum, r.carry = int64(s), int64(c)
    43  	return
    44  }
    45  
    46  func bitsMulU32(x, y int32) (r struct{ hi, lo int32 }) {
    47  	hi, lo := bits.Mul32(uint32(x), uint32(y))
    48  	r.hi, r.lo = int32(hi), int32(lo)
    49  	return
    50  }
    51  
    52  func bitsMulU64(x, y int64) (r struct{ hi, lo int64 }) {
    53  	hi, lo := bits.Mul64(uint64(x), uint64(y))
    54  	r.hi, r.lo = int64(hi), int64(lo)
    55  	return
    56  }
    57  
    58  func bitsDiv128u(hi, lo, y int64) (r struct{ quo, rem int64 }) {
    59  	q, rem := bits.Div64(uint64(hi), uint64(lo), uint64(y))
    60  	r.quo, r.rem = int64(q), int64(rem)
    61  	return
    62  }
    63  
    64  // bool2int converts bool to int: true to 1, false to 0
    65  func bool2int(x bool) int {
    66  	var b int
    67  	if x {
    68  		b = 1
    69  	}
    70  	return b
    71  }
    72  
    73  // canLoadUnaligned reports if the architecture supports unaligned load operations.
    74  func canLoadUnaligned(c *ssa.Config) bool {
    75  	return c.Ctxt.Arch.Alignment == 1
    76  }
    77  
    78  // canRotate reports whether the architecture supports
    79  // rotates of integer registers with the given number of bits.
    80  func canRotate(c *ssa.Config, bits int64) bool {
    81  	if bits > c.PtrSize*8 {
    82  		// Don't rewrite to rotates bigger than the machine word.
    83  		return false
    84  	}
    85  	switch c.Arch {
    86  	case "386", "amd64", "arm64", "loong64", "riscv64":
    87  		return true
    88  	case "arm", "s390x", "ppc64", "ppc64le", "wasm":
    89  		return bits >= 32
    90  	default:
    91  		return false
    92  	}
    93  }
    94  
    95  func copyCompatibleType(t1, t2 *types.Type) bool {
    96  	if t1.Size() != t2.Size() {
    97  		return false
    98  	}
    99  	if t1.IsInteger() {
   100  		return t2.IsInteger()
   101  	}
   102  	if ssa.IsPtr(t1) {
   103  		return ssa.IsPtr(t2)
   104  	}
   105  	return t1.Compare(t2) == types.CMPeq
   106  }
   107  
   108  func devirtLECall(v *ssa.Value, sym *obj.LSym) *ssa.Value {
   109  	v.Op = ssaop.OpStaticLECall
   110  	auxcall := v.Aux.(*ssa.AuxCall)
   111  	auxcall.Fn = sym
   112  	// Remove first arg
   113  	v.Args[0].Uses--
   114  	copy(v.Args[0:], v.Args[1:])
   115  	v.Args[len(v.Args)-1] = nil // aid GC
   116  	v.Args = v.Args[:len(v.Args)-1]
   117  	if f := v.Block.Func; f.Pass.Debug > 0 {
   118  		f.Warnl(v.Pos, "de-virtualizing call")
   119  	}
   120  	return v
   121  }
   122  
   123  // hasSmallRotate reports whether the architecture has rotate instructions
   124  // for sizes < 32-bit.  This is used to decide whether to promote some rotations.
   125  func hasSmallRotate(c *ssa.Config) bool {
   126  	switch c.Arch {
   127  	case "amd64", "386":
   128  		return true
   129  	default:
   130  		return false
   131  	}
   132  }
   133  
   134  func invertibleBool(op ssaop.Op) bool {
   135  	switch op {
   136  	case ssaop.OpLess64, ssaop.OpLess32, ssaop.OpLess16, ssaop.OpLess8,
   137  		ssaop.OpLeq64, ssaop.OpLeq32, ssaop.OpLeq16, ssaop.OpLeq8,
   138  		ssaop.OpLess64U, ssaop.OpLess32U, ssaop.OpLess16U, ssaop.OpLess8U,
   139  		ssaop.OpLeq64U, ssaop.OpLeq32U, ssaop.OpLeq16U, ssaop.OpLeq8U,
   140  		ssaop.OpEq64, ssaop.OpEq32, ssaop.OpEq16, ssaop.OpEq8,
   141  		ssaop.OpNeq64, ssaop.OpNeq32, ssaop.OpNeq16, ssaop.OpNeq8,
   142  		ssaop.OpNot:
   143  		return true
   144  	default:
   145  		return false
   146  	}
   147  }
   148  
   149  func isDictArgSym(sym ssa.Sym) bool {
   150  	return sym.(*ir.Name).Sym().Name == typecheck.LocalDictName
   151  }
   152  
   153  // isDirectAndComparableIface reports whether v represents an itab
   154  // (a *runtime._itab) for a type whose value is stored directly
   155  // in an interface (i.e., is pointer or pointer-like) and is comparable.
   156  func isDirectAndComparableIface(v *ssa.Value) bool {
   157  	return isDirectAndComparableIface1(v, 9)
   158  }
   159  
   160  // v is an itab
   161  func isDirectAndComparableIface1(v *ssa.Value, depth int) bool {
   162  	if depth == 0 {
   163  		return false
   164  	}
   165  	switch v.Op {
   166  	case ssaop.OpITab:
   167  		return isDirectAndComparableIface2(v.Args[0], depth-1)
   168  	case ssaop.OpAddr:
   169  		lsym := v.Aux.(*obj.LSym)
   170  		if ii := lsym.ItabInfo(); ii != nil {
   171  			t := ii.Type.(*types.Type)
   172  			return types.IsDirectIface(t) && types.IsComparable(t)
   173  		}
   174  	case ssaop.OpConstNil:
   175  		// We can treat this as direct, because if the itab is
   176  		// nil, the data field must be nil also.
   177  		return true
   178  	}
   179  	return false
   180  }
   181  
   182  // v is an interface
   183  func isDirectAndComparableIface2(v *ssa.Value, depth int) bool {
   184  	if depth == 0 {
   185  		return false
   186  	}
   187  	switch v.Op {
   188  	case ssaop.OpIMake:
   189  		return isDirectAndComparableIface1(v.Args[0], depth-1)
   190  	case ssaop.OpPhi:
   191  		for _, a := range v.Args {
   192  			if !isDirectAndComparableIface2(a, depth-1) {
   193  				return false
   194  			}
   195  		}
   196  		return true
   197  	}
   198  	return false
   199  }
   200  
   201  // isDirectAndComparableType reports whether v represents a type
   202  // (a *runtime._type) whose value is stored directly in an
   203  // interface (i.e., is pointer or pointer-like) and is comparable.
   204  func isDirectAndComparableType(v *ssa.Value) bool {
   205  	return isDirectAndComparableType1(v)
   206  }
   207  
   208  // v is a type
   209  func isDirectAndComparableType1(v *ssa.Value) bool {
   210  	switch v.Op {
   211  	case ssaop.OpITab:
   212  		return isDirectAndComparableType2(v.Args[0])
   213  	case ssaop.OpAddr:
   214  		lsym := v.Aux.(*obj.LSym)
   215  		if ti := lsym.TypeInfo(); ti != nil {
   216  			t := ti.Type.(*types.Type)
   217  			return types.IsDirectIface(t) && types.IsComparable(t)
   218  		}
   219  	}
   220  	return false
   221  }
   222  
   223  // v is an empty interface
   224  func isDirectAndComparableType2(v *ssa.Value) bool {
   225  	switch v.Op {
   226  	case ssaop.OpIMake:
   227  		return isDirectAndComparableType1(v.Args[0])
   228  	}
   229  	return false
   230  }
   231  
   232  // isFixedLoad returns true if the load can be resolved to fixed address or constant,
   233  // and can be rewritten by rewriteFixedLoad.
   234  func isFixedLoad(v *ssa.Value, sym ssa.Sym, off int64) bool {
   235  	lsym := sym.(*obj.LSym)
   236  	if (v.Type.IsPtrShaped() || v.Type.IsUintptr()) && lsym.Type == objabi.SRODATA {
   237  		for _, r := range lsym.R {
   238  			if (r.Type == objabi.R_ADDR || r.Type == objabi.R_WEAKADDR) && int64(r.Off) == off && r.Add == 0 {
   239  				return true
   240  			}
   241  		}
   242  		return false
   243  	}
   244  
   245  	if ti := lsym.TypeInfo(); ti != nil {
   246  		// Type symbols do not contain information about their fields, unlike the cases above.
   247  		// Hand-implement field accesses.
   248  		// TODO: can this be replaced with reflectdata.writeType and just use the code above?
   249  
   250  		t := ti.Type.(*types.Type)
   251  
   252  		for _, f := range rttype.Type.Fields() {
   253  			if f.Offset == off && copyCompatibleType(v.Type, f.Type) {
   254  				switch f.Sym.Name {
   255  				case "Size_", "PtrBytes", "Hash", "Kind_", "GCData":
   256  					return true
   257  				case "TFlag":
   258  					// A noalg descriptor can be replaced by one with
   259  					// algorithms, changing TFlagRegularMemory.
   260  					return t.TFlagComputed() && !types.TypeHasNoAlg(t)
   261  				default:
   262  					// fmt.Println("unknown field", f.Sym.Name)
   263  					return false
   264  				}
   265  			}
   266  		}
   267  
   268  		if t.IsPtr() && off == rttype.PtrType.OffsetOf("Elem") {
   269  			return true
   270  		}
   271  
   272  		return false
   273  	}
   274  
   275  	return false
   276  }
   277  
   278  func isInlinableMemclr(c *ssa.Config, sz int64) bool {
   279  	if sz < 0 {
   280  		return false
   281  	}
   282  	// TODO: expand this check to allow other architectures
   283  	// see CL 454255 and issue 56997
   284  	switch c.Arch {
   285  	case "amd64", "arm64":
   286  		return true
   287  	case "ppc64le", "ppc64", "loong64":
   288  		return sz < 512
   289  	}
   290  	return false
   291  }
   292  
   293  func isMalloc(aux ssa.Aux) bool {
   294  	return ssa.IsNewObjectCall(aux) || ssa.IsSpecializedMalloc(aux)
   295  }
   296  
   297  // isNonNegative reports whether v is known to be greater or equal to zero.
   298  // Note that this is pretty simplistic. The prove pass generates more detailed
   299  // nonnegative information about values.
   300  func isNonNegative(v *ssa.Value) bool {
   301  	if !v.Type.IsInteger() {
   302  		v.Fatalf("isNonNegative bad type: %v", v.Type)
   303  	}
   304  	// TODO: return true if !v.Type.IsSigned()
   305  	// SSA isn't type-safe enough to do that now (issue 37753).
   306  	// The checks below depend only on the pattern of bits.
   307  
   308  	switch v.Op {
   309  	case ssaop.OpConst64:
   310  		return v.AuxInt >= 0
   311  
   312  	case ssaop.OpConst32:
   313  		return int32(v.AuxInt) >= 0
   314  
   315  	case ssaop.OpConst16:
   316  		return int16(v.AuxInt) >= 0
   317  
   318  	case ssaop.OpConst8:
   319  		return int8(v.AuxInt) >= 0
   320  
   321  	case ssaop.OpStringLen, ssaop.OpSliceLen, ssaop.OpSliceCap,
   322  		ssaop.OpZeroExt8to64, ssaop.OpZeroExt16to64, ssaop.OpZeroExt32to64,
   323  		ssaop.OpZeroExt8to32, ssaop.OpZeroExt16to32, ssaop.OpZeroExt8to16,
   324  		ssaop.OpCtz64, ssaop.OpCtz32, ssaop.OpCtz16, ssaop.OpCtz8,
   325  		ssaop.OpCtz64NonZero, ssaop.OpCtz32NonZero, ssaop.OpCtz16NonZero, ssaop.OpCtz8NonZero,
   326  		ssaop.OpBitLen64, ssaop.OpBitLen32, ssaop.OpBitLen16, ssaop.OpBitLen8:
   327  		return true
   328  
   329  	case ssaop.OpRsh64Ux64, ssaop.OpRsh32Ux64:
   330  		by := v.Args[1]
   331  		return by.Op == ssaop.OpConst64 && by.AuxInt > 0
   332  
   333  	case ssaop.OpRsh64x64, ssaop.OpRsh32x64, ssaop.OpRsh8x64, ssaop.OpRsh16x64, ssaop.OpRsh32x32, ssaop.OpRsh64x32,
   334  		ssaop.OpSignExt32to64, ssaop.OpSignExt16to64, ssaop.OpSignExt8to64, ssaop.OpSignExt16to32, ssaop.OpSignExt8to32:
   335  		return isNonNegative(v.Args[0])
   336  
   337  	case ssaop.OpAnd64, ssaop.OpAnd32, ssaop.OpAnd16, ssaop.OpAnd8:
   338  		return isNonNegative(v.Args[0]) || isNonNegative(v.Args[1])
   339  
   340  	case ssaop.OpMod64, ssaop.OpMod32, ssaop.OpMod16, ssaop.OpMod8,
   341  		ssaop.OpDiv64, ssaop.OpDiv32, ssaop.OpDiv16, ssaop.OpDiv8,
   342  		ssaop.OpOr64, ssaop.OpOr32, ssaop.OpOr16, ssaop.OpOr8,
   343  		ssaop.OpXor64, ssaop.OpXor32, ssaop.OpXor16, ssaop.OpXor8:
   344  		return isNonNegative(v.Args[0]) && isNonNegative(v.Args[1])
   345  
   346  		// We could handle OpPhi here, but the improvements from doing
   347  		// so are very minor, and it is neither simple nor cheap.
   348  	}
   349  	return false
   350  }
   351  
   352  func isStackPtr(v *ssa.Value) bool {
   353  	for v.Op == ssaop.OpOffPtr || v.Op == ssaop.OpAddPtr {
   354  		v = v.Args[0]
   355  	}
   356  	return v.Op == ssaop.OpSP || v.Op == ssaop.OpLocalAddr
   357  }
   358  
   359  // needRaceCleanup reports whether this call to racefuncenter/exit isn't needed.
   360  func needRaceCleanup(sym *ssa.AuxCall, v *ssa.Value) bool {
   361  	f := v.Block.Func
   362  	if !f.Config.Race {
   363  		return false
   364  	}
   365  	if !ssa.IsSameCall(sym, "runtime.racefuncenter") && !ssa.IsSameCall(sym, "runtime.racefuncexit") {
   366  		return false
   367  	}
   368  	for _, b := range f.Blocks {
   369  		for _, v := range b.Values {
   370  			switch v.Op {
   371  			case ssaop.OpStaticCall, ssaop.OpStaticLECall:
   372  				// Check for racefuncenter will encounter racefuncexit and vice versa.
   373  				// Allow calls to panic*
   374  				s := v.Aux.(*ssa.AuxCall).Fn.String()
   375  				switch s {
   376  				case "runtime.racefuncenter", "runtime.racefuncexit",
   377  					"runtime.panicdivide", "runtime.panicwrap",
   378  					"runtime.panicshift":
   379  					continue
   380  				}
   381  				// If we encountered any call, we need to keep racefunc*,
   382  				// for accurate stacktraces.
   383  				return false
   384  			case ssaop.OpPanicBounds, ssaop.OpPanicExtend:
   385  				// Note: these are panic generators that are ok (like the static calls above).
   386  			case ssaop.OpClosureCall, ssaop.OpInterCall, ssaop.OpClosureLECall, ssaop.OpInterLECall:
   387  				// We must keep the race functions if there are any other call types.
   388  				return false
   389  			}
   390  		}
   391  	}
   392  	if ssa.IsSameCall(sym, "runtime.racefuncenter") {
   393  		// TODO REGISTER ABI this needs to be cleaned up.
   394  		// If we're removing racefuncenter, remove its argument as well.
   395  		if v.Args[0].Op != ssaop.OpStore {
   396  			if v.Op == ssaop.OpStaticLECall {
   397  				// there is no store, yet.
   398  				return true
   399  			}
   400  			return false
   401  		}
   402  		mem := v.Args[0].Args[2]
   403  		v.Args[0].Reset(ssaop.OpCopy)
   404  		v.Args[0].AddArg(mem)
   405  	}
   406  	return true
   407  }
   408  
   409  func nlz16(x int16) int { return bits.LeadingZeros16(uint16(x)) }
   410  
   411  func nlz32(x int32) int { return bits.LeadingZeros32(uint32(x)) }
   412  
   413  // nlzX returns the number of leading zeros.
   414  func nlz64(x int64) int { return bits.LeadingZeros64(uint64(x)) }
   415  
   416  func nlz8(x int8) int { return bits.LeadingZeros8(uint8(x)) }
   417  
   418  func ntz16(x int16) int { return bits.TrailingZeros16(uint16(x)) }
   419  
   420  func ntz32(x int32) int { return bits.TrailingZeros32(uint32(x)) }
   421  
   422  func ntz8(x int8) int { return bits.TrailingZeros8(uint8(x)) }
   423  
   424  // reciprocalExact32 reports whether 1/c is exactly representable.
   425  func reciprocalExact32(c float32) bool {
   426  	b := math.Float32bits(c)
   427  	man := b & (1<<23 - 1)
   428  	if man != 0 {
   429  		return false // not a power of 2, denormal, or NaN
   430  	}
   431  	exp := b >> 23 & (1<<8 - 1)
   432  	// exponent bias is 0x7f.  So taking the reciprocal of a number
   433  	// changes the exponent to 0xfe-exp.
   434  	switch exp {
   435  	case 0:
   436  		return false // ±0
   437  	case 0xff:
   438  		return false // ±inf
   439  	case 0xfe:
   440  		return false // exponent is not representable
   441  	default:
   442  		return true
   443  	}
   444  }
   445  
   446  // reciprocalExact64 reports whether 1/c is exactly representable.
   447  func reciprocalExact64(c float64) bool {
   448  	b := math.Float64bits(c)
   449  	man := b & (1<<52 - 1)
   450  	if man != 0 {
   451  		return false // not a power of 2, denormal, or NaN
   452  	}
   453  	exp := b >> 52 & (1<<11 - 1)
   454  	// exponent bias is 0x3ff.  So taking the reciprocal of a number
   455  	// changes the exponent to 0x7fe-exp.
   456  	switch exp {
   457  	case 0:
   458  		return false // ±0
   459  	case 0x7ff:
   460  		return false // ±inf
   461  	case 0x7fe:
   462  		return false // exponent is not representable
   463  	default:
   464  		return true
   465  	}
   466  }
   467  
   468  // registerizable reports whether t is a primitive type that fits in
   469  // a register. It assumes float64 values will always fit into registers
   470  // even if that isn't strictly true.
   471  func registerizable(b *ssa.Block, typ *types.Type) bool {
   472  	if typ.IsPtrShaped() || typ.IsFloat() || typ.IsBoolean() {
   473  		return true
   474  	}
   475  	if typ.IsInteger() {
   476  		return typ.Size() <= b.Func.Config.RegSize
   477  	}
   478  	return false
   479  }
   480  
   481  // resetCopy resets v to be a copy of arg.
   482  // Always returns true.
   483  func resetCopy(v *ssa.Value, arg *ssa.Value) bool {
   484  	v.Reset(ssaop.OpCopy)
   485  	v.AddArg(arg)
   486  	return true
   487  }
   488  
   489  // rewriteCondSelectIntoMath reports whether x OP (y * constant) should be used instead of a CondSelect.
   490  // x arbitrary, y in [0,1]
   491  func rewriteCondSelectIntoMath(config *ssa.Config, op ssaop.Op, constant int64) bool {
   492  	// at worst this becomes a left shift by a constant which has asymmetric latency (1:3 vs 2:2)
   493  	// but performs better in accumulation chains.
   494  	// Various arches do strictly superior for specific cases, but this is a good general default.
   495  	// FIXME: optimize more constants in arches where this is possible.
   496  	switch config.Arch {
   497  	case "arm64":
   498  		switch op {
   499  		case ssaop.OpAdd64, ssaop.OpAdd32, ssaop.OpAdd16, ssaop.OpAdd8:
   500  			if constant == 1 {
   501  				return false // better done as CSINC
   502  			}
   503  			fallthrough
   504  		default:
   505  			// add sub or xor & and are implemented using inline LSL
   506  			// the rest becomes the default LSL
   507  			return ssa.IsPowerOfTwo(uint64(constant))
   508  		}
   509  	default:
   510  		return ssa.IsPowerOfTwo(uint64(constant))
   511  	}
   512  }
   513  
   514  // rewriteFixedLoad rewrites a load to a fixed address or constant, if isFixedLoad returns true.
   515  func rewriteFixedLoad(v *ssa.Value, sym ssa.Sym, sb *ssa.Value, off int64) *ssa.Value {
   516  	b := v.Block
   517  	f := b.Func
   518  
   519  	lsym := sym.(*obj.LSym)
   520  	if (v.Type.IsPtrShaped() || v.Type.IsUintptr()) && lsym.Type == objabi.SRODATA {
   521  		for _, r := range lsym.R {
   522  			if (r.Type == objabi.R_ADDR || r.Type == objabi.R_WEAKADDR) && int64(r.Off) == off && r.Add == 0 {
   523  				if r.Sym.IsGoType() {
   524  					// In case we're loading a type out of a dictionary, we need to record
   525  					// that the containing function might put that type in an interface.
   526  					// That information is currently recorded in relocations in the dictionary,
   527  					// but if we perform this load at compile time then the dictionary
   528  					// might be dead.
   529  					reflectdata.MarkTypeSymUsedInInterface(r.Sym, f.Fe.Func().Linksym())
   530  				} else if strings.HasPrefix(r.Sym.Name, "go:itab") {
   531  					// Same, but if we're using an itab we need to record that the
   532  					// itab._type might be put in an interface.
   533  					reflectdata.MarkTypeSymUsedInInterface(r.Sym, f.Fe.Func().Linksym())
   534  				}
   535  				v.Reset(ssaop.OpAddr)
   536  				v.Aux = ssa.SymToAux(r.Sym)
   537  				v.AddArg(sb)
   538  				return v
   539  			}
   540  		}
   541  		base.Fatalf("fixedLoad data not known for %s:%d", sym, off)
   542  	}
   543  
   544  	if ti := lsym.TypeInfo(); ti != nil {
   545  		// Type symbols do not contain information about their fields, unlike the cases above.
   546  		// Hand-implement field accesses.
   547  		// TODO: can this be replaced with reflectdata.writeType and just use the code above?
   548  
   549  		t := ti.Type.(*types.Type)
   550  
   551  		ptrSizedOpConst := ssaop.OpConst64
   552  		if f.Config.PtrSize == 4 {
   553  			ptrSizedOpConst = ssaop.OpConst32
   554  		}
   555  
   556  		for _, f := range rttype.Type.Fields() {
   557  			if f.Offset == off && copyCompatibleType(v.Type, f.Type) {
   558  				switch f.Sym.Name {
   559  				case "Size_":
   560  					v.Reset(ptrSizedOpConst)
   561  					v.AuxInt = t.Size()
   562  					return v
   563  				case "PtrBytes":
   564  					v.Reset(ptrSizedOpConst)
   565  					v.AuxInt = types.PtrDataSize(t)
   566  					return v
   567  				case "Hash":
   568  					v.Reset(ssaop.OpConst32)
   569  					v.AuxInt = int64(int32(types.TypeHash(t)))
   570  					return v
   571  				case "TFlag":
   572  					v.Reset(ssaop.OpConst8)
   573  					v.AuxInt = int64(t.TFlag())
   574  					return v
   575  				case "Kind_":
   576  					v.Reset(ssaop.OpConst8)
   577  					v.AuxInt = int64(int8(reflectdata.ABIKindOfType(t)))
   578  					return v
   579  				case "GCData":
   580  					gcdata, _ := reflectdata.GCSym(t, true)
   581  					v.Reset(ssaop.OpAddr)
   582  					v.Aux = ssa.SymToAux(gcdata)
   583  					v.AddArg(sb)
   584  					return v
   585  				default:
   586  					base.Fatalf("unknown field %s for fixedLoad of %s at offset %d", f.Sym.Name, lsym.Name, off)
   587  				}
   588  			}
   589  		}
   590  
   591  		if t.IsPtr() && off == rttype.PtrType.OffsetOf("Elem") {
   592  			elemSym := reflectdata.TypeLinksym(t.Elem())
   593  			reflectdata.MarkTypeSymUsedInInterface(elemSym, f.Fe.Func().Linksym())
   594  			v.Reset(ssaop.OpAddr)
   595  			v.Aux = ssa.SymToAux(elemSym)
   596  			v.AddArg(sb)
   597  			return v
   598  		}
   599  
   600  		base.Fatalf("fixedLoad data not known for %s:%d", sym, off)
   601  	}
   602  
   603  	base.Fatalf("fixedLoad data not known for %s:%d", sym, off)
   604  	return nil
   605  }
   606  
   607  func rewriteStructLoad(v *ssa.Value) *ssa.Value {
   608  	b := v.Block
   609  	ptr := v.Args[0]
   610  	mem := v.Args[1]
   611  
   612  	t := v.Type
   613  	args := make([]*ssa.Value, t.NumFields())
   614  	for i := range args {
   615  		ft := t.FieldType(i)
   616  		addr := b.NewValue1I(v.Pos, ssaop.OpOffPtr, ft.PtrTo(), t.FieldOff(i), ptr)
   617  		args[i] = b.NewValue2(v.Pos, ssaop.OpLoad, ft, addr, mem)
   618  	}
   619  
   620  	v.Reset(ssaop.OpStructMake)
   621  	v.AddArgs(args...)
   622  	return v
   623  }
   624  
   625  // symIsROZero reports whether sym is a read-only global whose data contains all zeros.
   626  func symIsROZero(sym ssa.Sym) bool {
   627  	lsym := sym.(*obj.LSym)
   628  	if lsym.Type != objabi.SRODATA || len(lsym.R) != 0 {
   629  		return false
   630  	}
   631  	for _, b := range lsym.P {
   632  		if b != 0 {
   633  			return false
   634  		}
   635  	}
   636  	return true
   637  }
   638  
   639  // uaddOvf reports whether unsigned a+b would overflow.
   640  func uaddOvf(a, b int64) bool {
   641  	return uint64(a)+uint64(b) < uint64(a)
   642  }
   643  
   644  // warnRule generates compiler debug output with string s when
   645  // v is not in autogenerated code, cond is true and the rule has fired.
   646  func warnRule(cond bool, v *ssa.Value, s string) bool {
   647  	if pos := v.Pos; pos.Line() > 1 && cond {
   648  		v.Block.Func.Warnl(pos, s)
   649  	}
   650  	return true
   651  }
   652  
   653  func bitsSub64(x, y, borrow int64) (r struct{ diff, borrow int64 }) {
   654  	d, b := bits.Sub64(uint64(x), uint64(y), uint64(borrow))
   655  	r.diff, r.borrow = int64(d), int64(b)
   656  	return
   657  }
   658  
   659  func modularMultiplicativeInverse(x uint64) (y uint64) {
   660  	if x%2 != 1 {
   661  		panic("even numbers in a power-of-two modulus do not have a multiplicative inverse")
   662  	}
   663  	// we start with 3 bits of precision because each odd number is its own multiplicative inverse mod 8
   664  	y = x // 3 bits
   665  
   666  	// now use the Newton-Raphson method to double the number of correct bits in each iteration.
   667  	y *= 2 - x*y // 6 bits
   668  	y *= 2 - x*y // 12 bits
   669  	y *= 2 - x*y // 24 bits
   670  	y *= 2 - x*y // 48 bits
   671  	y *= 2 - x*y // 96 bits; good enough
   672  	return
   673  }
   674  

View as plain text