cmd/compile: mark block control instruction unsafe in "all unsafe" functions

Currently, for runtime functions and nosplit functions, it is
considered "all unsafe", meaning that the entire function body is
unsafe points. In the past, we didn't mark CALLs in such
functions unsafe, which is fixed in CL 230541. We also didn't
mark block control instructions (for mostly-empty blocks) unsafe.
This CL fixes it.

May fix #36110.

Change-Id: I3be8fdcef2b294e5367b31eb1c1b5e79966565fa
Reviewed-on: https://go-review.googlesource.com/c/go/+/236597
Reviewed-by: Austin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go
index e2de628..7e1c0c1 100644
--- a/src/cmd/compile/internal/gc/plive.go
+++ b/src/cmd/compile/internal/gc/plive.go
@@ -680,8 +680,9 @@
 	}
 }
 
-// markUnsafePoints finds unsafe points and computes lv.unsafePoints.
-func (lv *Liveness) markUnsafePoints() {
+// allUnsafe indicates that all points in this function are
+// unsafe-points.
+func allUnsafe(f *ssa.Func) bool {
 	// The runtime assumes the only safe-points are function
 	// prologues (because that's how it used to be). We could and
 	// should improve that, but for now keep consider all points
@@ -691,7 +692,12 @@
 	// go:nosplit functions are similar. Since safe points used to
 	// be coupled with stack checks, go:nosplit often actually
 	// means "no safe points in this function".
-	if compiling_runtime || lv.f.NoSplit {
+	return compiling_runtime || f.NoSplit
+}
+
+// markUnsafePoints finds unsafe points and computes lv.unsafePoints.
+func (lv *Liveness) markUnsafePoints() {
+	if allUnsafe(lv.f) {
 		// No complex analysis necessary.
 		lv.allUnsafe = true
 		return
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index c0902cd..d4d23a2 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -6010,8 +6010,8 @@
 		// for an empty block this will be used for its control
 		// instruction. We won't use the actual liveness map on a
 		// control instruction. Just mark it something that is
-		// preemptible.
-		s.pp.nextLive = LivenessIndex{-1, -1, false}
+		// preemptible, unless this function is "all unsafe".
+		s.pp.nextLive = LivenessIndex{-1, -1, allUnsafe(f)}
 
 		// Emit values in block
 		thearch.SSAMarkMoves(&s, b)