@@ -2,6 +2,7 @@ use crate::base;
22use crate :: common:: CodegenCx ;
33use crate :: debuginfo;
44use crate :: llvm:: { self , True } ;
5+ use crate :: llvm_util;
56use crate :: type_:: Type ;
67use crate :: type_of:: LayoutLlvmExt ;
78use crate :: value:: Value ;
@@ -37,7 +38,7 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) ->
3738 alloc : & ' a Allocation ,
3839 range : Range < usize > ,
3940 ) {
40- let mut chunks = alloc
41+ let chunks = alloc
4142 . init_mask ( )
4243 . range_as_init_chunks ( Size :: from_bytes ( range. start ) , Size :: from_bytes ( range. end ) ) ;
4344
@@ -53,30 +54,26 @@ pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) ->
5354 }
5455 } ;
5556
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;
6369
64- if allow_partially_uninit {
70+ if allow_uninit_chunks {
6571 llvals. extend ( chunks. map ( chunk_to_llval) ) ;
6672 } 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) ) ;
8077 }
8178 }
8279
0 commit comments