@@ -18,6 +18,7 @@ use rustc_session::config::{PrintKind, PrintRequest};
18
18
use rustc_span:: Symbol ;
19
19
use rustc_target:: spec:: { MergeFunctions , PanicStrategy , SmallDataThresholdSupport } ;
20
20
use rustc_target:: target_features:: { RUSTC_SPECIAL_FEATURES , RUSTC_SPECIFIC_FEATURES } ;
21
+ use smallvec:: { SmallVec , smallvec} ;
21
22
22
23
use crate :: back:: write:: create_informational_target_machine;
23
24
use crate :: errors:: {
@@ -179,27 +180,27 @@ impl<'a> TargetFeatureFoldStrength<'a> {
179
180
180
181
pub ( crate ) struct LLVMFeature < ' a > {
181
182
llvm_feature_name : & ' a str ,
182
- dependency : Option < TargetFeatureFoldStrength < ' a > > ,
183
+ dependencies : SmallVec < [ TargetFeatureFoldStrength < ' a > ; 1 ] > ,
183
184
}
184
185
185
186
impl < ' a > LLVMFeature < ' a > {
186
187
fn new ( llvm_feature_name : & ' a str ) -> Self {
187
- Self { llvm_feature_name, dependency : None }
188
+ Self { llvm_feature_name, dependencies : SmallVec :: new ( ) }
188
189
}
189
190
190
- fn with_dependency (
191
+ fn with_dependencies (
191
192
llvm_feature_name : & ' a str ,
192
- dependency : TargetFeatureFoldStrength < ' a > ,
193
+ dependencies : SmallVec < [ TargetFeatureFoldStrength < ' a > ; 1 ] > ,
193
194
) -> Self {
194
- Self { llvm_feature_name, dependency : Some ( dependency ) }
195
+ Self { llvm_feature_name, dependencies }
195
196
}
196
197
197
- fn contains ( & self , feat : & str ) -> bool {
198
+ fn contains ( & ' a self , feat : & str ) -> bool {
198
199
self . iter ( ) . any ( |dep| dep == feat)
199
200
}
200
201
201
202
fn iter ( & ' a self ) -> impl Iterator < Item = & ' a str > {
202
- let dependencies = self . dependency . iter ( ) . map ( |feat| feat. as_str ( ) ) ;
203
+ let dependencies = self . dependencies . iter ( ) . map ( |feat| feat. as_str ( ) ) ;
203
204
std:: iter:: once ( self . llvm_feature_name ) . chain ( dependencies)
204
205
}
205
206
}
@@ -209,7 +210,7 @@ impl<'a> IntoIterator for LLVMFeature<'a> {
209
210
type IntoIter = impl Iterator < Item = & ' a str > ;
210
211
211
212
fn into_iter ( self ) -> Self :: IntoIter {
212
- let dependencies = self . dependency . into_iter ( ) . map ( |feat| feat. as_str ( ) ) ;
213
+ let dependencies = self . dependencies . into_iter ( ) . map ( |feat| feat. as_str ( ) ) ;
213
214
std:: iter:: once ( self . llvm_feature_name ) . chain ( dependencies)
214
215
}
215
216
}
@@ -239,9 +240,9 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
239
240
& * sess. target . arch
240
241
} ;
241
242
match ( arch, s) {
242
- ( "x86" , "sse4.2" ) => Some ( LLVMFeature :: with_dependency (
243
+ ( "x86" , "sse4.2" ) => Some ( LLVMFeature :: with_dependencies (
243
244
"sse4.2" ,
244
- TargetFeatureFoldStrength :: EnableOnly ( "crc32" ) ,
245
+ smallvec ! [ TargetFeatureFoldStrength :: EnableOnly ( "crc32" ) ] ,
245
246
) ) ,
246
247
( "x86" , "pclmulqdq" ) => Some ( LLVMFeature :: new ( "pclmul" ) ) ,
247
248
( "x86" , "rdrand" ) => Some ( LLVMFeature :: new ( "rdrnd" ) ) ,
@@ -261,9 +262,10 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
261
262
( "aarch64" , "sme-b16b16" ) if get_version ( ) . 0 < 20 => Some ( LLVMFeature :: new ( "b16b16" ) ) ,
262
263
( "aarch64" , "flagm2" ) => Some ( LLVMFeature :: new ( "altnzcv" ) ) ,
263
264
// Rust ties fp and neon together.
264
- ( "aarch64" , "neon" ) => {
265
- Some ( LLVMFeature :: with_dependency ( "neon" , TargetFeatureFoldStrength :: Both ( "fp-armv8" ) ) )
266
- }
265
+ ( "aarch64" , "neon" ) => Some ( LLVMFeature :: with_dependencies (
266
+ "neon" ,
267
+ smallvec ! [ TargetFeatureFoldStrength :: Both ( "fp-armv8" ) ] ,
268
+ ) ) ,
267
269
// In LLVM neon implicitly enables fp, but we manually enable
268
270
// neon when a feature only implicitly enables fp
269
271
( "aarch64" , "fhm" ) => Some ( LLVMFeature :: new ( "fp16fml" ) ) ,
@@ -274,9 +276,10 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
274
276
// Filter out features that are not supported by the current LLVM version
275
277
( "riscv32" | "riscv64" , "zacas" ) if get_version ( ) . 0 < 20 => None ,
276
278
// Enable the evex512 target feature if an avx512 target feature is enabled.
277
- ( "x86" , s) if s. starts_with ( "avx512" ) => {
278
- Some ( LLVMFeature :: with_dependency ( s, TargetFeatureFoldStrength :: EnableOnly ( "evex512" ) ) )
279
- }
279
+ ( "x86" , s) if s. starts_with ( "avx512" ) => Some ( LLVMFeature :: with_dependencies (
280
+ s,
281
+ smallvec ! [ TargetFeatureFoldStrength :: EnableOnly ( "evex512" ) ] ,
282
+ ) ) ,
280
283
// Support for `wide-arithmetic` will first land in LLVM 20 as part of
281
284
// llvm/llvm-project#111598
282
285
( "wasm32" | "wasm64" , "wide-arithmetic" ) if get_version ( ) < ( 20 , 0 , 0 ) => None ,
@@ -765,7 +768,7 @@ pub(crate) fn global_llvm_features(
765
768
"{}{}" ,
766
769
enable_disable, llvm_feature. llvm_feature_name
767
770
) )
768
- . chain ( llvm_feature. dependency . into_iter ( ) . filter_map (
771
+ . chain ( llvm_feature. dependencies . into_iter ( ) . filter_map (
769
772
move |feat| match ( enable, feat) {
770
773
( _, TargetFeatureFoldStrength :: Both ( f) )
771
774
| ( true , TargetFeatureFoldStrength :: EnableOnly ( f) ) => {
0 commit comments