diff options
author | David Feuer <david.feuer@gmail.com> | 2017-01-31 18:44:14 -0500 |
---|---|---|
committer | David Feuer <David.Feuer@gmail.com> | 2017-01-31 18:44:15 -0500 |
commit | b3576ed22570364f917c620a3cd29709355e4d51 (patch) | |
tree | b69620349c0b318be32efe61b19ec5967d959805 | |
parent | 748b79741652028827b6225c36b8ab55d22bdeb0 (diff) | |
download | haskell-b3576ed22570364f917c620a3cd29709355e4d51.tar.gz |
Mark reallyUnsafePtrEquality# as can_fail
As described in the note, floating `reallyUnsafePtrEquality#`
out can make it much less precise. Marking it `can_fail` will
prevent it from floating out, which I believe is particularly
important in light of 5a9a1738023aeb742e537fb4a59c4aa8fecc1f8a,
and should also help prevent let/app invariant failures as seen
in #11444 and #13027.
Reviewers: simonpj, austin, bgamari
Subscribers: thomie
Differential Revision: https://phabricator.haskell.org/D2987
GHC Trac Issues: #13027, #11444
-rw-r--r-- | compiler/prelude/primops.txt.pp | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/compiler/prelude/primops.txt.pp b/compiler/prelude/primops.txt.pp index 6795ca700c..524527282a 100644 --- a/compiler/prelude/primops.txt.pp +++ b/compiler/prelude/primops.txt.pp @@ -2542,6 +2542,41 @@ section "Unsafe pointer equality" primop ReallyUnsafePtrEqualityOp "reallyUnsafePtrEquality#" GenPrimOp a -> a -> Int# + { Returns 1# if the given pointers are equal and 0# otherwise. } + with + can_fail = True -- See Note [reallyUnsafePtrEquality#] + + +-- Note [reallyUnsafePtrEquality#] +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-- +-- reallyUnsafePtrEquality# can't actually fail, per se, but we mark it can_fail +-- anyway. Until 5a9a1738023a, GHC considered primops okay for speculation only +-- when their arguments were known to be forced. This was unnecessarily +-- conservative, but it prevented reallyUnsafePtrEquality# from floating out of +-- places where its arguments were known to be forced. Unfortunately, GHC could +-- sometimes lose track of whether those arguments were forced, leading to let/app +-- invariant failures (see Trac 13027 and the discussion in Trac 11444). Now that +-- ok_for_speculation skips over lifted arguments, we need to explicitly prevent +-- reallyUnsafePtrEquality# from floating out. The reasons are closely related +-- to those described in Note [dataToTag#], although the consequences are less +-- severe. Imagine if we had +-- +-- \x y . case x of x' +-- DEFAULT -> +-- case y of y' +-- DEFAULT -> +-- let eq = reallyUnsafePtrEquality# x' y' +-- in ... +-- +-- If the let floats out, we'll get +-- +-- \x y . let eq = reallyUnsafePtrEquality# x y +-- in case x of ... +-- +-- The trouble is that pointer equality between thunks is very different +-- from pointer equality between the values those thunks reduce to, and the latter +-- is typically much more precise. ------------------------------------------------------------------------ section "Parallelism" |