[llvm] [SPIRV] Sign-extend operands of sign-sensitive ops on sub-pow2 widths (PR #203661)
Faijul Amin via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 11 10:34:18 PDT 2026
mdfaijul wrote:
> Apologies, it flew under my radar before my vacation, now I'm back.
>
> Overall the patch is doing a good job, but I believe there is a bug for truncation (not sure exactly were). Please consider this following sample (I reduced it sometime ago for a similar bug and hoped that this PR could fix it):
>
> ```
> define spir_kernel void @f(i64 %a, ptr addrspace(1) %out) {
> %t = trunc i64 %a to i24
> %c = icmp slt i24 %t, 0
> %r = sext i1 %c to i8
> store i8 %r, ptr addrspace(1) %out
> ret void
> }
> ```
>
> with the patch it compiles to:
>
> ```
> ...
> %12 = OpConstant %2 16777215
> ...
> %16 = OpBitwiseAnd %2 %13 %12
> %17 = OpUConvert %7 %16
> %18 = OpSLessThan %8 %17 %11
> ```
>
> I believe that this sequence is a miscompile. Take %a = 0x800000, as a 24-bit signed value that's -8388608 (bit 23, the sign bit, is set), so icmp slt i24 %t, 0 should be true. But trace the generated code: %16 = 0x800000 & 0xFFFFFF = 0x800000, %17 = UConvert(%16) = 8388608 (as an i32, still positive UConvert is a plain unsigned width conversion, not sign-extension), %18 = SLessThan(8388608, 0) = false. So unless I'm missing something - it prodces a wrong answer.
>
> Probably we shouldn't source "original width" from the MRI type at all - either capture original widths for every sub-pow2 register in a single prepass before the G_TRUNC loop runs, or track true bit width via something immutable to this pass
Thanks for pointing out this issue. I have taken your suggestion to capture original widths before the G_TRUNC loop.
https://github.com/llvm/llvm-project/pull/203661
More information about the llvm-commits
mailing list