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

Update the minimum external LLVM to 19 #139275

Merged
merged 1 commit into from
Apr 6, 2025
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
17 changes: 1 addition & 16 deletions compiler/rustc_codegen_llvm/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,13 @@ use rustc_target::callconv::{
use rustc_target::spec::SanitizerSet;
use smallvec::SmallVec;

use crate::attributes::llfn_attrs_from_instance;
use crate::attributes::{self, llfn_attrs_from_instance};
use crate::builder::Builder;
use crate::context::CodegenCx;
use crate::llvm::{self, Attribute, AttributePlace};
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
use crate::{attributes, llvm_util};

trait ArgAttributesExt {
fn apply_attrs_to_llfn(&self, idx: AttributePlace, cx: &CodegenCx<'_, '_>, llfn: &Value);
Expand Down Expand Up @@ -437,7 +436,6 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {

let apply_range_attr = |idx: AttributePlace, scalar: rustc_abi::Scalar| {
if cx.sess().opts.optimize != config::OptLevel::No
&& llvm_util::get_version() >= (19, 0, 0)
&& matches!(scalar.primitive(), Primitive::Int(..))
// If the value is a boolean, the range is 0..2 and that ultimately
// become 0..0 when the type becomes i1, which would be rejected
Expand Down Expand Up @@ -571,19 +569,6 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
}
_ => {}
}
if bx.cx.sess().opts.optimize != config::OptLevel::No
&& llvm_util::get_version() < (19, 0, 0)
&& let BackendRepr::Scalar(scalar) = self.ret.layout.backend_repr
&& matches!(scalar.primitive(), Primitive::Int(..))
// If the value is a boolean, the range is 0..2 and that ultimately
// become 0..0 when the type becomes i1, which would be rejected
// by the LLVM verifier.
&& !scalar.is_bool()
// LLVM also rejects full range.
&& !scalar.is_always_valid(bx)
{
bx.range_metadata(callsite, scalar.valid_range(bx));
}
for arg in self.args.iter() {
match &arg.mode {
PassMode::Ignore => {}
Expand Down
50 changes: 21 additions & 29 deletions compiler/rustc_codegen_llvm/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,30 +407,28 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
// Do not set sanitizer attributes for naked functions.
to_add.extend(sanitize_attrs(cx, codegen_fn_attrs.no_sanitize));

if llvm_util::get_version() >= (19, 0, 0) {
// For non-naked functions, set branch protection attributes on aarch64.
if let Some(BranchProtection { bti, pac_ret }) =
cx.sess().opts.unstable_opts.branch_protection
{
assert!(cx.sess().target.arch == "aarch64");
if bti {
to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement"));
}
if let Some(PacRet { leaf, pc, key }) = pac_ret {
if pc {
to_add.push(llvm::CreateAttrString(cx.llcx, "branch-protection-pauth-lr"));
}
to_add.push(llvm::CreateAttrStringValue(
cx.llcx,
"sign-return-address",
if leaf { "all" } else { "non-leaf" },
));
to_add.push(llvm::CreateAttrStringValue(
cx.llcx,
"sign-return-address-key",
if key == PAuthKey::A { "a_key" } else { "b_key" },
));
// For non-naked functions, set branch protection attributes on aarch64.
if let Some(BranchProtection { bti, pac_ret }) =
cx.sess().opts.unstable_opts.branch_protection
{
assert!(cx.sess().target.arch == "aarch64");
if bti {
to_add.push(llvm::CreateAttrString(cx.llcx, "branch-target-enforcement"));
}
if let Some(PacRet { leaf, pc, key }) = pac_ret {
if pc {
to_add.push(llvm::CreateAttrString(cx.llcx, "branch-protection-pauth-lr"));
}
to_add.push(llvm::CreateAttrStringValue(
cx.llcx,
"sign-return-address",
if leaf { "all" } else { "non-leaf" },
));
to_add.push(llvm::CreateAttrStringValue(
cx.llcx,
"sign-return-address-key",
if key == PAuthKey::A { "a_key" } else { "b_key" },
));
}
}
}
Expand Down Expand Up @@ -510,12 +508,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
InstructionSetAttr::ArmA32 => "-thumb-mode".to_string(),
InstructionSetAttr::ArmT32 => "+thumb-mode".to_string(),
}))
// HACK: LLVM versions 19+ do not have the FPMR feature and treat it as always enabled
// It only exists as a feature in LLVM 18, cannot be passed down for any other version
.chain(match &*cx.tcx.sess.target.arch {
"aarch64" if llvm_util::get_version().0 == 18 => vec!["+fpmr".to_string()],
_ => vec![],
})
.collect::<Vec<String>>();

if cx.tcx.sess.target.is_like_wasm {
Expand Down
30 changes: 7 additions & 23 deletions compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use smallvec::SmallVec;
use tracing::{debug, instrument};

use crate::abi::FnAbiLlvmExt;
use crate::attributes;
use crate::common::Funclet;
use crate::context::{CodegenCx, FullCx, GenericCx, SCx};
use crate::llvm::{
Expand All @@ -38,7 +39,6 @@ use crate::llvm::{
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
use crate::{attributes, llvm_util};

#[must_use]
pub(crate) struct GenericBuilder<'a, 'll, CX: Borrow<SCx<'ll>>> {
Expand Down Expand Up @@ -927,11 +927,9 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
debug_assert_ne!(self.val_ty(val), dest_ty);

let trunc = self.trunc(val, dest_ty);
if llvm_util::get_version() >= (19, 0, 0) {
unsafe {
if llvm::LLVMIsAInstruction(trunc).is_some() {
llvm::LLVMSetNUW(trunc, True);
}
unsafe {
if llvm::LLVMIsAInstruction(trunc).is_some() {
llvm::LLVMSetNUW(trunc, True);
}
}
trunc
Expand All @@ -941,11 +939,9 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
debug_assert_ne!(self.val_ty(val), dest_ty);

let trunc = self.trunc(val, dest_ty);
if llvm_util::get_version() >= (19, 0, 0) {
unsafe {
if llvm::LLVMIsAInstruction(trunc).is_some() {
llvm::LLVMSetNSW(trunc, True);
}
unsafe {
if llvm::LLVMIsAInstruction(trunc).is_some() {
llvm::LLVMSetNSW(trunc, True);
}
}
trunc
Expand Down Expand Up @@ -1899,10 +1895,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
hash: &'ll Value,
bitmap_bits: &'ll Value,
) {
assert!(
crate::llvm_util::get_version() >= (19, 0, 0),
"MCDC intrinsics require LLVM 19 or later"
);
self.call_intrinsic("llvm.instrprof.mcdc.parameters", &[fn_name, hash, bitmap_bits]);
}

Expand All @@ -1914,10 +1906,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
bitmap_index: &'ll Value,
mcdc_temp: &'ll Value,
) {
assert!(
crate::llvm_util::get_version() >= (19, 0, 0),
"MCDC intrinsics require LLVM 19 or later"
);
let args = &[fn_name, hash, bitmap_index, mcdc_temp];
self.call_intrinsic("llvm.instrprof.mcdc.tvbitmap.update", args);
}
Expand All @@ -1929,10 +1917,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {

#[instrument(level = "debug", skip(self))]
pub(crate) fn mcdc_condbitmap_update(&mut self, cond_index: &'ll Value, mcdc_temp: &'ll Value) {
assert!(
crate::llvm_util::get_version() >= (19, 0, 0),
"MCDC intrinsics require LLVM 19 or later"
);
let align = self.tcx.data_layout.i32_align.abi;
let current_tv_index = self.load(self.cx.type_i32(), mcdc_temp, align);
let new_tv_index = self.add(current_tv_index, cond_index);
Expand Down
23 changes: 2 additions & 21 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,23 +164,6 @@ pub(crate) unsafe fn create_module<'ll>(
let mut target_data_layout = sess.target.data_layout.to_string();
let llvm_version = llvm_util::get_version();

if llvm_version < (19, 0, 0) {
if sess.target.arch == "aarch64" || sess.target.arch.starts_with("arm64") {
// LLVM 19 sets -Fn32 in its data layout string for 64-bit ARM
// Earlier LLVMs leave this default, so remove it.
// See https://github.com/llvm/llvm-project/pull/90702
target_data_layout = target_data_layout.replace("-Fn32", "");
}
}

if llvm_version < (19, 0, 0) {
if sess.target.arch == "loongarch64" {
// LLVM 19 updates the LoongArch64 data layout.
// See https://github.com/llvm/llvm-project/pull/93814
target_data_layout = target_data_layout.replace("-n32:64", "-n64");
}
}

if llvm_version < (20, 0, 0) {
if sess.target.arch == "aarch64" || sess.target.arch.starts_with("arm64") {
// LLVM 20 defines three additional address spaces for alternate
Expand Down Expand Up @@ -1218,10 +1201,8 @@ impl<'ll> CodegenCx<'ll, '_> {

if self.sess().instrument_coverage() {
ifn!("llvm.instrprof.increment", fn(ptr, t_i64, t_i32, t_i32) -> void);
if crate::llvm_util::get_version() >= (19, 0, 0) {
ifn!("llvm.instrprof.mcdc.parameters", fn(ptr, t_i64, t_i32) -> void);
ifn!("llvm.instrprof.mcdc.tvbitmap.update", fn(ptr, t_i64, t_i32, ptr) -> void);
}
ifn!("llvm.instrprof.mcdc.parameters", fn(ptr, t_i64, t_i32) -> void);
ifn!("llvm.instrprof.mcdc.tvbitmap.update", fn(ptr, t_i64, t_i32, ptr) -> void);
}

ifn!("llvm.type.test", fn(ptr, t_metadata) -> i1);
Expand Down
17 changes: 2 additions & 15 deletions compiler/rustc_codegen_llvm/src/llvm_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,6 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
("aarch64", "pmuv3") => Some(LLVMFeature::new("perfmon")),
("aarch64", "paca") => Some(LLVMFeature::new("pauth")),
("aarch64", "pacg") => Some(LLVMFeature::new("pauth")),
("aarch64", "pauth-lr") if get_version().0 < 19 => None,
// Before LLVM 20 those two features were packaged together as b16b16
("aarch64", "sve-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")),
("aarch64", "sme-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")),
Expand All @@ -270,20 +269,9 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
("aarch64", "fhm") => Some(LLVMFeature::new("fp16fml")),
("aarch64", "fp16") => Some(LLVMFeature::new("fullfp16")),
// Filter out features that are not supported by the current LLVM version
("aarch64", "fpmr") if get_version().0 != 18 => None,
("aarch64", "fpmr") => None, // only existed in 18
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to retain this feature?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure in which context it would have been specified and needed to be filtered out before. e.g. was that only from unstable #[target_feature] or -Ctarget-feature?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mrkajetanp Do we need to keep this target feature around?

It looks like there is some runtime detection support for it: https://github.com/rust-lang/stdarch/blob/65712f37fb4d8f275e5eb7bd7b0057fdd68a91aa/crates/std_detect/src/detect/arch/aarch64.rs#L162-L164

I'm not super clear on how/why we're supporting target features that LLVM doesn't.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The relevant discussion was here: #128192
The approach we settled on was this:

We switch it on by default through target specs on LLVM 18, it's already switched on on LLVM 19+ and it doesn't exist on older LLVM versions. But we do keep the detection in std_detect.

So, if we no longer support LLVM 18 then it should not be necessary.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need to remove it from stdarch first though, right? If so, then I suggest:

  1. Merge this PR with the => None filter.
  2. Remove "fpmr" from stdarch.
  3. Update stdarch and drop that line in a followup.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In that case, it would be nice to add an appropriate FIXME comment to this PR that mentions the stdarch plan.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be desirable to keep it in stdarch for runtime detection. You no longer need to enable it for LLVM to use it, but you may still want to check whether the machine your code runs on actually supports it.

("arm", "fp16") => Some(LLVMFeature::new("fullfp16")),
// In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single
// feature called `fast-unaligned-access`. In LLVM 19, it was split back out.
("riscv32" | "riscv64", "unaligned-scalar-mem" | "unaligned-vector-mem")
if get_version().0 == 18 =>
{
Some(LLVMFeature::new("fast-unaligned-access"))
}
// Filter out features that are not supported by the current LLVM version
("riscv32" | "riscv64", "zaamo") if get_version().0 < 19 => None,
("riscv32" | "riscv64", "zabha") if get_version().0 < 19 => None,
("riscv32" | "riscv64", "zalrsc") if get_version().0 < 19 => None,
("riscv32" | "riscv64", "zama16b") if get_version().0 < 19 => None,
("riscv32" | "riscv64", "zacas") if get_version().0 < 20 => None,
// Enable the evex512 target feature if an avx512 target feature is enabled.
("x86", s) if s.starts_with("avx512") => {
Expand All @@ -295,10 +283,9 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
("sparc", "leoncasa") => Some(LLVMFeature::new("hasleoncasa")),
// In LLVM 19, there is no `v8plus` feature and `v9` means "SPARC-V9 instruction available and SPARC-V8+ ABI used".
// https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp#L27-L28
// Before LLVM 19, there is no `v8plus` feature and `v9` means "SPARC-V9 instruction available".
// Before LLVM 19, there was no `v8plus` feature and `v9` means "SPARC-V9 instruction available".
// https://github.com/llvm/llvm-project/blob/llvmorg-18.1.0/llvm/lib/Target/Sparc/MCTargetDesc/SparcELFObjectWriter.cpp#L26
("sparc", "v8plus") if get_version().0 == 19 => Some(LLVMFeature::new("v9")),
("sparc", "v8plus") if get_version().0 < 19 => None,
("powerpc", "power8-crypto") => Some(LLVMFeature::new("crypto")),
// These new `amx` variants and `movrs` were introduced in LLVM20
("x86", "amx-avx512" | "amx-fp8" | "amx-movrs" | "amx-tf32" | "amx-transpose")
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ struct LLVMRustMCDCBranchParameters {
int16_t ConditionIDs[2];
};

#if LLVM_VERSION_GE(19, 0)
static coverage::mcdc::BranchParameters
fromRust(LLVMRustMCDCBranchParameters Params) {
return coverage::mcdc::BranchParameters(
Expand All @@ -59,7 +58,6 @@ fromRust(LLVMRustMCDCDecisionParameters Params) {
return coverage::mcdc::DecisionParameters(Params.BitmapIdx,
Params.NumConditions);
}
#endif

// Must match the layout of
// `rustc_codegen_llvm::coverageinfo::ffi::CoverageSpan`.
Expand Down Expand Up @@ -203,7 +201,6 @@ extern "C" void LLVMRustCoverageWriteFunctionMappingsToBuffer(
Region.Span.LineEnd, Region.Span.ColumnEnd));
}

#if LLVM_VERSION_GE(19, 0)
// MC/DC branch regions:
for (const auto &Region : ArrayRef(MCDCBranchRegions, NumMCDCBranchRegions)) {
MappingRegions.push_back(coverage::CounterMappingRegion::makeBranchRegion(
Expand All @@ -221,7 +218,6 @@ extern "C" void LLVMRustCoverageWriteFunctionMappingsToBuffer(
Region.Span.LineStart, Region.Span.ColumnStart, Region.Span.LineEnd,
Region.Span.ColumnEnd));
}
#endif

// Write the converted expressions and mappings to a byte buffer.
auto CoverageMappingWriter = coverage::CoverageMappingWriter(
Expand Down
58 changes: 14 additions & 44 deletions compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@
#include <vector>

// Conditional includes prevent clang-format from fully sorting the list,
// so keep them separate.
#if LLVM_VERSION_GE(19, 0)
#include "llvm/Support/PGOOptions.h"
#endif
// so if any are needed, keep them separate down here.

using namespace llvm;

Expand Down Expand Up @@ -432,31 +429,15 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
}
if (!strcmp("zlib", DebugInfoCompression) &&
llvm::compression::zlib::isAvailable()) {
#if LLVM_VERSION_GE(19, 0)
Options.MCOptions.CompressDebugSections = DebugCompressionType::Zlib;
#else
Options.CompressDebugSections = DebugCompressionType::Zlib;
#endif
} else if (!strcmp("zstd", DebugInfoCompression) &&
llvm::compression::zstd::isAvailable()) {
#if LLVM_VERSION_GE(19, 0)
Options.MCOptions.CompressDebugSections = DebugCompressionType::Zstd;
#else
Options.CompressDebugSections = DebugCompressionType::Zstd;
#endif
} else if (!strcmp("none", DebugInfoCompression)) {
#if LLVM_VERSION_GE(19, 0)
Options.MCOptions.CompressDebugSections = DebugCompressionType::None;
#else
Options.CompressDebugSections = DebugCompressionType::None;
#endif
}

#if LLVM_VERSION_GE(19, 0)
Options.MCOptions.X86RelaxRelocations = RelaxELFRelocations;
#else
Options.RelaxELFRelocations = RelaxELFRelocations;
#endif
Options.UseInitArray = UseInitArray;
Options.EmulatedTLS = UseEmulatedTls;

Expand Down Expand Up @@ -753,34 +734,23 @@ extern "C" LLVMRustResult LLVMRustOptimize(
auto FS = vfs::getRealFileSystem();
if (PGOGenPath) {
assert(!PGOUsePath && !PGOSampleUsePath);
PGOOpt = PGOOptions(PGOGenPath, "", "", "", FS, PGOOptions::IRInstr,
PGOOptions::NoCSAction,
#if LLVM_VERSION_GE(19, 0)
PGOOptions::ColdFuncOpt::Default,
#endif
DebugInfoForProfiling);
PGOOpt = PGOOptions(
PGOGenPath, "", "", "", FS, PGOOptions::IRInstr, PGOOptions::NoCSAction,
PGOOptions::ColdFuncOpt::Default, DebugInfoForProfiling);
} else if (PGOUsePath) {
assert(!PGOSampleUsePath);
PGOOpt = PGOOptions(PGOUsePath, "", "", "", FS, PGOOptions::IRUse,
PGOOptions::NoCSAction,
#if LLVM_VERSION_GE(19, 0)
PGOOptions::ColdFuncOpt::Default,
#endif
DebugInfoForProfiling);
PGOOpt = PGOOptions(
PGOUsePath, "", "", "", FS, PGOOptions::IRUse, PGOOptions::NoCSAction,
PGOOptions::ColdFuncOpt::Default, DebugInfoForProfiling);
} else if (PGOSampleUsePath) {
PGOOpt = PGOOptions(PGOSampleUsePath, "", "", "", FS, PGOOptions::SampleUse,
PGOOptions::NoCSAction,
#if LLVM_VERSION_GE(19, 0)
PGOOptions::ColdFuncOpt::Default,
#endif
DebugInfoForProfiling);
PGOOpt =
PGOOptions(PGOSampleUsePath, "", "", "", FS, PGOOptions::SampleUse,
PGOOptions::NoCSAction, PGOOptions::ColdFuncOpt::Default,
DebugInfoForProfiling);
} else if (DebugInfoForProfiling) {
PGOOpt = PGOOptions("", "", "", "", FS, PGOOptions::NoAction,
PGOOptions::NoCSAction,
#if LLVM_VERSION_GE(19, 0)
PGOOptions::ColdFuncOpt::Default,
#endif
DebugInfoForProfiling);
PGOOpt = PGOOptions(
"", "", "", "", FS, PGOOptions::NoAction, PGOOptions::NoCSAction,
PGOOptions::ColdFuncOpt::Default, DebugInfoForProfiling);
}

auto PB = PassBuilder(TM, PTO, PGOOpt, &PIC);
Expand Down
Loading
Loading