Skip to content
GitLab
Projects Groups Topics Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Register
  • Sign in
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
    • Locked files
  • Issues 5.6k
    • Issues 5.6k
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 663
    • Merge requests 663
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Artifacts
    • Schedules
    • Test cases
  • Deployments
    • Deployments
    • Releases
  • Packages and registries
    • Packages and registries
    • Model experiments
  • Analytics
    • Analytics
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell CompilerGlasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #23749

Aarch64 NCG doesn't always uphold the invariants mentioned in `Note [Signed arithmetic on AArch64]`

The Note describes this invariant:

-- We handle 16-and 8-bit values by using the 32-bit operations and
-- sign-/zero-extending operands and truncate results as necessary. For
-- simplicity we maintain the invariant that a register containing a
-- sub-word-size value always contains the zero-extended form of that value
-- in between operations.

However the fast path for addition with immediate doesn't uphold this. There we have:

    CmmMachOp (MO_Add w) [(CmmReg reg), CmmLit (CmmInt n _)]
      | n > 0 && n < 4096 -> return $ Any (intFormat w) (\d -> unitOL $ annExpr expr (ADD (OpReg w d) (OpReg w' r') (OpImm (ImmInteger n))))
      -- TODO: 12bits lsl #12; e.g. lower 12 bits of n are 0; shift n >> 12, and set lsl to #12.
      where w' = formatToWidth (cmmTypeFormat (cmmRegType reg))
            r' = getRegisterReg plat reg

Which means expressions such as reg + 1 can overflow the high bits resulting in a violation of the invariant.

I wasn't (yet) able to make this go wrong on a larger scale, as we don't seem to really rely on this invariant much (and re-zero in most other places). Best I could do was this cmm:

high_bits(I16 x) {
 A:
  I16 y;
  y = x + 1;
  call foo(y);
}

Resulting in foo being called with a high bit potentially set depending on the initial value of x:

	mov w18, w22
	add w18, w18, #1
	adrp x17, .Lblock_c4_info
	add x17, x17, :lo12:.Lblock_c4_info
	str x17, [ x20, -8 ]
	mov x22, x18
	sub x20, x20, #8
	b foo

Maybe this could cause issues in mac where we are responsible for zeroing out the high bits. But I won't spend more time on what issues this can cause I will just fix it.

Edited Jul 29, 2023 by Andreas Klebinger
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking