@@ -854,12 +854,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
854854
855855 // --- End Recovery Path ---
856856
857+ // FIXME(eddyb) the comments below might not make much sense, because this
858+ // used to be in the "fallback path" before being moved to before merging.
859+ //
860+ // Before emitting the AccessChain, explicitly cast the base pointer `ptr` to
861+ // ensure its pointee type matches the input `ty`. This is required because the
862+ // SPIR-V `AccessChain` instruction implicitly uses the size of the base
863+ // pointer's pointee type when applying the *first* index operand (our
864+ // `ptr_base_index`). If `ty` and `original_pointee_ty` mismatched and we
865+ // reached this fallback, this cast ensures SPIR-V validity.
866+ trace ! ( "maybe_inbounds_gep fallback path calling pointercast" ) ;
867+ // Cast ptr to point to `ty`.
868+ // HACK(eddyb) temporary workaround for untyped pointers upstream.
869+ // FIXME(eddyb) replace with untyped memory SPIR-V + `qptr` or similar.
870+ let ptr = self . pointercast ( ptr, self . type_ptr_to ( ty) ) ;
871+ // Get the ID of the (potentially newly casted) pointer.
872+ let ptr_id = ptr. def ( self ) ;
873+ // HACK(eddyb) updated pointee type of `ptr` post-`pointercast`.
874+ let original_pointee_ty = ty;
875+
857876 // --- Attempt GEP Merging Path ---
858877
859878 // Check if the base pointer `ptr` itself was the result of a previous
860879 // AccessChain instruction. Merging is only attempted if the input type `ty`
861880 // matches the pointer's actual underlying pointee type `original_pointee_ty`.
862881 // If they differ, merging could be invalid.
882+ // HACK(eddyb) always attempted now, because we `pointercast` first, which:
883+ // - is noop when `ty == original_pointee_ty` pre-`pointercast` (old condition)
884+ // - may generate (potentially mergeable) new `AccessChain`s in other cases
863885 let maybe_original_access_chain = if ty == original_pointee_ty {
864886 // Search the current function's instructions...
865887 // FIXME(eddyb) this could get ridiculously expensive, at the very least
@@ -908,12 +930,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
908930 // 2. The *last* index of the original AccessChain is a constant.
909931 // 3. The *first* index (`ptr_base_index`) of the *current* GEP is a constant.
910932 // Merging usually involves adding these two constant indices.
933+ //
934+ // FIXME(eddyb) the above comment seems inaccurate, there is no reason
935+ // why runtime indices couldn't be added together just like constants
936+ // (and in fact this is needed nowadays for all array indexing).
911937 let can_merge = if let Some ( & last_original_idx_id) = original_indices. last ( ) {
912- // Check if both the last original index and the current base index are constant scalars.
913- self . builder
914- . lookup_const_scalar ( last_original_idx_id. with_type ( ptr_base_index. ty ) )
915- . is_some ( )
916- && self . builder . lookup_const_scalar ( ptr_base_index) . is_some ( )
938+ // HACK(eddyb) see the above comment, this bypasses the const
939+ // check below, without tripping a clippy warning etc.
940+ let always_merge = true ;
941+ always_merge || {
942+ // Check if both the last original index and the current base index are constant scalars.
943+ self . builder
944+ . lookup_const_scalar ( last_original_idx_id. with_type ( ptr_base_index. ty ) )
945+ . is_some ( )
946+ && self . builder . lookup_const_scalar ( ptr_base_index) . is_some ( )
947+ }
917948 } else {
918949 // Original access chain had no indices to merge with.
919950 false
@@ -966,21 +997,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
966997 // This path is taken if neither the Recovery nor the Merging path succeeded or applied.
967998 // It performs a more direct translation of the GEP request.
968999
969- // HACK(eddyb): Workaround for potential upstream issues where pointers might lack precise type info.
970- // FIXME(eddyb): Ideally, this should use untyped memory features if available/necessary.
971-
972- // Before emitting the AccessChain, explicitly cast the base pointer `ptr` to
973- // ensure its pointee type matches the input `ty`. This is required because the
974- // SPIR-V `AccessChain` instruction implicitly uses the size of the base
975- // pointer's pointee type when applying the *first* index operand (our
976- // `ptr_base_index`). If `ty` and `original_pointee_ty` mismatched and we
977- // reached this fallback, this cast ensures SPIR-V validity.
978- trace ! ( "maybe_inbounds_gep fallback path calling pointercast" ) ;
979- // Cast ptr to point to `ty`.
980- let ptr = self . pointercast ( ptr, self . type_ptr_to ( ty) ) ;
981- // Get the ID of the (potentially newly casted) pointer.
982- let ptr_id = ptr. def ( self ) ;
983-
9841000 trace ! (
9851001 "emitting access chain via fallback path with pointer type: {}" ,
9861002 self . debug_type( final_spirv_ptr_type)
0 commit comments