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

    <tr>
        <th>Summary</th>
        <td>
            [GlobalISel] Cross-typed G_CONSTANT
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            question,
            llvm:globalisel
      </td>
    </tr>

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

    <tr>
      <th>Reporter</th>
      <td>
          e-kud
      </td>
    </tr>
</table>

<pre>
    Let's consider the following code
```cpp
int *foo() {
    return nullptr;
}
```
When we translate it regardless of target, we obtain cross-typed `G_CONSTANT`
```
bb.1.entry:
  %0:_(p0) = G_CONSTANT i64 0
  $rax = COPY %0:_(p0)
  RET 0, implicit $rax
```

It happens because there is no requirement to have the same typed operand and return value
```
// Only supports scalar result types
def G_CONSTANT : GenericInstruction {
  let OutOperandList = (outs type0:$dst);
  let InOperandList = (ins unknown:$imm);
  let hasSideEffects = false;
}
```

I think it looks weird because we have `G_INTTOPTR` and generally speaking any specific pointer should be casted from integer. However, we have these cross-typed constants.
```
test/CodeGen/AArch64/GlobalISel/select-dup.mir: %cst:gpr(p0) = G_CONSTANT i64 3
...
test/CodeGen/AMDGPU/GlobalISel/artifact-combiner-trunc.mir: %1:_(p0) = G_CONSTANT i64 1
...
test/CodeGen/RISCV/GlobalISel/instruction-select/icmp-rv64.mir: %1:gprb(p0) = G_CONSTANT i64 -10
test/CodeGen/RISCV/GlobalISel/instruction-select/icmp-rv64.mir: %1:gprb(p0) = G_CONSTANT i64 10
```

My questions here:
1) Is it by design to have cross typed constants? I think pointer is just a particular case. When we have a separate type for floats, it is easy to imagine `%1:_(f64) = G_CONSTANT i64 1`. `MachineVerifier` checks only bit width.
2) Do we want to shift to a combination of `G_CONSTANT + G_INTTOPTR` and probably fix `G_CONSTANT` definition to match operand and return types.
3) Alternatively, there may be a special case for nulls. E.g. it's ok to have `%0:_(p0) = G_CONSTANT i64 0` but non null pointers should be introduced through  `G_CONSTANT + G_INTTOPTR`

/cc @aemerson @arsenm @qcolombet @tschuett @topperc @MalaySanghi 
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0Vk9v2z4S_TT0ZWBBpmwlPvjgJnU2QNMUTbaLPRUUNZLYUKTKGdn1t19QshPXSZu9_IDEFk3OH75580aKyNQOcSUWH8TieqJ6bnxY4fSpLyeFL_erT8hCXhBo78iUGIAbhMpb63fG1aB9iSK9Fula5On4p7tu_MU4BiHXlfdCXgq5BHHxYdwBAAjIfXDgems7DiI7bImL6zN_4_I_DTrYIXBQjqxiBMMQsFahtEgEvgJWoY7ZXsVzvmBlHOjgiaa877AEkac336_uPz88rj8_Pjs-i1MUySxBx2EvsvUxWyEXqcjW34W87NLhJtk1vPgCk88hfTk8D-rXcOTq_st_Xxkfz339-AhpzNa0nTXa8MHyzbTGz1uGRnUdOoICteoJYzkCgiFwHgL-7E3AFh0De2jUdtgHUi3CiIHvMChXQvw_VGCrbH9ew8NSboTcwL2ze6C-63xgAtLKqgABqbc8eKXxdInVKSYiW8MNOgxG3zri0Gs23p1ywCLDfc_3Y0qfDPEAmpCXvmcaXEfghJyXxBG47DfTW_eGpXEEvXtyfudGU9O2r00bRQ-mxI9VhZppsK2UJXyXhYcyADfGPUUGWu-fCHZoQvlckh2O0A98u_38-Hj_5fGryNMB9DpComxEtEP1FHtIuWGhTWU0dN44xgDU-N5Gn6AVMZZQBd9C3KsxJPAvv8MthgPZj5Um_I3wsWdZOabkzcswRlg3V77EG3RCbtbroJt8LuTmxvpC2dsHtEJuCC1qnpZ9l7QmxLoKudDEIlvXXfhbT2RjoCRJ_hTx7vrmy7_PA6rAplKap9q3hXEYphx6p0-iz97rxtl7kb_ePlx9Ow9sXog6HW8df9RtNw3bfH4Wv-5C8bcUprM_4fzPx569LW7j590efvZIMRJBlI9npZtFd7cUiV3socQ4HJ6VZGAWnDFLZBs4tsORuobgR08MCrpYSd1HvdCKMIGjig8OFRB2KkQtj16h8gEq6xXToIocHaGifczAtKo2buipk_JXkax_qH-eJvH0ndKNcfgNg6kMhtiGukH9ROCjrBWGYWdKbg48kdHftY857tQoo9SYanhQMPJRDULmq98HCgj5AV73exd8oQq7h8r8ejWBoMTKODP4Yw-tYt28JdGDyh4yzGKGa8sYYiJbtPuI1jgGWrWPiqFGOVF2QH3ANY5ZSuBjUidgxonun55LO6L6f4y4PIWiZ3B-HNzHktOJXBnHwZe9xhK4Cb6vG3gPqFNyCrnRGsQ8VdhioDgx5qkKhK6NTz-1t74tkOOCSTc98vjsuw7DYHmnrNo_KFc3BiblKiuX2VJNcDW7mOXLeSbzbNKsKl1kGeo8XS5Vms7K5WyeaVwu8xzzXC5wYlYylfN0IZdpOp-lWbLMZtllWV7icrHI8vJSzFNslbGJtds28aGeGKIeV8sslxcTqwq0NLxXSXlsNyGlkFdCymgS23gQAENRAGR8_wqruDMt-prEPLWGmF7cs2E7vKmd6MbiGq5OFP8F5Ukf7Kph7miYg3GQ14abvki0b4XcDBmMX9Mu-B8HvYk3ICE34yW2K_m_AAAA__93tRqV">