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

Method optimize_branches

cranelift/codegen/src/machinst/buffer.rs:999–1271  ·  view source on GitHub ↗

Performs various optimizations on branches pointing at the current label.

(&mut self, ctrl_plane: &mut ControlPlane)

Source from the content-addressed store, hash-verified

997
998 /// Performs various optimizations on branches pointing at the current label.
999 pub fn optimize_branches(&mut self, ctrl_plane: &mut ControlPlane) {
1000 if ctrl_plane.get_decision() {
1001 return;
1002 }
1003
1004 self.lazily_clear_labels_at_tail();
1005 // Invariants valid at this point.
1006
1007 trace!(
1008 "enter optimize_branches:\n b = {:?}\n l = {:?}\n f = {:?}",
1009 self.latest_branches, self.labels_at_tail, self.pending_fixup_records
1010 );
1011
1012 // We continue to munch on branches at the tail of the buffer until no
1013 // more rules apply. Note that the loop only continues if a branch is
1014 // actually truncated (or if labels are redirected away from a branch),
1015 // so this always makes progress.
1016 while let Some(b) = self.latest_branches.last() {
1017 let cur_off = self.cur_offset();
1018 trace!("optimize_branches: last branch {:?} at off {}", b, cur_off);
1019 // If there has been any code emission since the end of the last branch or
1020 // label definition, then there's nothing we can edit (because we
1021 // don't move code once placed, only back up and overwrite), so
1022 // clear the records and finish.
1023 if b.end < cur_off {
1024 break;
1025 }
1026
1027 // If the "labels at this branch" list on this branch is
1028 // longer than a threshold, don't do any simplification,
1029 // and let the branch remain to separate those labels from
1030 // the current tail. This avoids quadratic behavior (see
1031 // #3468): otherwise, if a long string of "goto next;
1032 // next:" patterns are emitted, all of the labels will
1033 // coalesce into a long list of aliases for the current
1034 // buffer tail. We must track all aliases of the current
1035 // tail for correctness, but we are also allowed to skip
1036 // optimization (removal) of any branch, so we take the
1037 // escape hatch here and let it stand. In effect this
1038 // "spreads" the many thousands of labels in the
1039 // pathological case among an actual (harmless but
1040 // suboptimal) instruction once per N labels.
1041 if b.labels_at_this_branch.len() > LABEL_LIST_THRESHOLD {
1042 break;
1043 }
1044
1045 // Invariant: we are looking at a branch that ends at the tail of
1046 // the buffer.
1047
1048 // For any branch, conditional or unconditional:
1049 // - If the target is a label at the current offset, then remove
1050 // the conditional branch, and reset all labels that targeted
1051 // the current offset (end of branch) to the truncated
1052 // end-of-code.
1053 //
1054 // Preserves execution semantics: a branch to its own fallthrough
1055 // address is equivalent to a no-op; in both cases, nextPC is the
1056 // fallthrough.

Callers 2

bind_labelMethod · 0.80
emitMethod · 0.80

Calls 15

fromFunction · 0.85
cur_offsetMethod · 0.80
resolve_label_offsetMethod · 0.80
truncate_last_branchMethod · 0.80
is_uncondMethod · 0.80
is_condMethod · 0.80
purge_latest_branchesMethod · 0.80
get_decisionMethod · 0.45
lastMethod · 0.45
lenMethod · 0.45
unwrapMethod · 0.45

Tested by

no test coverage detected