prefetch.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 2 // This file is part of the deltavm library. 3 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at: 7 8 // http://www.apache.org/licenses/LICENSE-2.0 9 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 #[macro_export] 17 macro_rules! prefetch_slice { 18 ($curve: ident, $slice_1: ident, $slice_2: ident, $prefetch_iter: ident) => { 19 if let Some((idp_1, idp_2)) = $prefetch_iter.next() { 20 $crate::msm::variable_base::prefetch::prefetch::<$curve>(&$slice_1[*idp_1 as usize]); 21 $crate::msm::variable_base::prefetch::prefetch::<$curve>(&$slice_2[*idp_2 as usize]); 22 } 23 }; 24 25 ($curve: ident, $slice_1: ident, $prefetch_iter: ident) => { 26 if let Some((idp_1, _)) = $prefetch_iter.next() { 27 $crate::msm::variable_base::prefetch::prefetch::<$curve>(&$slice_1[*idp_1 as usize]); 28 } 29 }; 30 } 31 32 #[macro_export] 33 macro_rules! prefetch_slice_write { 34 ($curve: ident, $slice_1: ident, $slice_2: ident, $prefetch_iter: ident) => { 35 if let Some((idp_1, idp_2)) = $prefetch_iter.next() { 36 $crate::msm::variable_base::prefetch::prefetch::<$curve>(&$slice_1[*idp_1 as usize]); 37 if *idp_2 != !0u32 { 38 $crate::msm::variable_base::prefetch::prefetch::<$curve>(&$slice_2[*idp_2 as usize]); 39 } 40 } 41 }; 42 } 43 44 const fn n_lines<T>() -> isize { 45 ((std::mem::size_of::<T>() - 1) / 64 + 1) as isize 46 } 47 48 #[macro_export] 49 macro_rules! unroll { 50 (0, |$i:ident| $s:stmt) => {}; 51 (1, |$i:ident| $s:stmt) => {{ 52 let $i: isize = 0; 53 $s 54 }}; 55 (2, |$i:ident| $s:stmt) => {{ 56 unroll!(1, |$i| $s); 57 let $i: isize = 1; 58 $s 59 }}; 60 (3, |$i:ident| $s:stmt) => {{ 61 unroll!(2, |$i| $s); 62 let $i: isize = 2; 63 $s 64 }}; 65 (4, |$i:ident| $s:stmt) => {{ 66 unroll!(3, |$i| $s); 67 let $i: isize = 3; 68 $s 69 }}; 70 (5, |$i:ident| $s:stmt) => {{ 71 unroll!(4, |$i| $s); 72 let $i: isize = 4; 73 $s 74 }}; 75 (6, |$i:ident| $s:stmt) => {{ 76 unroll!(5, |$i| $s); 77 let $i: isize = 5; 78 $s 79 }}; 80 (7, |$i:ident| $s:stmt) => {{ 81 unroll!(6, |$i| $s); 82 let $i: isize = 6; 83 $s 84 }}; 85 (8, |$i:ident| $s:stmt) => {{ 86 unroll!(7, |$i| $s); 87 let $i: isize = 7; 88 $s 89 }}; 90 (9, |$i:ident| $s:stmt) => {{ 91 unroll!(8, |$i| $s); 92 let $i: isize = 8; 93 $s 94 }}; 95 (10, |$i:ident| $s:stmt) => {{ 96 unroll!(9, |$i| $s); 97 let $i: isize = 9; 98 $s 99 }}; 100 (11, |$i:ident| $s:stmt) => {{ 101 unroll!(10, |$i| $s); 102 let $i: isize = 10; 103 $s 104 }}; 105 (12, |$i:ident| $s:stmt) => {{ 106 unroll!(11, |$i| $s); 107 let $i: isize = 11; 108 $s 109 }}; 110 (13, |$i:ident| $s:stmt) => {{ 111 unroll!(12, |$i| $s); 112 let $i: isize = 12; 113 $s 114 }}; 115 (14, |$i:ident| $s:stmt) => {{ 116 unroll!(13, |$i| $s); 117 let $i: isize = 13; 118 $s 119 }}; 120 (15, |$i:ident| $s:stmt) => {{ 121 unroll!(14, |$i| $s); 122 let $i: isize = 14; 123 $s 124 }}; 125 (16, |$i:ident| $s:stmt) => {{ 126 unroll!(15, |$i| $s); 127 let $i: isize = 15; 128 $s 129 }}; 130 } 131 132 /// Prefetches as many cache lines as is occupied by the type T. 133 /// We assume 64B cache lines. 134 #[allow(unsafe_code)] 135 #[inline(always)] 136 pub fn prefetch<T>(p: *const T) { 137 unsafe { 138 match n_lines::<T>() { 139 1 => unroll!(1, |i| core::arch::x86_64::_mm_prefetch( 140 (p as *const i8).offset(i * 64), 141 core::arch::x86_64::_MM_HINT_T0 142 )), 143 2 => unroll!(2, |i| core::arch::x86_64::_mm_prefetch( 144 (p as *const i8).offset(i * 64), 145 core::arch::x86_64::_MM_HINT_T0 146 )), 147 3 => unroll!(3, |i| core::arch::x86_64::_mm_prefetch( 148 (p as *const i8).offset(i * 64), 149 core::arch::x86_64::_MM_HINT_T0 150 )), 151 4 => unroll!(4, |i| core::arch::x86_64::_mm_prefetch( 152 (p as *const i8).offset(i * 64), 153 core::arch::x86_64::_MM_HINT_T0 154 )), 155 5 => unroll!(5, |i| core::arch::x86_64::_mm_prefetch( 156 (p as *const i8).offset(i * 64), 157 core::arch::x86_64::_MM_HINT_T0 158 )), 159 6 => unroll!(6, |i| core::arch::x86_64::_mm_prefetch( 160 (p as *const i8).offset(i * 64), 161 core::arch::x86_64::_MM_HINT_T0 162 )), 163 7 => unroll!(7, |i| core::arch::x86_64::_mm_prefetch( 164 (p as *const i8).offset(i * 64), 165 core::arch::x86_64::_MM_HINT_T0 166 )), 167 8 => unroll!(8, |i| core::arch::x86_64::_mm_prefetch( 168 (p as *const i8).offset(i * 64), 169 core::arch::x86_64::_MM_HINT_T0 170 )), 171 9 => unroll!(9, |i| core::arch::x86_64::_mm_prefetch( 172 (p as *const i8).offset(i * 64), 173 core::arch::x86_64::_MM_HINT_T0 174 )), 175 10 => unroll!(10, |i| core::arch::x86_64::_mm_prefetch( 176 (p as *const i8).offset(i * 64), 177 core::arch::x86_64::_MM_HINT_T0 178 )), 179 11 => unroll!(11, |i| core::arch::x86_64::_mm_prefetch( 180 (p as *const i8).offset(i * 64), 181 core::arch::x86_64::_MM_HINT_T0 182 )), 183 12 => unroll!(12, |i| core::arch::x86_64::_mm_prefetch( 184 (p as *const i8).offset(i * 64), 185 core::arch::x86_64::_MM_HINT_T0 186 )), 187 13 => unroll!(13, |i| core::arch::x86_64::_mm_prefetch( 188 (p as *const i8).offset(i * 64), 189 core::arch::x86_64::_MM_HINT_T0 190 )), 191 14 => unroll!(14, |i| core::arch::x86_64::_mm_prefetch( 192 (p as *const i8).offset(i * 64), 193 core::arch::x86_64::_MM_HINT_T0 194 )), 195 15 => unroll!(15, |i| core::arch::x86_64::_mm_prefetch( 196 (p as *const i8).offset(i * 64), 197 core::arch::x86_64::_MM_HINT_T0 198 )), 199 _ => unroll!(16, |i| core::arch::x86_64::_mm_prefetch( 200 (p as *const i8).offset(i * 64), 201 core::arch::x86_64::_MM_HINT_T0 202 )), 203 } 204 } 205 }