Opened 5 years ago

Last modified 5 years ago

#10005 new bug

Operations on string literals won't be inlined

Reported by: fread2281 Owned by:
Priority: normal Milestone:
Component: Compiler Version: 7.8.4
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Runtime performance bug Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


An example is attached, GHC won't optimize

head "stringliteral"



Attachments (2)

test.hs (83 bytes) - added by fread2281 5 years ago.
test.dump-simpl (821 bytes) - added by fread2281 5 years ago.
-ddump-simpl for test.hs

Download all attachments as: .zip

Change History (5)

Changed 5 years ago by fread2281

Attachment: test.hs added

Changed 5 years ago by fread2281

Attachment: test.dump-simpl added

-ddump-simpl for test.hs

comment:1 Changed 5 years ago by rwbarton

Your definition of head' is wrong of course, but that's not the issue.

I have good news and bad news.

  • Your program (with the definition of head' fixed) does optimize properly in HEAD. (I assume due to ticket:9400#comment:9.) It also optimizes properly without the INLINE pragma.
  • However, if you use the real Prelude.head, then rules fire that turn test = head "foo" into
    test =
        @ Char
        (\ (x_arw :: Char) _ [Occ=Dead] -> x_arw)
        (GHC.List.badHead @ Char)

and that is more or less a dead end.

comment:2 Changed 5 years ago by simonpj

We wanted literal strings to be good producers, so that map f "wubble" would work without generating and then pattern matching on the intermediate string. That is why "foo" desugars to

build (unpackFoldrCString# "foo"#)

This seems reasonable.

Now head has this rule:

"head/build"    forall (g::forall b.(a->b->b)->b->b) .
                head (build g) = g (\x _ -> x) badHead

(goal: make head a good consumer), and that rule fires on head "foo" giving the result in comment:1.

It is a bit stupid, but I don't see an immediate way out. One alternative would be to kill off the head/build rule. After all, most fold/build rules save an entire traversal of the list whereas this one saves the allocation and pattern match on a single cons cell. So the win is much smaller.

If someone would like to

  • Switch off RULES head/build and head/augment (in GHC.List)
  • See what performance difference, if any, happens in nofib
  • Track down any increases

that would be a splendid thing.

More radical would be to nuke the entire unpackFoldrCString ideaa, so that literal strings are not good producers. But I think that would probably be bad.


comment:3 Changed 5 years ago by thomie

Type of failure: Compile-time performance bugRuntime performance bug

I believe we use the term compile-time performance bugs for the performance of ghc itself.

Note: See TracTickets for help on using tickets.