diff --git a/src/cmd/compile/internal/ssa/known_bits.go b/src/cmd/compile/internal/ssa/known_bits.go index 693e494219e82f..063586a6d06573 100644 --- a/src/cmd/compile/internal/ssa/known_bits.go +++ b/src/cmd/compile/internal/ssa/known_bits.go @@ -45,6 +45,7 @@ func KnownBits(f *Func) { } val, k := kb.fold(v) if k != -1 { + kb.simplifyValue(v) continue } if f.Pass.Debug > 0 { @@ -273,6 +274,43 @@ func (kb *knownBitsState) fold(v *Value) (value, known int64) { } } +func (kb *knownBitsState) simplifyValue(v *Value) { + switch v.Op { + case ssaop.OpAnd64, ssaop.OpAnd32, ssaop.OpAnd16, ssaop.OpAnd8: + x, xk := kb.fold(v.Args[0]) + y, yk := kb.fold(v.Args[1]) + for i := range 2 { + xAllCouldBeOnes := x | ^xk + yAllCouldBeZeros := ^y + if xAllCouldBeOnes&yAllCouldBeZeros == 0 { + if f := v.Block.Func; f.Pass.Debug > 0 { + f.Warnl(v.Pos, "Removed %v no-op %v", v, v.Op) + } + v.CopyOf(v.Args[i]) + return + } + x, y = y, x + xk, yk = yk, xk + } + case ssaop.OpOr64, ssaop.OpOr32, ssaop.OpOr16, ssaop.OpOr8: + x, xk := kb.fold(v.Args[0]) + y, yk := kb.fold(v.Args[1]) + for i := range 2 { + xAllCouldBeZeros := ^x + yAllCouldBeOnes := y | ^yk + if xAllCouldBeZeros&yAllCouldBeOnes == 0 { + if f := v.Block.Func; f.Pass.Debug > 0 { + f.Warnl(v.Pos, "Removed %v no-op %v", v, v.Op) + } + v.CopyOf(v.Args[i]) + return + } + x, y = y, x + xk, yk = yk, xk + } + } +} + func (kbe knownBitsEntry) String() string { lut := []rune{ // indexed by knownBit<<1 | valueBit 0b00: '?', diff --git a/src/cmd/go/testdata/script/cover_atomic_pkgall.txt b/src/cmd/go/testdata/script/cover_atomic_pkgall.txt index 8f4397b4602de3..ad2093b7ad83c6 100644 --- a/src/cmd/go/testdata/script/cover_atomic_pkgall.txt +++ b/src/cmd/go/testdata/script/cover_atomic_pkgall.txt @@ -7,6 +7,8 @@ stdout ok[\s\S]+?coverage [!race] stop +[GOARCH:loong64] skip 'broken on loong64: #78219' + go test -coverpkg=all -race x stdout ok[\s\S]+?coverage diff --git a/src/cmd/go/testdata/script/cover_pkgall_runtime.txt b/src/cmd/go/testdata/script/cover_pkgall_runtime.txt index f92df35f636c01..600941b315c716 100644 --- a/src/cmd/go/testdata/script/cover_pkgall_runtime.txt +++ b/src/cmd/go/testdata/script/cover_pkgall_runtime.txt @@ -7,6 +7,8 @@ stdout ok[\s\S]+?coverage [!race] stop +[GOARCH:loong64] skip 'broken on loong64: #78219' + go test -coverpkg=all -race x stdout ok[\s\S]+?coverage diff --git a/src/cmd/go/testdata/script/cover_test_race_issue56370.txt b/src/cmd/go/testdata/script/cover_test_race_issue56370.txt index a18c2a7a41c870..94b2ea05d3cae9 100644 --- a/src/cmd/go/testdata/script/cover_test_race_issue56370.txt +++ b/src/cmd/go/testdata/script/cover_test_race_issue56370.txt @@ -1,5 +1,7 @@ [!race] skip +[GOARCH:loong64] skip 'broken on loong64: #78219' + go test -race -cover issue.56370/filter -- go.mod -- diff --git a/src/cmd/go/testdata/script/test_race.txt b/src/cmd/go/testdata/script/test_race.txt index c42f494bd84328..948c45105ea8b6 100644 --- a/src/cmd/go/testdata/script/test_race.txt +++ b/src/cmd/go/testdata/script/test_race.txt @@ -2,6 +2,8 @@ go test testrace +[GOARCH:loong64] skip 'broken on loong64: #78219' + ! go test -race testrace stdout 'FAIL: TestRace' ! stdout 'PASS' diff --git a/src/cmd/go/testdata/script/test_race_issue26995.txt b/src/cmd/go/testdata/script/test_race_issue26995.txt index f979facd7e16eb..a19da4b892220a 100644 --- a/src/cmd/go/testdata/script/test_race_issue26995.txt +++ b/src/cmd/go/testdata/script/test_race_issue26995.txt @@ -1,5 +1,7 @@ [!race] skip +[GOARCH:loong64] skip 'broken on loong64: #78219' + go test -v -race stdout 'testing_test.go:26: directCall' stdout 'testing_test.go:27: interfaceTBCall' diff --git a/src/cmd/go/testdata/script/testing_issue40908.txt b/src/cmd/go/testdata/script/testing_issue40908.txt index 70122cdb8c8b33..8f744a89fc9986 100644 --- a/src/cmd/go/testdata/script/testing_issue40908.txt +++ b/src/cmd/go/testdata/script/testing_issue40908.txt @@ -1,5 +1,7 @@ [!race] skip +[GOARCH:loong64] skip 'broken on loong64: #78219' + go test -race testrace -- go.mod -- diff --git a/test/known_bits.go b/test/known_bits.go index 5d6f2bdb203507..5de802ee9e00bf 100644 --- a/test/known_bits.go +++ b/test/known_bits.go @@ -429,3 +429,47 @@ func unknownBitsSextAfterTrunc(x int64, cond1, cond2 bool) int64 { return int64(truncated) & (-1 << 63) } + +func pruneNoopAnd(x, y uint8) uint8 { + // x & y => is x &= y a noop ? + // 1. 0 & 0 => noop + // 2. 1 & 0 => keep and + // 3. ? & 0 => keep and + // 4. 0 & 1 => noop + // 5. 1 & 1 => noop + // 6. ? & 1 => noop + // 7. 0 & ? => noop; can't be handled by prove + // 8. 1 & ? => keep and + // 9. ? & ? => keep and + + // Test patterns: 76541 + x &= 0b01000 + x |= 0b00100 + y &= 0b10000 + y |= 0b01110 + + return x & y // ERROR "Removed v[0-9]+ no-op And8$" +} + +func pruneNoopOr(x, y uint8) uint8 { + // x | y => is x |= y a noop ? + // 1. 0 | 0 => noop + // 2. 1 | 0 => noop + // 3. ? | 0 => noop + // 4. 0 | 1 => keep or + // 5. 1 | 1 => noop + // 6. ? | 1 => keep or + // 7. 0 | ? => keep or + // 8. 1 | ? => noop; can't be handled by prove + // 9. ? | ? => keep or + + // Test patterns: 85321 + // invert the and & or in setup otherwise generic.rules reassociate in a + // form known bits doesn't for. + x |= 0b11010 + x &= 0b11110 + y |= 0b01000 + y &= 0b11000 + + return x | y // ERROR "Removed v[0-9]+ no-op Or8$" +}