MCPcopy Create free account
hub / github.com/bytecodealliance/wasmtime / optimize_pure_enode

Method optimize_pure_enode

cranelift/codegen/src/egraph/mod.rs:347–454  ·  view source on GitHub ↗

Optimizes an enode by applying any matching mid-end rewrite rules (or store-to-load forwarding, which is a special case), unioning together all possible optimized (or rewritten) forms of this expression into an eclass and returning the `Value` that represents that eclass.

(&mut self, inst: Inst)

Source from the content-addressed store, hash-verified

345 /// of this expression into an eclass and returning the `Value`
346 /// that represents that eclass.
347 fn optimize_pure_enode(&mut self, inst: Inst) -> Value {
348 // A pure node always has exactly one result.
349 let orig_value = self.func.dfg.first_result(inst);
350
351 let mut guard = TakeAndReplace::new(self, |x| &mut x.optimized_values);
352 let (ctx, optimized_values) = guard.get();
353
354 // Limit rewrite depth. When we apply optimization rules, they
355 // may create new nodes (values) and those are, recursively,
356 // optimized eagerly as soon as they are created. So we may
357 // have more than one ISLE invocation on the stack. (This is
358 // necessary so that as the toplevel builds the
359 // right-hand-side expression bottom-up, it uses the "latest"
360 // optimized values for all the constituent parts.) To avoid
361 // infinite or problematic recursion, we bound the rewrite
362 // depth to a small constant here.
363 const REWRITE_LIMIT: usize = 5;
364 if ctx.rewrite_depth >= REWRITE_LIMIT {
365 ctx.stats.rewrite_depth_limit += 1;
366 return orig_value;
367 }
368 ctx.rewrite_depth += 1;
369 trace!("Incrementing rewrite depth; now {}", ctx.rewrite_depth);
370
371 // Invoke the ISLE toplevel constructor, getting all new
372 // values produced as equivalents to this value.
373 trace!("Calling into ISLE with original value {}", orig_value);
374 ctx.stats.rewrite_rule_invoked += 1;
375 debug_assert!(optimized_values.is_empty());
376 crate::opts::generated_code::constructor_simplify(
377 &mut IsleContext { ctx },
378 orig_value,
379 optimized_values,
380 );
381
382 ctx.stats.rewrite_rule_results += optimized_values.len() as u64;
383
384 // It's not supposed to matter what order `simplify` returns values in.
385 ctx.ctrl_plane.shuffle(optimized_values);
386
387 let num_matches = optimized_values.len();
388 if num_matches > MATCHES_LIMIT {
389 trace!(
390 "Reached maximum matches limit; too many optimized values \
391 ({num_matches} > {MATCHES_LIMIT}); ignoring rest.",
392 );
393 optimized_values.truncate(MATCHES_LIMIT);
394 }
395
396 // Sort and deduplicate optimized values, in case multiple
397 // rules produced the same simplification.
398 optimized_values.sort_unstable();
399 optimized_values.dedup();
400
401 trace!(" -> returned from ISLE: {orig_value} -> {optimized_values:?}");
402
403 // Construct a union-node tree representing the new eclass
404 // that results from rewriting. If any returned value was

Callers 1

insert_pure_enodeMethod · 0.80

Calls 14

fromFunction · 0.85
first_resultMethod · 0.80
unionMethod · 0.80
merge_availabilityMethod · 0.80
newFunction · 0.50
getMethod · 0.45
lenMethod · 0.45
shuffleMethod · 0.45
truncateMethod · 0.45
findMethod · 0.45
iterMethod · 0.45
containsMethod · 0.45

Tested by

no test coverage detected