// errorcheck -0 -d=ssa/critical/debug=1 //go:build goexperiment.simd && amd64 // 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. // Test that blocks created by the critical pass to split critical // edges inherit the CPU features of the edge they sit on, so that // later consumers (e.g. regalloc-inserted shuffle copies) can use // feature-dependent instruction encodings there. There are three // paths through the pass, each exercised below: // // 1. a fresh split block for an edge into a block with a single phi // 2. a fresh split block for an edge into a block with several phis // (or none) // 3. a split block reused for several predecessor edges carrying the // same phi argument, which keeps only the features all of its // predecessors guarantee package foo import "simd/archsimd" var cond bool // Case 1: the merge block has a single phi (x), so the split block for // the critical edge is created on the single-phi path. It inherits // avx from its predecessor and successor. func singlePhi(a, b archsimd.Int64x4) archsimd.Int64x4 { x := a.Add(b) if cond { // ERROR "split critical edge" "split-edge block b[0-9]+ has features avx$" x = x.Add(a) } return x } // Case 2: the merge block has two phis (x and y), so the split block // for the critical edge is created on the no-single-phi path. func multiPhi(a, b archsimd.Int64x4) (archsimd.Int64x4, archsimd.Int64x4) { x := a.Add(b) y := b.Sub(a) if cond { // ERROR "split critical edge" "split-edge block b[0-9]+ has features avx$" x = x.Add(a) y = y.Sub(b) } return x, y } // Case 3: the short-circuit && evaluates each operand in its own // block, and both false edges jump to the single-phi merge block with // the same phi argument (the zero value of x). The split block is // created for the edge from the second operand's block, whose features // are avx+avx2+avx512 (it is dominated by the first operand's block // and holds the 512-bit ops); when it is reused for the edge from the // first operand's block, which only guarantees avx, its features must // drop to the common subset rather than keep avx512. func reuseIntersect(s []int64, s8 []int64) { var x archsimd.Int64x4 if archsimd.LoadInt64x4(s).IsZero() && // ERROR "split critical edge" "reused split-edge block b[0-9]+ has features avx$" "split-edge block b[0-9]+ has features avx$" archsimd.LoadInt64x8(s8).Equal(archsimd.LoadInt64x8(s8)).ToBits() != 0 { // ERROR "split critical edge" "split-edge block b[0-9]+ has features avx[+]avx2[+]avx512$" x = archsimd.LoadInt64x4(s) } x.Store(s) }