prefetch.rs
1 // Copyright (c) 2025-2026 ACDC Network 2 // This file is part of the alphavm library. 3 // 4 // Alpha Chain | Delta Chain Protocol 5 // International Monetary Graphite. 6 // 7 // Derived from Aleo (https://aleo.org) and ProvableHQ (https://provable.com). 8 // They built world-class ZK infrastructure. We installed the EASY button. 9 // Their cryptography: elegant. Our modifications: bureaucracy-compatible. 10 // Original brilliance: theirs. Robert's Rules: ours. Bugs: definitely ours. 11 // 12 // Original Aleo/ProvableHQ code subject to Apache 2.0 https://www.apache.org/licenses/LICENSE-2.0 13 // All modifications and new work: CC0 1.0 Universal Public Domain Dedication. 14 // No rights reserved. No permission required. No warranty. No refunds. 15 // 16 // https://creativecommons.org/publicdomain/zero/1.0/ 17 // SPDX-License-Identifier: CC0-1.0 18 19 #[macro_export] 20 macro_rules! prefetch_slice { 21 ($curve: ident, $slice_1: ident, $slice_2: ident, $prefetch_iter: ident) => { 22 if let Some((idp_1, idp_2)) = $prefetch_iter.next() { 23 $crate::msm::variable_base::prefetch::prefetch::<$curve>(&$slice_1[*idp_1 as usize]); 24 $crate::msm::variable_base::prefetch::prefetch::<$curve>(&$slice_2[*idp_2 as usize]); 25 } 26 }; 27 28 ($curve: ident, $slice_1: ident, $prefetch_iter: ident) => { 29 if let Some((idp_1, _)) = $prefetch_iter.next() { 30 $crate::msm::variable_base::prefetch::prefetch::<$curve>(&$slice_1[*idp_1 as usize]); 31 } 32 }; 33 } 34 35 #[macro_export] 36 macro_rules! prefetch_slice_write { 37 ($curve: ident, $slice_1: ident, $slice_2: ident, $prefetch_iter: ident) => { 38 if let Some((idp_1, idp_2)) = $prefetch_iter.next() { 39 $crate::msm::variable_base::prefetch::prefetch::<$curve>(&$slice_1[*idp_1 as usize]); 40 if *idp_2 != !0u32 { 41 $crate::msm::variable_base::prefetch::prefetch::<$curve>(&$slice_2[*idp_2 as usize]); 42 } 43 } 44 }; 45 } 46 47 const fn n_lines<T>() -> isize { 48 ((std::mem::size_of::<T>() - 1) / 64 + 1) as isize 49 } 50 51 #[macro_export] 52 macro_rules! unroll { 53 (0, |$i:ident| $s:stmt) => {}; 54 (1, |$i:ident| $s:stmt) => {{ 55 let $i: isize = 0; 56 $s 57 }}; 58 (2, |$i:ident| $s:stmt) => {{ 59 unroll!(1, |$i| $s); 60 let $i: isize = 1; 61 $s 62 }}; 63 (3, |$i:ident| $s:stmt) => {{ 64 unroll!(2, |$i| $s); 65 let $i: isize = 2; 66 $s 67 }}; 68 (4, |$i:ident| $s:stmt) => {{ 69 unroll!(3, |$i| $s); 70 let $i: isize = 3; 71 $s 72 }}; 73 (5, |$i:ident| $s:stmt) => {{ 74 unroll!(4, |$i| $s); 75 let $i: isize = 4; 76 $s 77 }}; 78 (6, |$i:ident| $s:stmt) => {{ 79 unroll!(5, |$i| $s); 80 let $i: isize = 5; 81 $s 82 }}; 83 (7, |$i:ident| $s:stmt) => {{ 84 unroll!(6, |$i| $s); 85 let $i: isize = 6; 86 $s 87 }}; 88 (8, |$i:ident| $s:stmt) => {{ 89 unroll!(7, |$i| $s); 90 let $i: isize = 7; 91 $s 92 }}; 93 (9, |$i:ident| $s:stmt) => {{ 94 unroll!(8, |$i| $s); 95 let $i: isize = 8; 96 $s 97 }}; 98 (10, |$i:ident| $s:stmt) => {{ 99 unroll!(9, |$i| $s); 100 let $i: isize = 9; 101 $s 102 }}; 103 (11, |$i:ident| $s:stmt) => {{ 104 unroll!(10, |$i| $s); 105 let $i: isize = 10; 106 $s 107 }}; 108 (12, |$i:ident| $s:stmt) => {{ 109 unroll!(11, |$i| $s); 110 let $i: isize = 11; 111 $s 112 }}; 113 (13, |$i:ident| $s:stmt) => {{ 114 unroll!(12, |$i| $s); 115 let $i: isize = 12; 116 $s 117 }}; 118 (14, |$i:ident| $s:stmt) => {{ 119 unroll!(13, |$i| $s); 120 let $i: isize = 13; 121 $s 122 }}; 123 (15, |$i:ident| $s:stmt) => {{ 124 unroll!(14, |$i| $s); 125 let $i: isize = 14; 126 $s 127 }}; 128 (16, |$i:ident| $s:stmt) => {{ 129 unroll!(15, |$i| $s); 130 let $i: isize = 15; 131 $s 132 }}; 133 } 134 135 /// Prefetches as many cache lines as is occupied by the type T. 136 /// We assume 64B cache lines. 137 #[allow(unsafe_code)] 138 #[inline(always)] 139 pub fn prefetch<T>(p: *const T) { 140 unsafe { 141 match n_lines::<T>() { 142 1 => unroll!(1, |i| core::arch::x86_64::_mm_prefetch( 143 (p as *const i8).offset(i * 64), 144 core::arch::x86_64::_MM_HINT_T0 145 )), 146 2 => unroll!(2, |i| core::arch::x86_64::_mm_prefetch( 147 (p as *const i8).offset(i * 64), 148 core::arch::x86_64::_MM_HINT_T0 149 )), 150 3 => unroll!(3, |i| core::arch::x86_64::_mm_prefetch( 151 (p as *const i8).offset(i * 64), 152 core::arch::x86_64::_MM_HINT_T0 153 )), 154 4 => unroll!(4, |i| core::arch::x86_64::_mm_prefetch( 155 (p as *const i8).offset(i * 64), 156 core::arch::x86_64::_MM_HINT_T0 157 )), 158 5 => unroll!(5, |i| core::arch::x86_64::_mm_prefetch( 159 (p as *const i8).offset(i * 64), 160 core::arch::x86_64::_MM_HINT_T0 161 )), 162 6 => unroll!(6, |i| core::arch::x86_64::_mm_prefetch( 163 (p as *const i8).offset(i * 64), 164 core::arch::x86_64::_MM_HINT_T0 165 )), 166 7 => unroll!(7, |i| core::arch::x86_64::_mm_prefetch( 167 (p as *const i8).offset(i * 64), 168 core::arch::x86_64::_MM_HINT_T0 169 )), 170 8 => unroll!(8, |i| core::arch::x86_64::_mm_prefetch( 171 (p as *const i8).offset(i * 64), 172 core::arch::x86_64::_MM_HINT_T0 173 )), 174 9 => unroll!(9, |i| core::arch::x86_64::_mm_prefetch( 175 (p as *const i8).offset(i * 64), 176 core::arch::x86_64::_MM_HINT_T0 177 )), 178 10 => unroll!(10, |i| core::arch::x86_64::_mm_prefetch( 179 (p as *const i8).offset(i * 64), 180 core::arch::x86_64::_MM_HINT_T0 181 )), 182 11 => unroll!(11, |i| core::arch::x86_64::_mm_prefetch( 183 (p as *const i8).offset(i * 64), 184 core::arch::x86_64::_MM_HINT_T0 185 )), 186 12 => unroll!(12, |i| core::arch::x86_64::_mm_prefetch( 187 (p as *const i8).offset(i * 64), 188 core::arch::x86_64::_MM_HINT_T0 189 )), 190 13 => unroll!(13, |i| core::arch::x86_64::_mm_prefetch( 191 (p as *const i8).offset(i * 64), 192 core::arch::x86_64::_MM_HINT_T0 193 )), 194 14 => unroll!(14, |i| core::arch::x86_64::_mm_prefetch( 195 (p as *const i8).offset(i * 64), 196 core::arch::x86_64::_MM_HINT_T0 197 )), 198 15 => unroll!(15, |i| core::arch::x86_64::_mm_prefetch( 199 (p as *const i8).offset(i * 64), 200 core::arch::x86_64::_MM_HINT_T0 201 )), 202 _ => unroll!(16, |i| core::arch::x86_64::_mm_prefetch( 203 (p as *const i8).offset(i * 64), 204 core::arch::x86_64::_MM_HINT_T0 205 )), 206 } 207 } 208 }