improve sidmdid config
This commit is contained in:
@@ -86,6 +86,7 @@ namespace StgSharp.Mathematics.Numeric
|
||||
1 => KernelSideCountSse<T>(),
|
||||
2 => KernelSideCountAvx2<T>(),
|
||||
3 => KernelSideCountAvx512<T>(),
|
||||
4 => KernelSideCountAvx512<T>(),
|
||||
_ => throw new NotSupportedException("Unsupported SIMD level."),
|
||||
};
|
||||
default:
|
||||
@@ -145,6 +146,7 @@ namespace StgSharp.Mathematics.Numeric
|
||||
1 => PanelSideFromBits<T>(128),
|
||||
2 => PanelSideFromBits<T>(256),
|
||||
3 => PanelSideFromBits<T>(512),
|
||||
4 => PanelSideFromBits<T>(512),
|
||||
_ => throw new NotSupportedException("Unsupported SIMD level."),
|
||||
};
|
||||
default:
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace StgSharp.Mathematics.Internal
|
||||
internal unsafe struct SIMDID
|
||||
{
|
||||
|
||||
[FieldOffset(0)] public fixed byte MaskByte[16];
|
||||
[FieldOffset(0)] public fixed byte MaskByte[8];
|
||||
[FieldOffset(0)] public ulong Mask;
|
||||
|
||||
internal SIMDID(
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace StgSharp.Mathematics.Numeric
|
||||
2 => 32,
|
||||
3 => 64,
|
||||
4 => 64,
|
||||
5 => 64,
|
||||
_ => 8,
|
||||
},
|
||||
_ => 8,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# SIMDID (x86-64) 64-bit Specification (Completed per fixed layout)
|
||||
|
||||
This document completes the **64-bit SIMDID** bit layout as specified, with emphasis on the design of the **AVX512 Feature section ([31..16])**, so it can cover the messy AVX-512 subsets while keeping branching logic compact. It also allocates an **AVX Feature byte** adjacent to the AVX512/AMX regions for AVX-family capabilities, and an **AVX10 Feature byte** for the converged AVX10 ISA.
|
||||
This document defines the compact **64-bit SIMDID** layout, including AVX/AVX-512/AVX10 capabilities and per-core execution-policy hints. AMX is not represented by the current policy.
|
||||
|
||||
> Convention: bit0 is the least significant bit (LSB). Only x86-64 interpreter semantics are defined here; the header's Root ISA allows extension to other architectures.
|
||||
|
||||
@@ -12,7 +12,7 @@ This document completes the **64-bit SIMDID** bit layout as specified, with emph
|
||||
SIMDID (64 bits) [63 ........................................................ 0]
|
||||
+----------+-----------+-----------+----------------+----------------+----------------+--------+-------+
|
||||
| [63..56] | [55..48] | [47..40] | [39..32] | [31..16] | [15..8] | [7..4] | [3..0]|
|
||||
| uArchHi | AVX10Feat | AVX Feat | AMX Future | AVX512 Feature | MainLevel | Manuf | Root |
|
||||
| Reserved | uArchHi | AVX10Feat | AVX Feature | AVX512 Feature | MainLevel | Manuf | Root |
|
||||
+----------+-----------+-----------+----------------+----------------+----------------+--------+-------+
|
||||
```
|
||||
|
||||
@@ -20,10 +20,10 @@ SIMDID (64 bits) [63 ........................................................ 0
|
||||
- **[7..4] Manufacture**: Vendor info (Intel/AMD for x86)
|
||||
- **[15..8] MainLevel**: Main ISA level (ascending, shared bit semantics)
|
||||
- **[31..16] AVX512 Feature**: AVX-512 features/subsets/implementation form (key part)
|
||||
- **[39..32] AMX Future**: AMX features (few bits for now)
|
||||
- **[47..40] AVX Feature**: AVX-family capabilities (base requires AVX+AVX2; key extensions include FMA/F16C)
|
||||
- **[55..48] AVX10 Feature**: AVX10 converged ISA version and vector width support
|
||||
- **[63..56] uArchHi**: Optional microarchitecture/policy hints (default 0, no functional impact).
|
||||
- **[39..32] AVX Feature**: AVX-family capabilities (base requires AVX+AVX2; key extensions include FMA/F16C)
|
||||
- **[47..40] AVX10 Feature**: AVX10 version and tracked discrete features
|
||||
- **[55..48] uArchHi**: Optional microarchitecture/policy hints
|
||||
- **[63..56] Reserved**: tail space for future extension
|
||||
|
||||
---
|
||||
|
||||
@@ -82,14 +82,11 @@ For other Root ISAs, this nibble is defined by their interpreters.
|
||||
| 0 | NONE |
|
||||
| 1 | SSE (full SSE family: SSE1..SSE4.2) |
|
||||
| 2 | AVX2 |
|
||||
| 3 | AVX2_FMA |
|
||||
| 4 | AVX2_FMA_F16C (from this level onward, 16-bit types are supported) |
|
||||
| 5 | AVX512 (check [31..16]) |
|
||||
| 6 | AMX |
|
||||
| 7 | AVX10 (check [55..48]) |
|
||||
| 8..255 | Reserved |
|
||||
| 3 | AVX512 (check [31..16]) |
|
||||
| 4 | AVX10 (check [47..40]) |
|
||||
| 5..255 | Reserved |
|
||||
|
||||
> Scheduling suggestion: `MainLevel` is the primary switch; only when `MainLevel >= AVX512` should `AVX512 Feature` be parsed; only when `MainLevel >= AMX` should `AMX Future` be parsed; only when `MainLevel >= AVX10` should `AVX10 Feature` be parsed. AVX Feature sits beside AMX/AVX512 and is meaningful when AVX or higher is present.
|
||||
> `MainLevel` is the primary switch. Parse AVX512 Feature at AVX512 or later and AVX10 Feature only at AVX10.
|
||||
|
||||
---
|
||||
|
||||
@@ -97,7 +94,7 @@ For other Root ISAs, this nibble is defined by their interpreters.
|
||||
|
||||
1) **Base AVX512 one-shot check**: Use 1 bit for the bundle `F + CD + VL + DQ + BW`, avoiding multiple subset checks.
|
||||
2) **Glue vs native**: Use an implementation field to distinguish `AVX512-DUAL` (glue/downclock risk) from `AVX512-NATIVE` (full 512-bit ALU).
|
||||
3) **Niche/AI extensions separated**: VNNI, BF16/FP16, and similar extensions each get a dedicated bit so the base path stays simple.
|
||||
3) **Minimal extension tracking**: VNNI is the only AVX-512 extension currently retained.
|
||||
|
||||
---
|
||||
|
||||
@@ -107,7 +104,7 @@ AVX512 Feature (bits 31..16)
|
||||
|
||||
| **bit** | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 |
|
||||
|-----------|-----|-----|------|------|------|-------|------|------|-------|-------|----|------|----|----|----|----|
|
||||
| **Usage** | R | R | FP16 | BF16 | VNNI | VBMI2 | VBMI | R/AI | Impl1 | Impl0 | R | BASE | R | R | R | R |
|
||||
| **Usage** | R | R | R | R | VNNI | R | R | R | Impl1 | Impl0 | R | BASE | R | R | R | R |
|
||||
|
||||
Notes:
|
||||
|
||||
@@ -123,61 +120,56 @@ Notes:
|
||||
|
||||
> **Note**: Intel SKX/CLX/CPX have two 512-bit FMA ports (port-0 + port-5) and are **NATIVE** — genuine 512-bit throughput. Intel downclocking on heavy ZMM workloads is a separate concern not encoded here. DUAL-PUMP applies only where a single 256-bit unit fires twice per 512-bit op (AMD Zen4-style).
|
||||
|
||||
- **VBMI/VBMI2/VNNI/BF16/FP16 ([29..25])**: Commonly needed niche or AI-related small-type extensions; set as needed.
|
||||
- **VNNI (bit 27)**: the only AVX-512 extension currently tracked; the surrounding extension bits are reserved.
|
||||
- **R/AI (bit 24)**: Reserved for future AI or other non-crypto extensions.
|
||||
- **[31..30], [21], [19..16]**: Reserved for future allocation.
|
||||
|
||||
---
|
||||
|
||||
## 7) AVX Feature Byte ([47..40], 8 bits)
|
||||
## 7) AVX Feature Byte ([39..32], 8 bits)
|
||||
|
||||
Purpose: compact AVX-family capability encoding adjacent to AVX512/AMX. Base requirement: AVX **and** AVX2 present. Key extensions: FMA and F16C. Additional bits reserved for other extensions.
|
||||
Purpose: compact AVX-family capability encoding. Base requirement: AVX **and** AVX2 present. Key extensions: FMA and F16C.
|
||||
|
||||
AVX Feature (bits 47..40)
|
||||
AVX Feature (bits 39..32)
|
||||
|
||||
| bit | 47 | 46 | 45 | 44 | 43 | 42 | 41 | 40 |
|
||||
| bit | 39 | 38 | 37 | 36 | 35 | 34 | 33 | 32 |
|
||||
|-----|----|----|----|----|----|----|----|----|
|
||||
| use | R | R | R | DUAL | F16C | FMA | AVX2 | AVX |
|
||||
|
||||
Rules:
|
||||
- **AVX (bit 40)**: AVX present.
|
||||
- **AVX2 (bit 41)**: AVX2 present. For the AVX feature byte to be considered valid, both AVX and AVX2 must be set.
|
||||
- **FMA (bit 42)**: FMA present.
|
||||
- **F16C (bit 43)**: F16C present.
|
||||
- **DUAL (bit 44)**: YMM execution is **glued/split-lane** (two fused 128-bit units rather than a native 256-bit path). Detection: AMD Zen1/Zen+ (Family 0x17, model < 0x30), Hygon (all, Zen1-based), VIA/Zhaoxin (all). When set, code using YMM operations may incur split-register overhead; prefer 128-bit SSE paths on these targets.
|
||||
- **[45..47]**: Reserved for other AVX-family extensions (e.g., IFMA, XOP) as needed.
|
||||
- **AVX (bit 32)**: AVX present.
|
||||
- **AVX2 (bit 33)**: AVX2 present. For the AVX feature byte to be considered valid, both AVX and AVX2 must be set.
|
||||
- **FMA (bit 34)**: FMA present.
|
||||
- **F16C (bit 35)**: F16C present.
|
||||
- **DUAL (bit 36)**: YMM execution is **glued/split-lane** (two fused 128-bit units rather than a native 256-bit path). Detection: AMD Zen1/Zen+ (Family 0x17, model < 0x30), Hygon (all, Zen1-based), VIA/Zhaoxin (all). When set, code using YMM operations may incur split-register overhead; prefer 128-bit SSE paths on these targets.
|
||||
- **[37..39]**: Reserved for other AVX-family extensions as needed.
|
||||
|
||||
---
|
||||
|
||||
## 8) AVX10 Feature Byte ([55..48], 8 bits)
|
||||
## 8) AVX10 Feature Byte ([47..40], 8 bits)
|
||||
|
||||
Purpose: encode the converged AVX10 ISA version and supported vector widths. AVX10 unifies and replaces the fragmented AVX-512 subset model; a single version number implies a defined set of instructions (e.g., AVX10.1 implies F+CD+VL+DQ+BW+VBMI+VBMI2+VNNI+BF16+FP16 converged). The width bits indicate what maximum vector width the hardware actually implements.
|
||||
Purpose: encode the converged AVX10 ISA version and the discrete features relevant to this runtime. Under the current specification every AVX10 processor supports 128-, 256-, and 512-bit vector lengths, so vector width is not encoded.
|
||||
|
||||
**CPUID detection**: `CPUID leaf 0x24, subleaf 0`.
|
||||
- EBX[7:0] = AVX10 converged ISA version number (≥ 1 if supported).
|
||||
- EBX[16] = 128-bit vector support (always 1 when AVX10 is present).
|
||||
- EBX[17] = 256-bit vector support.
|
||||
- EBX[18] = 512-bit vector support.
|
||||
- EBX[18:16] are reserved at 1. Earlier specifications used them for VL128/VL256/VL512; they must not be interpreted as width capabilities.
|
||||
- `CPUID.24H.1:ECX[2]` enumerates `AVX10_VNNI_INT` when subleaf 1 exists.
|
||||
|
||||
AVX10 Feature (bits 55..48)
|
||||
AVX10 Feature (bits 47..40)
|
||||
|
||||
| bit | 55 | 54 | 53 | 52 | 51 | 50 | 49 | 48 |
|
||||
|-----|----|----|----| ---- | ---- |----|----|------|
|
||||
| use | R | R | R | 512W | 256W | V2 | V1 | AVX10 |
|
||||
| bit | 47 | 46..40 |
|
||||
|-----|----------|---------|
|
||||
| use | VNNI_INT | Version |
|
||||
|
||||
Rules:
|
||||
- **AVX10 (bit 48)**: CPU declares AVX10 converged ISA support (leaf 0x24 reports a valid version ≥ 1).
|
||||
- **V1 (bit 49)**: AVX10 version ≥ 1 (AVX10.1). Set when `EBX[7:0] >= 1`.
|
||||
- **V2 (bit 50)**: AVX10 version ≥ 2 (AVX10.2). Set when `EBX[7:0] >= 2`.
|
||||
- **256W (bit 51)**: Hardware supports 256-bit vector width for AVX10 instructions (`EBX[17]` == 1).
|
||||
- **512W (bit 52)**: Hardware supports 512-bit vector width for AVX10 instructions (`EBX[18]` == 1).
|
||||
- **[53..55]**: Reserved for future AVX10 versions (V3, V4...) or additional width/feature bits.
|
||||
- **Version ([46..40])**: numeric AVX10 version, saturated to 7 bits. Zero means AVX10 is absent.
|
||||
- **VNNI_INT (bit 47)**: `CPUID.24H.1:ECX[2]`.
|
||||
|
||||
> Note: When `AVX10 == 1`, the 128-bit width is always implied and does not need a dedicated bit. `V1` and `V2` are cumulative — if `V2` is set, `V1` must also be set.
|
||||
> AVX10 version comparison is numeric. Merging two SIMDIDs keeps the lower version and intersects discrete feature bits.
|
||||
|
||||
**Relationship with AVX512 Feature**:
|
||||
- AVX10 is a superset specification. When `MainLevel == AVX10`, the `AVX512 Feature` field may still be populated for backward-compatible code paths (e.g., checking `AVX512_IMPL` to select DUAL vs NATIVE 512-bit policy).
|
||||
- AVX10/256 hardware does **not** support 512-bit operations; code should check `512W` before using zmm registers.
|
||||
- Current AVX10 hardware is architecturally AVX10/512. OS support still requires the full XCR0 SSE/AVX/opmask/ZMM state.
|
||||
|
||||
---
|
||||
|
||||
@@ -189,33 +181,18 @@ Rules:
|
||||
- Otherwise:
|
||||
- Check `BASE`; if 0, fall back to AVX2/FMA (or treat as detection failure).
|
||||
- Check `AVX512_IMPL`: `DUAL` uses 256-bit/downclock-safe path, `NATIVE` uses 512-bit path.
|
||||
- When small-type/AI capabilities are required, consult `VNNI/BF16/FP16/VBMI/VBMI2` bits.
|
||||
- Consult `VNNI` when the integer dot-product path requires it.
|
||||
- If `MainLevel == AVX10`: prefer AVX10 Feature for capability checks; `AVX512 Feature` remains valid for legacy branching.
|
||||
|
||||
---
|
||||
|
||||
## 10) AMX Future ([39..32], 8 bits)
|
||||
|
||||
A single byte is reserved; define three common bits for now, leave the rest reserved:
|
||||
|
||||
| bit (relative to [39..32]) | Name | Note |
|
||||
|---:|------|------|
|
||||
| 0 | AMX_TILE | Tile base |
|
||||
| 1 | AMX_INT8 | INT8 tile |
|
||||
| 2 | AMX_BF16 | BF16 tile |
|
||||
| 3..7 | Reserved | |
|
||||
|
||||
When `MainLevel < AMX`, this byte can be all zeros.
|
||||
|
||||
---
|
||||
|
||||
## 11) uArchHi ([63..56], 8 bits)
|
||||
## 10) uArchHi ([55..48], 8 bits)
|
||||
|
||||
Purpose: **bitmask** byte encoding core topology classification and SIMD execution-width policy for the detected core. All bits default to 0.
|
||||
|
||||
uArchHi bitmask layout:
|
||||
|
||||
| bit (relative to [63..56]) | Name | Note |
|
||||
| bit (relative to [55..48]) | Name | Note |
|
||||
|---:|------|------|
|
||||
| 0 | HYBRID_E | E-core (efficiency/small core) in a hybrid-topology processor (e.g., Intel Alder Lake+ E-core) |
|
||||
| 1 | HYBRID_P | P-core (performance/big core) in a hybrid-topology processor (e.g., Intel Alder Lake+ P-core) |
|
||||
@@ -253,21 +230,20 @@ Detection:
|
||||
- Set `AVX512_IMPL`:
|
||||
- **Intel (all)**: NATIVE — all Intel AVX-512 CPUs have genuine 512-bit execution units
|
||||
- **AMD Zen4 (Family 0x19)**: DUAL — single 256-bit ALU, dual-pump
|
||||
- **AMD Zen5+ (Family 0x1A+)**: NATIVE — native full-width 512-bit units
|
||||
- **AMD other/future**: UNKNOWN (conservative)
|
||||
- **AMD Family 0x1A models 00h..0Fh (EPYC 9005)**: NATIVE — full-width 512-bit path
|
||||
- **AMD Family 0x1A models 10h..1Fh**: UNKNOWN — this CPUID range is shared by full-width EPYC 9005 Zen5c and 256-bit dual-pumped EPYC 8005 products
|
||||
- **AMD other client/future models**: UNKNOWN unless their execution width can be identified without an ambiguous product-name heuristic
|
||||
- **Hygon**: UNKNOWN (AVX-512 characteristics unclear)
|
||||
- **VIA/other**: UNKNOWN
|
||||
- When VNNI/BF16/FP16/VBMI/VBMI2 are detected, set the corresponding bits.
|
||||
4) If `MainLevel >= AMX`: fill the AMX byte.
|
||||
5) When AVX/AVX2 are present, populate the AVX Feature byte: set `AVX` and `AVX2`; set `FMA` and `F16C` when detected; set `DUAL` when the YMM execution path is split/glued (AMD Zen1/Zen+ Family 0x17 model < 0x30, Hygon all models, VIA/Zhaoxin all models).
|
||||
6) **AVX10 detection** (requires `CPUID leaf 7 subleaf 1, EDX[19] == 1` as the AVX10 convergence bit):
|
||||
- Set VNNI when detected; other AVX-512 extension bits remain reserved.
|
||||
4) When AVX/AVX2 are present, populate the AVX Feature byte: set `AVX` and `AVX2`; set `FMA` and `F16C` when detected; set `DUAL` when the YMM execution path is split/glued (AMD Zen1/Zen+ Family 0x17 model < 0x30, Hygon all models, VIA/Zhaoxin all models).
|
||||
5) **AVX10 detection** (requires `CPUID leaf 7 subleaf 1, EDX[19] == 1` as the AVX10 convergence bit):
|
||||
- If AVX10 is indicated, query `CPUID leaf 0x24, subleaf 0`:
|
||||
- Read `EBX[7:0]` for version number; set `AVX10`, `V1`, and optionally `V2`.
|
||||
- Read `EBX[17]` for 256-bit support → set `256W`.
|
||||
- Read `EBX[18]` for 512-bit support → set `512W`.
|
||||
- Promote `MainLevel` to `AVX10` (value 7).
|
||||
- Read `EBX[7:0]` as the numeric version; do not interpret `EBX[18:16]` as vector-width bits.
|
||||
- If subleaf 1 exists, read `ECX[2]` as `AVX10_VNNI_INT`.
|
||||
- Promote `MainLevel` to `AVX10` (value 4).
|
||||
- The `AVX512 Feature` field should still be filled for backward compatibility.
|
||||
7) Populate uArchHi:
|
||||
6) Populate uArchHi:
|
||||
- If `CPUID.7.0 EDX[15]` (HYBRID) **not** set: set `HYBRID_P | HYBRID_E` (unified = 11).
|
||||
- If HYBRID is set, read `CPUID.0x1A.0 EAX[31:24]`:
|
||||
- `0x40` (P-core) → set only `HYBRID_P` (topology = 10).
|
||||
@@ -279,4 +255,4 @@ Detection:
|
||||
|
||||
## 13) Choice for High Bits Reservation
|
||||
|
||||
`[31..24]` is reserved for AVX512 extensions/AI. `[47..45]` is reserved for AVX-family extensions (bit 44 is now `DUAL`). `[55..53]` is reserved for future AVX10 versions. uArchHi `[63..56]` bits [3..7] are reserved; bits [0..2] encode hybrid topology and SIMD-dual policy.
|
||||
`[31..24]` is reserved for AVX512 extensions/AI. `[39..37]` is reserved for AVX-family extensions. AVX10 `[47..40]` stores one tracked discrete feature plus a 7-bit version. uArchHi `[55..48]` bits [3..7] are reserved; bits [0..2] encode hybrid topology and SIMD-dual policy. `[63..56]` is reserved tail space.
|
||||
|
||||
@@ -23,19 +23,17 @@
|
||||
// bits [7..4] : Manufacture (ISA-specific)
|
||||
// bits [15..8] : MainLevel (monotonic capability)
|
||||
// bits [31..16]: AVX512 Feature
|
||||
// bits [39..32]: AMX Feature
|
||||
// bits [47..40]: AVX Feature
|
||||
// bits [55..48]: AVX10 Feature
|
||||
// bits [63..56]: uArchHi / Policy (optional)
|
||||
// bits [39..32]: AVX Feature
|
||||
// bits [47..40]: AVX10 Feature
|
||||
// bits [55..48]: uArchHi / Policy (optional)
|
||||
// bits [63..56]: Reserved for future tail extension
|
||||
// -----------------------------------------------------------------------------
|
||||
#define SIMDID_SHIFT_AVX512 16
|
||||
#define SIMDID_SHIFT_AMX 32
|
||||
#define SIMDID_SHIFT_AVX 40
|
||||
#define SIMDID_SHIFT_AVX10 48
|
||||
#define SIMDID_SHIFT_UARCH 56
|
||||
#define SIMDID_SHIFT_AVX 32
|
||||
#define SIMDID_SHIFT_AVX10 40
|
||||
#define SIMDID_SHIFT_UARCH 48
|
||||
|
||||
#define SIMDID_MASK_AVX512 (0xFFFFULL << SIMDID_SHIFT_AVX512)
|
||||
#define SIMDID_MASK_AMX (0xFFULL << SIMDID_SHIFT_AMX)
|
||||
#define SIMDID_MASK_AVX (0xFFULL << SIMDID_SHIFT_AVX)
|
||||
#define SIMDID_MASK_AVX10 (0xFFULL << SIMDID_SHIFT_AVX10)
|
||||
#define SIMDID_MASK_UARCH (0xFFULL << SIMDID_SHIFT_UARCH)
|
||||
@@ -52,16 +50,10 @@
|
||||
#define SIMDID_MAIN_LVL_SSE 0x01u /* SSE1..SSE4.2 */
|
||||
#define SIMDID_MAIN_LVL_AVX2 0x02u
|
||||
#define SIMDID_MAIN_LVL_AVX512 0x03u
|
||||
#define SIMDID_MAIN_LVL_AMX 0x04u
|
||||
#define SIMDID_MAIN_LVL_AVX10 0x05u
|
||||
#define SIMDID_MAIN_LVL_AVX10 0x04u
|
||||
|
||||
#ifndef SIMDID_AVX512_BASE
|
||||
#define SIMDID_AVX512_FP16 (1U << 13) /* relative bit 13 within [31..16] */
|
||||
#define SIMDID_AVX512_BF16 (1U << 12)
|
||||
#define SIMDID_AVX512_VNNI (1U << 11)
|
||||
#define SIMDID_AVX512_VBMI2 (1U << 10)
|
||||
#define SIMDID_AVX512_VBMI (1U << 9)
|
||||
#define SIMDID_AVX512_AI_RESERVED (1U << 8)
|
||||
#define SIMDID_AVX512_BASE (1U << 4)
|
||||
#define SIMDID_AVX512_IMPL_SHIFT 6
|
||||
#define SIMDID_AVX512_IMPL_MASK (0x3U << SIMDID_AVX512_IMPL_SHIFT)
|
||||
@@ -71,7 +63,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef SIMDID_AVX_BASE
|
||||
#define SIMDID_AVX (1U << 0) /* relative bit 0 within [47..40] */
|
||||
#define SIMDID_AVX (1U << 0) /* relative bit 0 within [39..32] */
|
||||
#define SIMDID_AVX2 (1U << 1)
|
||||
#define SIMDID_AVX_FMA (1U << 2)
|
||||
#define SIMDID_AVX_F16C (1U << 3)
|
||||
@@ -79,21 +71,12 @@
|
||||
(1U << 4) /* glued/split-lane YMM (two 128-bit units; Zen1, Hygon, VIA/Zhaoxin) */
|
||||
#endif
|
||||
|
||||
#ifndef SIMDID_AMX_TILE
|
||||
#define SIMDID_AMX_TILE (1U << 0) /* relative bit 0 within [39..32] */
|
||||
#define SIMDID_AMX_INT8 (1U << 1)
|
||||
#define SIMDID_AMX_BF16 (1U << 2)
|
||||
#ifndef SIMDID_AVX10_VERSION_MASK
|
||||
#define SIMDID_AVX10_VERSION_MASK 0x7FU /* CPUID.24H.0:EBX[7:0], saturated to 7 bits */
|
||||
#define SIMDID_AVX10_VNNI_INT (1U << 7) /* CPUID.24H.1:ECX[2] */
|
||||
#endif
|
||||
|
||||
#ifndef SIMDID_AVX10_BASE
|
||||
#define SIMDID_AVX10 (1U << 0) /* relative bit 0 within [55..48] */
|
||||
#define SIMDID_AVX10_V1 (1U << 1)
|
||||
#define SIMDID_AVX10_V2 (1U << 2)
|
||||
#define SIMDID_AVX10_256W (1U << 3)
|
||||
#define SIMDID_AVX10_512W (1U << 4)
|
||||
#endif
|
||||
|
||||
/* uArchHi ([63..56]) bitmask — core topology and SIMD-width execution policy */
|
||||
/* uArchHi ([55..48]) bitmask — core topology and SIMD-width execution policy */
|
||||
#ifndef SIMDID_UARCH_HYBRID_P
|
||||
/* Topology 2-bit field (bits [1..0] of uArchHi byte):
|
||||
* 00 = unknown (undetected hybrid type or pre-CPUID.1A hardware)
|
||||
@@ -112,7 +95,6 @@
|
||||
(SIMDID_PACK_ROOT(root) | SIMDID_PACK_MANU(manu) | SIMDID_PACK_MAIN(main))
|
||||
#define SIMDID_PACK_AVX512(avx512_bits) \
|
||||
(((uint64_t)(avx512_bits) & 0xFFFFULL) << SIMDID_SHIFT_AVX512)
|
||||
#define SIMDID_PACK_AMX(amx_bits) (((uint64_t)(amx_bits) & 0xFFULL) << SIMDID_SHIFT_AMX)
|
||||
#define SIMDID_PACK_AVX(avx_bits) (((uint64_t)(avx_bits) & 0xFFULL) << SIMDID_SHIFT_AVX)
|
||||
#define SIMDID_PACK_AVX10(avx10_bits) (((uint64_t)(avx10_bits) & 0xFFULL) << SIMDID_SHIFT_AVX10)
|
||||
#define SIMDID_PACK_UARCH(uarch_hi) (((uint64_t)(uarch_hi) & 0xFFULL) << SIMDID_SHIFT_UARCH)
|
||||
@@ -123,7 +105,6 @@
|
||||
#define SIMDID_MAIN_ENC_SSE SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_SSE)
|
||||
#define SIMDID_MAIN_ENC_AVX2 SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AVX2)
|
||||
#define SIMDID_MAIN_ENC_AVX512 SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AVX512)
|
||||
#define SIMDID_MAIN_ENC_AMX SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AMX)
|
||||
#define SIMDID_MAIN_ENC_AVX10 SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AVX10)
|
||||
|
||||
#pragma region matix function
|
||||
|
||||
@@ -32,7 +32,6 @@ SN_API void SN_DECL load_intrinsic_function(void *intrinsic_context, uint64_t id
|
||||
load_intrinsic_avx(context, simdid);
|
||||
break;
|
||||
case SIMDID_MAIN_LVL_AVX512:
|
||||
case SIMDID_MAIN_LVL_AMX:
|
||||
case SIMDID_MAIN_LVL_AVX10:
|
||||
load_intrinsic_512(context, simdid);
|
||||
break;
|
||||
@@ -65,7 +64,7 @@ void load_intrinsic_sse(sn_intrinsic *context, SIMDID id)
|
||||
|
||||
void load_intrinsic_avx(sn_intrinsic *context, SIMDID id)
|
||||
{
|
||||
char avx_seg = id.make_byte[5];
|
||||
char avx_seg = id.make_byte[4];
|
||||
char is_fma = (avx_seg & SIMDID_AVX_FMA) != 0;
|
||||
|
||||
context->city_hash_simplify = city_hash_simplify_sse;
|
||||
|
||||
@@ -36,28 +36,32 @@ static void get_cpuid(int leaf, int subleaf, int *eax, int *ebx, int *ecx, int *
|
||||
#endif
|
||||
}
|
||||
|
||||
static int xgetbv_has_xmm_ymm(void)
|
||||
/* XCR0 is per logical processor. Reading it after thread affinity is applied
|
||||
* verifies that the OS saves/restores the register state needed by this core. */
|
||||
static unsigned long long read_xcr0(void)
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
unsigned __int64 xcr0 = _xgetbv(0);
|
||||
return _xgetbv(0);
|
||||
#else
|
||||
unsigned long long xcr0 = __builtin_ia32_xgetbv(0);
|
||||
return __builtin_ia32_xgetbv(0);
|
||||
#endif
|
||||
return ((xcr0 & 0x6) == 0x6);
|
||||
}
|
||||
|
||||
static int xgetbv_has_avx512_state(void)
|
||||
static int os_has_xsave_state(unsigned long long required)
|
||||
{
|
||||
const unsigned long long mask = (1ull << 0) | (1ull << 1) | (1ull << 2) | (1ull << 5) |
|
||||
(1ull << 6);
|
||||
#if defined(_MSC_VER)
|
||||
unsigned __int64 xcr0 = _xgetbv(0);
|
||||
#else
|
||||
unsigned long long xcr0 = __builtin_ia32_xgetbv(0);
|
||||
#endif
|
||||
return ((xcr0 & mask) == mask);
|
||||
return (read_xcr0() & required) == required;
|
||||
}
|
||||
|
||||
#define XCR0_X87 (1ull << 0)
|
||||
#define XCR0_XMM (1ull << 1)
|
||||
#define XCR0_YMM (1ull << 2)
|
||||
#define XCR0_OPMASK (1ull << 5)
|
||||
#define XCR0_ZMM_HI256 (1ull << 6)
|
||||
#define XCR0_HI16_ZMM (1ull << 7)
|
||||
#define XCR0_AVX_STATE (XCR0_X87 | XCR0_XMM | XCR0_YMM)
|
||||
#define XCR0_AVX512_STATE \
|
||||
(XCR0_AVX_STATE | XCR0_OPMASK | XCR0_ZMM_HI256 | XCR0_HI16_ZMM)
|
||||
|
||||
static void decode_family_model(int cpuid1_eax, int *family, int *model)
|
||||
{
|
||||
int family_value = 0;
|
||||
@@ -83,19 +87,23 @@ static void decode_family_model(int cpuid1_eax, int *family, int *model)
|
||||
*model = model_value;
|
||||
}
|
||||
|
||||
/* AVX-512 execution-width classification for AMD, by CPU family.
|
||||
* Zen4 (0x19): single 256-bit ALU, 512-bit op = two 256-bit micro-ops (dual-pump) → DUAL.
|
||||
* Zen5+ (>=0x1A): native 512-bit execution units → NATIVE.
|
||||
* Other/future AMD families → UNKNOWN (conservative). */
|
||||
static uint64_t amd_avx512_impl(int family)
|
||||
/* AVX-512 execution-width classification for AMD.
|
||||
* Family 19h (Zen4) uses a 256-bit dual-pumped path.
|
||||
* Family 1Ah models 00h-0Fh are documented for the full-width EPYC 9005
|
||||
* implementation. Models 10h-1Fh are intentionally UNKNOWN: that CPUID
|
||||
* range is used by both full-width EPYC 9005 Zen5c and dual-pumped EPYC
|
||||
* 8005 products, and CPUID has no architectural execution-width bit. */
|
||||
static uint64_t amd_avx512_impl(int family, int model)
|
||||
{
|
||||
if (family == 0x19) {
|
||||
return SIMDID_AVX512_IMPL_DUAL;
|
||||
} else if (family >= 0x1A) {
|
||||
return SIMDID_AVX512_IMPL_NATIVE;
|
||||
} else {
|
||||
return SIMDID_AVX512_IMPL_UNKNOWN;
|
||||
}
|
||||
if (family == 0x1A) {
|
||||
if (model >= 0x00 && model <= 0x0F) {
|
||||
return SIMDID_AVX512_IMPL_NATIVE;
|
||||
}
|
||||
}
|
||||
return SIMDID_AVX512_IMPL_UNKNOWN;
|
||||
}
|
||||
|
||||
/* Returns 1 if this AMD/Hygon CPU uses split-lane YMM (two fused 128-bit execution units).
|
||||
@@ -172,7 +180,6 @@ SN_API SIMDID SN_DECL sn_get_simd_level_local()
|
||||
uint64_t main_lvl = SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_NONE);
|
||||
uint64_t avx_bits = 0;
|
||||
uint64_t avx512_bits = 0;
|
||||
uint64_t amx_bits = 0;
|
||||
uint64_t avx10_bits = 0;
|
||||
uint64_t uarch_bits = 0;
|
||||
int has_hybrid = 0;
|
||||
@@ -181,7 +188,7 @@ SN_API SIMDID SN_DECL sn_get_simd_level_local()
|
||||
main_lvl = SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_SSE);
|
||||
}
|
||||
|
||||
if (has_avx && has_osxsave && xgetbv_has_xmm_ymm()) {
|
||||
if (has_avx && has_osxsave && os_has_xsave_state(XCR0_AVX_STATE)) {
|
||||
avx_bits |= SIMDID_AVX;
|
||||
|
||||
if (is_amd_glue_ymm(vendor, cpuid1_eax) || is_via) {
|
||||
@@ -194,24 +201,15 @@ SN_API SIMDID SN_DECL sn_get_simd_level_local()
|
||||
const int has_avx2 = (ebx & (1 << 5)) != 0;
|
||||
const int has_avx512f = (ebx & (1 << 16)) != 0;
|
||||
const int has_avx512dq = (ebx & (1 << 17)) != 0;
|
||||
const int has_avx512cd = (ebx & (1 << 28)) != 0;
|
||||
const int has_avx512bw = (ebx & (1 << 30)) != 0;
|
||||
const int has_avx512vl = (ebx & (1u << 31)) != 0;
|
||||
const int has_avx512_vnni = (ecx & (1 << 11)) != 0;
|
||||
const int has_vbmi = (ecx & (1 << 1)) != 0;
|
||||
const int has_vbmi2 = (ecx & (1 << 6)) != 0;
|
||||
|
||||
const int has_amx_tile = (edx & (1 << 24)) != 0;
|
||||
const int has_amx_int8 = (edx & (1 << 25)) != 0;
|
||||
const int has_amx_bf16 = (edx & (1 << 22)) != 0;
|
||||
has_hybrid = (edx & (1 << 15)) != 0;
|
||||
|
||||
int has_bf16 = 0;
|
||||
int has_fp16 = 0;
|
||||
int has_avx10 = 0;
|
||||
if (eax >= 1) {
|
||||
get_cpuid(7, 1, &eax, &ebx, &ecx, &edx);
|
||||
has_bf16 = (eax & (1 << 5)) != 0;
|
||||
has_fp16 = (eax & (1 << 23)) != 0;
|
||||
has_avx10 = (edx & (1 << 19)) != 0;
|
||||
}
|
||||
|
||||
@@ -226,70 +224,46 @@ SN_API SIMDID SN_DECL sn_get_simd_level_local()
|
||||
main_lvl = SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AVX2);
|
||||
}
|
||||
|
||||
if (has_avx512f && xgetbv_has_avx512_state()) {
|
||||
if (has_avx512bw && has_avx512vl && has_avx512dq) {
|
||||
if (has_avx512f && has_avx512cd && has_avx512dq && has_avx512bw &&
|
||||
has_avx512vl && os_has_xsave_state(XCR0_AVX512_STATE)) {
|
||||
avx512_bits |= SIMDID_AVX512_BASE;
|
||||
}
|
||||
if (has_avx512_vnni) {
|
||||
avx512_bits |= SIMDID_AVX512_VNNI;
|
||||
}
|
||||
if (has_bf16) {
|
||||
avx512_bits |= SIMDID_AVX512_BF16;
|
||||
}
|
||||
if (has_fp16) {
|
||||
avx512_bits |= SIMDID_AVX512_FP16;
|
||||
}
|
||||
if (has_vbmi) {
|
||||
avx512_bits |= SIMDID_AVX512_VBMI;
|
||||
}
|
||||
if (has_vbmi2) {
|
||||
avx512_bits |= SIMDID_AVX512_VBMI2;
|
||||
}
|
||||
|
||||
if (is_intel) {
|
||||
avx512_bits |= SIMDID_AVX512_IMPL_NATIVE;
|
||||
} else if (is_amd) {
|
||||
avx512_bits |= amd_avx512_impl(family);
|
||||
avx512_bits |= amd_avx512_impl(family, model);
|
||||
} else {
|
||||
avx512_bits |= SIMDID_AVX512_IMPL_UNKNOWN;
|
||||
}
|
||||
|
||||
main_lvl = SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AVX512);
|
||||
|
||||
if (has_amx_tile) {
|
||||
amx_bits |= SIMDID_AMX_TILE;
|
||||
if (has_amx_int8) {
|
||||
amx_bits |= SIMDID_AMX_INT8;
|
||||
}
|
||||
if (has_amx_bf16) {
|
||||
amx_bits |= SIMDID_AMX_BF16;
|
||||
}
|
||||
main_lvl = SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AMX);
|
||||
}
|
||||
|
||||
if (has_avx10 && (max_basic_leaf >= 0x24)) {
|
||||
int a10_eax = 0;
|
||||
int a10_ebx = 0;
|
||||
int a10_ecx = 0;
|
||||
int a10_edx = 0;
|
||||
int avx10_ver = 0;
|
||||
int has_256w = 0;
|
||||
int has_512w = 0;
|
||||
|
||||
get_cpuid(0x24, 0, &a10_eax, &a10_ebx, &a10_ecx, &a10_edx);
|
||||
avx10_ver = a10_ebx & 0xFF;
|
||||
if (avx10_ver >= 1) {
|
||||
avx10_bits |= SIMDID_AVX10 | SIMDID_AVX10_V1;
|
||||
if (avx10_ver >= 2) {
|
||||
avx10_bits |= SIMDID_AVX10_V2;
|
||||
unsigned max_avx10_subleaf = (unsigned)a10_eax;
|
||||
unsigned stored_version = (unsigned)avx10_ver;
|
||||
if (stored_version > SIMDID_AVX10_VERSION_MASK) {
|
||||
stored_version = SIMDID_AVX10_VERSION_MASK;
|
||||
}
|
||||
has_256w = (a10_ebx & (1 << 17)) != 0;
|
||||
has_512w = (a10_ebx & (1 << 18)) != 0;
|
||||
if (has_256w) {
|
||||
avx10_bits |= SIMDID_AVX10_256W;
|
||||
avx10_bits = stored_version;
|
||||
|
||||
if (max_avx10_subleaf >= 1) {
|
||||
get_cpuid(0x24, 1, &a10_eax, &a10_ebx,
|
||||
&a10_ecx, &a10_edx);
|
||||
if ((a10_ecx & (1 << 2)) != 0) {
|
||||
avx10_bits |= SIMDID_AVX10_VNNI_INT;
|
||||
}
|
||||
if (has_512w) {
|
||||
avx10_bits |= SIMDID_AVX10_512W;
|
||||
}
|
||||
main_lvl = SIMDID_PACK_MAIN(SIMDID_MAIN_LVL_AVX10);
|
||||
}
|
||||
@@ -331,7 +305,6 @@ SN_API SIMDID SN_DECL sn_get_simd_level_local()
|
||||
final_mask |= manu;
|
||||
final_mask |= main_lvl;
|
||||
final_mask |= SIMDID_PACK_AVX512(avx512_bits);
|
||||
final_mask |= SIMDID_PACK_AMX(amx_bits);
|
||||
final_mask |= SIMDID_PACK_AVX(avx_bits);
|
||||
final_mask |= SIMDID_PACK_AVX10(avx10_bits);
|
||||
final_mask |= SIMDID_PACK_UARCH(uarch_bits);
|
||||
|
||||
@@ -13,19 +13,18 @@
|
||||
* [7..4] Manufacture make_byte[0] high nibble
|
||||
* [15..8] MainLevel make_byte[1]
|
||||
* [31..16] AVX512 Feature make_byte[2..3] (16 bits)
|
||||
* [39..32] AMX Feature make_byte[4]
|
||||
* [47..40] AVX Feature make_byte[5]
|
||||
* [55..48] AVX10 Feature make_byte[6]
|
||||
* [63..56] uArchHi make_byte[7]
|
||||
* [39..32] AVX Feature make_byte[4]
|
||||
* [47..40] AVX10 Feature make_byte[5]
|
||||
* [55..48] uArchHi make_byte[6]
|
||||
* [63..56] Reserved make_byte[7]
|
||||
* ----------------------------------------------------------------------- */
|
||||
|
||||
#define FIELD_MAIN(id) ((unsigned char)(id).make_byte[1])
|
||||
#define FIELD_AVX512(id) \
|
||||
((uint16_t)((unsigned char)(id).make_byte[2] | ((unsigned char)(id).make_byte[3] << 8)))
|
||||
#define FIELD_AMX(id) ((unsigned char)(id).make_byte[4])
|
||||
#define FIELD_AVX(id) ((unsigned char)(id).make_byte[5])
|
||||
#define FIELD_AVX10(id) ((unsigned char)(id).make_byte[6])
|
||||
#define FIELD_UARCH(id) ((unsigned char)(id).make_byte[7])
|
||||
#define FIELD_AVX(id) ((unsigned char)(id).make_byte[4])
|
||||
#define FIELD_AVX10(id) ((unsigned char)(id).make_byte[5])
|
||||
#define FIELD_UARCH(id) ((unsigned char)(id).make_byte[6])
|
||||
|
||||
/* Portable popcount for a 16-bit value. */
|
||||
static int popcount16(uint16_t v)
|
||||
@@ -56,9 +55,8 @@ static int impl_strength(uint16_t avx512)
|
||||
* capability set that is safe to use on BOTH cores:
|
||||
* - MainLevel : min (only assume what both cores support)
|
||||
* - AVX512 features : bitwise AND (IMPL field: pick the weaker one)
|
||||
* - AMX features : bitwise AND
|
||||
* - AVX features : bitwise AND
|
||||
* - AVX10 features : bitwise AND
|
||||
* - AVX10 version : min; discrete features: bitwise AND
|
||||
* - Root / Manu : keep left (must be same arch in practice)
|
||||
* - uArchHi : bitwise OR (HYBRID_P/E union; SIMD_DUAL set if either core is dual)
|
||||
* ----------------------------------------------------------------------- */
|
||||
@@ -92,23 +90,28 @@ SN_API SIMDID SN_DECL sn_get_unite_simd(SIMDID left, SIMDID right)
|
||||
out.make_byte[2] = (char)(merged & 0xFF);
|
||||
out.make_byte[3] = (char)((merged >> 8) & 0xFF);
|
||||
|
||||
/* AMX (byte 4): AND */
|
||||
/* AVX (byte 4): AND */
|
||||
out.make_byte[4] = left.make_byte[4] & right.make_byte[4];
|
||||
|
||||
/* AVX (byte 5): AND */
|
||||
out.make_byte[5] = left.make_byte[5] & right.make_byte[5];
|
||||
/* AVX10 (byte 5): minimum version and common discrete features. */
|
||||
unsigned char lavx10 = FIELD_AVX10(left);
|
||||
unsigned char ravx10 = FIELD_AVX10(right);
|
||||
unsigned char lver = lavx10 & SIMDID_AVX10_VERSION_MASK;
|
||||
unsigned char rver = ravx10 & SIMDID_AVX10_VERSION_MASK;
|
||||
unsigned char common = (lavx10 & ravx10) & SIMDID_AVX10_VNNI_INT;
|
||||
out.make_byte[5] = (char)((lver < rver ? lver : rver) | common);
|
||||
|
||||
/* AVX10 (byte 6): AND */
|
||||
out.make_byte[6] = left.make_byte[6] & right.make_byte[6];
|
||||
|
||||
/* uArchHi (byte 7):
|
||||
/* uArchHi (byte 6):
|
||||
* topology bits [1..0]: AND — conservative intersection (weaker topology wins)
|
||||
* SIMD_DUAL bit [2]: OR — dual if either core is dual */
|
||||
unsigned char lu = FIELD_UARCH(left);
|
||||
unsigned char ru = FIELD_UARCH(right);
|
||||
unsigned char topo = (lu & 0x3u) & (ru & 0x3u);
|
||||
unsigned char dual = (lu | ru) & (unsigned char)SIMDID_UARCH_SIMD_DUAL;
|
||||
out.make_byte[7] = (char)(topo | dual);
|
||||
out.make_byte[6] = (char)(topo | dual);
|
||||
|
||||
/* Reserved tail byte. */
|
||||
out.make_byte[7] = 0;
|
||||
|
||||
return out;
|
||||
}
|
||||
@@ -125,19 +128,18 @@ SN_API SIMDID SN_DECL sn_get_unite_simd(SIMDID left, SIMDID right)
|
||||
*
|
||||
* 1. MainLevel ([15..8])
|
||||
* Higher value = stronger. This is the primary discriminator:
|
||||
* NONE < SSE < AVX2 < AVX512 < AMX < AVX10
|
||||
* NONE < SSE < AVX2 < AVX512 < AVX10
|
||||
*
|
||||
* 2. AVX10 vector width ([55..48])
|
||||
* 2. AVX10 version and discrete features ([47..40])
|
||||
* Only meaningful when both MainLevel == AVX10.
|
||||
* 512W > 256W-only. Compared by the full AVX10 byte value since
|
||||
* width bits are in higher positions than version bits.
|
||||
* Higher versions are stronger; VNNI_INT is a tie-breaker.
|
||||
*
|
||||
* 3. AVX512 BASE bit (bit 4 of [31..16])
|
||||
* Only meaningful when both MainLevel >= AVX512.
|
||||
* BASE=1 (F+CD+VL+DQ+BW all present) > BASE=0.
|
||||
*
|
||||
* 4. AVX512 extension popcount
|
||||
* Count of set extension bits (VNNI/BF16/FP16/VBMI/VBMI2/AI_RESERVED).
|
||||
* VNNI is currently the only tracked AVX512 extension.
|
||||
* The IMPL and BASE bits are masked out before counting so they don't
|
||||
* inflate the extension count.
|
||||
*
|
||||
@@ -160,12 +162,19 @@ SN_API int SN_DECL sn_compare_simd(SIMDID left, SIMDID right)
|
||||
if (lm != rm)
|
||||
return lm > rm ? 1 : -1;
|
||||
|
||||
/* 2. AVX10 width (only when MainLevel == AVX10) */
|
||||
/* 2. AVX10 version and discrete features (only at AVX10). */
|
||||
if (lm >= SIMDID_MAIN_LVL_AVX10) {
|
||||
unsigned la = FIELD_AVX10(left);
|
||||
unsigned ra = FIELD_AVX10(right);
|
||||
if (la != ra)
|
||||
return la > ra ? 1 : -1;
|
||||
unsigned lv = la & SIMDID_AVX10_VERSION_MASK;
|
||||
unsigned rv = ra & SIMDID_AVX10_VERSION_MASK;
|
||||
if (lv != rv)
|
||||
return lv > rv ? 1 : -1;
|
||||
|
||||
int lvnni = (la & SIMDID_AVX10_VNNI_INT) != 0;
|
||||
int rvnni = (ra & SIMDID_AVX10_VNNI_INT) != 0;
|
||||
if (lvnni != rvnni)
|
||||
return lvnni ? 1 : -1;
|
||||
}
|
||||
|
||||
/* 3. AVX512 BASE (only when MainLevel >= AVX512) */
|
||||
|
||||
@@ -72,13 +72,16 @@ namespace StgSharp.RegularAnalysis.Text
|
||||
|
||||
#endregion
|
||||
|
||||
#region verb generate
|
||||
#region basic verb generate
|
||||
|
||||
private static void GenerateAlt(
|
||||
RegexAstNode node,
|
||||
[NotNull] in SequenceEmitter<string> sc,
|
||||
in List<SequenceEmitter<string>> func_list
|
||||
) { }
|
||||
)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private static void GenerateConcat(
|
||||
RegexAstNode node,
|
||||
|
||||
Reference in New Issue
Block a user