diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index f0ef102..c99304d 100644
*** a/src/backend/optimizer/util/clauses.c
--- b/src/backend/optimizer/util/clauses.c
*************** evaluate_function(Oid funcid, Oid result
*** 4645,4651 ****
   * unreasonably expensive to evaluate.  The expensiveness check not only
   * prevents us from doing multiple evaluations of an expensive parameter
   * at runtime, but is a safety value to limit growth of an expression due
!  * to repeated inlining.
   *
   * We must also beware of changing the volatility or strictness status of
   * functions by inlining them.
--- 4645,4653 ----
   * unreasonably expensive to evaluate.  The expensiveness check not only
   * prevents us from doing multiple evaluations of an expensive parameter
   * at runtime, but is a safety value to limit growth of an expression due
!  * to repeated inlining.  (Currently, the expensiveness check is expressed
!  * as a limit on the total additional cost of extra parameter evaluations,
!  * rather than of any one parameter.)
   *
   * We must also beware of changing the volatility or strictness status of
   * functions by inlining them.
*************** inline_function(Oid funcid, Oid result_t
*** 4682,4687 ****
--- 4684,4690 ----
  	Query	   *querytree;
  	Node	   *newexpr;
  	int		   *usecounts;
+ 	Cost		delta_param_cost;
  	ListCell   *arg;
  	int			i;
  
*************** inline_function(Oid funcid, Oid result_t
*** 4876,4882 ****
  	newexpr = substitute_actual_parameters(newexpr, funcform->pronargs,
  										   args, usecounts);
  
! 	/* Now check for parameter usage */
  	i = 0;
  	foreach(arg, args)
  	{
--- 4879,4889 ----
  	newexpr = substitute_actual_parameters(newexpr, funcform->pronargs,
  										   args, usecounts);
  
! 	/*
! 	 * Check for parameter usage, and estimate the delta in evaluation cost
! 	 * resulting from parameters possibly being evaluated more than once.
! 	 */
! 	delta_param_cost = 0.0;
  	i = 0;
  	foreach(arg, args)
  	{
*************** inline_function(Oid funcid, Oid result_t
*** 4887,4922 ****
  			/* Param not used at all: uncool if func is strict */
  			if (funcform->proisstrict)
  				goto fail;
  		}
  		else if (usecounts[i] != 1)
  		{
! 			/* Param used multiple times: uncool if expensive or volatile */
  			QualCost	eval_cost;
  
  			/*
! 			 * We define "expensive" as "contains any subplan or more than 10
! 			 * operators".  Note that the subplan search has to be done
! 			 * explicitly, since cost_qual_eval() will barf on unplanned
! 			 * subselects.
  			 */
  			if (contain_subplans(param))
  				goto fail;
- 			cost_qual_eval(&eval_cost, list_make1(param), NULL);
- 			if (eval_cost.startup + eval_cost.per_tuple >
- 				10 * cpu_operator_cost)
- 				goto fail;
  
  			/*
! 			 * Check volatility last since this is more expensive than the
! 			 * above tests
  			 */
! 			if (contain_volatile_functions(param))
! 				goto fail;
  		}
  		i++;
  	}
  
  	/*
  	 * Whew --- we can make the substitution.  Copy the modified expression
  	 * out of the temporary memory context, and clean up.
  	 */
--- 4894,4949 ----
  			/* Param not used at all: uncool if func is strict */
  			if (funcform->proisstrict)
  				goto fail;
+ 
+ 			/*
+ 			 * In principle, we should credit the eval cost of the param expr
+ 			 * as a savings from inlining.  However, it's hard to deal with
+ 			 * subplans properly, so we don't bother.  This case is unlikely
+ 			 * anyway, so we just try to be semantically correct.
+ 			 */
  		}
  		else if (usecounts[i] != 1)
  		{
! 			/* Param used multiple times: uncool if volatile */
  			QualCost	eval_cost;
  
+ 			if (contain_volatile_functions(param))
+ 				goto fail;
+ 
  			/*
! 			 * If the param contains any SubLinks, cost_qual_eval() will barf
! 			 * on it.  Arbitrarily assume that the true cost of a subplan is
! 			 * high enough that we should not inline.
  			 */
  			if (contain_subplans(param))
  				goto fail;
  
  			/*
! 			 * Otherwise, estimate the evaluation cost of the param, and
! 			 * charge for the N-1 extra evaluations.  Note that we consider
! 			 * only per-tuple cost not startup cost.  Ideally we'd account for
! 			 * that somehow, but it's hard since we have as yet no idea how
! 			 * many times the query will execute this expression.
  			 */
! 			cost_qual_eval_node(&eval_cost, param, context->root);
! 			delta_param_cost += eval_cost.per_tuple * (usecounts[i] - 1);
  		}
  		i++;
  	}
  
  	/*
+ 	 * If the incremental cost of multiple parameter evaluation exceeds the
+ 	 * nominal cost of the function we're inlining, don't inline.  With the
+ 	 * default cost for a SQL-language function, this rule causes us to not
+ 	 * inline if multiple evaluation would add more than 100 times
+ 	 * cpu_operator_cost.  However, function authors can adjust the claimed
+ 	 * cost of inlinable functions to encourage or discourage inlining in the
+ 	 * presence of multiple parameter usage.
+ 	 */
+ 	if (delta_param_cost > funcform->procost * cpu_operator_cost)
+ 		goto fail;
+ 
+ 	/*
  	 * Whew --- we can make the substitution.  Copy the modified expression
  	 * out of the temporary memory context, and clean up.
  	 */
