#12603: INLINE and manually inlining produce different code -------------------------------------+------------------------------------- Reporter: bgamari | Owner: bgamari Type: task | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by MikolajKonarski): I've compared the resulting Core. The difference is that the version with INLINE recomputes `((2 ^ (8 :: Int) - 1)` every time, while the manually inlined version uses a value computed just once (note that the value is of type `Word32` --- I haven't verified that it matters). In the source code the constant is, e.g., here: https://github.com/LambdaHack/LambdaHack/blob /ghc-bug-12603/Game/LambdaHack/Common/Color.hs#L94 Here are the relevant snippets of Core. {{{ 379842537fadd870f9dd3304e0182c0b attrCharFromW1 :: Word32 {- Unfolding: (case $wf 2## 8# of ww { DEFAULT -> W32# (narrow32Word# (minusWord# ww 1##)) }) -} 0a91b1a84599352c004a37572b9588c1 $wf :: Word# -> Int# -> Word# {- Arity: 2, HasNoCafRefs, Strictness: <L,U><S,U>, Inline: [0] -} 41b3e215bf375441beb5fb607472bd73 $wattrCharFromW32 :: Word# -> (# Attr, Char# #) {- Arity: 1, Strictness: <S,U>, Inline: [0], Unfolding: (\ (ww :: Word#) -> case attrCharFromW1 of wild1 { W32# y# -> let { x :: Int# = word2Int# (and# (uncheckedShiftRL# ww 8#) y#) } in case tagToEnum# @ Bool (>=# x 0#) of wild { False -> case $fBinaryColor3 x ret_ty (# Attr, Char# #) of {} True -> case tagToEnum# @ Bool (<=# x 15#) of wild2 { False -> case $fBinaryColor3 x ret_ty (# Attr, Char# #) of {} True -> case tagToEnum# @ Color x of dt { DEFAULT -> let { x1 :: Int# = word2Int# (and# ww y#) } in case tagToEnum# @ Bool (>=# x1 0#) of wild3 { False -> case $fBinaryColor3 x1 ret_ty (# Attr, Char# #) of {} True -> case tagToEnum# @ Bool (<=# x1 15#) of wild4 { False -> case $fBinaryColor3 x1 ret_ty (# Attr, Char# #) of {} True -> case tagToEnum# @ Color x1 of dt1 { DEFAULT -> let { i# :: Int# = word2Int# (uncheckedShiftRL# ww 16#) } in case tagToEnum# @ Bool (leWord# (int2Word# i#) 1114111##) of wild5 { False -> case chr2 i# ret_ty (# Attr, Char# #) of {} True -> (# Attr dt dt1, chr# i# #) } } } } } } } }) -} 8b854d1c31d32d5f70ae60f00eb8d52b $wattrCharFromW32' :: Word# -> (# Attr, Char# #) {- Arity: 1, Strictness: <S,U>, Inline: [0], Unfolding: (\ (ww :: Word#) -> case $wf 2## 8# of ww1 { DEFAULT -> let { x :: Int# = word2Int# (and# (uncheckedShiftRL# ww 8#) (narrow32Word# (minusWord# ww1 1##))) } in case tagToEnum# @ Bool (>=# x 0#) of wild { False -> case $fBinaryColor3 x ret_ty (# Attr, Char# #) of {} True -> case tagToEnum# @ Bool (<=# x 15#) of wild1 { False -> case $fBinaryColor3 x ret_ty (# Attr, Char# #) of {} True -> case tagToEnum# @ Color x of dt { DEFAULT -> let { x1 :: Int# = word2Int# (and# ww (narrow32Word# (minusWord# ww1 1##))) } in case tagToEnum# @ Bool (>=# x1 0#) of wild2 { False -> case $fBinaryColor3 x1 ret_ty (# Attr, Char# #) of {} True -> case tagToEnum# @ Bool (<=# x1 15#) of wild3 { False -> case $fBinaryColor3 x1 ret_ty (# Attr, Char# #) of {} True -> case tagToEnum# @ Color x1 of dt1 { DEFAULT -> let { i# :: Int# = word2Int# (uncheckedShiftRL# ww 16#) } in case tagToEnum# @ Bool (leWord# (int2Word# i#) 1114111##) of wild4 { False -> case chr2 i# ret_ty (# Attr, Char# #) of {} True -> (# Attr dt dt1, chr# i# #) } } } } } } } }) -} }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12603#comment:6> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler