Merge pull request #3469 from cfallin/machbuffer-quadratic-labels
Avoid quadratic behavior in pathological label-alias case in MachBuffer.
This commit is contained in:
@@ -250,8 +250,12 @@ pub struct MachBufferFinalized {
|
|||||||
pub unwind_info: SmallVec<[(CodeOffset, UnwindInst); 8]>,
|
pub unwind_info: SmallVec<[(CodeOffset, UnwindInst); 8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
static UNKNOWN_LABEL_OFFSET: CodeOffset = 0xffff_ffff;
|
const UNKNOWN_LABEL_OFFSET: CodeOffset = 0xffff_ffff;
|
||||||
static UNKNOWN_LABEL: MachLabel = MachLabel(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
|
/// 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"
|
/// the point at which it is used by emitted code; the buffer records "fixups"
|
||||||
@@ -791,6 +795,24 @@ impl<I: VCodeInst> MachBuffer<I> {
|
|||||||
break;
|
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
|
// Invariant: we are looking at a branch that ends at the tail of
|
||||||
// the buffer.
|
// the buffer.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user