Skip to content

Commit

Permalink
Auto merge of #92731 - bjorn3:asm_support_changes, r=nagisa
Browse files Browse the repository at this point in the history
Avoid unnecessary monomorphization of inline asm related functions

This should reduce build time for codegen backends by avoiding duplicated monomorphization of certain inline asm related functions for each passed in closure type.
  • Loading branch information
bors committed Jan 18, 2022
2 parents 7bc7be8 + 9336fe3 commit 9ad5d82
Show file tree
Hide file tree
Showing 21 changed files with 133 additions and 105 deletions.
6 changes: 3 additions & 3 deletions compiler/rustc_ast_lowering/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rustc_data_structures::stable_set::FxHashSet;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_session::parse::feature_err;
use rustc_span::{sym, Span, Symbol};
use rustc_span::{sym, Span};
use rustc_target::asm;
use std::collections::hash_map::Entry;
use std::fmt::Write;
Expand Down Expand Up @@ -66,7 +66,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
for (abi_name, abi_span) in &asm.clobber_abis {
match asm::InlineAsmClobberAbi::parse(
asm_arch,
|feature| self.sess.target_features.contains(&Symbol::intern(feature)),
&self.sess.target_features,
&self.sess.target,
*abi_name,
) {
Expand Down Expand Up @@ -134,7 +134,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch {
asm::InlineAsmReg::parse(
asm_arch,
|feature| sess.target_features.contains(&Symbol::intern(feature)),
&sess.target_features,
&sess.target,
s,
)
Expand Down
12 changes: 4 additions & 8 deletions compiler/rustc_codegen_cranelift/src/inline_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::fmt::Write;

use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_middle::mir::InlineAsmOperand;
use rustc_span::Symbol;
use rustc_span::sym;
use rustc_target::asm::*;

pub(crate) fn codegen_inline_asm<'tcx>(
Expand Down Expand Up @@ -182,11 +182,7 @@ struct InlineAssemblyGenerator<'a, 'tcx> {
impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
fn allocate_registers(&mut self) {
let sess = self.tcx.sess;
let map = allocatable_registers(
self.arch,
|feature| sess.target_features.contains(&Symbol::intern(feature)),
&sess.target,
);
let map = allocatable_registers(self.arch, &sess.target_features, &sess.target);
let mut allocated = FxHashMap::<_, (bool, bool)>::default();
let mut regs = vec![None; self.operands.len()];

Expand Down Expand Up @@ -319,9 +315,9 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
// Allocate stack slots for saving clobbered registers
let abi_clobber = InlineAsmClobberAbi::parse(
self.arch,
|feature| self.tcx.sess.target_features.contains(&Symbol::intern(feature)),
&self.tcx.sess.target_features,
&self.tcx.sess.target,
Symbol::intern("C"),
sym::C,
)
.unwrap()
.clobbered_regs();
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_gcc/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{AsmBuilderMethods, AsmMethods, BaseTypeMethods, BuilderMethods, GlobalAsmOperandRef, InlineAsmOperandRef};

use rustc_middle::{bug, ty::Instance};
use rustc_span::{Span, Symbol};
use rustc_span::Span;
use rustc_target::asm::*;

use std::borrow::Cow;
Expand Down Expand Up @@ -172,7 +172,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
let is_target_supported = reg.reg_class().supported_types(asm_arch).iter()
.any(|&(_, feature)| {
if let Some(feature) = feature {
self.tcx.sess.target_features.contains(&Symbol::intern(feature))
self.tcx.sess.target_features.contains(&feature)
} else {
true // Register class is unconditionally supported
}
Expand Down
7 changes: 3 additions & 4 deletions compiler/rustc_codegen_llvm/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use rustc_codegen_ssa::traits::*;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::{bug, span_bug, ty::Instance};
use rustc_span::{Pos, Span, Symbol};
use rustc_span::{Pos, Span};
use rustc_target::abi::*;
use rustc_target::asm::*;

Expand Down Expand Up @@ -45,9 +45,8 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
for &(_, feature) in reg_class.supported_types(asm_arch) {
if let Some(feature) = feature {
let codegen_fn_attrs = self.tcx.codegen_fn_attrs(instance.def_id());
let feature_name = Symbol::intern(feature);
if self.tcx.sess.target_features.contains(&feature_name)
|| codegen_fn_attrs.target_features.contains(&feature_name)
if self.tcx.sess.target_features.contains(&feature)
|| codegen_fn_attrs.target_features.contains(&feature)
{
return true;
}
Expand Down
16 changes: 9 additions & 7 deletions compiler/rustc_passes/src/intrinsicck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,8 @@ impl<'tcx> ExprVisitor<'tcx> {
// (!). In that case we still need the earlier check to verify that the
// register class is usable at all.
if let Some(feature) = feature {
let feat_sym = Symbol::intern(feature);
if !self.tcx.sess.target_features.contains(&feat_sym)
&& !target_features.contains(&feat_sym)
if !self.tcx.sess.target_features.contains(&feature)
&& !target_features.contains(&feature)
{
let msg = &format!("`{}` target feature is not enabled", feature);
let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
Expand Down Expand Up @@ -377,9 +376,8 @@ impl<'tcx> ExprVisitor<'tcx> {
{
match feature {
Some(feature) => {
let feat_sym = Symbol::intern(feature);
if self.tcx.sess.target_features.contains(&feat_sym)
|| attrs.target_features.contains(&feat_sym)
if self.tcx.sess.target_features.contains(&feature)
|| attrs.target_features.contains(&feature)
{
missing_required_features.clear();
break;
Expand Down Expand Up @@ -413,7 +411,11 @@ impl<'tcx> ExprVisitor<'tcx> {
let msg = format!(
"register class `{}` requires at least one of the following target features: {}",
reg_class.name(),
features.join(", ")
features
.iter()
.map(|f| f.as_str())
.intersperse(", ")
.collect::<String>(),
);
self.tcx.sess.struct_span_err(*op_sp, &msg).emit();
// register isn't enabled, don't do more checks
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_passes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(crate_visibility_modifier)]
#![feature(iter_intersperse)]
#![feature(let_else)]
#![feature(map_try_insert)]
#![feature(min_specialization)]
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ symbols! {
allow_internal_unsafe,
allow_internal_unstable,
allowed,
alu32,
always,
and,
and_then,
Expand Down Expand Up @@ -362,7 +363,10 @@ symbols! {
augmented_assignments,
auto_traits,
automatically_derived,
avx,
avx512_target_feature,
avx512bw,
avx512f,
await_macro,
bang,
begin_panic,
Expand Down Expand Up @@ -593,6 +597,7 @@ symbols! {
dylib,
dyn_metadata,
dyn_trait,
e,
edition_macro_pats,
edition_panic,
eh_catch_typeinfo,
Expand Down Expand Up @@ -683,6 +688,7 @@ symbols! {
format_args_macro,
format_args_nl,
format_macro,
fp,
freeze,
freg,
frem_fast,
Expand Down Expand Up @@ -908,6 +914,7 @@ symbols! {
neg,
negate_unsigned,
negative_impls,
neon,
never,
never_type,
never_type_fallback,
Expand Down Expand Up @@ -1102,6 +1109,7 @@ symbols! {
repr_packed,
repr_simd,
repr_transparent,
reserved_r9: "reserved-r9",
residual,
result,
rhs,
Expand Down Expand Up @@ -1296,6 +1304,7 @@ symbols! {
sqrtf64,
sreg,
sreg_low16,
sse,
sse4a_target_feature,
stable,
staged_api,
Expand Down Expand Up @@ -1362,6 +1371,8 @@ symbols! {
thread,
thread_local,
thread_local_macro,
thumb2,
thumb_mode: "thumb-mode",
todo_macro,
tool_attributes,
tool_lints,
Expand Down Expand Up @@ -1455,6 +1466,7 @@ symbols! {
vec,
vec_macro,
version,
vfp2,
vis,
visible_private_types,
volatile,
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_target/src/asm/aarch64.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use super::{InlineAsmArch, InlineAsmType};
use crate::spec::Target;
use rustc_data_structures::stable_set::FxHashSet;
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt;

def_reg_class! {
Expand Down Expand Up @@ -58,11 +60,11 @@ impl AArch64InlineAsmRegClass {
pub fn supported_types(
self,
_arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] {
) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self {
Self::reg => types! { _: I8, I16, I32, I64, F32, F64; },
Self::vreg | Self::vreg_low16 => types! {
"fp": I8, I16, I32, I64, F32, F64,
fp: I8, I16, I32, I64, F32, F64,
VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2), VecF64(1),
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2);
},
Expand All @@ -73,7 +75,7 @@ impl AArch64InlineAsmRegClass {

pub fn reserved_x18(
_arch: InlineAsmArch,
_has_feature: impl FnMut(&str) -> bool,
_target_features: &FxHashSet<Symbol>,
target: &Target,
) -> Result<(), &'static str> {
if target.os == "android"
Expand Down
32 changes: 17 additions & 15 deletions compiler/rustc_target/src/asm/arm.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use super::{InlineAsmArch, InlineAsmType};
use crate::spec::Target;
use rustc_data_structures::stable_set::FxHashSet;
use rustc_macros::HashStable_Generic;
use rustc_span::{sym, Symbol};
use std::fmt;

def_reg_class! {
Expand Down Expand Up @@ -44,31 +46,31 @@ impl ArmInlineAsmRegClass {
pub fn supported_types(
self,
_arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] {
) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self {
Self::reg => types! { _: I8, I16, I32, F32; },
Self::sreg | Self::sreg_low16 => types! { "vfp2": I32, F32; },
Self::sreg | Self::sreg_low16 => types! { vfp2: I32, F32; },
Self::dreg | Self::dreg_low16 | Self::dreg_low8 => types! {
"vfp2": I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2);
vfp2: I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2);
},
Self::qreg | Self::qreg_low8 | Self::qreg_low4 => types! {
"neon": VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4);
neon: VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4);
},
}
}
}

// This uses the same logic as useR7AsFramePointer in LLVM
fn frame_pointer_is_r7(mut has_feature: impl FnMut(&str) -> bool, target: &Target) -> bool {
target.is_like_osx || (!target.is_like_windows && has_feature("thumb-mode"))
fn frame_pointer_is_r7(target_features: &FxHashSet<Symbol>, target: &Target) -> bool {
target.is_like_osx || (!target.is_like_windows && target_features.contains(&sym::thumb_mode))
}

fn frame_pointer_r11(
_arch: InlineAsmArch,
has_feature: impl FnMut(&str) -> bool,
target_features: &FxHashSet<Symbol>,
target: &Target,
) -> Result<(), &'static str> {
if !frame_pointer_is_r7(has_feature, target) {
if !frame_pointer_is_r7(target_features, target) {
Err("the frame pointer (r11) cannot be used as an operand for inline asm")
} else {
Ok(())
Expand All @@ -77,10 +79,10 @@ fn frame_pointer_r11(

fn frame_pointer_r7(
_arch: InlineAsmArch,
has_feature: impl FnMut(&str) -> bool,
target_features: &FxHashSet<Symbol>,
target: &Target,
) -> Result<(), &'static str> {
if frame_pointer_is_r7(has_feature, target) {
if frame_pointer_is_r7(target_features, target) {
Err("the frame pointer (r7) cannot be used as an operand for inline asm")
} else {
Ok(())
Expand All @@ -89,10 +91,10 @@ fn frame_pointer_r7(

fn not_thumb1(
_arch: InlineAsmArch,
mut has_feature: impl FnMut(&str) -> bool,
target_features: &FxHashSet<Symbol>,
_target: &Target,
) -> Result<(), &'static str> {
if has_feature("thumb-mode") && !has_feature("thumb2") {
if target_features.contains(&sym::thumb_mode) && !target_features.contains(&sym::thumb2) {
Err("high registers (r8+) cannot be used in Thumb-1 code")
} else {
Ok(())
Expand All @@ -101,14 +103,14 @@ fn not_thumb1(

fn reserved_r9(
arch: InlineAsmArch,
mut has_feature: impl FnMut(&str) -> bool,
target_features: &FxHashSet<Symbol>,
target: &Target,
) -> Result<(), &'static str> {
not_thumb1(arch, &mut has_feature, target)?;
not_thumb1(arch, target_features, target)?;

// We detect this using the reserved-r9 feature instead of using the target
// because the relocation model can be changed with compiler options.
if has_feature("reserved-r9") {
if target_features.contains(&sym::reserved_r9) {
Err("the RWPI static base register (r9) cannot be used as an operand for inline asm")
} else {
Ok(())
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_target/src/asm/avr.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::{InlineAsmArch, InlineAsmType};
use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt;

def_reg_class! {
Expand Down Expand Up @@ -39,7 +40,7 @@ impl AvrInlineAsmRegClass {
pub fn supported_types(
self,
_arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] {
) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self {
Self::reg => types! { _: I8; },
Self::reg_upper => types! { _: I8; },
Expand Down
10 changes: 6 additions & 4 deletions compiler/rustc_target/src/asm/bpf.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use super::{InlineAsmArch, InlineAsmType, Target};
use rustc_data_structures::stable_set::FxHashSet;
use rustc_macros::HashStable_Generic;
use rustc_span::{sym, Symbol};
use std::fmt;

def_reg_class! {
Expand Down Expand Up @@ -33,20 +35,20 @@ impl BpfInlineAsmRegClass {
pub fn supported_types(
self,
_arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] {
) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self {
Self::reg => types! { _: I8, I16, I32, I64; },
Self::wreg => types! { "alu32": I8, I16, I32; },
Self::wreg => types! { alu32: I8, I16, I32; },
}
}
}

fn only_alu32(
_arch: InlineAsmArch,
mut has_feature: impl FnMut(&str) -> bool,
target_features: &FxHashSet<Symbol>,
_target: &Target,
) -> Result<(), &'static str> {
if !has_feature("alu32") {
if !target_features.contains(&sym::alu32) {
Err("register can't be used without the `alu32` target feature")
} else {
Ok(())
Expand Down
Loading

0 comments on commit 9ad5d82

Please sign in to comment.