Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid unnecessary monomorphization of inline asm related functions #92731

Merged
merged 3 commits into from
Jan 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -361,7 +362,10 @@ symbols! {
augmented_assignments,
auto_traits,
automatically_derived,
avx,
avx512_target_feature,
avx512bw,
avx512f,
await_macro,
bang,
begin_panic,
Expand Down Expand Up @@ -592,6 +596,7 @@ symbols! {
dylib,
dyn_metadata,
dyn_trait,
e,
edition_macro_pats,
edition_panic,
eh_catch_typeinfo,
Expand Down Expand Up @@ -682,6 +687,7 @@ symbols! {
format_args_macro,
format_args_nl,
format_macro,
fp,
freeze,
freg,
frem_fast,
Expand Down Expand Up @@ -907,6 +913,7 @@ symbols! {
neg,
negate_unsigned,
negative_impls,
neon,
never,
never_type,
never_type_fallback,
Expand Down Expand Up @@ -1101,6 +1108,7 @@ symbols! {
repr_packed,
repr_simd,
repr_transparent,
reserved_r9: "reserved-r9",
residual,
result,
rhs,
Expand Down Expand Up @@ -1294,6 +1302,7 @@ symbols! {
sqrtf64,
sreg,
sreg_low16,
sse,
sse4a_target_feature,
stable,
staged_api,
Expand Down Expand Up @@ -1360,6 +1369,8 @@ symbols! {
thread,
thread_local,
thread_local_macro,
thumb2,
thumb_mode: "thumb-mode",
todo_macro,
tool_attributes,
tool_lints,
Expand Down Expand Up @@ -1453,6 +1464,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