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

Method simplify_skeleton_inst

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

Find the best simplification of the given skeleton instruction, if any, by consulting our `simplify_skeleton` ISLE rules.

(&mut self, inst: Inst)

Source from the content-addressed store, hash-verified

576 /// Find the best simplification of the given skeleton instruction, if any,
577 /// by consulting our `simplify_skeleton` ISLE rules.
578 fn simplify_skeleton_inst(&mut self, inst: Inst) -> Option<SkeletonInstSimplification> {
579 // NB: we support simplifying branch terminators (e.g. `brif` with a
580 // constant condition into `jump`). This can make blocks unreachable,
581 // but a separate `eliminate_unreachable_code` pass handles removing
582 // them after the egraph pass completes.
583 //
584 // We do NOT yet support simplifying non-terminators into terminators
585 // (e.g. `trapz` into `trap`) because that would introduce a
586 // terminator in the middle of a block, requiring removal of trailing
587 // instructions and their value definitions.
588
589 let mut guard = TakeAndReplace::new(self, |x| &mut x.optimized_insts);
590 let (ctx, optimized_insts) = guard.get();
591
592 crate::opts::generated_code::constructor_simplify_skeleton(
593 &mut IsleContext { ctx },
594 inst,
595 optimized_insts,
596 );
597
598 let simplifications_len = optimized_insts.len();
599 log::trace!(" -> simplify_skeleton: yielded {simplifications_len} simplification(s)");
600 if simplifications_len > MATCHES_LIMIT {
601 log::trace!(" too many candidate simplifications; truncating to {MATCHES_LIMIT}");
602 optimized_insts.truncate(MATCHES_LIMIT);
603 }
604
605 // Find the best simplification, if any, from our candidates.
606 //
607 // Unlike simplifying pure values, we do not add side-effectful
608 // instructions to the egraph, nor do we extract the best version via
609 // dynamic programming and considering the costs of operands. Instead,
610 // we greedily choose the best simplification. This is because there is
611 // an impedance mismatch: the egraph and our pure rewrites are centered
612 // around *values*, but we don't represent side-effects with values, we
613 // represent them implicitly in their *instructions*.
614 //
615 // The initial best choice is "no simplification, just use the original
616 // instruction" which has the original instruction's cost.
617 let mut best = None;
618 let mut best_cost = cost::Cost::of_skeleton_op(
619 ctx.func.dfg.insts[inst].opcode(),
620 ctx.func.dfg.inst_args(inst).len(),
621 );
622 while let Some(simplification) = optimized_insts.pop() {
623 let (new_inst, new_val) = match simplification {
624 // We can't do better than completely removing the skeleton
625 // instruction, so short-cicuit the loop and eagerly return the
626 // `Remove*` simplifications.
627 SkeletonInstSimplification::Remove => {
628 log::trace!(" -> simplify_skeleton: remove inst");
629 debug_assert!(ctx.func.dfg.inst_results(inst).is_empty());
630 return Some(simplification);
631 }
632 SkeletonInstSimplification::RemoveWithVal { val } => {
633 log::trace!(" -> simplify_skeleton: remove inst and use {val} as its result");
634 if cfg!(debug_assertions) {
635 let results = ctx.func.dfg.inst_results(inst);

Callers 1

Calls 11

inst_argsMethod · 0.80
newFunction · 0.50
getMethod · 0.45
lenMethod · 0.45
truncateMethod · 0.45
opcodeMethod · 0.45
popMethod · 0.45
inst_resultsMethod · 0.45
as_refMethod · 0.45
iterMethod · 0.45
value_typeMethod · 0.45

Tested by

no test coverage detected