diff --git a/doc/src/sgml/xindex.sgml b/doc/src/sgml/xindex.sgml
index 9f5c0c3..2f00930 100644
--- a/doc/src/sgml/xindex.sgml
+++ b/doc/src/sgml/xindex.sgml
@@ -546,6 +546,11 @@
        index-only scans (optional)</entry>
        <entry>9</entry>
       </row>
+      <row>
+       <entry><function>options</function></entry>
+       <entry>parse opclass-specific options (optional)</entry>
+       <entry>10</entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 51c32e4..e260e2e 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -94,6 +94,7 @@ gisthandler(PG_FUNCTION_ARGS)
 	amroutine->amestimateparallelscan = NULL;
 	amroutine->aminitparallelscan = NULL;
 	amroutine->amparallelrescan = NULL;
+	amroutine->amopclassoptions = gistopclassoptions;
 
 	PG_RETURN_POINTER(amroutine);
 }
@@ -1445,6 +1446,7 @@ initGISTstate(Relation index)
 	giststate->scanCxt = scanCxt;
 	giststate->tempCxt = scanCxt;	/* caller must change this if needed */
 	giststate->tupdesc = index->rd_att;
+	giststate->opclassoptions = RelationGetParsedOpclassOptions(index);
 
 	for (i = 0; i < index->rd_att->natts; i++)
 	{
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index b30b931..fe8d75e 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -194,6 +194,7 @@ gistindex_keytest(IndexScanDesc scan,
 			Datum		test;
 			bool		recheck;
 			GISTENTRY	de;
+			bytea	   *options = giststate->opclassoptions[key->sk_attno - 1];
 
 			gistdentryinit(giststate, key->sk_attno - 1, &de,
 						   datum, r, page, offset,
@@ -214,13 +215,14 @@ gistindex_keytest(IndexScanDesc scan,
 			 */
 			recheck = true;
 
-			test = FunctionCall5Coll(&key->sk_func,
+			test = FunctionCall6Coll(&key->sk_func,
 									 key->sk_collation,
 									 PointerGetDatum(&de),
 									 key->sk_argument,
 									 Int16GetDatum(key->sk_strategy),
 									 ObjectIdGetDatum(key->sk_subtype),
-									 PointerGetDatum(&recheck));
+									 PointerGetDatum(&recheck),
+									 PointerGetDatum(options));
 
 			if (!DatumGetBool(test))
 				return false;
@@ -255,6 +257,7 @@ gistindex_keytest(IndexScanDesc scan,
 			Datum		dist;
 			bool		recheck;
 			GISTENTRY	de;
+			bytea	   *options = giststate->opclassoptions[key->sk_attno - 1];
 
 			gistdentryinit(giststate, key->sk_attno - 1, &de,
 						   datum, r, page, offset,
@@ -277,13 +280,14 @@ gistindex_keytest(IndexScanDesc scan,
 			 * about the flag, but are expected to never be lossy.
 			 */
 			recheck = false;
-			dist = FunctionCall5Coll(&key->sk_func,
+			dist = FunctionCall6Coll(&key->sk_func,
 									 key->sk_collation,
 									 PointerGetDatum(&de),
 									 key->sk_argument,
 									 Int16GetDatum(key->sk_strategy),
 									 ObjectIdGetDatum(key->sk_subtype),
-									 PointerGetDatum(&recheck));
+									 PointerGetDatum(&recheck),
+									 PointerGetDatum(options));
 			*recheck_distances_p |= recheck;
 			*distance_p = DatumGetFloat8(dist);
 		}
diff --git a/src/backend/access/gist/gistsplit.c b/src/backend/access/gist/gistsplit.c
index a7038cc..96a9290 100644
--- a/src/backend/access/gist/gistsplit.c
+++ b/src/backend/access/gist/gistsplit.c
@@ -378,18 +378,20 @@ genericPickSplit(GISTSTATE *giststate, GistEntryVector *entryvec, GIST_SPLITVEC
 	evec->n = v->spl_nleft;
 	memcpy(evec->vector, entryvec->vector + FirstOffsetNumber,
 		   sizeof(GISTENTRY) * evec->n);
-	v->spl_ldatum = FunctionCall2Coll(&giststate->unionFn[attno],
+	v->spl_ldatum = FunctionCall3Coll(&giststate->unionFn[attno],
 									  giststate->supportCollation[attno],
 									  PointerGetDatum(evec),
-									  PointerGetDatum(&nbytes));
+									  PointerGetDatum(&nbytes),
+									  PointerGetDatum(giststate->opclassoptions[attno]));
 
 	evec->n = v->spl_nright;
 	memcpy(evec->vector, entryvec->vector + FirstOffsetNumber + v->spl_nleft,
 		   sizeof(GISTENTRY) * evec->n);
-	v->spl_rdatum = FunctionCall2Coll(&giststate->unionFn[attno],
+	v->spl_rdatum = FunctionCall3Coll(&giststate->unionFn[attno],
 									  giststate->supportCollation[attno],
 									  PointerGetDatum(evec),
-									  PointerGetDatum(&nbytes));
+									  PointerGetDatum(&nbytes),
+									  PointerGetDatum(giststate->opclassoptions[attno]));
 }
 
 /*
@@ -430,10 +432,11 @@ gistUserPicksplit(Relation r, GistEntryVector *entryvec, int attno, GistSplitVec
 	 * Let the opclass-specific PickSplit method do its thing.  Note that at
 	 * this point we know there are no null keys in the entryvec.
 	 */
-	FunctionCall2Coll(&giststate->picksplitFn[attno],
+	FunctionCall3Coll(&giststate->picksplitFn[attno],
 					  giststate->supportCollation[attno],
 					  PointerGetDatum(entryvec),
-					  PointerGetDatum(sv));
+					  PointerGetDatum(sv),
+					  PointerGetDatum(giststate->opclassoptions[attno]));
 
 	if (sv->spl_nleft == 0 || sv->spl_nright == 0)
 	{
diff --git a/src/backend/access/gist/gistutil.c b/src/backend/access/gist/gistutil.c
index 55cccd2..bab02f1 100644
--- a/src/backend/access/gist/gistutil.c
+++ b/src/backend/access/gist/gistutil.c
@@ -23,6 +23,7 @@
 #include "storage/indexfsm.h"
 #include "storage/lmgr.h"
 #include "utils/builtins.h"
+#include "utils/ruleutils.h"
 #include "utils/syscache.h"
 
 
@@ -199,10 +200,11 @@ gistMakeUnionItVec(GISTSTATE *giststate, IndexTuple *itvec, int len,
 			}
 
 			/* Make union and store in attr array */
-			attr[i] = FunctionCall2Coll(&giststate->unionFn[i],
+			attr[i] = FunctionCall3Coll(&giststate->unionFn[i],
 										giststate->supportCollation[i],
 										PointerGetDatum(evec),
-										PointerGetDatum(&attrsize));
+										PointerGetDatum(&attrsize),
+										PointerGetDatum(giststate->opclassoptions[i]));
 
 			isnull[i] = false;
 		}
@@ -268,10 +270,11 @@ gistMakeUnionKey(GISTSTATE *giststate, int attno,
 		}
 
 		*dstisnull = false;
-		*dst = FunctionCall2Coll(&giststate->unionFn[attno],
+		*dst = FunctionCall3Coll(&giststate->unionFn[attno],
 								 giststate->supportCollation[attno],
 								 PointerGetDatum(evec),
-								 PointerGetDatum(&dstsize));
+								 PointerGetDatum(&dstsize),
+								 PointerGetDatum(giststate->opclassoptions[attno]));
 	}
 }
 
@@ -280,10 +283,11 @@ gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b)
 {
 	bool		result;
 
-	FunctionCall3Coll(&giststate->equalFn[attno],
+	FunctionCall4Coll(&giststate->equalFn[attno],
 					  giststate->supportCollation[attno],
 					  a, b,
-					  PointerGetDatum(&result));
+					  PointerGetDatum(&result),
+					  PointerGetDatum(giststate->opclassoptions[attno]));
 	return result;
 }
 
@@ -556,9 +560,10 @@ gistdentryinit(GISTSTATE *giststate, int nkey, GISTENTRY *e,
 			return;
 
 		dep = (GISTENTRY *)
-			DatumGetPointer(FunctionCall1Coll(&giststate->decompressFn[nkey],
+			DatumGetPointer(FunctionCall2Coll(&giststate->decompressFn[nkey],
 											  giststate->supportCollation[nkey],
-											  PointerGetDatum(e)));
+											  PointerGetDatum(e),
+											  PointerGetDatum(giststate->opclassoptions[nkey])));
 		/* decompressFn may just return the given pointer */
 		if (dep != e)
 			gistentryinit(*e, dep->key, dep->rel, dep->page, dep->offset,
@@ -593,9 +598,10 @@ gistFormTuple(GISTSTATE *giststate, Relation r,
 			/* there may not be a compress function in opclass */
 			if (OidIsValid(giststate->compressFn[i].fn_oid))
 				cep = (GISTENTRY *)
-					DatumGetPointer(FunctionCall1Coll(&giststate->compressFn[i],
+					DatumGetPointer(FunctionCall2Coll(&giststate->compressFn[i],
 													  giststate->supportCollation[i],
-													  PointerGetDatum(&centry)));
+													  PointerGetDatum(&centry),
+													  PointerGetDatum(giststate->opclassoptions[i])));
 			else
 				cep = &centry;
 			compatt[i] = cep->key;
@@ -624,9 +630,10 @@ gistFetchAtt(GISTSTATE *giststate, int nkey, Datum k, Relation r)
 	gistentryinit(fentry, k, r, NULL, (OffsetNumber) 0, false);
 
 	fep = (GISTENTRY *)
-		DatumGetPointer(FunctionCall1Coll(&giststate->fetchFn[nkey],
+		DatumGetPointer(FunctionCall2Coll(&giststate->fetchFn[nkey],
 										  giststate->supportCollation[nkey],
-										  PointerGetDatum(&fentry)));
+										  PointerGetDatum(&fentry),
+										  PointerGetDatum(giststate->opclassoptions[nkey])));
 
 	/* fetchFn set 'key', return it to the caller */
 	return fep->key;
@@ -694,11 +701,12 @@ gistpenalty(GISTSTATE *giststate, int attno,
 	if (giststate->penaltyFn[attno].fn_strict == false ||
 		(isNullOrig == false && isNullAdd == false))
 	{
-		FunctionCall3Coll(&giststate->penaltyFn[attno],
+		FunctionCall4Coll(&giststate->penaltyFn[attno],
 						  giststate->supportCollation[attno],
 						  PointerGetDatum(orig),
 						  PointerGetDatum(add),
-						  PointerGetDatum(&penalty));
+						  PointerGetDatum(&penalty),
+						  PointerGetDatum(giststate->opclassoptions[attno]));
 		/* disallow negative or NaN penalty */
 		if (isnan(penalty) || penalty < 0.0)
 			penalty = 0.0;
@@ -860,6 +868,14 @@ gistoptions(Datum reloptions, bool validate)
 	return (bytea *) rdopts;
 }
 
+bytea *
+gistopclassoptions(Relation index, AttrNumber attnum, Datum options, bool validate)
+{
+	return index_opclass_options_generic(index, attnum, GIST_OPCLASSOPT_PROC,
+										 options, validate);
+}
+
+
 /*
  *	gistproperty() -- Check boolean properties of indexes.
  *
diff --git a/src/backend/access/gist/gistvalidate.c b/src/backend/access/gist/gistvalidate.c
index dd87dad..0fa5646 100644
--- a/src/backend/access/gist/gistvalidate.c
+++ b/src/backend/access/gist/gistvalidate.c
@@ -108,37 +108,46 @@ gistvalidate(Oid opclassoid)
 		{
 			case GIST_CONSISTENT_PROC:
 				ok = check_amproc_signature(procform->amproc, BOOLOID, false,
-											5, 5, INTERNALOID, opcintype,
-											INT2OID, OIDOID, INTERNALOID);
+											5, 6, INTERNALOID, opcintype,
+											INT2OID, OIDOID, INTERNALOID,
+											INTERNALOID);
 				break;
 			case GIST_UNION_PROC:
 				ok = check_amproc_signature(procform->amproc, opckeytype, false,
-											2, 2, INTERNALOID, INTERNALOID);
+											2, 3, INTERNALOID, INTERNALOID,
+											INTERNALOID);
 				break;
 			case GIST_COMPRESS_PROC:
 			case GIST_DECOMPRESS_PROC:
 			case GIST_FETCH_PROC:
 				ok = check_amproc_signature(procform->amproc, INTERNALOID, true,
-											1, 1, INTERNALOID);
+											1, 2, INTERNALOID, INTERNALOID);
 				break;
 			case GIST_PENALTY_PROC:
 				ok = check_amproc_signature(procform->amproc, INTERNALOID, true,
-											3, 3, INTERNALOID,
-											INTERNALOID, INTERNALOID);
+											3, 4, INTERNALOID,
+											INTERNALOID, INTERNALOID,
+											INTERNALOID);
 				break;
 			case GIST_PICKSPLIT_PROC:
 				ok = check_amproc_signature(procform->amproc, INTERNALOID, true,
-											2, 2, INTERNALOID, INTERNALOID);
+											2, 3, INTERNALOID, INTERNALOID,
+											INTERNALOID);
 				break;
 			case GIST_EQUAL_PROC:
 				ok = check_amproc_signature(procform->amproc, INTERNALOID, false,
-											3, 3, opckeytype, opckeytype,
-											INTERNALOID);
+											3, 4, opckeytype, opckeytype,
+											INTERNALOID, INTERNALOID);
 				break;
 			case GIST_DISTANCE_PROC:
 				ok = check_amproc_signature(procform->amproc, FLOAT8OID, false,
-											5, 5, INTERNALOID, opcintype,
-											INT2OID, OIDOID, INTERNALOID);
+											5, 6, INTERNALOID, opcintype,
+											INT2OID, OIDOID, INTERNALOID,
+											INTERNALOID);
+				break;
+			case GIST_OPCLASSOPT_PROC:
+				ok = check_amproc_signature(procform->amproc, INTERNALOID, false,
+											2, 2, INTERNALOID, BOOLOID);
 				break;
 			default:
 				ereport(INFO,
@@ -259,7 +268,8 @@ gistvalidate(Oid opclassoid)
 			(opclassgroup->functionset & (((uint64) 1) << i)) != 0)
 			continue;			/* got it */
 		if (i == GIST_DISTANCE_PROC || i == GIST_FETCH_PROC ||
-			i == GIST_COMPRESS_PROC || i == GIST_DECOMPRESS_PROC)
+			i == GIST_COMPRESS_PROC || i == GIST_DECOMPRESS_PROC ||
+			i == GIST_OPCLASSOPT_PROC)
 			continue;			/* optional methods */
 		ereport(INFO,
 				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
diff --git a/src/include/access/gist.h b/src/include/access/gist.h
index 827566d..08e7ada 100644
--- a/src/include/access/gist.h
+++ b/src/include/access/gist.h
@@ -34,7 +34,8 @@
 #define GIST_EQUAL_PROC					7
 #define GIST_DISTANCE_PROC				8
 #define GIST_FETCH_PROC					9
-#define GISTNProcs					9
+#define GIST_OPCLASSOPT_PROC			10
+#define GISTNProcs						10
 
 /*
  * Page opaque data in a GiST index page.
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
index 36ed724..eedd896 100644
--- a/src/include/access/gist_private.h
+++ b/src/include/access/gist_private.h
@@ -94,6 +94,8 @@ typedef struct GISTSTATE
 
 	/* Collations to pass to the support functions */
 	Oid			supportCollation[INDEX_MAX_KEYS];
+
+	bytea	  **opclassoptions;	/* parsed opclass-specific options */
 } GISTSTATE;
 
 
@@ -436,6 +438,8 @@ extern bool gistvalidate(Oid opclassoid);
 #define GIST_DEFAULT_FILLFACTOR		90
 
 extern bytea *gistoptions(Datum reloptions, bool validate);
+extern bytea *gistopclassoptions(Relation index, AttrNumber colno,
+				   Datum options, bool validate);
 extern bool gistproperty(Oid index_oid, int attno,
 			 IndexAMProperty prop, const char *propname,
 			 bool *res, bool *isnull);
