depending on whether we have to use a case or let
binding for the expression (see needsCaseBinding).
It's used by the desugarer to avoid building bindings
that give Core Lint a heart attack, although actually
the simplifier deals with them perfectly well. See
also mkCoreLet

So, it does not treat variables as evaluated, unless they say they are.
However, it does treat partial applications and constructor applications
as values, even if their arguments are non-trivial, provided the argument
type is lifted. For example, both of these are values:

Safe to evaluate even if normal order eval might not
evaluate the expression at all, or

Safe not to evaluate even if normal order would do so

It is usually called on arguments of unlifted type, but not always
In particular, Simplify.rebuildCase calls it on lifted types
when a 'case' is a plain seq. See the example in
Note [exprOkForSpeculation: case expressions] below

Precisely, it returns True iff:
a) The expression guarantees to terminate,
b) soon,
c) without causing a write side effect (e.g. writing a mutable variable)
d) without throwing a Haskell exception
e) without risking an unchecked runtime exception (array out of bounds,
divide by zero)

Safe to evaluate even if normal order eval might not
evaluate the expression at all, or

Safe not to evaluate even if normal order would do so

It is usually called on arguments of unlifted type, but not always
In particular, Simplify.rebuildCase calls it on lifted types
when a 'case' is a plain seq. See the example in
Note [exprOkForSpeculation: case expressions] below

Precisely, it returns True iff:
a) The expression guarantees to terminate,
b) soon,
c) without causing a write side effect (e.g. writing a mutable variable)
d) without throwing a Haskell exception
e) without risking an unchecked runtime exception (array out of bounds,
divide by zero)

Extract a literal string from an expression that is zero or more Ticks
wrapped around a literal string. Returns Nothing if the expression has a
different shape.
Used to "look through" Ticks in places that need to handle literal strings.

The main problem here is that while we expect the binds to have the
same order in both lists, this is not guaranteed. To do this
properly we'd either have to do some sort of unification or check
all possible mappings, which would be seriously expensive. So
instead we simply match single bindings as far as we can. This
leaves us just with mutually recursive and/or mismatching bindings,
which we then speculatively match by ordering them. It's by no means
perfect, but gets the job done well enough.