@@ -2,6 +2,7 @@ use crate::base;
2
2
use crate :: common:: CodegenCx ;
3
3
use crate :: debuginfo;
4
4
use crate :: llvm:: { self , True } ;
5
+ use crate :: llvm_util;
5
6
use crate :: type_:: Type ;
6
7
use crate :: type_of:: LayoutLlvmExt ;
7
8
use crate :: value:: Value ;
@@ -37,7 +38,7 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) ->
37
38
alloc : & ' a Allocation ,
38
39
range : Range < usize > ,
39
40
) {
40
- let mut chunks = alloc
41
+ let chunks = alloc
41
42
. init_mask ( )
42
43
. range_as_init_chunks ( Size :: from_bytes ( range. start ) , Size :: from_bytes ( range. end ) ) ;
43
44
@@ -53,30 +54,26 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) ->
53
54
}
54
55
} ;
55
56
56
- // Generating partially-uninit consts inhibits optimizations, so it is disabled by default.
57
- // See https://github.com/rust-lang/rust/issues/84565.
58
- let allow_partially_uninit =
59
- match cx. sess ( ) . opts . debugging_opts . partially_uninit_const_threshold {
60
- Some ( max) => range. len ( ) <= max,
61
- None => false ,
62
- } ;
57
+ // Generating partially-uninit consts is limited to small numbers of chunks,
58
+ // to avoid the cost of generating large complex const expressions.
59
+ // For example, `[(u32, u8); 1024 * 1024]` contains uninit padding in each element,
60
+ // and would result in `{ [5 x i8] zeroinitializer, [3 x i8] undef, ...repeat 1M times... }`.
61
+ let max = if llvm_util:: get_version ( ) < ( 14 , 0 , 0 ) {
62
+ // Generating partially-uninit consts inhibits optimizations in LLVM < 14.
63
+ // See https://github.com/rust-lang/rust/issues/84565.
64
+ 1
65
+ } else {
66
+ cx. sess ( ) . opts . debugging_opts . uninit_const_chunk_threshold
67
+ } ;
68
+ let allow_uninit_chunks = chunks. clone ( ) . take ( max. saturating_add ( 1 ) ) . count ( ) <= max;
63
69
64
- if allow_partially_uninit {
70
+ if allow_uninit_chunks {
65
71
llvals. extend ( chunks. map ( chunk_to_llval) ) ;
66
72
} else {
67
- let llval = match ( chunks. next ( ) , chunks. next ( ) ) {
68
- ( Some ( chunk) , None ) => {
69
- // exactly one chunk, either fully init or fully uninit
70
- chunk_to_llval ( chunk)
71
- }
72
- _ => {
73
- // partially uninit, codegen as if it was initialized
74
- // (using some arbitrary value for uninit bytes)
75
- let bytes = alloc. inspect_with_uninit_and_ptr_outside_interpreter ( range) ;
76
- cx. const_bytes ( bytes)
77
- }
78
- } ;
79
- llvals. push ( llval) ;
73
+ // If this allocation contains any uninit bytes, codegen as if it was initialized
74
+ // (using some arbitrary value for uninit bytes).
75
+ let bytes = alloc. inspect_with_uninit_and_ptr_outside_interpreter ( range) ;
76
+ llvals. push ( cx. const_bytes ( bytes) ) ;
80
77
}
81
78
}
82
79
0 commit comments