[GHC] #15570: Core transformations generate bad indexCharOffAddr# call
GHC
ghc-devs at haskell.org
Mon Sep 3 18:27:19 UTC 2018
#15570: Core transformations generate bad indexCharOffAddr# call
-------------------------------------+-------------------------------------
Reporter: alpmestan | Owner: alpmestan
Type: bug | Status: new
Priority: normal | Milestone: 8.6.1
Component: Compiler | Version: 8.5
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 simonpj):
No I can repro, I can return to the OP.
I'm deeply puzzled about the case-match on `GHC.Real.even3`. But leaving
that aside,
I'm not so sure that the Core shown in the Description is wrong. After
all, suppose
we made the call
{{{
f -9223372036854775808
}}}
Then we'd get into the `n<62` branch, so we'd call `chooseChar62` of that
ridiculous number.
So semantically, while the code is very strange, it's not actually wrong.
'''So why do you get a link error'''? I think that is a bug all by
itself.
If I write
{{{
x = C# (indexCharOffAddr# "foo"# -9223372036854775808#)
}}}
that might seg-fault at runtime, but it should not cause a link error.
-------------------
How can stupid code like this arise? Consider
{{{
h :: Int# -> Int#
h x = let !t = case x of
-1000# -> 4#
_ -> x
in
t +# indexIntOffAddr# "foo"# x)
}}}
Notice that `h` unconditionally indexes the string with `x` (just like `f`
does in the
Description); presumably the caller is going to guaranteed that `x` is in
bounds.
That turns into
{{{
h x = case (case x of { -1000 -> 4#; _ -> x }) of
t -> t +# indexIntOffAddr# "foo"# x
}}}
Now case-of-case produces
{{{
h x = case x of
-1000 -> 4# +# indexIntOffAddr# "foo#" x
_ -> x +# indexIntOffAddr# "foo#" x
}}}
But in the top branch we know that `x` is `-1000`, so we finally get
{{{
h x = case x of
-1000 -> 4# +# indexIntOffAddr# "foo#" -1000
_ -> x +# indexIntOffAddr# "foo#" x
}}}
This is, in essence, what is happening in the Description. And it should
jolly well
be fine.
Of course, if the caller never calls the function with `-1000` as the
argument,
the top branch will never be executed.
------------------
So my claim so far is: the code is correct; and it's a bug that we get a
linker error.
However the code, while correct, is TERRIBLE. For this function (similar
to Description, slightly simplified)
{{{
go :: Int -> [Char] -> [Char]
go n cs | n < 62
= let !c = chooseChar62 n in c : cs
| otherwise
= go q cs
where
!(q, _) = quotRem n 62
}}}
HEAD produces the very civilised result
{{{
Bug.$wgo [InlPrag=NOUSERINLINE[2], Occ=LoopBreaker]
:: Int# -> [Char] -> (# Char, [Char] #)
[GblId, Arity=2, Caf=NoCafRefs, Str=<S,U><L,U>, Unf=OtherCon []]
Bug.$wgo
= \ (ww_s2Ag :: Int#) (w_s2Ad :: [Char]) ->
case quotRemInt# ww_s2Ag 62# of { (# ipv_a2yf, ipv1_a2yg #) ->
case <# ww_s2Ag 62# of {
__DEFAULT -> Bug.$wgo ipv_a2yf w_s2Ad;
1# ->
case indexCharOffAddr# lvl_r2Bs ww_s2Ag of wild_X4 { __DEFAULT
->
(# GHC.Types.C# wild_X4, w_s2Ad #)
}
}
}
}}}
while the Hadrian build produces the horrible code similar to that above.
I'll look at that next.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15570#comment:9>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list