Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
GHC
GHC
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 4,321
    • Issues 4,321
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
    • Iterations
  • Merge Requests 359
    • Merge Requests 359
  • Requirements
    • Requirements
    • List
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Security & Compliance
    • Security & Compliance
    • Dependency List
    • License Compliance
  • Operations
    • Operations
    • Incidents
    • Environments
  • Analytics
    • Analytics
    • CI / CD
    • Code Review
    • Insights
    • Issue
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • Glasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #8336

Closed
Open
Opened Sep 20, 2013 by Jan Stolarek@trac-jstolarek

Sinking pass could optimize some assignments better

Compiling this program:

{-# LANGUAGE BangPatterns, MagicHash, CPP #-}
{-# OPTIONS_GHC -O2 -funbox-strict-fields #-}
module HashStr where

import Foreign.C
import GHC.Exts
import Data.Word

#define hASH_TBL_SIZE          4091

hashStr  :: Ptr Word8 -> Int -> Int
 -- use the Addr to produce a hash value between 0 & m (inclusive)
hashStr (Ptr a#) (I# len#) = loop 0# 0#
   where
    loop h n | n GHC.Exts.==# len# = I# h
             | otherwise  = loop h2 (n GHC.Exts.+# 1#)
          where !c = ord# (indexCharOffAddr# a# n)
                !h2 = (c GHC.Exts.+# (h GHC.Exts.*# 128#)) `remInt#`
                      hASH_TBL_SIZE#

produces following Cmm code for hashStr function:

{offset
  cut:
      goto cux;
  cux:
      _stC::I64 = R3;
      _stB::I64 = R2;
      _stF::I64 = 0;
      _stE::I64 = 0;
      goto stD;
  stD:
      if (_stF::I64 == _stC::I64) goto cuH; else goto cuI;
  cuH:
      R1 = _stE::I64;
      call (P64[Sp])(R1) args: 8, res: 0, upd: 8;
  cuI:
      _stM::I64 = %MO_S_Rem_W64(%MO_UU_Conv_W8_W64(I8[_stB::I64 + _stF::I64]) + (_stE::I64 << 7),
                                4091);
      _stF::I64 = _stF::I64 + 1;
      _stE::I64 = _stM::I64;
      goto stD;
}

The problem here is that three last assignments:

_stM::I64 = %MO_S_Rem_W64(%MO_UU_Conv_W8_W64(I8[_stB::I64 + _stF::I64]) + (_stE::I64 << 7), 4091);
_stF::I64 = _stF::I64 + 1;
_stE::I64 = _stM::I64;

could be optimized as:

_stE::I64 = %MO_S_Rem_W64(%MO_UU_Conv_W8_W64(I8[_stB::I64 + _stF::I64]) + (_stE::I64 << 7), 4091);
_stF::I64 = _stF::I64 + 1;

We should improve sinking pass so that it can optimize such cases. See Note [dependent assignments] in !CmmSink.

Edited Mar 09, 2019 by Jan Stolarek
Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
Reference: ghc/ghc#8336