Source file test/fixedbugs/issue81842.go

     1  // run
     2  
     3  // Copyright 2026 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  // Issue 81842: on ppc64 and ppc64le, signed division compared the
     8  // divisor with -1 in CR0 without marking the op as clobbering flags, so
     9  // flagalloc could keep a flag live across the division and a branch
    10  // after it tested the wrong condition.
    11  
    12  package main
    13  
    14  import (
    15  	"fmt"
    16  	"math"
    17  )
    18  
    19  var sinkA, sinkB int
    20  var q64 int64
    21  var q32 int32
    22  
    23  //go:noinline
    24  func div64(c bool, a, b int64) {
    25  	sinkB = 0
    26  	if b == 0 { // b is known nonzero below, so the division has no zero check
    27  		return
    28  	}
    29  	if c {
    30  		sinkA = 1
    31  	}
    32  	q64 = a / b
    33  	if !c {
    34  		sinkB = 1
    35  	}
    36  }
    37  
    38  //go:noinline
    39  func div32(c bool, a, b int32) {
    40  	sinkB = 0
    41  	if b == 0 {
    42  		return
    43  	}
    44  	if c {
    45  		sinkA = 1
    46  	}
    47  	q32 = a / b
    48  	if !c {
    49  		sinkB = 1
    50  	}
    51  }
    52  
    53  //go:noinline
    54  func div16(c bool, a, b int16) {
    55  	sinkB = 0
    56  	if b == 0 {
    57  		return
    58  	}
    59  	if c {
    60  		sinkA = 1
    61  	}
    62  	q64 = int64(a / b)
    63  	if !c {
    64  		sinkB = 1
    65  	}
    66  }
    67  
    68  //go:noinline
    69  func div8(c bool, a, b int8) {
    70  	sinkB = 0
    71  	if b == 0 {
    72  		return
    73  	}
    74  	if c {
    75  		sinkA = 1
    76  	}
    77  	q64 = int64(a / b)
    78  	if !c {
    79  		sinkB = 1
    80  	}
    81  }
    82  
    83  //go:noinline
    84  func mod64(c bool, a, b int64) {
    85  	sinkB = 0
    86  	if b == 0 {
    87  		return
    88  	}
    89  	if c {
    90  		sinkA = 1
    91  	}
    92  	q64 = a % b
    93  	if !c {
    94  		sinkB = 1
    95  	}
    96  }
    97  
    98  //go:noinline
    99  func divCmp(x int, a, b int64) {
   100  	sinkB = 0
   101  	if b == 0 {
   102  		return
   103  	}
   104  	if x < 5 {
   105  		sinkA = 1
   106  	}
   107  	q64 = a / b
   108  	if x >= 5 {
   109  		sinkB = 1
   110  	}
   111  }
   112  
   113  func check(name string, gotQ, wantQ int64, gotB, wantB int) {
   114  	if gotQ != wantQ || gotB != wantB {
   115  		panic(fmt.Sprintf("%s: got q=%d sinkB=%d, want q=%d sinkB=%d", name, gotQ, gotB, wantQ, wantB))
   116  	}
   117  }
   118  
   119  func main() {
   120  	div64(false, 7, 2)
   121  	check("div64", q64, 3, sinkB, 1)
   122  	div64(false, math.MinInt64, -1)
   123  	check("div64(MinInt64, -1)", q64, math.MinInt64, sinkB, 1)
   124  	div32(false, 7, 2)
   125  	check("div32", int64(q32), 3, sinkB, 1)
   126  	div32(false, math.MinInt32, -1)
   127  	check("div32(MinInt32, -1)", int64(q32), math.MinInt32, sinkB, 1)
   128  	div16(false, 7, 2)
   129  	check("div16", q64, 3, sinkB, 1)
   130  	div8(false, 7, 2)
   131  	check("div8", q64, 3, sinkB, 1)
   132  	mod64(false, 7, 2)
   133  	check("mod64", q64, 1, sinkB, 1)
   134  	divCmp(0, 7, 2)
   135  	check("divCmp(0)", q64, 3, sinkB, 0)
   136  	divCmp(9, 7, -2)
   137  	check("divCmp(9)", q64, -3, sinkB, 1)
   138  }
   139  

View as plain text