Browse Source

Merge pull request #3469 from cfallin/machbuffer-quadratic-labels

Avoid quadratic behavior in pathological label-alias case in MachBuffer.
pull/2890/head
Chris Fallin 3 years ago
committed by GitHub
parent
commit
54896ac86d
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 26
      cranelift/codegen/src/machinst/buffer.rs

26
cranelift/codegen/src/machinst/buffer.rs

@ -250,8 +250,12 @@ pub struct MachBufferFinalized {
pub unwind_info: SmallVec<[(CodeOffset, UnwindInst); 8]>,
}
static UNKNOWN_LABEL_OFFSET: CodeOffset = 0xffff_ffff;
static UNKNOWN_LABEL: MachLabel = MachLabel(0xffff_ffff);
const UNKNOWN_LABEL_OFFSET: CodeOffset = 0xffff_ffff;
const UNKNOWN_LABEL: MachLabel = MachLabel(0xffff_ffff);
/// Threshold on max length of `labels_at_this_branch` list to avoid
/// unbounded quadratic behavior (see comment below at use-site).
const LABEL_LIST_THRESHOLD: usize = 100;
/// A label refers to some offset in a `MachBuffer`. It may not be resolved at
/// the point at which it is used by emitted code; the buffer records "fixups"
@ -791,6 +795,24 @@ impl<I: VCodeInst> MachBuffer<I> {
break;
}
// If the "labels at this branch" list on this branch is
// longer than a threshold, don't do any simplification,
// and let the branch remain to separate those labels from
// the current tail. This avoids quadratic behavior (see
// #3468): otherwise, if a long string of "goto next;
// next:" patterns are emitted, all of the labels will
// coalesce into a long list of aliases for the current
// buffer tail. We must track all aliases of the current
// tail for correctness, but we are also allowed to skip
// optimization (removal) of any branch, so we take the
// escape hatch here and let it stand. In effect this
// "spreads" the many thousands of labels in the
// pathological case among an actual (harmless but
// suboptimal) instruction once per N labels.
if b.labels_at_this_branch.len() > LABEL_LIST_THRESHOLD {
break;
}
// Invariant: we are looking at a branch that ends at the tail of
// the buffer.

Loading…
Cancel
Save