From 7ecf9d3613d14bb6eb45c8dcf1fd2eb673e33d73 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Tue, 8 Sep 2026 18:15:30 +0000 Subject: [PATCH 1/3] Seed alias analysis worklist in reverse post-order (#14290) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This visits a block's predecessors before the block itself, which minimizes the number of times we need to reprocess a block to reach the fixed point (ignoring backedges). Here are the Sightglass results (faster on 13/26 of the PCA subset; up to 1.02x faster), plus some extra benchmarks that use 1000 different globals in order to create benchmarks with many alias regions (up to 16.27x faster).
``` compilation :: cycles :: Sum Total Δ = 8422617.35 ± 280685.06 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.15x to 1.16x faster than 5e00554696-baseline.dylib! ┌──────────┬──────────┬─────────────┬──────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├──────────┼──────────┼─────────────┼──────────┼─────────────────────────────┤ │ 60331062 │ 64369397 │ 61754473.07 │ 61678752 │ 5e00554696-baseline.dylib │ ├──────────┼──────────┼─────────────┼──────────┼─────────────────────────────┤ │ 51846162 │ 55688043 │ 53331855.72 │ 53253352 │ c86906f168-A-rpo-seed.dylib │ └──────────┴──────────┴─────────────┴──────────┴─────────────────────────────┘ compilation :: instructions-retired :: Sum Total Δ = 7583044017.87 ± 17783614.28 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.05x to 1.05x faster than 5e00554696-baseline.dylib! ┌──────────────┬──────────────┬─────────────────┬──────────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├──────────────┼──────────────┼─────────────────┼──────────────┼─────────────────────────────┤ │ 168815527589 │ 168999930832 │ 168907183902.21 │ 168906273009 │ 5e00554696-baseline.dylib │ ├──────────────┼──────────────┼─────────────────┼──────────────┼─────────────────────────────┤ │ 161221272391 │ 161466420307 │ 161324139884.34 │ 161323996892 │ c86906f168-A-rpo-seed.dylib │ └──────────────┴──────────────┴─────────────────┴──────────────┴─────────────────────────────┘ compilation :: instructions-retired :: globals-1000-cfg Δ = 3488395020.90 ± 330370.05 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 16.27x to 16.27x faster than 5e00554696-baseline.dylib! ┌────────────┬────────────┬───────────────┬────────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 3714492504 │ 3720971964 │ 3716830864.19 │ 3716697153 │ 5e00554696-baseline.dylib │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 227560263 │ 229543940 │ 228435843.29 │ 228446605 │ c86906f168-A-rpo-seed.dylib │ └────────────┴────────────┴───────────────┴────────────┴─────────────────────────────┘ compilation :: instructions-retired :: globals-1000-loop Δ = 3676743569.51 ± 269112.72 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 14.98x to 14.99x faster than 5e00554696-baseline.dylib! ┌────────────┬────────────┬───────────────┬────────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 3938271014 │ 3942494061 │ 3939646001.25 │ 3939498236 │ 5e00554696-baseline.dylib │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 262014252 │ 264993857 │ 262902431.74 │ 262817743 │ c86906f168-A-rpo-seed.dylib │ └────────────┴────────────┴───────────────┴────────────┴─────────────────────────────┘ compilation :: cycles :: globals-1000-cfg Δ = 4080711.94 ± 12420.75 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 11.78x to 11.85x faster than 5e00554696-baseline.dylib! ┌─────────┬─────────┬────────────┬─────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├─────────┼─────────┼────────────┼─────────┼─────────────────────────────┤ │ 4353068 │ 4563437 │ 4458098.75 │ 4457209 │ 5e00554696-baseline.dylib │ ├─────────┼─────────┼────────────┼─────────┼─────────────────────────────┤ │ 325067 │ 427413 │ 377386.81 │ 377755 │ c86906f168-A-rpo-seed.dylib │ └─────────┴─────────┴────────────┴─────────┴─────────────────────────────┘ compilation :: cycles :: globals-1000-loop Δ = 4104661.05 ± 14351.30 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 10.61x to 10.68x faster than 5e00554696-baseline.dylib! ┌─────────┬─────────┬────────────┬─────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├─────────┼─────────┼────────────┼─────────┼─────────────────────────────┤ │ 4397623 │ 4666018 │ 4530267.27 │ 4533174 │ 5e00554696-baseline.dylib │ ├─────────┼─────────┼────────────┼─────────┼─────────────────────────────┤ │ 370362 │ 491900 │ 425606.22 │ 428477 │ c86906f168-A-rpo-seed.dylib │ └─────────┴─────────┴────────────┴─────────┴─────────────────────────────┘ compilation :: instructions-retired :: tinygo-json Δ = 107193076.80 ± 815883.64 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.02x to 1.02x faster than 5e00554696-baseline.dylib! ┌────────────┬────────────┬───────────────┬────────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 5439283619 │ 5450038733 │ 5445123463.82 │ 5445131000 │ 5e00554696-baseline.dylib │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 5332483991 │ 5345446881 │ 5337930387.02 │ 5337890931 │ c86906f168-A-rpo-seed.dylib │ └────────────┴────────────┴───────────────┴────────────┴─────────────────────────────┘ compilation :: instructions-retired :: kotlin-richards Δ = 12093387.57 ± 584630.03 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.02x to 1.02x faster than 5e00554696-baseline.dylib! ┌───────────┬───────────┬──────────────┬───────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 634797689 │ 643565242 │ 639630353.10 │ 639744730 │ 5e00554696-baseline.dylib │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 623934476 │ 631123628 │ 627536965.53 │ 627528340 │ c86906f168-A-rpo-seed.dylib │ └───────────┴───────────┴──────────────┴───────────┴─────────────────────────────┘ compilation :: instructions-retired :: meshoptimizer Δ = 2362359.47 ± 404322.82 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.01x to 1.01x faster than 5e00554696-baseline.dylib! ┌───────────┬───────────┬──────────────┬───────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 383858384 │ 390770689 │ 388053353.33 │ 388001245 │ 5e00554696-baseline.dylib │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 383261763 │ 387923421 │ 385690993.86 │ 385615471 │ c86906f168-A-rpo-seed.dylib │ └───────────┴───────────┴──────────────┴───────────┴─────────────────────────────┘ compilation :: instructions-retired :: shootout-minicsv Δ = 601519.85 ± 472227.74 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.00x to 1.01x faster than 5e00554696-baseline.dylib! ┌───────────┬───────────┬──────────────┬───────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 117035013 │ 123844363 │ 120882817.37 │ 121027989 │ 5e00554696-baseline.dylib │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 116974294 │ 123132924 │ 120281297.52 │ 120136429 │ c86906f168-A-rpo-seed.dylib │ └───────────┴───────────┴──────────────┴───────────┴─────────────────────────────┘ compilation :: instructions-retired :: quicksort Δ = 881381.59 ± 416211.85 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.00x to 1.01x faster than 5e00554696-baseline.dylib! ┌───────────┬───────────┬──────────────┬───────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 223787543 │ 229133325 │ 225969513.23 │ 225822591 │ 5e00554696-baseline.dylib │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 222127742 │ 228398304 │ 225088131.64 │ 225055771 │ c86906f168-A-rpo-seed.dylib │ └───────────┴───────────┴──────────────┴───────────┴─────────────────────────────┘ compilation :: instructions-retired :: bz2 Δ = 2312715.06 ± 480227.08 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.00x to 1.00x faster than 5e00554696-baseline.dylib! ┌───────────┬───────────┬──────────────┬───────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 737107590 │ 743849687 │ 740178352.09 │ 740078124 │ 5e00554696-baseline.dylib │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 734533054 │ 741353972 │ 737865637.03 │ 737898085 │ c86906f168-A-rpo-seed.dylib │ └───────────┴───────────┴──────────────┴───────────┴─────────────────────────────┘ compilation :: instructions-retired :: sqlite3 Δ = 17102938.31 ± 978800.03 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.00x to 1.00x faster than 5e00554696-baseline.dylib! ┌────────────┬────────────┬───────────────┬────────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 6543461309 │ 6560165030 │ 6551934323.03 │ 6551923670 │ 5e00554696-baseline.dylib │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 6529868907 │ 6542054900 │ 6534831384.72 │ 6534691956 │ c86906f168-A-rpo-seed.dylib │ └────────────┴────────────┴───────────────┴────────────┴─────────────────────────────┘ compilation :: instructions-retired :: spidermonkey-regex Δ = 118389649.00 ± 4827636.02 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.00x to 1.00x faster than 5e00554696-baseline.dylib! ┌─────────────┬─────────────┬────────────────┬─────────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├─────────────┼─────────────┼────────────────┼─────────────┼─────────────────────────────┤ │ 45963049179 │ 46016697865 │ 45985854571.04 │ 45984800772 │ 5e00554696-baseline.dylib │ ├─────────────┼─────────────┼────────────────┼─────────────┼─────────────────────────────┤ │ 45839879682 │ 45907160559 │ 45867464922.04 │ 45866804291 │ c86906f168-A-rpo-seed.dylib │ └─────────────┴─────────────┴────────────────┴─────────────┴─────────────────────────────┘ compilation :: instructions-retired :: rust-compression Δ = 6712163.12 ± 856022.61 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.00x to 1.00x faster than 5e00554696-baseline.dylib! ┌────────────┬────────────┬───────────────┬────────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 3870353384 │ 3882887385 │ 3875855295.33 │ 3876293061 │ 5e00554696-baseline.dylib │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 3863295580 │ 3875095656 │ 3869143132.21 │ 3869057316 │ c86906f168-A-rpo-seed.dylib │ └────────────┴────────────┴───────────────┴────────────┴─────────────────────────────┘ compilation :: instructions-retired :: regex Δ = 5669354.36 ± 632864.99 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.00x to 1.00x faster than 5e00554696-baseline.dylib! ┌────────────┬────────────┬───────────────┬────────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 3285972090 │ 3294088345 │ 3289597651.01 │ 3289541728 │ 5e00554696-baseline.dylib │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 3279840034 │ 3287764296 │ 3283928296.65 │ 3283956957 │ c86906f168-A-rpo-seed.dylib │ └────────────┴────────────┴───────────────┴────────────┴─────────────────────────────┘ compilation :: instructions-retired :: tract-onnx-image-classification Δ = 135367927.19 ± 14795683.99 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.00x to 1.00x faster than 5e00554696-baseline.dylib! ┌─────────────┬─────────────┬────────────────┬─────────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├─────────────┼─────────────┼────────────────┼─────────────┼─────────────────────────────┤ │ 81407549211 │ 81562568478 │ 81475588637.09 │ 81473382979 │ 5e00554696-baseline.dylib │ ├─────────────┼─────────────┼────────────────┼─────────────┼─────────────────────────────┤ │ 81256299647 │ 81465756514 │ 81340220709.90 │ 81335906227 │ c86906f168-A-rpo-seed.dylib │ └─────────────┴─────────────┴────────────────┴─────────────┴─────────────────────────────┘ compilation :: instructions-retired :: hex-simd Δ = 779004.92 ± 525403.40 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.00x to 1.00x faster than 5e00554696-baseline.dylib! ┌───────────┬───────────┬──────────────┬───────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 508671283 │ 515352203 │ 512220005.11 │ 512185404 │ 5e00554696-baseline.dylib │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 508728739 │ 515958257 │ 511441000.19 │ 511357702 │ c86906f168-A-rpo-seed.dylib │ └───────────┴───────────┴──────────────┴───────────┴─────────────────────────────┘ compilation :: instructions-retired :: libsodium-scalarmult_ed25519 Δ = 885006.64 ± 499263.19 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.00x to 1.00x faster than 5e00554696-baseline.dylib! ┌───────────┬───────────┬──────────────┬───────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 746252373 │ 753029861 │ 749924541.79 │ 749970953 │ 5e00554696-baseline.dylib │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 745419599 │ 752737391 │ 749039535.15 │ 749090622 │ c86906f168-A-rpo-seed.dylib │ └───────────┴───────────┴──────────────┴───────────┴─────────────────────────────┘ compilation :: instructions-retired :: hashset Δ = 1571708.63 ± 1175700.98 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.00x to 1.00x faster than 5e00554696-baseline.dylib! ┌────────────┬────────────┬───────────────┬────────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 1463796111 │ 1480612250 │ 1472991690.94 │ 1473144505 │ 5e00554696-baseline.dylib │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 1464040534 │ 1477349536 │ 1471419982.31 │ 1471875364 │ c86906f168-A-rpo-seed.dylib │ └────────────┴────────────┴───────────────┴────────────┴─────────────────────────────┘ compilation :: instructions-retired :: rust-html-rewriter Δ = 3230981.96 ± 641798.83 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.00x to 1.00x faster than 5e00554696-baseline.dylib! ┌────────────┬────────────┬───────────────┬────────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 3228518318 │ 3238197616 │ 3232722284.22 │ 3232812395 │ 5e00554696-baseline.dylib │ ├────────────┼────────────┼───────────────┼────────────┼─────────────────────────────┤ │ 3225242344 │ 3234092078 │ 3229491302.26 │ 3229350214 │ c86906f168-A-rpo-seed.dylib │ └────────────┴────────────┴───────────────┴────────────┴─────────────────────────────┘ compilation :: instructions-retired :: rust-protobuf Δ = 705588.07 ± 582552.52 (confidence = 99%) c86906f168-A-rpo-seed.dylib is 1.00x to 1.00x faster than 5e00554696-baseline.dylib! ┌───────────┬───────────┬──────────────┬───────────┬─────────────────────────────┐ │ Min │ Max │ Mean │ Median │ Engine │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 722339594 │ 731951556 │ 728193145.67 │ 728326686 │ 5e00554696-baseline.dylib │ ├───────────┼───────────┼──────────────┼───────────┼─────────────────────────────┤ │ 723792262 │ 731022735 │ 727487557.60 │ 727470029 │ c86906f168-A-rpo-seed.dylib │ └───────────┴───────────┴──────────────┴───────────┴─────────────────────────────┘ ```
--- cranelift/codegen/src/alias_analysis.rs | 26 +++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/cranelift/codegen/src/alias_analysis.rs b/cranelift/codegen/src/alias_analysis.rs index cc45328f7c95..e6cb6fce467f 100644 --- a/cranelift/codegen/src/alias_analysis.rs +++ b/cranelift/codegen/src/alias_analysis.rs @@ -867,20 +867,26 @@ impl<'a> AliasAnalysis<'a> { } fn compute_block_input_states(&mut self, func: &Function) { - let mut queue = vec![]; - let mut queue_set = FxHashSet::default(); - let entry = func.layout.entry_block().unwrap(); - queue.push(entry); - queue_set.insert(entry); + self.block_input.insert(entry, LastStores::default()); + + // Seed the worklist in reverse post-order (well, post order, but + // visited in reverse due to popping). This visits a block's + // predecessors before the block itself, which minimizes the number of + // times we need to reprocess a block to reach the fixed point (ignoring + // backedges). + let mut queue = self.domtree.cfg_postorder().to_vec(); + let mut queue_set: FxHashSet = queue.iter().copied().collect(); while let Some(block) = queue.pop() { queue_set.remove(&block); - let mut state = self - .block_input - .entry(block) - .or_insert_with(|| LastStores::default()) - .clone(); + + let Some(mut state) = self.block_input.get(&block).cloned() else { + // Nothing has propagated into this block yet, so there is + // nothing to propagate out of it. If/when some predecessor gets + // state to propagate to this block, it will be re-enqueued. + continue; + }; trace!("analyzing {block:?}"); trace!(" initial block state = {state:?}"); From 8680635e77606202a24c783ab2c6c932db66e4da Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Tue, 8 Sep 2026 23:52:32 +0000 Subject: [PATCH 2/3] Fix subtle ISLE extractor issue leading to incorrect matching in `*mul_overflow` lowering. (#14295) * Fix subtle ISLE extractor issue leading to incorrect matching in `*mul_overflow` lowering. In #14293, a test case that uses the *first* result (i.e., the product) of an `smul_overflow` operator as a condition (e.g. as part of `icmp eq` comparing to zero) incorrectly triggers the lowering rule I added in #14254 which was meant to match only compare-to-zero on the *second* (overflow) result. This was a result if a fairly subtle issue involving auto-conversions in ISLE. I had written ``` (rule (is_nonzero (second_result umul @ (smul_overflow ...))) ...) ``` where the intent was to match an `is_nonzero` (which is a helper term) lowering with the second result (overflow flag) of the `smul_overflow`. `second_result` has a term signature `(Value) Inst`, in other words it takes an `Inst` and returns an `Option`.` `is_nonzero` takes a `Value`. So we auto-convert the `Value` in the first arg position of `is_nonzer` to an `Inst`; that uses `def_inst`, which looks up the defining instruction of the given value. Then `second_result` takes that `Inst` and gives the second value. But then the next level, `(smul_overflow ...)`, *again* uses `def_inst` and goes from the (second result) `Value` back to the inst and matches. In other words, we're too permissive with the autoconversions on `Value` to `Inst`; all of this was designed at a time when we more or less only handled single-result instructions with any nontrivial lowering rule, so the two were mostly interchangeable. The handling for the overflow-flag ops changes that. The specific step in that chain above that is unambiguously wrong wrt intent is (first result) `Value` -> `Inst` -> `second_result` matching. So this PR instead introduces `is_second_result` that is `Value` -> `Option` and matches only when the specific `Value` is the second result of an instruction. This does have me thinking a bit more about the role that the `Value` -> `Inst` autoconvert matching plays. It is absolutely essential to the ergonomics of ISLE: without it, we couldn't write ``` (rule (lower (iadd (imul a b) c)) ...) ``` because `iadd`'s args are `Value`s and we need to match back to an `Inst` for `imul`. *But* we also have cases like the one in this PR where we really shouldn't be so permissive. Perhaps we want a kind of type modifier (`=Value` ?) that means "exactly this type, not autoconverted". I'll bring this up in the Cranelift meeting this week. Fixes #14293. * Review feedback. * Test minimization. --- cranelift/codegen/src/isa/aarch64/inst.isle | 14 +++++++------- cranelift/codegen/src/isa/x64/inst.isle | 10 +++++----- cranelift/codegen/src/machinst/isle.rs | 14 ++++++++++++++ cranelift/codegen/src/prelude_lower.isle | 13 +++++++++++++ .../filetests/filetests/runtests/issue-14293.clif | 15 +++++++++++++++ 5 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 cranelift/filetests/filetests/runtests/issue-14293.clif diff --git a/cranelift/codegen/src/isa/aarch64/inst.isle b/cranelift/codegen/src/isa/aarch64/inst.isle index b91d7657006f..281ab5d80a10 100644 --- a/cranelift/codegen/src/isa/aarch64/inst.isle +++ b/cranelift/codegen/src/isa/aarch64/inst.isle @@ -4992,7 +4992,7 @@ ;; give an opportunistic def of the other output. (rule 4 (is_nonzero - (second_result uadd @ (uadd_overflow (ty_32_or_64 ty) x y))) + (is_second_result uadd @ (uadd_overflow (ty_32_or_64 ty) x y))) (if-let (first_result sum_value) uadd) (let ((producer ProducesFlags (alu_rrr_with_flags_paired ty x y (ALUOp.AddS)))) (CondResult.Cond @@ -5012,7 +5012,7 @@ ;; cmp out, out, uxt{b,h} (rule 5 (is_nonzero - (second_result umul @ (umul_overflow (fits_in_16 ty) a b))) + (is_second_result umul @ (umul_overflow (fits_in_16 ty) a b))) (if-let (first_result prod_value) umul) (let ((a_uext Reg (put_in_reg_zext32 a)) (b_uext Reg (put_in_reg_zext32 b)) @@ -5031,7 +5031,7 @@ ;; cmp out, out, uxtw (rule 6 (is_nonzero - (second_result umul @ (umul_overflow $I32 a b))) + (is_second_result umul @ (umul_overflow $I32 a b))) (if-let (first_result prod_value) umul) (let ((dst WritableReg (temp_writable_reg $I64)) (producer ProducesFlags @@ -5048,7 +5048,7 @@ ;; cmp tmp, #0 (rule 7 (is_nonzero - (second_result umul @ (umul_overflow $I64 a b))) + (is_second_result umul @ (umul_overflow $I64 a b))) (let ((tmp Reg (umulh $I64 a b)) (producer ProducesFlags (cmp64_imm tmp (u8_into_imm12 0)))) (CondResult.Cond producer (Cond.Ne)))) @@ -5057,7 +5057,7 @@ ;; cmp out, out, sxt{b,h} (rule 8 (is_nonzero - (second_result smul @ (smul_overflow (fits_in_16 ty) a b))) + (is_second_result smul @ (smul_overflow (fits_in_16 ty) a b))) (if-let (first_result prod_value) smul) (let ((a_sext Reg (put_in_reg_sext32 a)) (b_sext Reg (put_in_reg_sext32 b)) @@ -5076,7 +5076,7 @@ ;; cmp out, out, sxtw (rule 9 (is_nonzero - (second_result smul @ (smul_overflow $I32 a b))) + (is_second_result smul @ (smul_overflow $I32 a b))) (if-let (first_result prod_value) smul) (let ((dst WritableReg (temp_writable_reg $I64)) (producer ProducesFlags @@ -5093,7 +5093,7 @@ ;; cmp tmp, out, asr #63 (rule 10 (is_nonzero - (second_result smul @ (smul_overflow $I64 a b))) + (is_second_result smul @ (smul_overflow $I64 a b))) (if-let (first_result prod_value) smul) (let ((prod Reg (put_in_reg prod_value)) (tmp Reg (smulh $I64 a b)) diff --git a/cranelift/codegen/src/isa/x64/inst.isle b/cranelift/codegen/src/isa/x64/inst.isle index d1744469c855..711c68fe8456 100644 --- a/cranelift/codegen/src/isa/x64/inst.isle +++ b/cranelift/codegen/src/isa/x64/inst.isle @@ -3879,7 +3879,7 @@ ;; opportunistic def of the other output. (rule 3 (is_nonzero - (second_result uadd @ (uadd_overflow (fits_in_64 ty) x y))) + (is_second_result uadd @ (uadd_overflow (fits_in_64 ty) x y))) (if-let (first_result sum_value) uadd) (let ((producer ProducesFlags (x64_add_with_flags_paired ty x y))) (CondResult.CC @@ -3892,7 +3892,7 @@ ;; `mul` of narrow types), so no extra compare is needed. (rule 4 (is_nonzero - (second_result umul @ (umul_overflow _ x y @ (value_type (ty_int_ref_16_to_64 ty))))) + (is_second_result umul @ (umul_overflow _ x y @ (value_type (ty_int_ref_16_to_64 ty))))) (if-let (first_result prod_value) umul) (let ((producer ProducesFlags (x64_mul_lo_with_flags_paired ty false x y))) (CondResult.CC @@ -3901,7 +3901,7 @@ (rule 5 (is_nonzero - (second_result umul @ (umul_overflow _ x y @ (value_type $I8)))) + (is_second_result umul @ (umul_overflow _ x y @ (value_type $I8)))) (if-let (first_result prod_value) umul) (let ((producer ProducesFlags (x64_mul8_with_flags_paired false x y))) (CondResult.CC @@ -3910,7 +3910,7 @@ (rule 6 (is_nonzero - (second_result smul @ (smul_overflow _ x y @ (value_type (ty_int_ref_16_to_64 ty))))) + (is_second_result smul @ (smul_overflow _ x y @ (value_type (ty_int_ref_16_to_64 ty))))) (if-let (first_result prod_value) smul) (let ((producer ProducesFlags (x64_mul_lo_with_flags_paired ty true x y))) (CondResult.CC @@ -3919,7 +3919,7 @@ (rule 7 (is_nonzero - (second_result smul @ (smul_overflow _ x y @ (value_type $I8)))) + (is_second_result smul @ (smul_overflow _ x y @ (value_type $I8)))) (if-let (first_result prod_value) smul) (let ((producer ProducesFlags (x64_mul8_with_flags_paired true x y))) (CondResult.CC diff --git a/cranelift/codegen/src/machinst/isle.rs b/cranelift/codegen/src/machinst/isle.rs index 0d4288bd6dba..a8c81dd3cbbe 100644 --- a/cranelift/codegen/src/machinst/isle.rs +++ b/cranelift/codegen/src/machinst/isle.rs @@ -213,6 +213,20 @@ macro_rules! isle_lower_prelude_methods { .copied() } + #[inline] + fn is_second_result(&mut self, val: Value) -> Option { + let inst = self.def_inst(val)?; + let is_match = self + .lower_ctx + .dfg() + .inst_results(inst) + .iter() + .skip(1) + .next() + == Some(&val); + if is_match { Some(val) } else { None } + } + #[inline] fn second_result_used(&mut self, inst: Inst) -> bool { let second_result = self.lower_ctx.dfg().inst_results(inst).get(1).copied(); diff --git a/cranelift/codegen/src/prelude_lower.isle b/cranelift/codegen/src/prelude_lower.isle index 46ce41d47ae2..3e0d88672d9b 100644 --- a/cranelift/codegen/src/prelude_lower.isle +++ b/cranelift/codegen/src/prelude_lower.isle @@ -301,10 +301,23 @@ (extern extractor first_result first_result) ;; Extract the second result value of the given instruction. +;; +;; Be careful using this: if used to match on a *`Value`*, the +;; auto-converter will take that `Value` to its defining `Inst`, then +;; the inner result of this extractor will be the second def of the +;; value; in other words, it will *fetch* the second result but will +;; not *assert/only match if* the initial `Value` is the second +;; result. Use `is_second_result` for that. (spec (second_result value) (provide (= result value))) (decl second_result (Value) Inst) (extern extractor second_result second_result) +;; Determine whether the given value is the second result of its +;; defining instruction. +(spec (is_second_result value) (provide (= result value))) +(decl is_second_result (Value) Value) +(extern extractor is_second_result is_second_result) + ;; Returns whether an instruction's second result still has uses to serve in ;; the lowering scan. Overflow operations use this while lowering their first ;; (non-boolean) result. diff --git a/cranelift/filetests/filetests/runtests/issue-14293.clif b/cranelift/filetests/filetests/runtests/issue-14293.clif new file mode 100644 index 000000000000..54ed9aca90cc --- /dev/null +++ b/cranelift/filetests/filetests/runtests/issue-14293.clif @@ -0,0 +1,15 @@ +test run +set opt_level=speed_and_size +target x86_64 +target aarch64 + +function %a(i64) -> i8 { +block0(v0: i64): + v1, v2 = smul_overflow.i64 v0, v0 + v3 = iconst.i64 0 + v4 = icmp eq v1, v3 + return v4 +} + +; run: %a(0) == 1 +; run: %a(8192) == 0 From e52e667217d49f832be7310f78a8570b0a82e649 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 9 Sep 2026 04:04:27 +0000 Subject: [PATCH 3/3] Adjust the recursive `run_concurrent` check (#14302) This commit adjust the previous `check_recursive_run` function found in `concurrent.rs` to instead be a check of the now-present `event_loop_running` bool. This allows disparate stores to run recursively as there should be no issue with that but still requires a single store just once and never recursively. This was discovered in Spin's update to Wasmtime 49 at spinframework/spin#3710 where delegation of an HTTP request from a p3 component (executed with `run_concurrent`) to a p2 component (instantiated with `instantiate_async`) started panicking with this recursive check in Wasmtime 49. The cause of this was the refactoring in #14146 where all instantiation now simulates the concurrent event loop where enabled for the `start` function. Spin executes the components in different stores, however, which is how this commit fixes that case. --- .../src/runtime/component/concurrent.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/crates/wasmtime/src/runtime/component/concurrent.rs b/crates/wasmtime/src/runtime/component/concurrent.rs index ce8e46eb6488..b7f8593a1f93 100644 --- a/crates/wasmtime/src/runtime/component/concurrent.rs +++ b/crates/wasmtime/src/runtime/component/concurrent.rs @@ -1224,7 +1224,13 @@ impl StoreContextMut<'_, T> { trap_on_idle: bool, ) -> Result { debug_assert!(self.0.concurrency_support()); - check_recursive_run(); + let already_running = self + .0 + .concurrent_state_mut_already_forced_current_thread() + .event_loop_running; + if already_running { + bail!("Recursive `StoreContextMut::run_concurrent` calls not supported") + } let token = StoreToken::new(self.as_context_mut()); struct Dropper<'a, T: 'static, V> { @@ -6103,16 +6109,6 @@ fn check_ambient_store(id: StoreId) { }); } -/// Assert that `StoreContextMut::run_concurrent` has not been called from -/// within an store's event loop. -fn check_recursive_run() { - tls::try_get(|store| { - if !matches!(store, tls::TryGet::None) { - panic!("Recursive `StoreContextMut::run_concurrent` calls not supported") - } - }); -} - fn unpack_callback_code(code: u32) -> (u32, u32) { (code & 0xF, code >> 4) }