| // run |
| |
| // 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. |
| |
| // Issue 81842: on ppc64 and ppc64le, signed division compared the |
| // divisor with -1 in CR0 without marking the op as clobbering flags, so |
| // flagalloc could keep a flag live across the division and a branch |
| // after it tested the wrong condition. |
| |
| package main |
| |
| import ( |
| "fmt" |
| "math" |
| ) |
| |
| var sinkA, sinkB int |
| var q64 int64 |
| var q32 int32 |
| |
| //go:noinline |
| func div64(c bool, a, b int64) { |
| sinkB = 0 |
| if b == 0 { // b is known nonzero below, so the division has no zero check |
| return |
| } |
| if c { |
| sinkA = 1 |
| } |
| q64 = a / b |
| if !c { |
| sinkB = 1 |
| } |
| } |
| |
| //go:noinline |
| func div32(c bool, a, b int32) { |
| sinkB = 0 |
| if b == 0 { |
| return |
| } |
| if c { |
| sinkA = 1 |
| } |
| q32 = a / b |
| if !c { |
| sinkB = 1 |
| } |
| } |
| |
| //go:noinline |
| func div16(c bool, a, b int16) { |
| sinkB = 0 |
| if b == 0 { |
| return |
| } |
| if c { |
| sinkA = 1 |
| } |
| q64 = int64(a / b) |
| if !c { |
| sinkB = 1 |
| } |
| } |
| |
| //go:noinline |
| func div8(c bool, a, b int8) { |
| sinkB = 0 |
| if b == 0 { |
| return |
| } |
| if c { |
| sinkA = 1 |
| } |
| q64 = int64(a / b) |
| if !c { |
| sinkB = 1 |
| } |
| } |
| |
| //go:noinline |
| func mod64(c bool, a, b int64) { |
| sinkB = 0 |
| if b == 0 { |
| return |
| } |
| if c { |
| sinkA = 1 |
| } |
| q64 = a % b |
| if !c { |
| sinkB = 1 |
| } |
| } |
| |
| //go:noinline |
| func divCmp(x int, a, b int64) { |
| sinkB = 0 |
| if b == 0 { |
| return |
| } |
| if x < 5 { |
| sinkA = 1 |
| } |
| q64 = a / b |
| if x >= 5 { |
| sinkB = 1 |
| } |
| } |
| |
| func check(name string, gotQ, wantQ int64, gotB, wantB int) { |
| if gotQ != wantQ || gotB != wantB { |
| panic(fmt.Sprintf("%s: got q=%d sinkB=%d, want q=%d sinkB=%d", name, gotQ, gotB, wantQ, wantB)) |
| } |
| } |
| |
| func main() { |
| div64(false, 7, 2) |
| check("div64", q64, 3, sinkB, 1) |
| div64(false, math.MinInt64, -1) |
| check("div64(MinInt64, -1)", q64, math.MinInt64, sinkB, 1) |
| div32(false, 7, 2) |
| check("div32", int64(q32), 3, sinkB, 1) |
| div32(false, math.MinInt32, -1) |
| check("div32(MinInt32, -1)", int64(q32), math.MinInt32, sinkB, 1) |
| div16(false, 7, 2) |
| check("div16", q64, 3, sinkB, 1) |
| div8(false, 7, 2) |
| check("div8", q64, 3, sinkB, 1) |
| mod64(false, 7, 2) |
| check("mod64", q64, 1, sinkB, 1) |
| divCmp(0, 7, 2) |
| check("divCmp(0)", q64, 3, sinkB, 0) |
| divCmp(9, 7, -2) |
| check("divCmp(9)", q64, -3, sinkB, 1) |
| } |