/ algorithms / src / msm / variable_base / prefetch.rs
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  }