mirror of
https://github.com/golang/go.git
synced 2026-06-26 10:50:23 +00:00
This pass performs bitwise constant folding. It's main goal is to optimize bitfields like generated by defer. You might have 3 defers in a function and the middle one is always taken, previously we couldn't remove the branch for it, this pass is able to do so. This is hit 93 times uniqued by LOC when building the std. My first thought was to implement this as parts of the limits code. However the way limits allows to set knownBits tighter and vice-versa means the code complexity between the two is multiplicative. Thus I have avoided this, someone might change it in the future but I don't have a good usecase now and this simple pass is sufficient. I have tried multiple places for the pass, we need it before any opt (here late opt) since we need the generic rules to optimize any user of a constant folded value. We also want one run of known bits after prove since prove removing some never / always taken branches allows known bits to do a better job. This yields real optimizations when you have a defer inside an always taken branch. I've thought prove might do a better job if some branches were removed by running an early known bits first. However after trying it, this never helped. I am sure you can build an example where this becomes true, but at least in the code I've looked at it didn't help. Thus I decided against running known bits twice (before and after prove). Fixes #78633 Change-Id: I90a46875cc11d5d26367f00ac83c29fed433cb6d Reviewed-on: https://go-review.googlesource.com/c/go/+/765560 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com> Auto-Submit: Jorropo <jorropo.pgm@gmail.com> Reviewed-by: Carlos Amedee <carlos@golang.org> LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
51 lines
770 B
Go
51 lines
770 B
Go
// asmcheck
|
|
|
|
// Copyright 2026 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.
|
|
|
|
package codegen
|
|
|
|
func knownBitsPhiAnd(cond bool) int {
|
|
x := 1
|
|
if cond {
|
|
x = 3
|
|
}
|
|
// amd64:-"AND"
|
|
// arm64:-"AND"
|
|
return x & 1
|
|
}
|
|
|
|
func knownBitsDeferPattern(a, b bool) int {
|
|
bits := 0
|
|
bits |= 1 << 0
|
|
if a {
|
|
bits |= 1 << 1
|
|
}
|
|
bits |= 1 << 2
|
|
if b {
|
|
bits |= 1 << 3
|
|
}
|
|
// amd64:-"AND"
|
|
// arm64:-"AND"
|
|
return bits & (1<<2 | 1<<0)
|
|
}
|
|
|
|
func knownBitsXorToggle(a, b, c bool) int {
|
|
bits := 0
|
|
bits ^= 1 << 0
|
|
if a {
|
|
bits ^= 1 << 1
|
|
}
|
|
bits ^= 1 << 2
|
|
if b {
|
|
bits ^= 1 << 3
|
|
}
|
|
bits ^= 1 << 2
|
|
if c {
|
|
bits ^= 1 << 4
|
|
}
|
|
// amd64:-"AND"
|
|
// arm64:-"AND"
|
|
return bits & (1<<2 | 1<<0)
|
|
}
|