diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c
index 06f836308d..c3131e6c2c 100644
--- a/src/backend/optimizer/path/clausesel.c
+++ b/src/backend/optimizer/path/clausesel.c
@@ -520,12 +520,18 @@ addRangeClause(RangeQueryClause **rqlist, Node *clause,
  *		Examine each clause in 'clauses' and determine if all clauses
  *		reference only a single relation.  If so return that relation,
  *		otherwise return NULL.
+ *
+ * The clauses may be either RestrictInfos or bare expression clauses, same as
+ * for clauselist_selectivity. The former is preferred since it allows caching
+ * of results, but some callers pass bare expressions.
+
  */
 static RelOptInfo *
 find_single_rel_for_clauses(PlannerInfo *root, List *clauses)
 {
 	int			lastrelid = 0;
 	ListCell   *l;
+	Bitmapset  *clause_relids;
 
 	foreach(l, clauses)
 	{
@@ -560,12 +566,20 @@ find_single_rel_for_clauses(PlannerInfo *root, List *clauses)
 			continue;
 		}
 
-		if (!IsA(rinfo, RestrictInfo))
-			return NULL;
+		/*
+		 * For a RestrictInfo, we can use the cached relids. Otherwise
+		 * inspect the clause to build the bitmap.
+		 */
+		if (IsA(rinfo, RestrictInfo))
+			clause_relids = rinfo->clause_relids;
+		else
+			clause_relids = pull_varnos(root, (Node *) rinfo);
+
 
-		if (bms_is_empty(rinfo->clause_relids))
-			continue;			/* we can ignore variable-free clauses */
-		if (!bms_get_singleton_member(rinfo->clause_relids, &relid))
+		if (bms_is_empty(clause_relids))
+			continue;			/* we can ignore variable-free clauses (this
+								 * includes pseudoconstants) */
+		if (!bms_get_singleton_member(clause_relids, &relid))
 			return NULL;		/* multiple relations in this clause */
 		if (lastrelid == 0)
 			lastrelid = relid;	/* first clause referencing a relation */
diff --git a/src/backend/statistics/extended_stats.c b/src/backend/statistics/extended_stats.c
index ca48395d5c..907141dfee 100644
--- a/src/backend/statistics/extended_stats.c
+++ b/src/backend/statistics/extended_stats.c
@@ -1560,9 +1560,9 @@ statext_is_compatible_clause(PlannerInfo *root, Node *clause, Index relid,
 							 Bitmapset **attnums, List **exprs)
 {
 	RangeTblEntry *rte = root->simple_rte_array[relid];
-	RestrictInfo *rinfo = (RestrictInfo *) clause;
-	int			clause_relid;
+	Bitmapset  *relids;
 	Oid			userid;
+	int			clause_relid;
 
 	/*
 	 * Special-case handling for bare BoolExpr AND clauses, because the
@@ -1574,10 +1574,7 @@ statext_is_compatible_clause(PlannerInfo *root, Node *clause, Index relid,
 		BoolExpr   *expr = (BoolExpr *) clause;
 		ListCell   *lc;
 
-		/*
-		 * Check that each sub-clause is compatible.  We expect these to be
-		 * RestrictInfos.
-		 */
+		/* Check that each sub-clause is compatible. */
 		foreach(lc, expr->args)
 		{
 			if (!statext_is_compatible_clause(root, (Node *) lfirst(lc),
@@ -1588,21 +1585,30 @@ statext_is_compatible_clause(PlannerInfo *root, Node *clause, Index relid,
 		return true;
 	}
 
-	/* Otherwise it must be a RestrictInfo. */
-	if (!IsA(rinfo, RestrictInfo))
-		return false;
+	/*
+	 * If the clause has a RestrictInfo on top, use the cached results.
+	 * Otherwise (if the clause is bare expression) calculate relids from
+	 * scratch.
+	 */
+	if (IsA(clause, RestrictInfo))
+	{
+		RestrictInfo *rinfo = (RestrictInfo *) clause;
 
-	/* Pseudoconstants are not really interesting here. */
-	if (rinfo->pseudoconstant)
-		return false;
+		relids = rinfo->clause_relids;
+
+		/* extract the bare expression */
+		clause = (Node *) rinfo->clause;
+	}
+	else
+		relids = pull_varnos(root, clause);
 
 	/* Clauses referencing other varnos are incompatible. */
-	if (!bms_get_singleton_member(rinfo->clause_relids, &clause_relid) ||
+	if (!bms_get_singleton_member(relids, &clause_relid) ||
 		clause_relid != relid)
 		return false;
 
 	/* Check the clause and determine what attributes it references. */
-	if (!statext_is_compatible_clause_internal(root, (Node *) rinfo->clause,
+	if (!statext_is_compatible_clause_internal(root, clause,
 											   relid, attnums, exprs))
 		return false;
 
