diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 728e78260cae459f6712cf821d671ddd269b2c73..8ccbec9dd6342c35ae7e7482721bfc715de60299 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -1465,10 +1465,7 @@ type Chain struct {
 	limit int // limit on entry to sym
 }
 
-var (
-	morestack *LSym
-	newstack  *LSym
-)
+var morestack *LSym
 
 // TODO: Record enough information in new object files to
 // allow stack checks here.
@@ -1488,7 +1485,6 @@ func dostkcheck() {
 	var ch Chain
 
 	morestack = Linklookup(Ctxt, "runtime.morestack", 0)
-	newstack = Linklookup(Ctxt, "runtime.newstack", 0)
 
 	// Every splitting function ensures that there are at least StackLimit
 	// bytes available below SP when the splitting prologue finishes.
@@ -1533,7 +1529,8 @@ func stkcheck(up *Chain, depth int) int {
 
 	// Don't duplicate work: only need to consider each
 	// function at top of safe zone once.
-	if limit == obj.StackLimit-callsize() {
+	top := limit == obj.StackLimit-callsize()
+	if top {
 		if s.Stkcheck != 0 {
 			return 0
 		}
@@ -1571,39 +1568,21 @@ func stkcheck(up *Chain, depth int) int {
 	var ch Chain
 	ch.up = up
 
-	// Check for a call to morestack anywhere and treat it
-	// as occurring at function entry.
-	// The decision about whether to call morestack occurs
-	// in the prolog, but the call site is near the end
-	// of the function on some architectures.
-	// This is needed because the stack check is flow-insensitive,
-	// so it incorrectly thinks the call to morestack happens wherever it shows up.
-	// This check will be wrong if there are any hand-inserted calls to morestack.
-	// There are not any now, nor should there ever be.
-	for _, r := range s.R {
-		if r.Sym == nil || !strings.HasPrefix(r.Sym.Name, "runtime.morestack") {
-			continue
-		}
-		// Ignore non-calls to morestack, such as the jump to morestack
-		// found in the implementation of morestack_noctxt.
-		switch r.Type {
-		default:
-			continue
-		case obj.R_CALL, obj.R_CALLARM, obj.R_CALLARM64, obj.R_CALLPOWER:
-		}
-
+	if s.Nosplit == 0 {
 		// Ensure we have enough stack to call morestack.
 		ch.limit = limit - callsize()
-		ch.sym = r.Sym
+		ch.sym = morestack
 		if stkcheck(&ch, depth+1) < 0 {
 			return -1
 		}
-		// Bump up the limit.
+		if !top {
+			return 0
+		}
+		// Raise limit to allow frame.
 		limit = int(obj.StackLimit + s.Locals)
 		if haslinkregister() {
 			limit += Thearch.Regsize
 		}
-		break // there can be only one
 	}
 
 	// Walk through sp adjustments in function, consuming relocs.
@@ -1628,11 +1607,6 @@ func stkcheck(up *Chain, depth int) int {
 			switch r.Type {
 			// Direct call.
 			case obj.R_CALL, obj.R_CALLARM, obj.R_CALLARM64, obj.R_CALLPOWER:
-				// We handled calls to morestack already.
-				if strings.HasPrefix(r.Sym.Name, "runtime.morestack") {
-					continue
-				}
-
 				ch.limit = int(int32(limit) - pcsp.value - int32(callsize()))
 				ch.sym = r.Sym
 				if stkcheck(&ch, depth+1) < 0 {
@@ -1670,6 +1644,9 @@ func stkprint(ch *Chain, limit int) {
 
 	if ch.sym != nil {
 		name = ch.sym.Name
+		if ch.sym.Nosplit != 0 {
+			name += " (nosplit)"
+		}
 	} else {
 		name = "function pointer"
 	}