diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go index 702b1d1cc5..a7fd704b85 100644 --- a/src/cmd/compile/internal/inline/inl.go +++ b/src/cmd/compile/internal/inline/inl.go @@ -381,6 +381,15 @@ func (v *hairyVisitor) doNode(n ir.Node) bool { case ir.OAPPEND: v.budget -= inlineExtraAppendCost + case ir.OADDR: + n := n.(*ir.AddrExpr) + // Make "&s.f" cost 0 when f's offset is zero. + if dot, ok := n.X.(*ir.SelectorExpr); ok && (dot.Op() == ir.ODOT || dot.Op() == ir.ODOTPTR) { + if _, ok := dot.X.(*ir.Name); ok && dot.Selection.Offset == 0 { + v.budget += 2 // undo ir.OADDR+ir.ODOT/ir.ODOTPTR + } + } + case ir.ODEREF: // *(*X)(unsafe.Pointer(&x)) is low-cost n := n.(*ir.StarExpr) diff --git a/src/sync/atomic/type.go b/src/sync/atomic/type.go index be11e6109e..87c98b1e77 100644 --- a/src/sync/atomic/type.go +++ b/src/sync/atomic/type.go @@ -14,19 +14,17 @@ type Bool struct { } // Load atomically loads and returns the value stored in x. -func (x *Bool) Load() bool { return LoadUint32((*uint32)(unsafe.Pointer(x))) != 0 } +func (x *Bool) Load() bool { return LoadUint32(&x.v) != 0 } // Store atomically stores val into x. -func (x *Bool) Store(val bool) { StoreUint32((*uint32)(unsafe.Pointer(x)), b32(val)) } +func (x *Bool) Store(val bool) { StoreUint32(&x.v, b32(val)) } // Swap atomically stores new into x and returns the previous value. -func (x *Bool) Swap(new bool) (old bool) { - return SwapUint32((*uint32)(unsafe.Pointer(x)), b32(new)) != 0 -} +func (x *Bool) Swap(new bool) (old bool) { return SwapUint32(&x.v, b32(new)) != 0 } // CompareAndSwap executes the compare-and-swap operation for the boolean value x. func (x *Bool) CompareAndSwap(old, new bool) (swapped bool) { - return CompareAndSwapUint32((*uint32)(unsafe.Pointer(x)), b32(old), b32(new)) + return CompareAndSwapUint32(&x.v, b32(old), b32(new)) } // b32 returns a uint32 0 or 1 representing b. @@ -48,21 +46,17 @@ type Pointer[T any] struct { } // Load atomically loads and returns the value stored in x. -func (x *Pointer[T]) Load() *T { return (*T)(LoadPointer((*unsafe.Pointer)(unsafe.Pointer(x)))) } +func (x *Pointer[T]) Load() *T { return (*T)(LoadPointer(&x.v)) } // Store atomically stores val into x. -func (x *Pointer[T]) Store(val *T) { - StorePointer((*unsafe.Pointer)(unsafe.Pointer(x)), unsafe.Pointer(val)) -} +func (x *Pointer[T]) Store(val *T) { StorePointer(&x.v, unsafe.Pointer(val)) } // Swap atomically stores new into x and returns the previous value. -func (x *Pointer[T]) Swap(new *T) (old *T) { - return (*T)(SwapPointer((*unsafe.Pointer)(unsafe.Pointer(x)), unsafe.Pointer(new))) -} +func (x *Pointer[T]) Swap(new *T) (old *T) { return (*T)(SwapPointer(&x.v, unsafe.Pointer(new))) } // CompareAndSwap executes the compare-and-swap operation for x. func (x *Pointer[T]) CompareAndSwap(old, new *T) (swapped bool) { - return CompareAndSwapPointer((*unsafe.Pointer)(unsafe.Pointer(x)), unsafe.Pointer(old), unsafe.Pointer(new)) + return CompareAndSwapPointer(&x.v, unsafe.Pointer(old), unsafe.Pointer(new)) } // An Int32 is an atomic int32. The zero value is zero. @@ -72,21 +66,21 @@ type Int32 struct { } // Load atomically loads and returns the value stored in x. -func (x *Int32) Load() int32 { return LoadInt32((*int32)(unsafe.Pointer(x))) } +func (x *Int32) Load() int32 { return LoadInt32(&x.v) } // Store atomically stores val into x. -func (x *Int32) Store(val int32) { StoreInt32((*int32)(unsafe.Pointer(x)), val) } +func (x *Int32) Store(val int32) { StoreInt32(&x.v, val) } // Swap atomically stores new into x and returns the previous value. -func (x *Int32) Swap(new int32) (old int32) { return SwapInt32((*int32)(unsafe.Pointer(x)), new) } +func (x *Int32) Swap(new int32) (old int32) { return SwapInt32(&x.v, new) } // CompareAndSwap executes the compare-and-swap operation for x. func (x *Int32) CompareAndSwap(old, new int32) (swapped bool) { - return CompareAndSwapInt32((*int32)(unsafe.Pointer(x)), old, new) + return CompareAndSwapInt32(&x.v, old, new) } // Add atomically adds delta to x and returns the new value. -func (x *Int32) Add(delta int32) (new int32) { return AddInt32((*int32)(unsafe.Pointer(x)), delta) } +func (x *Int32) Add(delta int32) (new int32) { return AddInt32(&x.v, delta) } // An Int64 is an atomic int64. The zero value is zero. type Int64 struct { @@ -96,21 +90,21 @@ type Int64 struct { } // Load atomically loads and returns the value stored in x. -func (x *Int64) Load() int64 { return LoadInt64((*int64)(unsafe.Pointer(x))) } +func (x *Int64) Load() int64 { return LoadInt64(&x.v) } // Store atomically stores val into x. -func (x *Int64) Store(val int64) { StoreInt64((*int64)(unsafe.Pointer(x)), val) } +func (x *Int64) Store(val int64) { StoreInt64(&x.v, val) } // Swap atomically stores new into x and returns the previous value. -func (x *Int64) Swap(new int64) (old int64) { return SwapInt64((*int64)(unsafe.Pointer(x)), new) } +func (x *Int64) Swap(new int64) (old int64) { return SwapInt64(&x.v, new) } // CompareAndSwap executes the compare-and-swap operation for x. func (x *Int64) CompareAndSwap(old, new int64) (swapped bool) { - return CompareAndSwapInt64((*int64)(unsafe.Pointer(x)), old, new) + return CompareAndSwapInt64(&x.v, old, new) } // Add atomically adds delta to x and returns the new value. -func (x *Int64) Add(delta int64) (new int64) { return AddInt64((*int64)(unsafe.Pointer(x)), delta) } +func (x *Int64) Add(delta int64) (new int64) { return AddInt64(&x.v, delta) } // An Uint32 is an atomic uint32. The zero value is zero. type Uint32 struct { @@ -119,23 +113,21 @@ type Uint32 struct { } // Load atomically loads and returns the value stored in x. -func (x *Uint32) Load() uint32 { return LoadUint32((*uint32)(unsafe.Pointer(x))) } +func (x *Uint32) Load() uint32 { return LoadUint32(&x.v) } // Store atomically stores val into x. -func (x *Uint32) Store(val uint32) { StoreUint32((*uint32)(unsafe.Pointer(x)), val) } +func (x *Uint32) Store(val uint32) { StoreUint32(&x.v, val) } // Swap atomically stores new into x and returns the previous value. -func (x *Uint32) Swap(new uint32) (old uint32) { return SwapUint32((*uint32)(unsafe.Pointer(x)), new) } +func (x *Uint32) Swap(new uint32) (old uint32) { return SwapUint32(&x.v, new) } // CompareAndSwap executes the compare-and-swap operation for x. func (x *Uint32) CompareAndSwap(old, new uint32) (swapped bool) { - return CompareAndSwapUint32((*uint32)(unsafe.Pointer(x)), old, new) + return CompareAndSwapUint32(&x.v, old, new) } // Add atomically adds delta to x and returns the new value. -func (x *Uint32) Add(delta uint32) (new uint32) { - return AddUint32((*uint32)(unsafe.Pointer(x)), delta) -} +func (x *Uint32) Add(delta uint32) (new uint32) { return AddUint32(&x.v, delta) } // An Uint64 is an atomic uint64. The zero value is zero. type Uint64 struct { @@ -145,23 +137,21 @@ type Uint64 struct { } // Load atomically loads and returns the value stored in x. -func (x *Uint64) Load() uint64 { return LoadUint64((*uint64)(unsafe.Pointer(x))) } +func (x *Uint64) Load() uint64 { return LoadUint64(&x.v) } // Store atomically stores val into x. -func (x *Uint64) Store(val uint64) { StoreUint64((*uint64)(unsafe.Pointer(x)), val) } +func (x *Uint64) Store(val uint64) { StoreUint64(&x.v, val) } // Swap atomically stores new into x and returns the previous value. -func (x *Uint64) Swap(new uint64) (old uint64) { return SwapUint64((*uint64)(unsafe.Pointer(x)), new) } +func (x *Uint64) Swap(new uint64) (old uint64) { return SwapUint64(&x.v, new) } // CompareAndSwap executes the compare-and-swap operation for x. func (x *Uint64) CompareAndSwap(old, new uint64) (swapped bool) { - return CompareAndSwapUint64((*uint64)(unsafe.Pointer(x)), old, new) + return CompareAndSwapUint64(&x.v, old, new) } // Add atomically adds delta to x and returns the new value. -func (x *Uint64) Add(delta uint64) (new uint64) { - return AddUint64((*uint64)(unsafe.Pointer(x)), delta) -} +func (x *Uint64) Add(delta uint64) (new uint64) { return AddUint64(&x.v, delta) } // An Uintptr is an atomic uintptr. The zero value is zero. type Uintptr struct { @@ -170,25 +160,21 @@ type Uintptr struct { } // Load atomically loads and returns the value stored in x. -func (x *Uintptr) Load() uintptr { return LoadUintptr((*uintptr)(unsafe.Pointer(x))) } +func (x *Uintptr) Load() uintptr { return LoadUintptr(&x.v) } // Store atomically stores val into x. -func (x *Uintptr) Store(val uintptr) { StoreUintptr((*uintptr)(unsafe.Pointer(x)), val) } +func (x *Uintptr) Store(val uintptr) { StoreUintptr(&x.v, val) } // Swap atomically stores new into x and returns the previous value. -func (x *Uintptr) Swap(new uintptr) (old uintptr) { - return SwapUintptr((*uintptr)(unsafe.Pointer(x)), new) -} +func (x *Uintptr) Swap(new uintptr) (old uintptr) { return SwapUintptr(&x.v, new) } // CompareAndSwap executes the compare-and-swap operation for x. func (x *Uintptr) CompareAndSwap(old, new uintptr) (swapped bool) { - return CompareAndSwapUintptr((*uintptr)(unsafe.Pointer(x)), old, new) + return CompareAndSwapUintptr(&x.v, old, new) } // Add atomically adds delta to x and returns the new value. -func (x *Uintptr) Add(delta uintptr) (new uintptr) { - return AddUintptr((*uintptr)(unsafe.Pointer(x)), delta) -} +func (x *Uintptr) Add(delta uintptr) (new uintptr) { return AddUintptr(&x.v, delta) } // noCopy may be added to structs which must not be copied // after the first use.