Files
gasm-sdk/lint/vector_test.go
T

96 lines
2.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: BSD-3-Clause
package lint
import (
"testing"
"sourcedock.dev/petrbalvin/gasm-sdk/arch"
"sourcedock.dev/petrbalvin/gasm-sdk/parser"
)
// TestVEXSSEMixing checks the encoding-mixing advisory: VEX and legacy SSE
// in one kernel pay a transition penalty on every switch, so the finding is
// informational, not a defect.
func TestVEXSSEMixing(t *testing.T) {
// GOROOT's memmove shape: VMOVDQU on Y registers beside MOVOU on X.
diags := lintSrc(t, `
#include "textflag.h"
TEXT ·copy(SB), NOSPLIT, $0
VMOVDQU (SI), Y4
MOVOU (SI), X0
RET
`)
if codes(diags)[CodeVEXSSEMixing] != 1 {
t.Fatalf("want one vex-sse-mixing, got %+v", diags)
}
// One encoding throughout is the recommendation.
diags = lintSrc(t, `
#include "textflag.h"
TEXT ·copy(SB), NOSPLIT, $0
VMOVDQU (SI), Y4
VPSUBD Y1, Y2, Y3
RET
`)
if codes(diags)[CodeVEXSSEMixing] != 0 {
t.Fatalf("pure VEX kernel must not be flagged: %+v", diags)
}
diags = lintSrc(t, `
#include "textflag.h"
TEXT ·copy(SB), NOSPLIT, $0
MOVOU (SI), X0
PADDB X1, X2
RET
`)
if codes(diags)[CodeVEXSSEMixing] != 0 {
t.Fatalf("pure legacy kernel must not be flagged: %+v", diags)
}
// VZEROUPPER is the boundary management, not a side of the mixing: the
// idiomatic epilogue after legacy SSE stays clean.
diags = lintSrc(t, `
#include "textflag.h"
TEXT ·copy(SB), NOSPLIT, $0
MOVOU (SI), X0
PADDB X1, X2
VZEROUPPER
RET
`)
if codes(diags)[CodeVEXSSEMixing] != 0 {
t.Fatalf("VZEROUPPER epilogue must not be flagged: %+v", diags)
}
// A symbol whose name collides with the register spelling (the runtime's
// internal∕cpu·X86 feature flags) is not a register.
diags = lintSrc(t, `
#include "textflag.h"
TEXT ·probe(SB), NOSPLIT, $0
CMPB internal∕cpu·X86+const_offsetX86HasERMS(SB), $1
VMOVDQU (SI), Y4
RET
`)
if codes(diags)[CodeVEXSSEMixing] != 0 {
t.Fatalf("a symbol named X86 must not count as legacy SSE: %+v", diags)
}
// The rule is amd64-only: arm64 V registers are not SSE at all.
diags = lintSrcArch(t, "f_arm64.s", `
#include "textflag.h"
TEXT ·f(SB), NOSPLIT, $0
VLD1 (R0), [V1.B16]
RET
`)
if codes(diags)[CodeVEXSSEMixing] != 0 {
t.Fatalf("arm64 must not be flagged: %+v", diags)
}
// -disable silences the rule.
f, _ := parser.Parse("t_amd64.s", "#include \"textflag.h\"\nTEXT ·copy(SB), NOSPLIT, $0\n\tVMOVDQU (SI), Y4\n\tMOVOU (SI), X0\n\tRET\n")
diags = File(f, Config{Arch: arch.AMD64, Disable: map[string]bool{CodeVEXSSEMixing: true}})
if codes(diags)[CodeVEXSSEMixing] != 0 {
t.Fatalf("disabled rule must stay silent: %+v", diags)
}
}