<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/145002>145002</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [SPIR-V] Fix unsupported downcast in LegalizePointerCast pass
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            backend:SPIR-V,
            SPIR-V
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          Keenuts
      </td>
    </tr>
</table>

<pre>
    The following pattern is generated from some offload test suite:

```llvm
; RUN: llc -O0 -mtriple=spirv1.6-unknown-vulkan1.3-compute -o - %s

target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G10"
target triple = "spirv1.6-unknown-vulkan1.3-compute"

@.str = private unnamed_addr constant [3 x i8] c"In\00", align 1

; Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none)
define void @main() local_unnamed_addr #0 {
entry:
  %4 = tail call target("spirv.VulkanBuffer", [0 x <4 x half>], 12, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0v4f16_12_0t(i32 0, i32 0, i32 1, i32 0, i1 false, ptr nonnull @.str)
  call void @llvm.spv.assign.type.tspirv.VulkanBuffer_a0v4f16_12_0t(target("spirv.VulkanBuffer", [0 x <4 x half>], 12, 0) %4, metadata target("spirv.VulkanBuffer", [0 x <4 x half>], 12, 0) poison)
  %8 = tail call noundef align 8 dereferenceable(8) ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0v4f16_12_0t(target("spirv.VulkanBuffer", [0 x <4 x half>], 12, 0) %4, i32 1)
  call void @llvm.spv.assign.ptr.type.p11(ptr addrspace(11) %8, metadata <4 x half> poison, i32 11)
  %9 = load <4 x half>, ptr addrspace(11) %8, align 8

 %15 = call ptr addrspace(11) @llvm.spv.ptrcast.p11.p11(ptr addrspace(11) %8, metadata i8 poison, i32 11)
  call void @llvm.spv.assign.ptr.type.p11(ptr addrspace(11) %8, metadata i8 poison, i32 11)

  %16 = call ptr addrspace(11) (i1, ptr addrspace(11), ...) @llvm.spv.gep.p11.p11(i1 true, ptr addrspace(11) %8, i64 2)
  call void @llvm.spv.assign.ptr.type.p11(ptr addrspace(11) %16, metadata i8 poison, i32 11)

  %17 = call ptr addrspace(11) @llvm.spv.ptrcast.p11.p11(ptr addrspace(11) %16, metadata half poison, i32 11)
  call void @llvm.spv.assign.ptr.type.p11(ptr addrspace(11) %17, metadata half poison, i32 11)

  %18 = load half, ptr addrspace(11) %17, align 2
  ret void
}

declare target("spirv.VulkanBuffer", [0 x <4 x half>], 12, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_a0v4f16_12_0t(i32 %0, i32 %1, i32 %2, i32 %3, i1 %4, ptr %5) #1
declare ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0v4f16_12_0t(target("spirv.VulkanBuffer", [0 x <4 x half>], 12, 0) %0, i32 %1) #1

declare void @llvm.spv.assign.type.tspirv.VulkanBuffer_a0v4f16_12_0t(target("spirv.VulkanBuffer", [0 x <4 x half>], 12, 0) %0, metadata %1) nounwind
declare void @llvm.spv.assign.ptr.type.p11(ptr addrspace(11) %0, metadata %1, i32 immarg %2) nounwind
declare ptr addrspace(11) @llvm.spv.ptrcast.p11.p11(ptr addrspace(11) %0, metadata %1, i32 immarg %2) nounwind
declare ptr addrspace(11) @llvm.spv.gep.p11.p11(i1 immarg %0, ptr addrspace(11) %1, ...) nounwind

attributes #0 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, inaccessiblemem: none) "approx-func-fp-math"="true" "frame-pointer"="all" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(none) }
```


Removing the intermediate ptrcast solves the issue. For some reason, the `assign.ptr.type` intrinsics are generated on already refined types. In this sample, the first load helps the backend correctly determine the pointer to be a `<4 x half>*`. A subsequent load also determines the type to be a `half*`, and this reconciliation is correctly handled by the pass. But in the middle, a `i8*` type is added because of the GEP.
Maybe the type scavenger should be fixed so the GEP type is correctly found?

@s-perron 
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzUWF9v4zgO_zTKC2FDku3UechD0mwWg_s3mLvb10Kx6UQ3suST5LSZT3-Q5PxpdzvtAlPsHpCiskT9SP5IkZaFc3KvEZekWpNqMxOjPxi7_AuiHr2b7Ux7Wv7rgNAZpcyj1HsYhPdoNUgHe9RohccWOmt6cKZHMF2njGjBo_PgRumRFCtC429O00-pYx-eizV8-fffSbECpRrI_kEh672Vg0JSbNwg7ZHl82zUX7V51NlxVF-FZnmRNaYfRo-QGciA8MolfC_sHj20wgslTmb0QIoNEM4xk_OSFKt5mR3ZnBQrNs-OPMwUPDsWfBqU9SSziDK8zo5sERZ5FeSr-XlYsTBbMZ4dGY044V-m6wgd0RLSz4wSzq-mJefOZr3tYdocfiXNnbdx52DlUXiEUWvRY_sg2tZCY7TzQnsg1bqAJ5A1qTbQEM4_aVLd02gHvweh5F4Dm1CLNWxH3XhpNKy8ty7Eoh-dH6zZW3QOtOksImgjtZI6DCw2o3Vh5E66AW1G_Sh1C49SKYt-tBp67I09EV5bFO2jDTnA70Fq0TTonNwp7LEPqrTRSPiC0FWLXYA_GtkCKWkvpCa8JnwByjRCPTxzlvCCArlbE7pC7e0pZRiEVCgjRV5IBY1QChLxESrxnf8SSV6PXYd2IoVUawpPQIr7Ep7gIFRHip9ItQlrLErQYAkpY-bmbjjmFp0ZbYP5QehWYcj_ndSt1Pvc_1rPg6DHsmPzB8YfaLBGFjxg3sOzAXs-w6ATykXuBm8DWXpUCqZcSLxBcvPM28W-dK5zfxrwXQb9UJ54VYaHHr0Ih_GHBmEw0hl9dp7wqn4R8ZCQLXZTptfQosUOLeoGxU4h4XVMq8BoSCY3iCZMMvZqiPfoByO1R5sPjP1hdE4Z8o6oD96myA_Bq_oVV3lVP4vSczsuRE-K2Q3li0h5LPMvjJ9S9XVtU1RS_QmzrIpg0Z-3YzJ42wjnYxx-l3OyftWhD6DyVW1nBtn8Ta95LdmrfIaFPM9f0rPH4YYaycDbEd8OipyXwH8oHWz-O_m4-6AseGFIyNOPTQR2916FF9_r63GK5-h78Urw6RTxiGDRR6MD4t0m4bbYKGHxz9z9CK8ufS_4dTPmN-Ni6oTnIhiIIbyqEh0Fu3H2_6qiv_D94syNP3-2nk6fd4vJ7vP73zsMf-8R-i1FiSzZ98Lupxz5Td0_tHh8rCG_KtZXUPr9GnBT_W80E7oS3lu5Gz266R05XDTu1n_AK32434hhsOYp60bdZN2Q9cIfQtIVG8J5akwh_XlnRY_ZdB4vAkKpaf2gnMr12PtD0O0uEoGG6e8q5w6ivUG53qOChDaZ1J37njHaZFrot0TinbnNvqE1b4l6K4ZB6v2rMs6L5ms2WOOx8cZmu3g6Mye_4UW8jrKxuj8PMXstxKGX7UTz9Rrtt0N7CV1qI-fb-nRXpKsv2Juj1HvwB4QYrR5bGa6i05kCZ9QRXVp3bsQctsam7wIWxdQDwyqZ0xdFgcxpwLRSO9k4CEfo-nnBaBAqRP8ENl4UWwh7XA6fNPiDdOBEPyg8w3fSOj91VFRDsijQgbqFxliLjVcnaDH4EM5AWJ8yELyBHYIINr58uw2k5LACN-4c_ndEPSkRypkrWlIXDLzFSq090ho6uG6T4RYboxuppIi3cOlu7EvdtYXdKRkonMthPXqQOk70sm2T01GDrBN-Ui1dqB5hNzZidAimi5t-_ulzTujqb-K0w6uhrhFH1Hu04A5mVGEXdPIJW3DmvO2Ce7WwC5ctUmwvXylcNqC1RsOsXRbtoliIGS7ZXUVLxth8MTsssWpEWxZtS8sS6Y6yclGzBb27Q7boalbP5JJTXtE5p3TBFnyRs6qp57RmC6xpgawlJcVeSJXHUmrsfhaTbcnKilI-U2KHysUPWpxPQSfF6p-fP33Jfkldj3B-faw2M7sMUNlu3LtQoaXz7grupVfx-9i0pdrAVj7BqN04DMaG_GzNo44HQGr4K-6Fkt_wc0qn-zAdIjcbrVoevB8cKVaEbwnf7qU_jLu8MT3h2_hRLP0L1eA_2HjCt9EzR_h2cu645P8LAAD__0V9D4w">