@@ -854,12 +854,34 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
854
854
855
855
// --- End Recovery Path ---
856
856
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
+
857
876
// --- Attempt GEP Merging Path ---
858
877
859
878
// Check if the base pointer `ptr` itself was the result of a previous
860
879
// AccessChain instruction. Merging is only attempted if the input type `ty`
861
880
// matches the pointer's actual underlying pointee type `original_pointee_ty`.
862
881
// 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
863
885
let maybe_original_access_chain = if ty == original_pointee_ty {
864
886
// Search the current function's instructions...
865
887
// FIXME(eddyb) this could get ridiculously expensive, at the very least
@@ -908,12 +930,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
908
930
// 2. The *last* index of the original AccessChain is a constant.
909
931
// 3. The *first* index (`ptr_base_index`) of the *current* GEP is a constant.
910
932
// 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).
911
937
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
+ }
917
948
} else {
918
949
// Original access chain had no indices to merge with.
919
950
false
@@ -966,21 +997,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
966
997
// This path is taken if neither the Recovery nor the Merging path succeeded or applied.
967
998
// It performs a more direct translation of the GEP request.
968
999
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
-
984
1000
trace ! (
985
1001
"emitting access chain via fallback path with pointer type: {}" ,
986
1002
self . debug_type( final_spirv_ptr_type)
0 commit comments