@@ -732,9 +732,10 @@ impl<'f> PerFunctionContext<'f> {
732732
733733 let expr = Expression :: ArrayElement ( array) ;
734734 references. expressions . insert ( array, expr) ;
735- let aliases = references. aliases . entry ( expr) . or_insert ( AliasSet :: known_empty ( ) ) ;
736735
737- self . add_array_aliases ( elements, aliases) ;
736+ let new_aliases = self . collect_array_aliases ( elements, references) ;
737+ let aliases = references. aliases . entry ( expr) . or_insert ( AliasSet :: known_empty ( ) ) ;
738+ aliases. unify ( & new_aliases) ;
738739 }
739740 }
740741 Instruction :: IfElse { then_value, else_value, .. } => {
@@ -785,16 +786,23 @@ impl<'f> PerFunctionContext<'f> {
785786 }
786787 }
787788
788- /// In order to handle nested arrays we need to recursively search whether there are any references
789- /// contained within an array's elements.
790- fn add_array_aliases ( & self , elements : & im:: Vector < ValueId > , aliases : & mut AliasSet ) {
789+ /// In order to handle nested arrays we need to recursively search for whether there
790+ /// are any aliases contained within an array's elements.
791+ fn collect_array_aliases (
792+ & self ,
793+ elements : & im:: Vector < ValueId > ,
794+ references : & Block ,
795+ ) -> AliasSet {
796+ let mut aliases = AliasSet :: known_empty ( ) ;
791797 for & element in elements {
792798 if let Some ( ( elements, _) ) = self . inserter . function . dfg . get_array_constant ( element) {
793- self . add_array_aliases ( & elements, aliases) ;
794- } else if self . inserter . function . dfg . value_is_reference ( element) {
795- aliases. insert ( element) ;
799+ aliases. unify ( & self . collect_array_aliases ( & elements, references) ) ;
800+ } else if self . inserter . function . dfg . type_of_value ( element) . contains_reference ( ) {
801+ // Handles both direct references and non-constant arrays (e.g., array_set results)
802+ aliases. unify ( & references. get_aliases_for_value ( element) ) ;
796803 }
797804 }
805+ aliases
798806 }
799807
800808 fn set_aliases ( & self , references : & mut Block , address : ValueId , new_aliases : AliasSet ) {
@@ -2886,4 +2894,67 @@ mod tests {
28862894 }
28872895 " ) ;
28882896 }
2897+
2898+ #[ test]
2899+ fn missing_make_array_alias_from_array_set_result ( ) {
2900+ let src = "
2901+ acir(inline) predicate_pure fn main f0 {
2902+ b0(v0: u32, v1: u8, v2: u8):
2903+ v3 = allocate -> &mut u8
2904+ store v1 at v3
2905+ v4 = allocate -> &mut [&mut u8; 1]
2906+ v5 = make_array [v3] : [&mut u8; 1]
2907+ store v5 at v4
2908+ constrain v0 == u32 0
2909+ v6 = load v4 -> [&mut u8; 1]
2910+ v7 = array_set v6, index v0, value v3
2911+ v8 = allocate -> &mut u8
2912+ store u8 0 at v8
2913+ v9 = make_array [v8] : [&mut u8; 1]
2914+ v10 = make_array [v7, v9] : [[&mut u8; 1]; 2]
2915+ v11 = array_get v10, index v0 -> [&mut u8; 1]
2916+ v12 = array_get v11, index u32 0 -> &mut u8
2917+ store v2 at v3
2918+ v13 = load v12 -> u8
2919+ constrain v13 == v2
2920+ return
2921+ }
2922+ " ;
2923+
2924+ let ssa = Ssa :: from_str ( src) . unwrap ( ) ;
2925+ let result = ssa. interpret ( vec ! [ Value :: u32 ( 0 ) , Value :: u8 ( 0 ) , Value :: u8 ( 0 ) ] ) ;
2926+ assert_eq ! ( result, Ok ( vec![ ] ) ) ;
2927+ let result = ssa. interpret ( vec ! [ Value :: u32 ( 0 ) , Value :: u8 ( 0 ) , Value :: u8 ( 1 ) ] ) ;
2928+ assert_eq ! ( result, Ok ( vec![ ] ) ) ;
2929+
2930+ let ssa = ssa. mem2reg ( ) ;
2931+ // Alias tracking should prevent `store v2 at v3` from being removed
2932+ let result = ssa. interpret ( vec ! [ Value :: u32 ( 0 ) , Value :: u8 ( 0 ) , Value :: u8 ( 0 ) ] ) ;
2933+ assert_eq ! ( result, Ok ( vec![ ] ) ) ;
2934+ let result = ssa. interpret ( vec ! [ Value :: u32 ( 0 ) , Value :: u8 ( 0 ) , Value :: u8 ( 1 ) ] ) ;
2935+ assert_eq ! ( result, Ok ( vec![ ] ) ) ;
2936+
2937+ // Only `store v5 at v4` is safe to remove
2938+ assert_ssa_snapshot ! ( ssa, @r"
2939+ acir(inline) predicate_pure fn main f0 {
2940+ b0(v0: u32, v1: u8, v2: u8):
2941+ v3 = allocate -> &mut u8
2942+ store v1 at v3
2943+ v4 = allocate -> &mut [&mut u8; 1]
2944+ v5 = make_array [v3] : [&mut u8; 1]
2945+ constrain v0 == u32 0
2946+ v7 = array_set v5, index v0, value v3
2947+ v8 = allocate -> &mut u8
2948+ store u8 0 at v8
2949+ v10 = make_array [v8] : [&mut u8; 1]
2950+ v11 = make_array [v7, v10] : [[&mut u8; 1]; 2]
2951+ v12 = array_get v11, index v0 -> [&mut u8; 1]
2952+ v13 = array_get v12, index u32 0 -> &mut u8
2953+ store v2 at v3
2954+ v14 = load v13 -> u8
2955+ constrain v14 == v2
2956+ return
2957+ }
2958+ " ) ;
2959+ }
28892960}
0 commit comments