
#9638: Speed up Data.Char.isDigit -------------------------------------+------------------------------------- Reporter: dfeuer | Owner: Type: feature request | Status: new Priority: normal | Milestone: 7.10.1 Component: Compiler | Version: 7.9 Keywords: | Operating System: Architecture: Unknown/Multiple | Unknown/Multiple Difficulty: Easy (less than 1 | Type of failure: Runtime hour) | performance bug Blocked By: | Test Case: Related Tickets: | Blocking: | Differential Revisions: -------------------------------------+------------------------------------- `isDigit` is currently defined like this: {{{#!hs isDigit :: Char -> Bool isDigit c = c >= '0' && c <= '9' }}} This will short-circuit the right way if you're looking for digits mixed with spaces, but the wrong way if you're looking for digits mixed with letters. It also requires a conditional jump to do that short-circuiting (confirmed by inspecting the assembly). It should be better to use an unsigned comparison instead: {{{#!hs isDigit :: Char -> Bool isDigit c = (fromIntegral (ord c) :: Word) - 48 <= 9 }}} The interesting section looks like this {{{ movq 7(%rbx),%rax addq $-48,%rax cmpq $9,%rax setbe %al movzbl %al,%eax shlq $3,%rax movq ghczmprim_GHCziTypes_Bool_closure_tbl(%rax),%rbx addq $8,%rbp jmp *(%rbp) }}} or like this with -fllvm: {{{ movq 7(%rbx), %rax addq $-48, %rax cmpq $10, %rax sbbq %rax, %rax andq $8, %rax movq ghczmprim_GHCziTypes_Bool_closure_tbl(%rax), %rbx movq 8(%rbp), %rax addq $8, %rbp jmpq *%rax # TAILCALL }}} -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/9638 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler