This CL adds the mem2reg pass for scalar variables. It's an attempt to translate LLVM's mem2reg pass: https://llvm.org/doxygen/PromoteMemoryToRegister_8cpp_source.html. The pass promotes address-taken stack variables to SSA values when the address is only used by Loads and Stores. For each qualifying variable, stores become the variable's current value, loads are replaced by that value, and the memory operations (and their VarDefs) are removed. For example, in var x int p := &x *p = a b := *p + 1 the store *p = a and the load *p never leave a value in memory: b is computed directly from a, and x's stack slot goes away entirely. This CL only handles variables whose loads and stores are all in a single basic block; a later CL extends the analysis across blocks with phi insertion. This CL has some edge cases not handled, they should be easily findable in the code by looking at where statistics are printed. This CL might help #73589. Updates #73589. Change-Id: Iedee627971ad00324cc04d580e351a37fe88a6de Reviewed-on: https://go-review.googlesource.com/c/go/+/713300 LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Keith Randall <khr@golang.org>
44 lines
860 B
Go
44 lines
860 B
Go
// errorcheck -0 -d=ssa/mem2reg/debug=4
|
|
|
|
// Copyright 2025 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.
|
|
|
|
// Test for variables accessed through pointers that can
|
|
// be promoted to register by the mem2reg pass.
|
|
|
|
package main
|
|
|
|
// The following functions are ported from src/cmd/compile/internal/ssa/mem2reg_test.go.
|
|
|
|
// Single-block mem2reg test
|
|
|
|
func justReturn0() int {
|
|
var x, y, z int // ERROR "promoted x in single block case" "promoted y in single block case" "promoted z in single block case"
|
|
xp := &x
|
|
yp := &y
|
|
zp := &z
|
|
*xp = 0
|
|
*yp = 1
|
|
*zp = 2
|
|
*yp = 3
|
|
*zp = 4
|
|
*yp = 5
|
|
valX1 := *xp
|
|
*zp = valX1 - 1
|
|
*xp = 1
|
|
*yp = 2
|
|
*xp = 3
|
|
*yp = 4
|
|
*xp = 5
|
|
valZ1 := *zp
|
|
*yp = valZ1 + 1
|
|
*zp = 1
|
|
*xp = 2
|
|
*zp = 3
|
|
*xp = 4
|
|
*zp = 5
|
|
valY1 := *yp
|
|
return valY1
|
|
}
|