Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 5,247
    • Issues 5,247
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 577
    • Merge requests 577
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • 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
  • #18067
Closed
Open
Issue created Apr 16, 2020 by Andreas Klebinger@AndreasKDeveloper

GHC should inline divInt#

Motivation

Currently divInt# is marked as {-# NOINLINE [0] modInt# #-}

This can lead to horrible situations where we get (in STG) a division by a constant:

case GHC.Classes.divInt# sat_shZP 3# of ww7_shZQ

Since it's a call we need to do some spilling first (in Cmm):

       cmCK: // global
           I64[Sp - 48] = cmCI;
           _sm3W::I64 = R3;
           R3 = 3;
           _sm3V::I64 = R2;
           R2 = I64[Sp + 8] + 2;
           I64[Sp - 40] = _sm3V::I64;
           I64[Sp - 32] = _sm3W::I64;
           P64[Sp - 24] = R4;
           I64[Sp - 16] = R5;
           P64[Sp - 8] = R6;
           Sp = Sp - 48;
           call GHC.Classes.divInt#_info(R3,
                                         R2) returns to cmCI, args: 8, res: 8, upd: 8;

Which adds a fair bit over overhead at the ASM level.

	movq $block_ciGt_info,-48(%rbp)
	movq %rsi,%rax
	movl $3,%esi
	movq 8(%rbp),%rbx
	movq %r14,%rcx
	leaq 2(%rbx),%r14
	movq %rcx,-40(%rbp)
	movq %rax,-32(%rbp)
	movq %rdi,-24(%rbp)
	movq %r8,-16(%rbp)
	movq %r9,-8(%rbp)
	addq $-48,%rbp
	jmp GHC.Classes.divInt#_info

When then execute divInt#

x# `divInt#` y#
        -- Be careful NOT to overflow if we do any additional arithmetic
        -- on the arguments...  the following  previous version of this
        -- code has problems with overflow:
--    | (x# ># 0#) && (y# <# 0#) = ((x# -# y#) -# 1#) `quotInt#` y#
--    | (x# <# 0#) && (y# ># 0#) = ((x# -# y#) +# 1#) `quotInt#` y#
    =      if isTrue# (x# ># 0#) && isTrue# (y# <# 0#) then ((x# -# 1#) `quotInt#` y#) -# 1#
      else if isTrue# (x# <# 0#) && isTrue# (y# ># 0#) then ((x# +# 1#) `quotInt#` y#) -# 1#
      else x# `quotInt#` y#

Proposal

divInt should probably be marked as INLINE [0] instead.

This would allow all of the overhead above to be constant folded away just leaving quotInt#, which I think compiles to a single instruction.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking