Skip to content

NCG: Use 32bit-comparisons when operating on pointer tags.

Summary

I came across this pointer check in Cmm:

       cGv: // global
           call (I64[R1])(R1) returns to cGu, args: 8, res: 8, upd: 8;
       cGu: // global
           if (R1 & 7 != 1) goto cGz; else goto cGy;

Which turns into this assembly:

        movq %rbx,%rax
        andl $7,%eax
        cmpq $1,%rax
        je .LcGy
.LcGz:

Using cmpq wastes a bit here for the 64bit encoding when the 32bit encoding would do.

I think the issue is that we generate the literal 1 as 64bit wide number resulting in a 64bit operation being used.

To reproduce:

module M where


{-# NOINLINE incMaybe #-}
incMaybe :: Maybe Int -> Int
incMaybe (Just x) = x + 1
incMaybe Nothing = 0

Compile with ghc A.hs -O2 -ddump-cmm -ddump-asm -dno-typeable-binds -fforce-recomp -ddump-to-file -fno-worker-wrapper -dcmm-lint

Environment

  • GHC version used:

Optional:

  • Operating System:
  • System Architecture:
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information