diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index a411e3a..7f1212d 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -8396,6 +8396,16 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
         <entry><literal>inet '192.168.1/24' &gt;&gt;= inet '192.168.1/24'</literal></entry>
        </row>
        <row>
+        <entry> <literal>&amp;&amp;</literal> </entry>
+        <entry>overlaps</entry>
+        <entry><literal>inet '192.168.1/24' &amp;&amp; inet '192.168.1/24'</literal></entry>
+       </row>
+       <row>
+        <entry> <literal>-|-</literal> </entry>
+        <entry>is adjacent to</entry>
+        <entry><literal>inet '192.168.1/24' -|- inet '192.168.1/24'</literal></entry>
+       </row>
+       <row>
         <entry> <literal>~</literal> </entry>
         <entry>bitwise NOT</entry>
         <entry><literal>~ inet '192.168.1.6'</literal></entry>
diff --git a/src/backend/utils/adt/Makefile b/src/backend/utils/adt/Makefile
index 41a8982..31590e3 100644
--- a/src/backend/utils/adt/Makefile
+++ b/src/backend/utils/adt/Makefile
@@ -24,7 +24,7 @@ OBJS = acl.o arrayfuncs.o array_selfuncs.o array_typanalyze.o \
 	oid.o oracle_compat.o pseudotypes.o rangetypes.o rangetypes_gist.o \
 	rowtypes.o regexp.o regproc.o ruleutils.o selfuncs.o \
 	tid.o timestamp.o varbit.o varchar.o varlena.o version.o xid.o \
-	network.o mac.o inet_cidr_ntop.o inet_net_pton.o \
+	network.o network_gist.o mac.o inet_cidr_ntop.o inet_net_pton.o \
 	ri_triggers.o pg_lzcompress.o pg_locale.o formatting.o \
 	ascii.o quote.o pgstatfuncs.o encode.o dbsize.o genfile.o trigfuncs.o \
 	tsginidx.o tsgistidx.o tsquery.o tsquery_cleanup.o tsquery_gist.o \
diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c
index f2c337c..fd81815 100644
--- a/src/backend/utils/adt/network.c
+++ b/src/backend/utils/adt/network.c
@@ -23,41 +23,10 @@
 
 
 static int32 network_cmp_internal(inet *a1, inet *a2);
-static int	bitncmp(void *l, void *r, int n);
 static bool addressOK(unsigned char *a, int bits, int family);
 static int	ip_addrsize(inet *inetptr);
 static inet *internal_inetpl(inet *ip, int64 addend);
 
-/*
- *	Access macros.	We use VARDATA_ANY so that we can process short-header
- *	varlena values without detoasting them.  This requires a trick:
- *	VARDATA_ANY assumes the varlena header is already filled in, which is
- *	not the case when constructing a new value (until SET_INET_VARSIZE is
- *	called, which we typically can't do till the end).  Therefore, we
- *	always initialize the newly-allocated value to zeroes (using palloc0).
- *	A zero length word will look like the not-1-byte case to VARDATA_ANY,
- *	and so we correctly construct an uncompressed value.
- *
- *	Note that ip_maxbits() and SET_INET_VARSIZE() require
- *	the family field to be set correctly.
- */
-
-#define ip_family(inetptr) \
-	(((inet_struct *) VARDATA_ANY(inetptr))->family)
-
-#define ip_bits(inetptr) \
-	(((inet_struct *) VARDATA_ANY(inetptr))->bits)
-
-#define ip_addr(inetptr) \
-	(((inet_struct *) VARDATA_ANY(inetptr))->ipaddr)
-
-#define ip_maxbits(inetptr) \
-	(ip_family(inetptr) == PGSQL_AF_INET ? 32 : 128)
-
-#define SET_INET_VARSIZE(dst) \
-	SET_VARSIZE(dst, VARHDRSZ + offsetof(inet_struct, ipaddr) + \
-				ip_addrsize(dst))
-
 
 /*
  * Return the number of bytes of address storage needed for this data type.
@@ -596,6 +565,36 @@ network_supeq(PG_FUNCTION_ARGS)
 	PG_RETURN_BOOL(false);
 }
 
+Datum
+network_overlap(PG_FUNCTION_ARGS)
+{
+	inet	   *a1 = PG_GETARG_INET_PP(0);
+	inet	   *a2 = PG_GETARG_INET_PP(1);
+
+	if (ip_family(a1) == ip_family(a2))
+	{
+		PG_RETURN_BOOL(bitncmp(ip_addr(a1), ip_addr(a2),
+					   Min(ip_bits(a1), ip_bits(a2))) == 0);
+	}
+
+	PG_RETURN_BOOL(false);
+}
+
+Datum
+network_adjacent(PG_FUNCTION_ARGS)
+{
+	inet	   *a1 = PG_GETARG_INET_PP(0);
+	inet	   *a2 = PG_GETARG_INET_PP(1);
+
+	if (ip_family(a1) == ip_family(a2))
+	{
+		PG_RETURN_BOOL(bitncmp(ip_addr(a1), ip_addr(a2),
+					   Min(ip_bits(a1), ip_bits(a2))) != 0);
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
 /*
  * Extract data from a network datatype.
  */
@@ -962,7 +961,7 @@ convert_network_to_scalar(Datum value, Oid typid)
  * author:
  *		Paul Vixie (ISC), June 1996
  */
-static int
+int
 bitncmp(void *l, void *r, int n)
 {
 	u_int		lb,
@@ -991,6 +990,49 @@ bitncmp(void *l, void *r, int n)
 	return 0;
 }
 
+/*
+ * Compare bit masks l and r for n bits
+ *
+ * Return the common bit count from the beginning. In contrast to
+ * it's purpose, it checks the bits from the end to the beggining
+ * to be more effective on modern computers based on the assumption
+ * that the inputs will usually be similar. Additional bits on the
+ * right would not effect the return value as expected. The return
+ * value is always less than the input n.
+ */
+int
+bitncommon(unsigned char *l, unsigned char *r, int n)
+{
+	int			byte,
+				nbits;
+	unsigned char diff;
+
+	byte = n / 8;
+	nbits = n % 8;
+
+	/* Compare bytes from the most to the least */
+	while (byte != 0 && memcmp(l, r, byte) != 0)
+	{
+		byte--;
+
+		/* At least one more bit in the last byte is not common */
+		nbits = 7;
+	}
+
+	/* Set the bits to discard */
+	if (nbits != 0)
+	{
+		/* Set the diff for the first byte which is not common */
+		diff = l[byte] ^ r[byte];
+
+		/* Compare the bits from the most to the least */
+		while (diff >> (8 - nbits) != 0)
+			nbits--;
+	}
+
+	return (8 * byte) + nbits;
+}
+
 static bool
 addressOK(unsigned char *a, int bits, int family)
 {
diff --git a/src/backend/utils/adt/network_gist.c b/src/backend/utils/adt/network_gist.c
new file mode 100644
index 0000000..3af56dc
--- /dev/null
+++ b/src/backend/utils/adt/network_gist.c
@@ -0,0 +1,563 @@
+/*-------------------------------------------------------------------------
+ *
+ * network_gist.c
+ *	  GiST support for network types.
+ *
+ * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  src/backend/utils/adt/network_gist.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/gist.h"
+#include "access/skey.h"
+#include "utils/inet.h"
+
+/*
+ * The GiST query consistency check
+ */
+Datum
+inet_gist_consistent(PG_FUNCTION_ARGS)
+{
+	GISTENTRY	   *ent = (GISTENTRY *) PG_GETARG_POINTER(0);
+	inet		   *orig = DatumGetInetP(ent->key),
+				   *query = PG_GETARG_INET_PP(1);
+	StrategyNumber  strategy = (StrategyNumber) PG_GETARG_UINT16(2);
+	/* Oid 			subtype = PG_GETARG_OID(3); */
+	bool	   	   *recheck = (bool *) PG_GETARG_POINTER(4);
+	int 			minbits,
+					order;
+
+	/* All operators served by this function are exact. */
+	*recheck = false;
+
+	/*
+	 * Check 0: different families
+	 *
+	 * 0 is the special number for the family field. It means sub nodes
+	 * include networks with different address families. The index should
+	 * only have this node on the top. Proper inet type has no chance
+	 * to have 0 on the family field.
+	 */
+	if (ip_family(orig) == 0)
+		PG_RETURN_BOOL(true);
+
+	/*
+	 * Check 1: different families
+	 *
+	 * Matching families do not help any of the strategies.
+	 */
+	if (ip_family(orig) != ip_family(query))
+	{
+		switch (strategy)
+		{
+			case INETSTRAT_LT:
+			case INETSTRAT_LE:
+				if (ip_family(orig) < ip_family(query))
+					PG_RETURN_BOOL(true);
+				break;
+
+			case INETSTRAT_GE:
+			case INETSTRAT_GT:
+				if (ip_family(orig) > ip_family(query))
+					PG_RETURN_BOOL(true);
+				break;
+		}
+
+		PG_RETURN_BOOL(false);
+	}
+
+	/*
+	 * Check 2: network bit count
+	 *
+	 * Network bit count (ip_bits) helps to check leaves for sub network
+	 * and sup network operators.
+	 */
+	switch (strategy)
+	{
+		case INETSTRAT_SUB:
+			if (GIST_LEAF(ent) && ip_bits(orig) <= ip_bits(query))
+				PG_RETURN_BOOL(false);
+			break;
+
+		case INETSTRAT_SUBEQ:
+			if (GIST_LEAF(ent) && ip_bits(orig) < ip_bits(query))
+				PG_RETURN_BOOL(false);
+			break;
+
+		case INETSTRAT_SUPEQ:
+			if (ip_bits(orig) > ip_bits(query))
+				PG_RETURN_BOOL(false);
+			break;
+
+		case INETSTRAT_SUP:
+			if (ip_bits(orig) >= ip_bits(query))
+				PG_RETURN_BOOL(false);
+			break;
+	}
+
+	/*
+	 * Check 3: empty address
+	 *
+	 * If there are not any possible common bits, do not go futher
+	 * return true as the leaves under this node can contain any address.
+	 */
+	minbits = Min(ip_bits(orig), ip_bits(query));
+
+	if (minbits == 0)
+	{
+		switch (strategy)
+		{
+			case INETSTRAT_SUB:
+			case INETSTRAT_SUBEQ:
+			case INETSTRAT_OVERLAPS:
+			case INETSTRAT_SUPEQ:
+			case INETSTRAT_SUP:
+				PG_RETURN_BOOL(true);
+		}
+
+		if (!GIST_LEAF(ent))
+			PG_RETURN_BOOL(true);
+	}
+
+	/*
+	 * Check 4: common network bits
+	 *
+	 * Common network bits is the final check for operators which
+	 * only consider the network part of the address.
+	 */
+	if (minbits > 0)
+	{
+		order = bitncmp(ip_addr(orig), ip_addr(query), minbits);
+
+		switch (strategy)
+		{
+			case INETSTRAT_SUB:
+			case INETSTRAT_SUBEQ:
+			case INETSTRAT_OVERLAPS:
+			case INETSTRAT_SUPEQ:
+			case INETSTRAT_SUP:
+				PG_RETURN_BOOL(order == 0);
+
+			case INETSTRAT_LT:
+			case INETSTRAT_LE:
+				if (order > 0)
+					PG_RETURN_BOOL(false);
+				if (order < 0 || !GIST_LEAF(ent))
+					PG_RETURN_BOOL(true);
+				break;
+
+			case INETSTRAT_EQ:
+				if (order != 0)
+					PG_RETURN_BOOL(false);
+				if (!GIST_LEAF(ent))
+					PG_RETURN_BOOL(true);
+				break;
+
+			case INETSTRAT_GE:
+			case INETSTRAT_GT:
+				if (order < 0)
+					PG_RETURN_BOOL(false);
+				if (order > 0 || !GIST_LEAF(ent))
+					PG_RETURN_BOOL(true);
+				break;
+		}
+	}
+
+	/* Remaining checks are only for leaves and basic comparison strategies. */
+	Assert(GIST_LEAF(ent));
+
+	/*
+	 * Check 5: network bit count
+	 *
+	 * Bits are used on the basic comparison of the addresses. Whole
+	 * addresses only compared if their network bits are the same.
+	 * See backend/utils/adt/network.c:network_cmp_internal for
+	 * the original comparison.
+	 */
+	switch (strategy)
+	{
+		case INETSTRAT_LT:
+		case INETSTRAT_LE:
+			if (ip_bits(orig) < ip_bits(query))
+				PG_RETURN_BOOL(true);
+			if (ip_bits(orig) > ip_bits(query))
+				PG_RETURN_BOOL(false);
+			break;
+
+		case INETSTRAT_EQ:
+			if (ip_bits(orig) != ip_bits(query))
+				PG_RETURN_BOOL(false);
+			break;
+
+		case INETSTRAT_GE:
+		case INETSTRAT_GT:
+			if (ip_bits(orig) > ip_bits(query))
+				PG_RETURN_BOOL(true);
+			if (ip_bits(orig) < ip_bits(query))
+				PG_RETURN_BOOL(false);
+			break;
+	}
+
+	order = bitncmp(ip_addr(orig), ip_addr(query), ip_maxbits(orig));
+
+	/*
+	 * Check 6: whole address
+	 *
+	 * Whole address check would not be required for most of the
+	 * strategies.
+	 */
+	switch (strategy)
+	{
+		case INETSTRAT_LT:
+			PG_RETURN_BOOL(order < 0);
+
+		case INETSTRAT_LE:
+			PG_RETURN_BOOL(order <= 0);
+
+		case INETSTRAT_EQ:
+			PG_RETURN_BOOL(order == 0);
+
+		case INETSTRAT_GE:
+			PG_RETURN_BOOL(order >= 0);
+
+		case INETSTRAT_GT:
+			PG_RETURN_BOOL(order > 0);
+	}
+
+	elog(ERROR, "unknown strategy for inet GiST");
+}
+
+/*
+ * The GiST union function
+ *
+ * The union of the networks is the network which contain all of them.
+ * The main question to calculate the union is that they have how many
+ * bits in common. After calculating the common bits, address of any of
+ * them can be used as the union by discarding the host bits.
+ */
+Datum
+inet_gist_union(PG_FUNCTION_ARGS)
+{
+	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+	GISTENTRY	   *ent = entryvec->vector;
+	int				family,
+					bits;
+	unsigned char  *addr;
+	inet		   *tmp;
+	OffsetNumber 	i,
+					numranges = entryvec->n;
+
+	/* Initilize variables using the first key. */
+	tmp = DatumGetInetP(ent[0].key);
+	family = ip_family(tmp);
+	bits = ip_bits(tmp);
+	addr = ip_addr(tmp);
+
+	for (i = 1; i < numranges; i++)
+	{
+		tmp = DatumGetInetP(ent[i].key);
+
+		/*
+		 * Return a network with the special number 0 on the family field
+		 * for addresses from different familes.
+		 */
+		if (ip_family(tmp) != family)
+		{
+			family = 0;
+			bits = 0;
+			break;
+		}
+
+		if (bits > ip_bits(tmp))
+			bits = ip_bits(tmp);
+
+		if (bits != 0)
+			bits = bitncommon(addr, ip_addr(tmp), bits);
+	}
+
+	/* Make sure any unused bits are zeroed. */
+	tmp = (inet *) palloc0(sizeof(inet));
+
+	/* Initilize the union as inet. */
+	ip_family(tmp) = family;
+	ip_bits(tmp) = bits;
+
+	/* Clone maximum bytes of the address. */
+	if (bits != 0)
+		memcpy(ip_addr(tmp), addr, (bits + 7) / 8);
+
+	/* Clean the partial byte. */
+	if (bits % 8 != 0)
+		ip_addr(tmp)[bits / 8] &= ~(0xFF >> (bits % 8));
+
+	SET_INET_VARSIZE(tmp);
+
+	PG_RETURN_INET_P(tmp);
+}
+
+/*
+ * The GiST compress function
+ */
+Datum
+inet_gist_compress(PG_FUNCTION_ARGS)
+{
+	GISTENTRY	   *ent = (GISTENTRY *) PG_GETARG_POINTER(0);
+
+	PG_RETURN_POINTER(ent);
+}
+
+/*
+ * The GiST decompress function
+ */
+Datum
+inet_gist_decompress(PG_FUNCTION_ARGS)
+{
+	GISTENTRY	   *ent = (GISTENTRY *) PG_GETARG_POINTER(0);
+
+	PG_RETURN_POINTER(ent);
+}
+
+/*
+ * The GiST page split penalty function
+ *
+ * Penalty is reverse of the common IP bits of the two addresses.
+ * Values bigger than 1 are used when the common IP bits cannot
+ * calculated.
+ */
+Datum
+inet_gist_penalty(PG_FUNCTION_ARGS)
+{
+	GISTENTRY	   *origent = (GISTENTRY *) PG_GETARG_POINTER(0);
+	GISTENTRY	   *newent = (GISTENTRY *) PG_GETARG_POINTER(1);
+	float		   *penalty = (float *) PG_GETARG_POINTER(2);
+	inet		   *orig = DatumGetInetP(origent->key),
+				   *new = DatumGetInetP(newent->key);
+	unsigned int	minbits,
+					commonbits;
+
+	if (ip_family(orig) == ip_family(new))
+	{
+		minbits = Min(ip_bits(orig), ip_bits(new));
+
+		if (minbits > 0)
+		{
+			commonbits = bitncommon(ip_addr(orig), ip_addr(new), minbits);
+
+			if (commonbits > 0)
+				*penalty = ((float) 1) / commonbits;
+			else
+				*penalty = 2;
+		}
+		else
+			*penalty = 3;
+	}
+	else
+		*penalty = 4;
+
+	PG_RETURN_POINTER(penalty);
+}
+
+/*
+ * The GiST PickSplit method
+ *
+ * There are two ways to split. First one is to split by address families.
+ * In this case, addresses of one first appeared family will be put to the
+ * left bucket, addresses of the other family will be put to right bucket.
+ * Only the root should contain addresses from different families, so only
+ * the root should be split this way.
+ *
+ * The second and the important way is to split by the union of the keys.
+ * Union of the keys calculated same way with the inet_gist_union function.
+ * The first and the last biggest subnets created from the calculated
+ * union. In this case addresses contained by the first subnet will be put
+ * to the left bucket, address contained by the last subnet will be put to
+ * the right bucket.
+ */
+Datum
+inet_gist_picksplit(PG_FUNCTION_ARGS)
+{
+	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+	GISTENTRY	   *ent = entryvec->vector;
+	GIST_SPLITVEC  *splitvec = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
+	int				minfamily,
+					maxfamily,
+					minbits,
+					commonbits,
+					real_index;
+	unsigned char  *addr;
+	inet		   *tmp,
+				   *left_union,
+				   *right_union;
+	OffsetNumber 	maxoff,
+					nbytes,
+					i,
+				   *left,
+				   *right;
+	GISTENTRY	  **raw_entryvec;
+
+	maxoff = entryvec->n - 1;
+	nbytes = (maxoff + 1) * sizeof(OffsetNumber);
+
+	left = (OffsetNumber *) palloc(nbytes);
+	right = (OffsetNumber *) palloc(nbytes);
+
+	splitvec->spl_left = left;
+	splitvec->spl_right = right;
+
+	splitvec->spl_nleft = 0;
+	splitvec->spl_nright = 0;
+
+	/* Initialize the raw entry vector. */
+	raw_entryvec = (GISTENTRY **) malloc(entryvec->n * sizeof(void *));
+	for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
+		raw_entryvec[i] = &(entryvec->vector[i]);
+
+	/* Initilize variables using the first key. */
+	tmp = DatumGetInetP(ent[FirstOffsetNumber].key);
+	minfamily = ip_family(tmp);
+	maxfamily = minfamily;
+	commonbits = ip_bits(tmp);
+	minbits = commonbits;
+	addr = ip_addr(tmp);
+
+	/* Start comparing from the second one to find the common bit count. */
+	for (i = OffsetNumberNext(FirstOffsetNumber); i <= maxoff;
+			i = OffsetNumberNext(i))
+	{
+		real_index = raw_entryvec[i] - entryvec->vector;
+
+		tmp = DatumGetInetP(entryvec->vector[real_index].key);
+		Assert(tmp != NULL);
+
+		/*
+		 * If there are networks from different address families the split
+		 * will be based on the family. So, first set the common bit count
+		 * to 0. Then, update the minfamily and the maxfamily variables.
+		 */
+		if (ip_family(tmp) != minfamily && ip_family(tmp) != maxfamily)
+		{
+			commonbits = 0;
+
+			if (ip_family(tmp) < minfamily)
+				minfamily = ip_family(tmp);
+
+			if (ip_family(tmp) > maxfamily)
+				maxfamily = ip_family(tmp);
+		}
+
+		if (minbits > ip_bits(tmp))
+			minbits = ip_bits(tmp);
+
+		if (commonbits > ip_bits(tmp))
+			commonbits = ip_bits(tmp);
+
+		if (commonbits != 0)
+			commonbits = bitncommon(addr, ip_addr(tmp), commonbits);
+	}
+
+	/* Make sure any unused bits are zeroed. */
+	left_union = (inet *) palloc0(sizeof(inet));
+	right_union = (inet *) palloc0(sizeof(inet));
+
+	ip_family(left_union) = minfamily;
+	ip_family(right_union) = maxfamily;
+
+	if (minfamily != maxfamily)
+	{
+		Assert(minfamily < maxfamily);
+
+		for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
+		{
+			real_index = raw_entryvec[i] - entryvec->vector;
+			tmp = DatumGetInetP(entryvec->vector[real_index].key);
+
+			if (ip_family(tmp) != maxfamily)
+			{
+				if (ip_family(tmp) != minfamily)
+					ip_family(left_union) = 0;
+
+				left[splitvec->spl_nleft++] = real_index;
+			}
+			else
+				right[splitvec->spl_nright++] = real_index;
+		}
+	}
+	else
+	{
+		Assert(minfamily > 0);
+
+		/*
+		 * If all of the bits are common; there is no chance to split
+		 * properly. It should mean that all of the elements have the same
+		 * network address.
+		 */
+		if (commonbits != minbits)
+			++commonbits;
+		else
+			ereport(DEBUG1,
+					(errmsg("inet GiST cannot pict to split"),
+					 errmsg_internal("all %d bits are the same for all items",
+							commonbits)));
+
+		ip_bits(left_union) = commonbits;
+		ip_bits(right_union) = commonbits;
+
+		/* Clone maximum bytes of the address to the left side. */
+		memcpy(ip_addr(left_union), addr, (commonbits + 6) / 8);
+		addr = ip_addr(left_union);
+
+		/* Clean the partial byte on the left side. */
+		if ((commonbits - 1) % 8 != 0)
+			addr[(commonbits - 1) / 8] &= ~(0xFF >> ((commonbits - 1) % 8));
+
+		/* Clone maximum bytes of the address to the right side. */
+		memcpy(ip_addr(right_union), addr, (commonbits + 6) / 8);
+		addr = ip_addr(right_union);
+
+		/* Set the last network bit of the address for the one on the right side. */
+		addr[(commonbits - 1) / 8] |= 1 << ((8 - (commonbits % 8)) % 8);
+
+		for (i = FirstOffsetNumber; i < entryvec->n; i = OffsetNumberNext(i))
+		{
+			real_index = raw_entryvec[i] - entryvec->vector;
+			tmp = DatumGetInetP(entryvec->vector[real_index].key);
+
+			if (bitncmp(addr, ip_addr(tmp), commonbits) != 0)
+				left[splitvec->spl_nleft++] = real_index;
+			else
+				right[splitvec->spl_nright++] = real_index;
+		}
+	}
+
+	SET_INET_VARSIZE(left_union);
+	SET_INET_VARSIZE(right_union);
+
+	splitvec->spl_ldatum = InetPGetDatum(left_union);
+	splitvec->spl_rdatum = InetPGetDatum(right_union);
+
+	PG_RETURN_POINTER(splitvec);
+}
+
+/*
+ * The GiST equality function
+ */
+Datum
+inet_gist_same(PG_FUNCTION_ARGS)
+{
+	inet		   *left = PG_GETARG_INET_P(0);
+	inet		   *right = PG_GETARG_INET_P(1);
+	bool		   *result = (bool *) PG_GETARG_POINTER(2);
+
+	*result = (ip_family(right) == ip_family(left) &&
+			   ip_bits(right) == ip_bits(left) &&
+			   bitncmp(ip_addr(left), ip_addr(right), ip_maxbits(left)) == 0);
+
+	PG_RETURN_POINTER(result);
+}
+
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
index c8a548c..6c65e14 100644
--- a/src/include/catalog/pg_amop.h
+++ b/src/include/catalog/pg_amop.h
@@ -791,4 +791,18 @@ DATA(insert (	3474   3831 3831 8 s	3892 4000 0 ));
 DATA(insert (	3474   3831 2283 16 s	3889 4000 0 ));
 DATA(insert (	3474   3831 3831 18 s	3882 4000 0 ));
 
+/*
+ * GiST inet_ops
+ */
+DATA(insert (	4049	869	869	3 s		4050 783 0 ));
+DATA(insert (	4049	869	869	7 s		934 783 0 ));
+DATA(insert (	4049	869	869	8 s		932 783 0 ));
+DATA(insert (	4049	869	869	10 s	933 783 0 ));
+DATA(insert (	4049	869	869	11 s	931 783 0 ));
+DATA(insert (	4049	869	869	16 s	1203 783 0 ));
+DATA(insert (	4049	869	869	17 s	1204 783 0 ));
+DATA(insert (	4049	869	869	18 s	1201 783 0 ));
+DATA(insert (	4049	869	869	19 s	1206 783 0 ));
+DATA(insert (	4049	869	869	20 s	1205 783 0 ));
+
 #endif   /* PG_AMOP_H */
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
index 53a3a7a..1a7fc7a 100644
--- a/src/include/catalog/pg_amproc.h
+++ b/src/include/catalog/pg_amproc.h
@@ -356,6 +356,13 @@ DATA(insert (	3919   3831 3831 4 3878 ));
 DATA(insert (	3919   3831 3831 5 3879 ));
 DATA(insert (	3919   3831 3831 6 3880 ));
 DATA(insert (	3919   3831 3831 7 3881 ));
+DATA(insert (	4049   869  869  1 4042 ));
+DATA(insert (	4049   869  869  2 4043 ));
+DATA(insert (	4049   869  869  3 4044 ));
+DATA(insert (	4049   869  869  4 4045 ));
+DATA(insert (	4049   869  869  5 4046 ));
+DATA(insert (	4049   869  869  6 4047 ));
+DATA(insert (	4049   869  869  7 4048 ));
 
 
 /* sp-gist */
diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h
index 0a3eb3e..dbef182 100644
--- a/src/include/catalog/pg_opclass.h
+++ b/src/include/catalog/pg_opclass.h
@@ -112,6 +112,7 @@ DATA(insert OID = 3123 ( 403	float8_ops	PGNSP PGUID 1970  701 t 0 ));
 DATA(insert (	405		float8_ops			PGNSP PGUID 1971  701 t 0 ));
 DATA(insert (	403		inet_ops			PGNSP PGUID 1974  869 t 0 ));
 DATA(insert (	405		inet_ops			PGNSP PGUID 1975  869 t 0 ));
+DATA(insert (	783		inet_ops			PGNSP PGUID 4049  869 t 869 ));
 DATA(insert OID = 1979 ( 403	int2_ops	PGNSP PGUID 1976   21 t 0 ));
 #define INT2_BTREE_OPS_OID 1979
 DATA(insert (	405		int2_ops			PGNSP PGUID 1977   21 t 0 ));
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
index 78efaa5..7d9bdb7 100644
--- a/src/include/catalog/pg_operator.h
+++ b/src/include/catalog/pg_operator.h
@@ -1150,6 +1150,12 @@ DESCR("is supernet");
 DATA(insert OID = 934  (  ">>="    PGNSP PGUID b f f 869 869	 16 932		0 network_supeq - - ));
 DESCR("is supernet or equal");
 #define OID_INET_SUPEQ_OP				934
+DATA(insert OID = 4050  (  "&&"    PGNSP PGUID b f f 869 869	 16 4050  4051 network_overlap - - ));
+DESCR("overlaps (is subnet or supernet)");
+#define OID_INET_OVERLAP_OP				4050
+DATA(insert OID = 4051  (  "-|-"   PGNSP PGUID b f f 869 869	 16 4051  4050 network_adjacent - - ));
+DESCR("is adjacent to");
+#define OID_INET_ADJACENT_OP			4051
 
 DATA(insert OID = 2634 (  "~"	   PGNSP PGUID l f f	  0 869 869 0 0 inetnot - - ));
 DESCR("bitwise not");
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
index 12ba456..e62b3f1 100644
--- a/src/include/catalog/pg_opfamily.h
+++ b/src/include/catalog/pg_opfamily.h
@@ -78,6 +78,7 @@ DATA(insert OID = 1971 (	405		float_ops		PGNSP PGUID ));
 DATA(insert OID = 1974 (	403		network_ops		PGNSP PGUID ));
 #define NETWORK_BTREE_FAM_OID 1974
 DATA(insert OID = 1975 (	405		network_ops		PGNSP PGUID ));
+DATA(insert OID = 4049 (	783		network_ops		PGNSP PGUID ));
 DATA(insert OID = 1976 (	403		integer_ops		PGNSP PGUID ));
 #define INTEGER_BTREE_FAM_OID 1976
 DATA(insert OID = 1977 (	405		integer_ops		PGNSP PGUID ));
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 0117500..623d010 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -2116,6 +2116,26 @@ DATA(insert OID = 927 (  network_sub		PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 1
 DATA(insert OID = 928 (  network_subeq		PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "869 869" _null_ _null_ _null_ _null_	network_subeq _null_ _null_ _null_ ));
 DATA(insert OID = 929 (  network_sup		PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "869 869" _null_ _null_ _null_ _null_	network_sup _null_ _null_ _null_ ));
 DATA(insert OID = 930 (  network_supeq		PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "869 869" _null_ _null_ _null_ _null_	network_supeq _null_ _null_ _null_ ));
+DATA(insert OID = 4040 (  network_overlap	PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "869 869" _null_ _null_ _null_ _null_	network_overlap	_null_ _null_ _null_ ));
+DATA(insert OID = 4041 (  network_adjacent  PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "869 869" _null_ _null_ _null_ _null_	network_adjacent _null_ _null_ _null_ ));
+
+/*
+ * GiST support for inet and cidr
+ */
+DATA(insert OID = 4042 (  inet_gist_consistent PGNSP PGUID 12 1 0 0 0 f f f f t f i 5 0 16 "2281 869 23 26 2281" _null_ _null_ _null_ _null_ inet_gist_consistent _null_ _null_ _null_ ));
+DESCR("GiST support");
+DATA(insert OID = 4043 (  inet_gist_union		PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ inet_gist_union _null_ _null_ _null_ ));
+DESCR("GiST support");
+DATA(insert OID = 4044 (  inet_gist_compress	PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ inet_gist_compress _null_ _null_ _null_ ));
+DESCR("GiST support");
+DATA(insert OID = 4045 (  inet_gist_decompress PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ inet_gist_decompress _null_ _null_ _null_ ));
+DESCR("GiST support");
+DATA(insert OID = 4046 (  inet_gist_penalty	PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 2281 "2281 2281 2281" _null_ _null_ _null_ _null_ inet_gist_penalty _null_ _null_ _null_ ));
+DESCR("GiST support");
+DATA(insert OID = 4047 (  inet_gist_picksplit	PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ inet_gist_picksplit _null_ _null_ _null_ ));
+DESCR("GiST support");
+DATA(insert OID = 4048 (  inet_gist_same		PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 2281 "869 869 2281" _null_ _null_ _null_ _null_ inet_gist_same _null_ _null_ _null_ ));
+DESCR("GiST support");
 
 /* inet/cidr functions */
 DATA(insert OID = 598 (  abbrev				PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 25 "869" _null_ _null_ _null_ _null_	inet_abbrev _null_ _null_ _null_ ));
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 1bfd145..dd0d355 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -887,6 +887,8 @@ extern Datum network_sub(PG_FUNCTION_ARGS);
 extern Datum network_subeq(PG_FUNCTION_ARGS);
 extern Datum network_sup(PG_FUNCTION_ARGS);
 extern Datum network_supeq(PG_FUNCTION_ARGS);
+extern Datum network_overlap(PG_FUNCTION_ARGS);
+extern Datum network_adjacent(PG_FUNCTION_ARGS);
 extern Datum network_network(PG_FUNCTION_ARGS);
 extern Datum network_netmask(PG_FUNCTION_ARGS);
 extern Datum network_hostmask(PG_FUNCTION_ARGS);
diff --git a/src/include/utils/inet.h b/src/include/utils/inet.h
index 3d8e31c..e7964bc 100644
--- a/src/include/utils/inet.h
+++ b/src/include/utils/inet.h
@@ -82,4 +82,67 @@ typedef struct macaddr
 #define PG_GETARG_MACADDR_P(n) DatumGetMacaddrP(PG_GETARG_DATUM(n))
 #define PG_RETURN_MACADDR_P(x) return MacaddrPGetDatum(x)
 
+/*
+ * Access macros
+ *
+ * We use VARDATA_ANY so that we can process short-header varlena values
+ * without detoasting them. This requires a trick: VARDATA_ANY assumes
+ * the varlena header is already filled in, which is not the case when
+ * constructing a new value (until SET_INET_VARSIZE is called, which we
+ * typically can't do till the end). Therefore, we always initialize
+ * the newly-allocated value to zeroes (using palloc0). A zero length
+ * word look like the not-1-byte case to VARDATA_ANY,  and so we correctly
+ * construct an uncompressed value.
+ *
+ * Note that ip_maxbits() and SET_INET_VARSIZE() require the family
+ * field to be set correctly.
+ */
+
+#define ip_family(inetptr) \
+	(((inet_struct *) VARDATA_ANY(inetptr))->family)
+
+#define ip_bits(inetptr) \
+	(((inet_struct *) VARDATA_ANY(inetptr))->bits)
+
+#define ip_addr(inetptr) \
+	(((inet_struct *) VARDATA_ANY(inetptr))->ipaddr)
+
+#define ip_maxbits(inetptr) \
+	(ip_family(inetptr) == PGSQL_AF_INET ? 32 : 128)
+
+#define SET_INET_VARSIZE(inetptr) \
+	SET_VARSIZE(inetptr, VARHDRSZ + offsetof(inet_struct, ipaddr) + \
+			(ip_family(inetptr) == PGSQL_AF_INET ? 4 : 16))
+
+/*
+ * Operator strategy numbers used in the GiST network opclass
+ */
+#define INETSTRAT_SUB			11
+#define INETSTRAT_SUBEQ			8
+#define INETSTRAT_OVERLAPS		3
+#define INETSTRAT_SUPEQ			7
+#define INETSTRAT_SUP			10
+#define INETSTRAT_LT			16
+#define INETSTRAT_LE			17
+#define INETSTRAT_EQ			18
+#define INETSTRAT_GE			19
+#define INETSTRAT_GT			20
+
+/*
+ * Static functions in network.c
+ */
+extern int		bitncmp(void *l, void *r, int n);
+extern int		bitncommon(unsigned char *l, unsigned char *r, int n);
+
+/*
+ * GiST support functions in network_gist.c
+ */
+extern Datum	inet_gist_consistent(PG_FUNCTION_ARGS);
+extern Datum	inet_gist_compress(PG_FUNCTION_ARGS);
+extern Datum	inet_gist_decompress(PG_FUNCTION_ARGS);
+extern Datum	inet_gist_union(PG_FUNCTION_ARGS);
+extern Datum	inet_gist_penalty(PG_FUNCTION_ARGS);
+extern Datum	inet_gist_picksplit(PG_FUNCTION_ARGS);
+extern Datum	inet_gist_same(PG_FUNCTION_ARGS);
+
 #endif   /* INET_H */
diff --git a/src/test/regress/expected/inet.out b/src/test/regress/expected/inet.out
index 356a397..d9fef4e 100644
--- a/src/test/regress/expected/inet.out
+++ b/src/test/regress/expected/inet.out
@@ -180,27 +180,28 @@ SELECT '' AS ten, i, c,
   i < c AS lt, i <= c AS le, i = c AS eq,
   i >= c AS ge, i > c AS gt, i <> c AS ne,
   i << c AS sb, i <<= c AS sbe,
-  i >> c AS sup, i >>= c AS spe
+  i >> c AS sup, i >>= c AS spe,
+  i && c AS ovr, i -|- c AS adj
   FROM INET_TBL;
- ten |        i         |         c          | lt | le | eq | ge | gt | ne | sb | sbe | sup | spe 
------+------------------+--------------------+----+----+----+----+----+----+----+-----+-----+-----
-     | 192.168.1.226/24 | 192.168.1.0/24     | f  | f  | f  | t  | t  | t  | f  | t   | f   | t
-     | 192.168.1.226    | 192.168.1.0/26     | f  | f  | f  | t  | t  | t  | f  | f   | f   | f
-     | 192.168.1.0/24   | 192.168.1.0/24     | f  | t  | t  | t  | f  | f  | f  | t   | f   | t
-     | 192.168.1.0/25   | 192.168.1.0/24     | f  | f  | f  | t  | t  | t  | t  | t   | f   | f
-     | 192.168.1.255/24 | 192.168.1.0/24     | f  | f  | f  | t  | t  | t  | f  | t   | f   | t
-     | 192.168.1.255/25 | 192.168.1.0/24     | f  | f  | f  | t  | t  | t  | t  | t   | f   | f
-     | 10.1.2.3/8       | 10.0.0.0/8         | f  | f  | f  | t  | t  | t  | f  | t   | f   | t
-     | 10.1.2.3/8       | 10.0.0.0/32        | t  | t  | f  | f  | f  | t  | f  | f   | t   | t
-     | 10.1.2.3         | 10.1.2.3/32        | f  | t  | t  | t  | f  | f  | f  | t   | f   | t
-     | 10.1.2.3/24      | 10.1.2.0/24        | f  | f  | f  | t  | t  | t  | f  | t   | f   | t
-     | 10.1.2.3/16      | 10.1.0.0/16        | f  | f  | f  | t  | t  | t  | f  | t   | f   | t
-     | 10.1.2.3/8       | 10.0.0.0/8         | f  | f  | f  | t  | t  | t  | f  | t   | f   | t
-     | 11.1.2.3/8       | 10.0.0.0/8         | f  | f  | f  | t  | t  | t  | f  | f   | f   | f
-     | 9.1.2.3/8        | 10.0.0.0/8         | t  | t  | f  | f  | f  | t  | f  | f   | f   | f
-     | 10:23::f1/64     | 10:23::f1/128      | t  | t  | f  | f  | f  | t  | f  | f   | t   | t
-     | 10:23::ffff      | 10:23::8000/113    | f  | f  | f  | t  | t  | t  | t  | t   | f   | f
-     | ::4.3.2.1/24     | ::ffff:1.2.3.4/128 | t  | t  | f  | f  | f  | t  | f  | f   | t   | t
+ ten |        i         |         c          | lt | le | eq | ge | gt | ne | sb | sbe | sup | spe | ovr | adj 
+-----+------------------+--------------------+----+----+----+----+----+----+----+-----+-----+-----+-----+-----
+     | 192.168.1.226/24 | 192.168.1.0/24     | f  | f  | f  | t  | t  | t  | f  | t   | f   | t   | t   | f
+     | 192.168.1.226    | 192.168.1.0/26     | f  | f  | f  | t  | t  | t  | f  | f   | f   | f   | f   | t
+     | 192.168.1.0/24   | 192.168.1.0/24     | f  | t  | t  | t  | f  | f  | f  | t   | f   | t   | t   | f
+     | 192.168.1.0/25   | 192.168.1.0/24     | f  | f  | f  | t  | t  | t  | t  | t   | f   | f   | t   | f
+     | 192.168.1.255/24 | 192.168.1.0/24     | f  | f  | f  | t  | t  | t  | f  | t   | f   | t   | t   | f
+     | 192.168.1.255/25 | 192.168.1.0/24     | f  | f  | f  | t  | t  | t  | t  | t   | f   | f   | t   | f
+     | 10.1.2.3/8       | 10.0.0.0/8         | f  | f  | f  | t  | t  | t  | f  | t   | f   | t   | t   | f
+     | 10.1.2.3/8       | 10.0.0.0/32        | t  | t  | f  | f  | f  | t  | f  | f   | t   | t   | t   | f
+     | 10.1.2.3         | 10.1.2.3/32        | f  | t  | t  | t  | f  | f  | f  | t   | f   | t   | t   | f
+     | 10.1.2.3/24      | 10.1.2.0/24        | f  | f  | f  | t  | t  | t  | f  | t   | f   | t   | t   | f
+     | 10.1.2.3/16      | 10.1.0.0/16        | f  | f  | f  | t  | t  | t  | f  | t   | f   | t   | t   | f
+     | 10.1.2.3/8       | 10.0.0.0/8         | f  | f  | f  | t  | t  | t  | f  | t   | f   | t   | t   | f
+     | 11.1.2.3/8       | 10.0.0.0/8         | f  | f  | f  | t  | t  | t  | f  | f   | f   | f   | f   | t
+     | 9.1.2.3/8        | 10.0.0.0/8         | t  | t  | f  | f  | f  | t  | f  | f   | f   | f   | f   | t
+     | 10:23::f1/64     | 10:23::f1/128      | t  | t  | f  | f  | f  | t  | f  | f   | t   | t   | t   | f
+     | 10:23::ffff      | 10:23::8000/113    | f  | f  | f  | t  | t  | t  | t  | t   | f   | f   | t   | f
+     | ::4.3.2.1/24     | ::ffff:1.2.3.4/128 | t  | t  | f  | f  | f  | t  | f  | f   | t   | t   | t   | f
 (17 rows)
 
 -- check the conversion to/from text and set_netmask
@@ -226,7 +227,7 @@ SELECT '' AS ten, set_masklen(inet(text(i)), 24) FROM INET_TBL;
      | ::4.3.2.1/24
 (17 rows)
 
--- check that index works correctly
+-- check that btree index works correctly
 CREATE INDEX inet_idx1 ON inet_tbl(i);
 SET enable_seqscan TO off;
 SELECT * FROM inet_tbl WHERE i<<'192.168.1.0/24'::cidr;
@@ -250,6 +251,114 @@ SELECT * FROM inet_tbl WHERE i<<='192.168.1.0/24'::cidr;
 
 SET enable_seqscan TO on;
 DROP INDEX inet_idx1;
+-- check that gist index works correctly
+CREATE INDEX inet_idx2 ON inet_tbl using gist (i);
+SET enable_seqscan TO off;
+SELECT * FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i;
+       c        |        i         
+----------------+------------------
+ 192.168.1.0/24 | 192.168.1.0/25
+ 192.168.1.0/24 | 192.168.1.255/25
+ 192.168.1.0/26 | 192.168.1.226
+(3 rows)
+
+SELECT * FROM inet_tbl WHERE i <<= '192.168.1.0/24'::cidr ORDER BY i;
+       c        |        i         
+----------------+------------------
+ 192.168.1.0/24 | 192.168.1.0/24
+ 192.168.1.0/24 | 192.168.1.226/24
+ 192.168.1.0/24 | 192.168.1.255/24
+ 192.168.1.0/24 | 192.168.1.0/25
+ 192.168.1.0/24 | 192.168.1.255/25
+ 192.168.1.0/26 | 192.168.1.226
+(6 rows)
+
+SELECT * FROM inet_tbl WHERE i && '192.168.1.0/24'::cidr ORDER BY i;
+       c        |        i         
+----------------+------------------
+ 192.168.1.0/24 | 192.168.1.0/24
+ 192.168.1.0/24 | 192.168.1.226/24
+ 192.168.1.0/24 | 192.168.1.255/24
+ 192.168.1.0/24 | 192.168.1.0/25
+ 192.168.1.0/24 | 192.168.1.255/25
+ 192.168.1.0/26 | 192.168.1.226
+(6 rows)
+
+SELECT * FROM inet_tbl WHERE i >>= '192.168.1.0/24'::cidr ORDER BY i;
+       c        |        i         
+----------------+------------------
+ 192.168.1.0/24 | 192.168.1.0/24
+ 192.168.1.0/24 | 192.168.1.226/24
+ 192.168.1.0/24 | 192.168.1.255/24
+(3 rows)
+
+SELECT * FROM inet_tbl WHERE i >> '192.168.1.0/24'::cidr ORDER BY i;
+ c | i 
+---+---
+(0 rows)
+
+SELECT * FROM inet_tbl WHERE i < '192.168.1.0/24'::cidr ORDER BY i;
+      c      |      i      
+-------------+-------------
+ 10.0.0.0/8  | 9.1.2.3/8
+ 10.0.0.0/32 | 10.1.2.3/8
+ 10.0.0.0/8  | 10.1.2.3/8
+ 10.0.0.0/8  | 10.1.2.3/8
+ 10.1.0.0/16 | 10.1.2.3/16
+ 10.1.2.0/24 | 10.1.2.3/24
+ 10.1.2.3/32 | 10.1.2.3
+ 10.0.0.0/8  | 11.1.2.3/8
+(8 rows)
+
+SELECT * FROM inet_tbl WHERE i <= '192.168.1.0/24'::cidr ORDER BY i;
+       c        |       i        
+----------------+----------------
+ 10.0.0.0/8     | 9.1.2.3/8
+ 10.0.0.0/8     | 10.1.2.3/8
+ 10.0.0.0/32    | 10.1.2.3/8
+ 10.0.0.0/8     | 10.1.2.3/8
+ 10.1.0.0/16    | 10.1.2.3/16
+ 10.1.2.0/24    | 10.1.2.3/24
+ 10.1.2.3/32    | 10.1.2.3
+ 10.0.0.0/8     | 11.1.2.3/8
+ 192.168.1.0/24 | 192.168.1.0/24
+(9 rows)
+
+SELECT * FROM inet_tbl WHERE i = '192.168.1.0/24'::cidr ORDER BY i;
+       c        |       i        
+----------------+----------------
+ 192.168.1.0/24 | 192.168.1.0/24
+(1 row)
+
+SELECT * FROM inet_tbl WHERE i >= '192.168.1.0/24'::cidr ORDER BY i;
+         c          |        i         
+--------------------+------------------
+ 192.168.1.0/24     | 192.168.1.0/24
+ 192.168.1.0/24     | 192.168.1.226/24
+ 192.168.1.0/24     | 192.168.1.255/24
+ 192.168.1.0/24     | 192.168.1.0/25
+ 192.168.1.0/24     | 192.168.1.255/25
+ 192.168.1.0/26     | 192.168.1.226
+ ::ffff:1.2.3.4/128 | ::4.3.2.1/24
+ 10:23::f1/128      | 10:23::f1/64
+ 10:23::8000/113    | 10:23::ffff
+(9 rows)
+
+SELECT * FROM inet_tbl WHERE i > '192.168.1.0/24'::cidr ORDER BY i;
+         c          |        i         
+--------------------+------------------
+ 192.168.1.0/24     | 192.168.1.226/24
+ 192.168.1.0/24     | 192.168.1.255/24
+ 192.168.1.0/24     | 192.168.1.0/25
+ 192.168.1.0/24     | 192.168.1.255/25
+ 192.168.1.0/26     | 192.168.1.226
+ ::ffff:1.2.3.4/128 | ::4.3.2.1/24
+ 10:23::f1/128      | 10:23::f1/64
+ 10:23::8000/113    | 10:23::ffff
+(8 rows)
+
+SET enable_seqscan TO on;
+DROP INDEX inet_idx2;
 -- simple tests of inet boolean and arithmetic operators
 SELECT i, ~i AS "~i" FROM inet_tbl;
         i         |                     ~i                     
diff --git a/src/test/regress/sql/inet.sql b/src/test/regress/sql/inet.sql
index 328f149..b88f95b 100644
--- a/src/test/regress/sql/inet.sql
+++ b/src/test/regress/sql/inet.sql
@@ -52,12 +52,14 @@ SELECT '' AS ten, i, c,
   i < c AS lt, i <= c AS le, i = c AS eq,
   i >= c AS ge, i > c AS gt, i <> c AS ne,
   i << c AS sb, i <<= c AS sbe,
-  i >> c AS sup, i >>= c AS spe
+  i >> c AS sup, i >>= c AS spe,
+  i && c AS ovr, i -|- c AS adj
   FROM INET_TBL;
 
 -- check the conversion to/from text and set_netmask
 SELECT '' AS ten, set_masklen(inet(text(i)), 24) FROM INET_TBL;
--- check that index works correctly
+
+-- check that btree index works correctly
 CREATE INDEX inet_idx1 ON inet_tbl(i);
 SET enable_seqscan TO off;
 SELECT * FROM inet_tbl WHERE i<<'192.168.1.0/24'::cidr;
@@ -65,6 +67,22 @@ SELECT * FROM inet_tbl WHERE i<<='192.168.1.0/24'::cidr;
 SET enable_seqscan TO on;
 DROP INDEX inet_idx1;
 
+-- check that gist index works correctly
+CREATE INDEX inet_idx2 ON inet_tbl using gist (i);
+SET enable_seqscan TO off;
+SELECT * FROM inet_tbl WHERE i << '192.168.1.0/24'::cidr ORDER BY i;
+SELECT * FROM inet_tbl WHERE i <<= '192.168.1.0/24'::cidr ORDER BY i;
+SELECT * FROM inet_tbl WHERE i && '192.168.1.0/24'::cidr ORDER BY i;
+SELECT * FROM inet_tbl WHERE i >>= '192.168.1.0/24'::cidr ORDER BY i;
+SELECT * FROM inet_tbl WHERE i >> '192.168.1.0/24'::cidr ORDER BY i;
+SELECT * FROM inet_tbl WHERE i < '192.168.1.0/24'::cidr ORDER BY i;
+SELECT * FROM inet_tbl WHERE i <= '192.168.1.0/24'::cidr ORDER BY i;
+SELECT * FROM inet_tbl WHERE i = '192.168.1.0/24'::cidr ORDER BY i;
+SELECT * FROM inet_tbl WHERE i >= '192.168.1.0/24'::cidr ORDER BY i;
+SELECT * FROM inet_tbl WHERE i > '192.168.1.0/24'::cidr ORDER BY i;
+SET enable_seqscan TO on;
+DROP INDEX inet_idx2;
+
 -- simple tests of inet boolean and arithmetic operators
 SELECT i, ~i AS "~i" FROM inet_tbl;
 SELECT i, c, i & c AS "and" FROM inet_tbl;
