Skip to content

Commit

Permalink
Rollup merge of rust-lang#116560 - ouz-a:efficient_ids, r=oli-obk
Browse files Browse the repository at this point in the history
In smir use `FxIndexMap` to store indexed ids

Previously we used `vec` for storing indexed types, which is fine for small cases but will lead to huge performance issues when we use `smir` for real world cases.

Addresses rust-lang/project-stable-mir#35

r? `@oli-obk`
  • Loading branch information
matthiaskrgr authored Oct 10, 2023
2 parents 42dcf77 + 0bcb058 commit 8c6b8bb
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 36 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4504,6 +4504,7 @@ dependencies = [
name = "rustc_smir"
version = "0.0.0"
dependencies = [
"rustc_data_structures",
"rustc_driver",
"rustc_hir",
"rustc_interface",
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_smir/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.0.0"
edition = "2021"

[dependencies]
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_driver = { path = "../rustc_driver" }
rustc_hir = { path = "../rustc_hir" }
rustc_interface = { path = "../rustc_interface" }
Expand Down
72 changes: 43 additions & 29 deletions compiler/rustc_smir/src/rustc_internal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,27 @@
//! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs
//! until stable MIR is complete.

use std::ops::{ControlFlow, Index};

use crate::rustc_internal;
use crate::rustc_smir::Tables;
use rustc_data_structures::fx;
use rustc_driver::{Callbacks, Compilation, RunCompiler};
use rustc_interface::{interface, Queries};
use rustc_middle::mir::interpret::AllocId;
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::{CrateNum, DefId};
use rustc_span::Span;
use stable_mir::ty::IndexedVal;
use stable_mir::CompilerError;
use std::fmt::Debug;
use std::hash::Hash;
use std::ops::{ControlFlow, Index};

impl<'tcx> Index<stable_mir::DefId> for Tables<'tcx> {
type Output = DefId;

#[inline(always)]
fn index(&self, index: stable_mir::DefId) -> &Self::Output {
&self.def_ids[index.0]
&self.def_ids[index]
}
}

Expand All @@ -29,7 +32,7 @@ impl<'tcx> Index<stable_mir::ty::Span> for Tables<'tcx> {

#[inline(always)]
fn index(&self, index: stable_mir::ty::Span) -> &Self::Output {
&self.spans[index.0]
&self.spans[index]
}
}

Expand Down Expand Up @@ -95,36 +98,15 @@ impl<'tcx> Tables<'tcx> {
}

fn create_def_id(&mut self, did: DefId) -> stable_mir::DefId {
// FIXME: this becomes inefficient when we have too many ids
for (i, &d) in self.def_ids.iter().enumerate() {
if d == did {
return stable_mir::DefId(i);
}
}
let id = self.def_ids.len();
self.def_ids.push(did);
stable_mir::DefId(id)
self.def_ids.create_or_fetch(did)
}

fn create_alloc_id(&mut self, aid: AllocId) -> stable_mir::AllocId {
// FIXME: this becomes inefficient when we have too many ids
if let Some(i) = self.alloc_ids.iter().position(|a| *a == aid) {
return stable_mir::AllocId(i);
};
let id = self.def_ids.len();
self.alloc_ids.push(aid);
stable_mir::AllocId(id)
self.alloc_ids.create_or_fetch(aid)
}

pub(crate) fn create_span(&mut self, span: Span) -> stable_mir::ty::Span {
for (i, &sp) in self.spans.iter().enumerate() {
if sp == span {
return stable_mir::ty::Span(i);
}
}
let id = self.spans.len();
self.spans.push(span);
stable_mir::ty::Span(id)
self.spans.create_or_fetch(span)
}
}

Expand All @@ -134,7 +116,13 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {

pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
stable_mir::run(
Tables { tcx, def_ids: vec![], alloc_ids: vec![], spans: vec![], types: vec![] },
Tables {
tcx,
def_ids: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() },
alloc_ids: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() },
spans: rustc_internal::IndexMap { index_map: fx::FxIndexMap::default() },
types: vec![],
},
f,
);
}
Expand Down Expand Up @@ -197,3 +185,29 @@ where
})
}
}

/// Simmilar to rustc's `FxIndexMap`, `IndexMap` with extra
/// safety features added.
pub struct IndexMap<K, V> {
index_map: fx::FxIndexMap<K, V>,
}

impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> IndexMap<K, V> {
pub fn create_or_fetch(&mut self, key: K) -> V {
let len = self.index_map.len();
let v = self.index_map.entry(key).or_insert(V::to_val(len));
*v
}
}

impl<K: PartialEq + Hash + Eq, V: Copy + Debug + PartialEq + IndexedVal> Index<V>
for IndexMap<K, V>
{
type Output = K;

fn index(&self, index: V) -> &Self::Output {
let (k, v) = self.index_map.get_index(index.to_index()).unwrap();
assert_eq!(*v, index, "Provided value doesn't match with indexed value");
k
}
}
7 changes: 4 additions & 3 deletions compiler/rustc_smir/src/rustc_smir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//!
//! For now, we are developing everything inside `rustc`, thus, we keep this module private.

use crate::rustc_internal::IndexMap;
use crate::rustc_smir::hir::def::DefKind;
use crate::rustc_smir::stable_mir::ty::{BoundRegion, EarlyBoundRegion, Region};
use rustc_hir as hir;
Expand Down Expand Up @@ -201,9 +202,9 @@ impl<S, R: PartialEq> PartialEq<R> for MaybeStable<S, R> {

pub struct Tables<'tcx> {
pub tcx: TyCtxt<'tcx>,
pub def_ids: Vec<DefId>,
pub alloc_ids: Vec<AllocId>,
pub spans: Vec<rustc_span::Span>,
pub def_ids: IndexMap<DefId, stable_mir::DefId>,
pub alloc_ids: IndexMap<AllocId, stable_mir::AllocId>,
pub spans: IndexMap<rustc_span::Span, Span>,
pub types: Vec<MaybeStable<stable_mir::ty::TyKind, Ty<'tcx>>>,
}

Expand Down
26 changes: 23 additions & 3 deletions compiler/stable_mir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ use std::fmt;
use std::fmt::Debug;

use self::ty::{
GenericPredicates, Generics, ImplDef, ImplTrait, Span, TraitDecl, TraitDef, Ty, TyKind,
GenericPredicates, Generics, ImplDef, ImplTrait, IndexedVal, Span, TraitDecl, TraitDef, Ty,
TyKind,
};

#[macro_use]
Expand All @@ -41,7 +42,7 @@ pub type CrateNum = usize;

/// A unique identification number for each item accessible for the current compilation unit.
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct DefId(pub usize);
pub struct DefId(usize);

impl Debug for DefId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand All @@ -52,9 +53,28 @@ impl Debug for DefId {
}
}

impl IndexedVal for DefId {
fn to_val(index: usize) -> Self {
DefId(index)
}

fn to_index(&self) -> usize {
self.0
}
}

/// A unique identification number for each provenance
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct AllocId(pub usize);
pub struct AllocId(usize);

impl IndexedVal for AllocId {
fn to_val(index: usize) -> Self {
AllocId(index)
}
fn to_index(&self) -> usize {
self.0
}
}

/// A list of crate items.
pub type CrateItems = Vec<CrateItem>;
Expand Down
17 changes: 16 additions & 1 deletion compiler/stable_mir/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub struct Placeholder<T> {
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Span(pub usize);
pub struct Span(usize);

impl Debug for Span {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Expand All @@ -86,6 +86,15 @@ impl Debug for Span {
}
}

impl IndexedVal for Span {
fn to_val(index: usize) -> Self {
Span(index)
}
fn to_index(&self) -> usize {
self.0
}
}

#[derive(Clone, Debug)]
pub enum TyKind {
RigidTy(RigidTy),
Expand Down Expand Up @@ -565,3 +574,9 @@ pub enum ImplPolarity {
Negative,
Reservation,
}

pub trait IndexedVal {
fn to_val(index: usize) -> Self;

fn to_index(&self) -> usize;
}

0 comments on commit 8c6b8bb

Please sign in to comment.