diff --git a/src/include/utils/pg_crc.h b/src/include/utils/pg_crc.h
index f871cba..916181e 100644
--- a/src/include/utils/pg_crc.h
+++ b/src/include/utils/pg_crc.h
@@ -51,7 +51,7 @@ typedef uint32 pg_crc32;
 #define INIT_CRC32C(crc) ((crc) = 0xFFFFFFFF)
 #define FIN_CRC32C(crc)	((crc) ^= 0xFFFFFFFF)
 #define COMP_CRC32C(crc, data, len)	\
-	COMP_CRC32_NORMAL_TABLE(crc, data, len, pg_crc32c_table)
+	((crc) = comp_crc32c((crc), (char *) (data), (len)))
 #define EQ_CRC32C(c1, c2) ((c1) == (c2))
 
 /*
@@ -118,4 +118,6 @@ do {															  \
 extern CRCDLLIMPORT const uint32 pg_crc32c_table[];
 extern CRCDLLIMPORT const uint32 pg_crc32_table[];
 
+extern pg_crc32 comp_crc32c(pg_crc32 crc, const char *data, uint32 len);
+
 #endif   /* PG_CRC_H */
diff --git a/src/include/utils/pg_crc_tables.h b/src/include/utils/pg_crc_tables.h
index cb6b470..0016716 100644
--- a/src/include/utils/pg_crc_tables.h
+++ b/src/include/utils/pg_crc_tables.h
@@ -95,6 +95,34 @@ const uint32 pg_crc32c_table[256] = {
 	0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
 };
 
+uint32
+comp_crc32c(uint32 crc, const char *data, uint32 len)
+{
+	const unsigned char *__data = (const unsigned char *) (data);
+
+	/* Process byte at a time until the data address is aligned */
+	while ((((uintptr_t) __data) & 3) != 0 && len > 0)
+	{
+		crc = __builtin_ia32_crc32qi(crc, *__data++);
+		len--;
+	}
+
+	while (len >= 8)
+	{
+		crc = __builtin_ia32_crc32di(crc, *(uint64*)__data);
+		len -= 8;
+		__data += 8;
+	}
+
+	/* Process remainder, a byte at a time */
+	while (len > 0)
+	{
+		crc = __builtin_ia32_crc32qi(crc, *__data++);
+		len--;
+	}
+
+	return crc;
+}
 
 /*
  * This table is based on the polynomial
diff --git a/src/port/pg_crc.c b/src/port/pg_crc.c
index ac6f6ff..4dd8cb0 100644
--- a/src/port/pg_crc.c
+++ b/src/port/pg_crc.c
@@ -18,4 +18,5 @@
 
 #include "c.h"
 
+#include "utils/pg_crc.h"
 #include "utils/pg_crc_tables.h"
