diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 5f74d3b36d..b628ac7bec 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -37,6 +37,7 @@
 #include "optimizer/paths.h"
 #include "optimizer/plancat.h"
 #include "optimizer/planner.h"
+#include "optimizer/predtest.h"
 #include "optimizer/prep.h"
 #include "optimizer/restrictinfo.h"
 #include "optimizer/tlist.h"
@@ -1052,6 +1053,27 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
 				/* Restriction reduces to constant TRUE, so drop it */
 				continue;
 			}
+
+			/*
+			 * For partitions, we may be able to eliminate some quals if
+			 * they're implied by the partition bound.
+			 */
+			if (childrel->partition_qual != NIL)
+			{
+				Node	   *checkqual = copyObject(childqual);
+
+				/*
+				 * Since the partition_qual has all Vars stored as varno=1, we
+				 * must convert all Vars of the childqual to have their varnos
+				 * set to 1 so that predicate_implied_by can properly match
+				 * implied quals.
+				 */
+				ChangeVarNodes(checkqual, childrel->relid, 1, 0);
+
+				if (predicate_implied_by(list_make1(checkqual), childrel->partition_qual, false))
+					continue;
+			}
+
 			/* might have gotten an AND clause, if so flatten it */
 			foreach(lc2, make_ands_implicit((Expr *) childqual))
 			{
