diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index b56666398e..9a7c8ea07b 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -1542,7 +1542,31 @@ trivial_subqueryscan(SubqueryScan *plan)
 static Plan *
 clean_up_removed_plan_level(Plan *parent, Plan *child)
 {
-	/* We have to be sure we don't lose any initplans */
+	ListCell   *lc;
+
+	/*
+	 * We have to be sure we don't lose any initplans, so move any that were
+	 * attached to the parent plan to the child.  If we do move any, the child
+	 * is no longer parallel-safe.  As a cosmetic matter, also add the
+	 * initplans' run costs to the child's costs (compare
+	 * SS_charge_for_initplans).
+	 */
+	foreach(lc, parent->initPlan)
+	{
+		SubPlan    *initsubplan = (SubPlan *) lfirst(lc);
+		Cost		initplan_cost;
+
+		child->parallel_safe = false;
+		initplan_cost = initsubplan->startup_cost + initsubplan->per_call_cost;
+		child->startup_cost += initplan_cost;
+		child->total_cost += initplan_cost;
+	}
+
+	/*
+	 * Attach plans this way so that parent's initplans are processed before
+	 * any pre-existing initplans of the child.  Probably doesn't matter, but
+	 * let's preserve the ordering just in case.
+	 */
 	child->initPlan = list_concat(parent->initPlan,
 								  child->initPlan);
 
