-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
RISC-V intrinsics with one or more target features are not inlined #137293
Comments
I'm pretty sure |
We do not have support for See the scalar crypto doc for riscv https://github.com/riscv/riscv-crypto/releases/tag/v1.0.1-scalar cc @Amanieu |
Is there any non-trivial reason why Rust does not support this behavior? |
When codegening the function #[target_feature(biskeshed_enable_one_of("zkne", "zknd")]
pub unsafe fn aes64ks2(rs1: u64, rs2: u64) -> u64 {
// ...
} which of the two features should be enabled? You have to enable at least one of them to be able to call the inner intrinsic, but there is no way to know which of the two features the caller has enabled. The |
ORing features is functionally equivalent to having a new feature called Incidentally this is very similar to rust-lang/compiler-team#778. |
Does LLVM have any support for that? |
I don't mean if LLVM supports it for declaring intrinsics, but if it supports it when defining functions. If stdarch writes #![feature(link_llvm_intrinsics, abi_unadjusted)]
unsafe extern "unadjusted" {
#[link_name = "llvm.riscv.aes64ks2"]
fn _aes64ks2(rs1: i64, rs2: i64) -> i64;
}
#[target_feature(enable = "zkne", enable = "zknd")]
pub unsafe fn aes64ks2(rs1: u64, rs2: u64) -> u64 {
_aes64ks2(rs1 as i64, rs2 as i64) as u64
} that currently results in the following LLVM IR: ; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable
define noundef i64 @aes64ks2(i64 noundef %rs1, i64 noundef %rs2) unnamed_addr #0 !dbg !8 {
start:
%_3 = tail call noundef i64 @llvm.riscv.aes64ks2(i64 noundef %rs1, i64 noundef %rs2) #2, !dbg !19
ret i64 %_3, !dbg !20
}
; Function Attrs: mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i64 @llvm.riscv.aes64ks2(i64, i64) unnamed_addr #1
attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable "target-cpu"="generic-rv64" "target-features"="+m,+a,+f,+d,+c,+zkne,+zknd" }
attributes #1 = { mustprogress nocallback nofree nosync nounwind speculatable willreturn memory(none) }
attributes #2 = { nounwind } What must be the value of the |
It seems like the answer is "there's not actually sufficient underlying codegen backend support for doing the thing you think it does". |
The Problem
The compiler does not inline RISC-V intrinsics that can be enabled with one or more target features (i.e.
#[target_feature(enable = "zkne", enable = "zknd")]
) unless all of them are present.Expected Behavior
At least one enabled feature should be enough for the compiler to generate inlined code.
Explanation
RISC-V intrinsics such as sha512sig0 require only one target feature:
When
zknh
is enabled, the compiler inlines the intrinsic with the appropriate instruction on nightly (https://godbolt.org/z/Kozx3KE11):Unfortunately, this is not the case for intrinsics that can be enabled by one or more target features. Let's take a look at aes64ks2:
The documentation states that the intrinsic is "safe to use if the
zkne
ORzknd
target feature is present." which means that enabling at least one of them should be enough to inline the intrinsic.However, the compiler exhibits this behavior only if two of them are enabled at the same time.
The compiler generates a stub if only one of
zkne
(https://godbolt.org/z/5TxeKo1sG), orzknd
(https://godbolt.org/z/KKqz8MWYY) is enabled:If they are both enabled, the compiler inlines the intrinsic as expected (https://godbolt.org/z/3fEjfr1v8):
Meta
Here is the output of the compiler:
The text was updated successfully, but these errors were encountered: