| // run | 
 |  | 
 | // Copyright 2019 The Go Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style | 
 | // license that can be found in the LICENSE file. | 
 |  | 
 | // Issue 30977: write barrier call clobbers volatile | 
 | // value when there are multiple uses of the value. | 
 |  | 
 | package main | 
 |  | 
 | import "runtime" | 
 |  | 
 | type T struct { | 
 | 	a, b, c, d, e string | 
 | } | 
 |  | 
 | //go:noinline | 
 | func g() T { | 
 | 	return T{"a", "b", "c", "d", "e"} | 
 | } | 
 |  | 
 | //go:noinline | 
 | func f() { | 
 | 	// The compiler optimizes this to direct copying | 
 | 	// the call result to both globals, with write | 
 | 	// barriers. The first write barrier call clobbers | 
 | 	// the result of g on stack. | 
 | 	X = g() | 
 | 	Y = X | 
 | } | 
 |  | 
 | var X, Y T | 
 |  | 
 | const N = 1000 | 
 |  | 
 | func main() { | 
 | 	// Keep GC running so the write barrier is on. | 
 | 	go func() { | 
 | 		for { | 
 | 			runtime.GC() | 
 | 		} | 
 | 	}() | 
 |  | 
 | 	for i := 0; i < N; i++ { | 
 | 		runtime.Gosched() | 
 | 		f() | 
 | 		if X != Y { | 
 | 			panic("FAIL") | 
 | 		} | 
 | 	} | 
 | } |