diff --git a/core/lib/Drupal/Core/Entity/Plugin/Derivative/SelectionBase.php b/core/lib/Drupal/Core/Entity/Plugin/Derivative/SelectionBase.php
index 0752494..5c113e4 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/Derivative/SelectionBase.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/Derivative/SelectionBase.php
@@ -58,7 +58,21 @@ public function getDerivativeDefinitions($base_plugin_definition) {
       $this->derivatives[$entity_type_id]['entity_types'] = array($entity_type_id);
       $this->derivatives[$entity_type_id]['label'] = t('@entity_type selection', array('@entity_type' => $entity_type->getLabel()));
       $this->derivatives[$entity_type_id]['base_plugin_label'] = (string) $base_plugin_definition['label'];
+
+      // If the entity type doesn't provide a 'label' key in its plugin
+      // definition, we have to use the alternate PhpSelection class as default
+      // plugin, which allows filtering the target entities by their label()
+      // method. The major downside of PhpSelection is that it is more expensive
+      // performance-wise than SelectionBase because it has to load all the
+      // target entities in order to perform the filtering process, regardless
+      // if a limit has been passed.
+      //
+      // @see \Drupal\Core\Entity\Plugin\EntityReferenceSelection\PhpSelection
+      if (!$entity_type->hasKey('label')) {
+        $this->derivatives[$entity_type_id]['class'] = 'Drupal\Core\Entity\Plugin\EntityReferenceSelection\PhpSelection';
+      }
     }
+
     return parent::getDerivativeDefinitions($base_plugin_definition);
   }
 
diff --git a/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/PhpSelection.php b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/PhpSelection.php
new file mode 100644
index 0000000..6678c78
--- /dev/null
+++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/PhpSelection.php
@@ -0,0 +1,122 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Entity\Plugin\EntityReferenceSelection\PhpSelection.
+ */
+
+namespace Drupal\Core\Entity\Plugin\EntityReferenceSelection;
+
+use Drupal\Component\Utility\Unicode;
+
+/**
+ * Defines an alternative to the default Entity Reference Selection plugin.
+ *
+ * This selection plugin uses PHP for more advanced cases when the entity query
+ * cannot filter properly, for example when the target entity type has no
+ * 'label' key provided in the entity type plugin definition.
+ *
+ * @see \Drupal\Core\Entity\Plugin\EntityReferenceSelection\SelectionBase
+ * @see \Drupal\Core\Entity\Plugin\Derivative\SelectionBase
+ */
+class PhpSelection extends SelectionBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
+    // No input, return everything from entity query.
+    if (empty($match)) {
+      return parent::getReferenceableEntities($match, $match_operator, $limit);
+    }
+
+    // Start with the selection results returned by the entity query. Don't use
+    // any limit because we have to apply a limit after filtering the items.
+    $options = parent::getReferenceableEntities($match, $match_operator);
+
+    $filtered = [];
+    $count = 0;
+    // Filter target entities by the output of their label() method.
+    foreach ($options as $bundle => &$items) {
+      foreach ($items as $entity_id => $safe_label) {
+        // The entity label is escaped by the parent method.
+        $label = htmlspecialchars_decode($safe_label, ENT_QUOTES);
+
+        if ($this->matchLabel($match, $match_operator, $label)) {
+          $filtered[$bundle][$entity_id] = $safe_label;
+          $count++;
+
+          if ($limit && $count >= $limit) {
+            break 2;
+          }
+        }
+      }
+    }
+
+    return $filtered;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function countReferenceableEntities($match = NULL, $match_operator = 'CONTAINS') {
+    $count = 0;
+    foreach ($this->getReferenceableEntities($match, $match_operator) as &$items) {
+      $count += count($items);
+    }
+
+    return $count;
+  }
+
+  /**
+   * Matches an entity label to an input string.
+   *
+   * @param string $match
+   *   The string to compare.
+   * @param string $match_operator
+   *   The comparison operator.
+   * @param string $label
+   *   The entity label to match against.
+   *
+   * @return bool
+   *   TRUE when matches, FALSE otherwise.
+   */
+  protected function matchLabel($match, $match_operator, $label) {
+    // We always want a case-insensitive match.
+    $label = !is_bool($label) ? Unicode::strtolower($label) : $label;
+    $match = is_string($match) ? Unicode::strtolower($match) : $match;
+
+    switch ($match_operator) {
+      case '=':
+        return $label == $match;
+      case '>':
+        return $label > $match;
+      case '<':
+        return $label < $match;
+      case '>=':
+        return $label >= $match;
+      case '<=':
+        return $label <= $match;
+      case '<>':
+        return $label != $match;
+      case 'IN':
+        return array_search($label, $match) !== FALSE;
+      case 'NOT IN':
+        return array_search($label, $match) === FALSE;
+      case 'STARTS_WITH':
+        return strpos($label, $match) === 0;
+      case 'CONTAINS':
+        return strpos($label, $match) !== FALSE;
+      case 'ENDS_WITH':
+        return substr($label, -strlen($match)) === (string) $match;
+      case 'IS NOT NULL':
+        return TRUE;
+      case 'IS NULL':
+        return FALSE;
+      default:
+        // Invalid match operator.
+        return FALSE;
+    }
+  }
+
+}
diff --git a/core/modules/system/src/Tests/Entity/EntityReferenceSelection/EntityReferenceSelectionReferenceableTest.php b/core/modules/system/src/Tests/Entity/EntityReferenceSelection/EntityReferenceSelectionReferenceableTest.php
new file mode 100644
index 0000000..a42873d
--- /dev/null
+++ b/core/modules/system/src/Tests/Entity/EntityReferenceSelection/EntityReferenceSelectionReferenceableTest.php
@@ -0,0 +1,192 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Tests\Entity\EntityReferenceSelection\EntityReferenceSelectionReferenceableTest.
+ */
+
+namespace Drupal\system\Tests\Entity\EntityReferenceSelection;
+
+use Drupal\Component\Utility\Unicode;
+use Drupal\entity_reference\Tests\EntityReferenceTestTrait;
+use Drupal\field\Entity\FieldConfig;
+use Drupal\node\Entity\NodeType;
+use Drupal\simpletest\KernelTestBase;
+
+/**
+ * Tests entity reference selection plugins.
+ *
+ * @group entity_reference
+ */
+class EntityReferenceSelectionReferenceableTest extends KernelTestBase {
+
+  use EntityReferenceTestTrait;
+
+  /**
+   * A random node-type.
+   *
+   * @var string
+   */
+  protected $nodeType;
+
+  /**
+   * The entity reference field name.
+   *
+   * @var string
+   */
+  protected $fieldName;
+
+  /**
+   * Bundle of 'entity_test_no_label' entity.
+   *
+   * @var string
+   */
+  protected $bundle;
+
+  /**
+   * Modules to be installed.
+   *
+   * @var array
+   */
+  public static $modules = ['system', 'user', 'field', 'entity_reference', 'node', 'entity_test'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->installEntitySchema('entity_test_no_label');
+
+    /** @var \Drupal\Core\Entity\EntityStorageInterface $storage */
+    $storage = $this->container->get('entity.manager')
+      ->getStorage('entity_test_no_label');
+
+    // Create a new node-type.
+    $this->nodeType = Unicode::strtolower($this->randomMachineName());
+    NodeType::create([
+      'type' => $this->nodeType,
+      'name' => $this->randomString(),
+    ])->save();
+
+    // Create an entity reference field targeting 'entity_test_no_label'
+    // entities.
+    $this->fieldName = Unicode::strtolower($this->randomMachineName());
+    $this->createEntityReferenceField('node', $this->nodeType, $this->fieldName, $this->randomString(), 'entity_test_no_label');
+
+    // Generate a bundle name to be used with 'entity_test_no_label'.
+    $this->bundle = Unicode::strtolower($this->randomMachineName());
+
+    // Create 6 entities to be referenced by the field.
+    foreach (['abc', 'Xyz_', 'xyabz_', 'foo_', 'bar_', 'baz_'] as $name) {
+      $storage->create([
+        'id' => Unicode::strtolower($this->randomMachineName()),
+        'name' => $name,
+        'type' => $this->bundle,
+      ])->save();
+    }
+  }
+
+  /**
+   * Tests values returned by SelectionInterface::getReferenceableEntities()
+   * when the target entity type has no 'label' key.
+   */
+  public function testReferenceablesWithNoLabelKey() {
+    $field_config = FieldConfig::loadByName('node', $this->nodeType, $this->fieldName);
+    /** @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface $handler */
+    $handler = $this->container->get('plugin.manager.entity_reference_selection')->getSelectionHandler($field_config);
+
+    foreach (static::getTestCases() as $case) {
+      // Assure defaults.
+      $case += [
+        'match' => NULL,
+        'match_operator' => 'CONTAINS',
+        'limit' => 0,
+        'count_limited' => 0,
+        'items' => [],
+        'count_all' => 0,
+      ];
+
+      // Test ::getReferenceableEntities().
+      $referenceables = $handler->getReferenceableEntities($case['match'], $case['match_operator'], $case['limit']);
+      // Number of returned items.
+      if (empty($case['count_limited'])) {
+        $this->assertTrue(empty($referenceables[$this->bundle]));
+      }
+      else {
+        $this->assertIdentical(count($referenceables[$this->bundle]), $case['count_limited']);
+      }
+
+      // Test returned items.
+      if (!empty($case['items'])) {
+        foreach ($case['items'] as $item) {
+          $this->assertTrue((bool) array_search($item, $referenceables[$this->bundle]));
+        }
+      }
+
+      // Test ::countReferenceableEntities().
+      $count_referenceables = $handler->countReferenceableEntities($case['match'], $case['match_operator']);
+      $this->assertIdentical($count_referenceables, $case['count_all']);
+    }
+  }
+
+  /**
+   * Provides test cases for ::testReferenceablesWithNoLabelKey() test.
+   *
+   * @return array[]
+   *   A list of test cases. Each item in the list is an associative array
+   *   having the next optional keys:
+   *   - match: The input text to be checked. Defaults to NULL.
+   *   - match_operator: The matching operator. Defaults to 'CONTAINS'.
+   *   - limit: The limit of returning records. Defaults to 0.
+   *   - count_limited: The expected number of limited entities to be retrieved.
+   *     Defaults to 0.
+   *   - items: Array of entity labels expected to be returned.
+   *   - count_all: The total number (unlimited) of entities to be retrieved.
+   *     Defaults to 0.
+   */
+  protected static function getTestCases() {
+    return [
+      // Get all referenceables, no limit. Expecting 3 items.
+      [
+        'count_limited' => 6,
+        'count_all' => 6,
+      ],
+      // Get referenceables containing 'w', no limit. Expecting no item.
+      [
+        'match' => 'w',
+      ],
+      // Get referenceables starting with 'w', no limit. Expecting no item.
+      [
+        'match' => 'w',
+        'match_operator' => 'STARTS_WITH',
+      ],
+      // Get referenceables containing 'ab', no limit. Expecting 2 items ('abc',
+      // 'xyabz').
+      [
+        'match' => 'ab',
+        'count_limited' => 2,
+        'items' => ['abc', 'xyabz_'],
+        'count_all' => 2,
+      ],
+      // Get referenceables starting with 'A', no limit. Expecting 1 item ('abc').
+      [
+        'match' => 'A',
+        'match_operator' => 'STARTS_WITH',
+        'count_limited' => 1,
+        'items' => ['abc'],
+        'count_all' => 1,
+      ],
+      // Get referenceables containing '_', limited to 3. Expecting 3 limited
+      // items ('Xyz_', 'xyabz_', 'foo_') and 5 total.
+      [
+        'match' => '_',
+        'limit' => 3,
+        'count_limited' => 3,
+        'items' => ['Xyz_', 'xyabz_', 'foo_'],
+        'count_all' => 5,
+      ],
+    ];
+  }
+
+}
diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestNoLabel.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestNoLabel.php
index 5ad3ba7..6525139 100644
--- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestNoLabel.php
+++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestNoLabel.php
@@ -23,4 +23,11 @@
  */
 class EntityTestNoLabel extends EntityTest {
 
+  /**
+   * @{inheritdoc}
+   */
+  public function label() {
+    return $this->getName();
+  }
+
 }
