Auto merge of #113116 - nnethercote:codegen-opts, r=oli-obk
A mish-mash of micro-optimizations These were aimed at speeding up LLVM codegen, but ended up affecting other places as well. r? `@bjorn3`
This commit is contained in:
commit
8aed93d912
@ -81,7 +81,7 @@ pub(crate) fn get_span_loc(
|
||||
|
||||
match tcx.sess.source_map().lookup_line(span.lo()) {
|
||||
Ok(SourceFileAndLine { sf: file, line }) => {
|
||||
let line_pos = file.line_begin_pos(span.lo());
|
||||
let line_pos = file.lines(|lines| lines[line]);
|
||||
|
||||
(
|
||||
file,
|
||||
|
@ -1,7 +1,6 @@
|
||||
//! Set and unset common attributes on LLVM values.
|
||||
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_data_structures::small_str::SmallStr;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
@ -481,8 +480,8 @@ pub fn from_fn_attrs<'ll, 'tcx>(
|
||||
|
||||
let global_features = cx.tcx.global_backend_features(()).iter().map(|s| s.as_str());
|
||||
let function_features = function_features.iter().map(|s| s.as_str());
|
||||
let target_features =
|
||||
global_features.chain(function_features).intersperse(",").collect::<SmallStr<1024>>();
|
||||
let target_features: String =
|
||||
global_features.chain(function_features).intersperse(",").collect();
|
||||
if !target_features.is_empty() {
|
||||
to_add.push(llvm::CreateAttrStringValue(cx.llcx, "target-features", &target_features));
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
use rustc_symbol_mangling::typeid::{kcfi_typeid_for_fnabi, typeid_for_fnabi, TypeIdOptions};
|
||||
use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange};
|
||||
use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target};
|
||||
use smallvec::SmallVec;
|
||||
use std::borrow::Cow;
|
||||
use std::iter;
|
||||
use std::ops::Deref;
|
||||
@ -225,7 +226,10 @@ fn invoke(
|
||||
let args = self.check_call("invoke", llty, llfn, args);
|
||||
let funclet_bundle = funclet.map(|funclet| funclet.bundle());
|
||||
let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
|
||||
let mut bundles = vec![funclet_bundle];
|
||||
let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
|
||||
if let Some(funclet_bundle) = funclet_bundle {
|
||||
bundles.push(funclet_bundle);
|
||||
}
|
||||
|
||||
// Emit CFI pointer type membership test
|
||||
self.cfi_type_test(fn_attrs, fn_abi, llfn);
|
||||
@ -233,9 +237,10 @@ fn invoke(
|
||||
// Emit KCFI operand bundle
|
||||
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn);
|
||||
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
|
||||
if let Some(kcfi_bundle) = kcfi_bundle {
|
||||
bundles.push(kcfi_bundle);
|
||||
}
|
||||
|
||||
bundles.retain(|bundle| bundle.is_some());
|
||||
let invoke = unsafe {
|
||||
llvm::LLVMRustBuildInvoke(
|
||||
self.llbuilder,
|
||||
@ -1181,7 +1186,10 @@ fn call(
|
||||
let args = self.check_call("call", llty, llfn, args);
|
||||
let funclet_bundle = funclet.map(|funclet| funclet.bundle());
|
||||
let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
|
||||
let mut bundles = vec![funclet_bundle];
|
||||
let mut bundles: SmallVec<[_; 2]> = SmallVec::new();
|
||||
if let Some(funclet_bundle) = funclet_bundle {
|
||||
bundles.push(funclet_bundle);
|
||||
}
|
||||
|
||||
// Emit CFI pointer type membership test
|
||||
self.cfi_type_test(fn_attrs, fn_abi, llfn);
|
||||
@ -1189,9 +1197,10 @@ fn call(
|
||||
// Emit KCFI operand bundle
|
||||
let kcfi_bundle = self.kcfi_operand_bundle(fn_attrs, fn_abi, llfn);
|
||||
let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
|
||||
if let Some(kcfi_bundle) = kcfi_bundle {
|
||||
bundles.push(kcfi_bundle);
|
||||
}
|
||||
|
||||
bundles.retain(|bundle| bundle.is_some());
|
||||
let call = unsafe {
|
||||
llvm::LLVMRustBuildCall(
|
||||
self.llbuilder,
|
||||
|
@ -65,10 +65,10 @@ fn make_mir_scope<'ll, 'tcx>(
|
||||
debug_context.scopes[parent]
|
||||
} else {
|
||||
// The root is the function itself.
|
||||
let loc = cx.lookup_debug_loc(mir.span.lo());
|
||||
let file = cx.sess().source_map().lookup_source_file(mir.span.lo());
|
||||
debug_context.scopes[scope] = DebugScope {
|
||||
file_start_pos: loc.file.start_pos,
|
||||
file_end_pos: loc.file.end_pos,
|
||||
file_start_pos: file.start_pos,
|
||||
file_end_pos: file.end_pos,
|
||||
..debug_context.scopes[scope]
|
||||
};
|
||||
instantiated.insert(scope);
|
||||
|
@ -262,7 +262,7 @@ impl CodegenCx<'_, '_> {
|
||||
pub fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc {
|
||||
let (file, line, col) = match self.sess().source_map().lookup_line(pos) {
|
||||
Ok(SourceFileAndLine { sf: file, line }) => {
|
||||
let line_pos = file.line_begin_pos(pos);
|
||||
let line_pos = file.lines(|lines| lines[line]);
|
||||
|
||||
// Use 1-based indexing.
|
||||
let line = (line + 1) as u32;
|
||||
@ -331,7 +331,7 @@ fn dbg_scope_fn(
|
||||
llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), fn_signature)
|
||||
};
|
||||
|
||||
let mut name = String::new();
|
||||
let mut name = String::with_capacity(64);
|
||||
type_names::push_item_name(tcx, def_id, false, &mut name);
|
||||
|
||||
// Find the enclosing function, in case this is a closure.
|
||||
|
@ -28,7 +28,7 @@ pub fn item_namespace<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DISco
|
||||
.map(|parent| item_namespace(cx, DefId { krate: def_id.krate, index: parent }));
|
||||
|
||||
let namespace_name_string = {
|
||||
let mut output = String::new();
|
||||
let mut output = String::with_capacity(64);
|
||||
type_names::push_item_name(cx.tcx, def_id, false, &mut output);
|
||||
output
|
||||
};
|
||||
|
@ -1301,7 +1301,7 @@ pub fn LLVMRustBuildInvoke<'a>(
|
||||
NumArgs: c_uint,
|
||||
Then: &'a BasicBlock,
|
||||
Catch: &'a BasicBlock,
|
||||
OpBundles: *const Option<&OperandBundleDef<'a>>,
|
||||
OpBundles: *const &OperandBundleDef<'a>,
|
||||
NumOpBundles: c_uint,
|
||||
Name: *const c_char,
|
||||
) -> &'a Value;
|
||||
@ -1673,7 +1673,7 @@ pub fn LLVMRustBuildCall<'a>(
|
||||
Fn: &'a Value,
|
||||
Args: *const &'a Value,
|
||||
NumArgs: c_uint,
|
||||
OpBundles: *const Option<&OperandBundleDef<'a>>,
|
||||
OpBundles: *const &OperandBundleDef<'a>,
|
||||
NumOpBundles: c_uint,
|
||||
) -> &'a Value;
|
||||
pub fn LLVMRustBuildMemCpy<'a>(
|
||||
|
@ -68,7 +68,6 @@ pub fn cold_path<F: FnOnce() -> R, R>(f: F) -> R {
|
||||
pub mod obligation_forest;
|
||||
pub mod sip128;
|
||||
pub mod small_c_str;
|
||||
pub mod small_str;
|
||||
pub mod snapshot_map;
|
||||
pub mod svh;
|
||||
pub use ena::snapshot_vec;
|
||||
|
@ -1,68 +0,0 @@
|
||||
use smallvec::SmallVec;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// Like SmallVec but for strings.
|
||||
#[derive(Default)]
|
||||
pub struct SmallStr<const N: usize>(SmallVec<[u8; N]>);
|
||||
|
||||
impl<const N: usize> SmallStr<N> {
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
SmallStr(SmallVec::default())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn push_str(&mut self, s: &str) {
|
||||
self.0.extend_from_slice(s.as_bytes());
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn spilled(&self) -> bool {
|
||||
self.0.spilled()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_str(&self) -> &str {
|
||||
unsafe { std::str::from_utf8_unchecked(self.0.as_slice()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> std::ops::Deref for SmallStr<N> {
|
||||
type Target = str;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &str {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, A: AsRef<str>> FromIterator<A> for SmallStr<N> {
|
||||
#[inline]
|
||||
fn from_iter<T>(iter: T) -> Self
|
||||
where
|
||||
T: IntoIterator<Item = A>,
|
||||
{
|
||||
let mut s = SmallStr::default();
|
||||
s.extend(iter);
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize, A: AsRef<str>> Extend<A> for SmallStr<N> {
|
||||
#[inline]
|
||||
fn extend<T>(&mut self, iter: T)
|
||||
where
|
||||
T: IntoIterator<Item = A>,
|
||||
{
|
||||
for a in iter.into_iter() {
|
||||
self.push_str(a.as_ref());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn empty() {
|
||||
let s = SmallStr::<1>::new();
|
||||
assert!(s.empty());
|
||||
assert_eq!("", s.as_str());
|
||||
assert!(!s.spilled());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_iter() {
|
||||
let s = ["aa", "bb", "cc"].iter().collect::<SmallStr<6>>();
|
||||
assert_eq!("aabbcc", s.as_str());
|
||||
assert!(!s.spilled());
|
||||
|
||||
let s = ["aa", "bb", "cc", "dd"].iter().collect::<SmallStr<6>>();
|
||||
assert_eq!("aabbccdd", s.as_str());
|
||||
assert!(s.spilled());
|
||||
}
|
@ -8,13 +8,13 @@
|
||||
|
||||
pub struct Derefer;
|
||||
|
||||
pub struct DerefChecker<'tcx> {
|
||||
pub struct DerefChecker<'a, 'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
patcher: MirPatch<'tcx>,
|
||||
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
|
||||
local_decls: &'a IndexVec<Local, LocalDecl<'tcx>>,
|
||||
}
|
||||
|
||||
impl<'tcx> MutVisitor<'tcx> for DerefChecker<'tcx> {
|
||||
impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> {
|
||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||
self.tcx
|
||||
}
|
||||
@ -36,7 +36,7 @@ fn visit_place(&mut self, place: &mut Place<'tcx>, cntxt: PlaceContext, loc: Loc
|
||||
|
||||
for (idx, (p_ref, p_elem)) in place.iter_projections().enumerate() {
|
||||
if !p_ref.projection.is_empty() && p_elem == ProjectionElem::Deref {
|
||||
let ty = p_ref.ty(&self.local_decls, self.tcx).ty;
|
||||
let ty = p_ref.ty(self.local_decls, self.tcx).ty;
|
||||
let temp = self.patcher.new_internal_with_info(
|
||||
ty,
|
||||
self.local_decls[p_ref.local].source_info.span,
|
||||
@ -70,7 +70,7 @@ fn visit_place(&mut self, place: &mut Place<'tcx>, cntxt: PlaceContext, loc: Loc
|
||||
|
||||
pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
|
||||
let patch = MirPatch::new(body);
|
||||
let mut checker = DerefChecker { tcx, patcher: patch, local_decls: body.local_decls.clone() };
|
||||
let mut checker = DerefChecker { tcx, patcher: patch, local_decls: &body.local_decls };
|
||||
|
||||
for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
|
||||
checker.visit_basic_block_data(bb, data);
|
||||
|
@ -1072,11 +1072,7 @@ pub fn lookup_byte_offset(&self, bpos: BytePos) -> SourceFileAndBytePos {
|
||||
/// This index is guaranteed to be valid for the lifetime of this `SourceMap`,
|
||||
/// since `source_files` is a `MonotonicVec`
|
||||
pub fn lookup_source_file_idx(&self, pos: BytePos) -> usize {
|
||||
self.files
|
||||
.borrow()
|
||||
.source_files
|
||||
.binary_search_by_key(&pos, |key| key.start_pos)
|
||||
.unwrap_or_else(|p| p - 1)
|
||||
self.files.borrow().source_files.partition_point(|x| x.start_pos <= pos) - 1
|
||||
}
|
||||
|
||||
pub fn count_lines(&self) -> usize {
|
||||
|
Loading…
Reference in New Issue
Block a user