@@ -54,7 +54,7 @@ impl hash::Hash for Function {
5454///
5555/// This asserts that the function at `fnptr` contains the instruction
5656/// `expected` provided.
57- pub fn assert ( shim_addr : usize , fnname : & str , expected : & str , not : & [ & str ] ) {
57+ pub fn assert ( shim_addr : usize , fnname : & str , expected : & str , not : & [ & str ] , limit : Option < usize > ) {
5858 // Make sure that the shim is not removed
5959 black_box ( shim_addr) ;
6060
@@ -131,68 +131,67 @@ pub fn assert(shim_addr: usize, fnname: &str, expected: &str, not: &[&str]) {
131131
132132 let instruction_limit = std:: env:: var ( "STDARCH_ASSERT_INSTR_LIMIT" )
133133 . ok ( )
134- . map_or_else (
135- || match expected {
136- // `cpuid` returns a pretty big aggregate structure, so exempt
137- // it from the slightly more restrictive 22 instructions below.
138- "cpuid" => 30 ,
139-
140- // These require 8 loads and stores, so it _just_ overflows the limit
141- "aesencwide128kl" | "aesencwide256kl" | "aesdecwide128kl" | "aesdecwide256kl" => 24 ,
142-
143- // Apparently, on Windows, LLVM generates a bunch of
144- // saves/restores of xmm registers around these instructions,
145- // which exceeds the limit of 20 below. As it seems dictated by
146- // Windows's ABI (I believe?), we probably can't do much
147- // about it.
148- "vzeroall" | "vzeroupper" if cfg ! ( windows ) => 30 ,
149-
150- // Intrinsics using `cvtpi2ps` are typically "composites" and
151- // in some cases exceed the limit.
152- "cvtpi2ps" => 25 ,
153- // core_arch/src/arm_shared/simd32
154- // vfmaq_n_f32_vfma : #instructions = 26 >= 22 (limit)
155- "usad8" | "vfma" | "vfms" => 27 ,
156- "qadd8 " | "qsub8 " | "sadd8" | "sel" | "shadd8" | "shsub8" | "usub8" | "ssub8" => 29 ,
157- // core_arch/src/arm_shared/simd32
158- // vst1q_s64_x4_vst1 : #instructions = 27 >= 22 (limit)
159- "vld3" => 28 ,
160- // core_arch/src/arm_shared/simd32
161- // vld4q_lane_u32_vld4 : #instructions = 36 >= 22 (limit)
162- "vld4" => 37 ,
163- // core_arch/src/arm_shared/simd32
164- // vst1q_s64_x4_vst1 : #instructions = 40 >= 22 (limit)
165- "vst1" => 41 ,
166- // core_arch/src/arm_shared/simd32
167- // vst3q_u32_vst3 : #instructions = 25 >= 22 (limit)
168- "vst3" => 26 ,
169- // core_arch/src/arm_shared/simd32
170- // vst4q_u32_vst4 : #instructions = 33 >= 22 (limit)
171- "vst4" => 34 ,
172-
173- // core_arch/src/arm_shared/simd32
174- // vst1q_p64_x4_nop : #instructions = 33 >= 22 (limit)
175- "nop" if fnname . contains ( "vst1q_p64" ) => 34 ,
176-
177- // AMX intrinsics generate a lot of move instructions to load/store the tile registers
178- // due to Rust ABI
179- _ if fnname . contains ( "___tile" ) => 165 ,
180-
181- // Original limit was 20 instructions, but ARM DSP Intrinsics
182- // are exactly 20 instructions long. So, bump the limit to 22
183- // instead of adding here a long list of exceptions.
184- _ => {
185- // aarch64_be may add reverse instructions which increases
186- // the number of instructions generated.
187- if cfg ! ( all ( target_endian = "big" , target_arch = "aarch64" ) ) {
188- 32
189- } else {
190- 22
191- }
134+ . map ( |v| v . parse ( ) . unwrap ( ) )
135+ . or ( limit . map ( |n| n + 1 ) ) // adjust for the `<` below: `limit = 2` means 2 instructions is okay
136+ . unwrap_or_else ( || match expected {
137+ // `cpuid` returns a pretty big aggregate structure, so exempt
138+ // it from the slightly more restrictive 22 instructions below.
139+ "cpuid" => 30 ,
140+
141+ // These require 8 loads and stores, so it _just_ overflows the limit
142+ "aesencwide128kl" | "aesencwide256kl" | "aesdecwide128kl" | "aesdecwide256kl" => 24 ,
143+
144+ // Apparently, on Windows, LLVM generates a bunch of
145+ // saves/restores of xmm registers around these instructions,
146+ // which exceeds the limit of 20 below. As it seems dictated by
147+ // Windows's ABI (I believe?), we probably can't do much
148+ // about it.
149+ "vzeroall" | "vzeroupper" if cfg ! ( windows ) => 30 ,
150+
151+ // Intrinsics using `cvtpi2ps` are typically "composites" and
152+ // in some cases exceed the limit.
153+ "cvtpi2ps" => 25 ,
154+ // core_arch/src/arm_shared/simd32
155+ // vfmaq_n_f32_vfma : #instructions = 26 >= 22 (limit)
156+ "usad8 " | "vfma " | "vfms" => 27 ,
157+ "qadd8" | "qsub8" | "sadd8" | "sel" | "shadd8" | "shsub8" | "usub8" | "ssub8" => 29 ,
158+ // core_arch/src/arm_shared/simd32
159+ // vst1q_s64_x4_vst1 : #instructions = 27 >= 22 (limit)
160+ "vld3" => 28 ,
161+ // core_arch/src/arm_shared/simd32
162+ // vld4q_lane_u32_vld4 : #instructions = 36 >= 22 (limit)
163+ "vld4" => 37 ,
164+ // core_arch/src/arm_shared/simd32
165+ // vst1q_s64_x4_vst1 : #instructions = 40 >= 22 (limit)
166+ "vst1" => 41 ,
167+ // core_arch/src/arm_shared/simd32
168+ // vst3q_u32_vst3 : #instructions = 25 >= 22 (limit)
169+ "vst3" => 26 ,
170+ // core_arch/src/arm_shared/simd32
171+ // vst4q_u32_vst4 : #instructions = 33 >= 22 (limit)
172+ "vst4" => 34 ,
173+
174+ // core_arch/src/arm_shared/simd32
175+ // vst1q_p64_x4_nop : #instructions = 33 >= 22 (limit)
176+ "nop" if fnname . contains ( "vst1q_p64" ) => 34 ,
177+
178+ // AMX intrinsics generate a lot of move instructions to load/store the tile registers
179+ // due to Rust ABI
180+ _ if fnname . contains ( "___tile" ) => 165 ,
181+
182+ // Original limit was 20 instructions, but ARM DSP Intrinsics
183+ // are exactly 20 instructions long. So, bump the limit to 22
184+ // instead of adding here a long list of exceptions.
185+ _ => {
186+ // aarch64_be may add reverse instructions which increases
187+ // the number of instructions generated.
188+ if cfg ! ( all ( target_endian = "big" , target_arch = "aarch64" ) ) {
189+ 32
190+ } else {
191+ 22
192192 }
193- } ,
194- |v| v. parse ( ) . unwrap ( ) ,
195- ) ;
193+ }
194+ } ) ;
196195 let probably_only_one_instruction = instrs. len ( ) < instruction_limit;
197196
198197 if found && found_bad. is_none ( ) && probably_only_one_instruction && !inlining_failed {
0 commit comments