def METHOD_NAME(stmt):
    """Get extra entities that are loaded from a ``stmt`` due to joinedload
    options specified in the statement options.
    These entities will not be returned directly by the query, but will prepopulate
    relationships in the returned data.
    For example::
        get_joinedload_entities(query(A).options(joinedload(A.bs))) == {A, B}
    """
    # there are two kinds of options that both represent the same information,
    # just in different ways.  This is largely a product of legacy options
    # that have things like strings, i.e. joinedload("addresses").  note we
    # aren't covering that here, which is legacy form.  you can if you want
    # raise an exception if you detect that form here.
    entities = set()
    for opt in stmt._with_options:
        if hasattr(opt, "_to_bind"):
            # these options are called _UnboundLoad
            for b in opt._to_bind:
                if ("lazy", "joined") in b.strategy:
                    # the "path" is a tuple showing the entity/relationships
                    # being targeted
                    # TODO check for wild card.
                    # TODO: Check whether entity is a string.
                    entities.add(b.path[-1].entity)
        elif hasattr(opt, "context"):
            # these options are called Load
            for key, loadopt in opt.context.items():
                if key[0] == "loader" and ("lazy", "joined") in loadopt.strategy:
                    # the "path" is a tuple showing the entity/relationships
                    # being targeted
                    # TODO: Check for of_type.
                    # TODO: Check whether entity is a string, unsupported.
                    # TODO check for wild card.
                    entities.add(key[1][-1].entity)
    return entities