@@ -759,8 +759,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
759759 if const_offset == Some ( Size :: ZERO ) {
760760 trace ! ( "ptr_offset_strided: strategy 1 picked: offset 0 => pointer cast" ) ;
761761
762- // FIXME(eddyb) could this just `return ptr;`? what even breaks?
763- return self . pointercast ( ptr, self . type_ptr_to ( stride_elem_ty ) ) ;
762+ // FIXME(eddyb) replace docs to remove mentions of pointer casting.
763+ return ptr;
764764 }
765765
766766 // Strategy 2: try recovering an `OpAccessChain` from a constant offset.
@@ -3261,6 +3261,7 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
32613261 Bitcast ( ID , ID ) ,
32623262 CompositeExtract ( ID , ID , u32 ) ,
32633263 InBoundsAccessChain ( ID , ID , u32 ) ,
3264+ InBoundsAccessChain2 ( ID , ID , u32 , u32 ) ,
32643265 Store ( ID , ID ) ,
32653266 Load ( ID , ID ) ,
32663267 CopyMemory ( ID , ID ) ,
@@ -3317,6 +3318,13 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
33173318 Inst :: Unsupported ( inst. class . opcode )
33183319 }
33193320 }
3321+ ( Op :: InBoundsAccessChain , Some ( r) , & [ p, i, j] ) => {
3322+ if let [ Some ( i) , Some ( j) ] = [ i, j] . map ( const_as_u32) {
3323+ Inst :: InBoundsAccessChain2 ( r, p, i, j)
3324+ } else {
3325+ Inst :: Unsupported ( inst. class . opcode )
3326+ }
3327+ }
33203328 ( Op :: Store , None , & [ p, v] ) => Inst :: Store ( p, v) ,
33213329 ( Op :: Load , Some ( r) , & [ p] ) => Inst :: Load ( r, p) ,
33223330 ( Op :: CopyMemory , None , & [ a, b] ) => Inst :: CopyMemory ( a, b) ,
@@ -3508,20 +3516,45 @@ impl<'a, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'tcx> {
35083516
35093517 let rev_copies_to_rt_args_array_src_ptrs: SmallVec < [ _ ; 4 ] > =
35103518 ( 0 ..rt_args_count) . rev ( ) . map ( |rt_arg_idx| {
3511- let copy_to_rt_args_array_insts = try_rev_take ( 4 ) . ok_or_else ( || {
3519+ let mut copy_to_rt_args_array_insts = try_rev_take ( 3 ) . ok_or_else ( || {
35123520 FormatArgsNotRecognized (
35133521 "[fmt::rt::Argument; N] copy: ran out of instructions" . into ( ) ,
35143522 )
35153523 } ) ?;
3524+
3525+ // HACK(eddyb) account for both the split and combined
3526+ // access chain cases that `inbounds_gep` can now cause.
3527+ if let Inst :: InBoundsAccessChain ( dst_field_ptr, dst_base_ptr, 0 ) =
3528+ copy_to_rt_args_array_insts[ 0 ]
3529+ {
3530+ if let Some ( mut prev_insts) = try_rev_take ( 1 ) {
3531+ assert_eq ! ( prev_insts. len( ) , 1 ) ;
3532+ let prev_inst = prev_insts. pop ( ) . unwrap ( ) ;
3533+
3534+ match prev_inst {
3535+ Inst :: InBoundsAccessChain (
3536+ array_elem_ptr,
3537+ array_ptr,
3538+ idx,
3539+ ) if dst_base_ptr == array_elem_ptr => {
3540+ copy_to_rt_args_array_insts[ 0 ] =
3541+ Inst :: InBoundsAccessChain2 ( dst_field_ptr, array_ptr, idx, 0 ) ;
3542+ }
3543+ _ => {
3544+ // HACK(eddyb) don't lose the taken `prev_inst`.
3545+ copy_to_rt_args_array_insts. insert ( 0 , prev_inst) ;
3546+ }
3547+ }
3548+ }
3549+ }
3550+
35163551 match copy_to_rt_args_array_insts[ ..] {
35173552 [
3518- Inst :: InBoundsAccessChain ( array_slot, array_base, array_idx) ,
3519- Inst :: InBoundsAccessChain ( dst_field_ptr, dst_base_ptr, 0 ) ,
3553+ Inst :: InBoundsAccessChain2 ( dst_field_ptr, dst_array_base_ptr, array_idx, 0 ) ,
35203554 Inst :: InBoundsAccessChain ( src_field_ptr, src_base_ptr, 0 ) ,
35213555 Inst :: CopyMemory ( copy_dst, copy_src) ,
3522- ] if array_base == rt_args_array_ptr_id
3556+ ] if dst_array_base_ptr == rt_args_array_ptr_id
35233557 && array_idx as usize == rt_arg_idx
3524- && dst_base_ptr == array_slot
35253558 && ( copy_dst, copy_src) == ( dst_field_ptr, src_field_ptr) =>
35263559 {
35273560 Ok ( src_base_ptr)
0 commit comments