diff --git a/gcc/config/rs6000/rs6000-builtins.def b/gcc/config/rs6000/rs6000-builtins.def
index f76f54793d73..11050e4c26d5 100644
--- a/gcc/config/rs6000/rs6000-builtins.def
+++ b/gcc/config/rs6000/rs6000-builtins.def
@@ -2010,12 +2010,13 @@
     XXSPLTD_V2DI vsx_xxspltd_v2di {}
 
 
 ; Power7 builtins (ISA 2.06).
 [power7]
-  const unsigned int __builtin_addg6s (unsigned int, unsigned int);
-    ADDG6S addg6s {}
+
+  const unsigned int __builtin_addg6s_32 (unsigned int, unsigned int);
+    ADDG6S_32 addg6ssi3 {}
 
   const signed long __builtin_bpermd (signed long, signed long);
     BPERMD bpermd_di {32bit}
 
   const unsigned int __builtin_cbcdtd (unsigned int);
@@ -2041,10 +2042,14 @@
     UNPACK_V1TI unpackv1ti {}
 
 
 ; Power7 builtins requiring 64-bit GPRs (even with 32-bit addressing).
 [power7-64]
+
+  const unsigned long __builtin_addg6s_64 (unsigned long, unsigned long);
+    ADDG6S addg6sdi3 {no32bit}
+
   const signed long long __builtin_divde (signed long long, signed long long);
     DIVDE dive_di {}
 
   const unsigned long long __builtin_divdeu (unsigned long long, \
                                              unsigned long long);
diff --git a/gcc/config/rs6000/rs6000-c.cc b/gcc/config/rs6000/rs6000-c.cc
index 566094626293..28e8b6761ce5 100644
--- a/gcc/config/rs6000/rs6000-c.cc
+++ b/gcc/config/rs6000/rs6000-c.cc
@@ -1919,10 +1919,35 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl,
 				   instance_code, fcode, types, args);
 	if (call != error_mark_node)
 	  return call;
 	break;
       }
+      /* We need to special case __builtin_addg6s because the overloaded
+	 forms of this function take (unsigned int, unsigned int) or
+	 (unsigned long long, unsigned long long).  Since C conventions
+	 allow the respective argument types to be implicitly coerced into
+	 each other, the default handling does not provide adequate
+	 discrimination between the desired forms of the function.  */
+    case RS6000_OVLD_ADDG6S_OV:
+      {
+	machine_mode arg1_mode = TYPE_MODE (types[0]);
+	machine_mode arg2_mode = TYPE_MODE (types[1]);
+
+	/* If any supplied arguments are wider than 32 bits, resolve to
+	   64-bit variant of built-in function.  */
+	if (GET_MODE_PRECISION (arg1_mode) > 32
+	    || GET_MODE_PRECISION (arg2_mode) > 32)
+	  instance_code = RS6000_BIF_ADDG6S;
+	else
+	  instance_code = RS6000_BIF_ADDG6S_32;
+
+	tree call = find_instance (&unsupported_builtin, &instance,
+				   instance_code, fcode, types, args);
+	if (call != error_mark_node)
+	  return call;
+	break;
+      }
     case RS6000_OVLD_VEC_VSIE:
       {
 	machine_mode arg1_mode = TYPE_MODE (types[0]);
 
 	/* If supplied first argument is wider than 64 bits, resolve to
diff --git a/gcc/config/rs6000/rs6000-overload.def b/gcc/config/rs6000/rs6000-overload.def
index 44e2945aaa0e..41b74c0c1500 100644
--- a/gcc/config/rs6000/rs6000-overload.def
+++ b/gcc/config/rs6000/rs6000-overload.def
@@ -193,10 +193,16 @@
   unsigned int __builtin_cmpb (unsigned int, unsigned int);
     CMPB_32
   unsigned long long __builtin_cmpb (unsigned long long, unsigned long long);
     CMPB
 
+[ADDG6S_OV, SKIP, __builtin_addg6s]
+  unsigned int __builtin_addg6s (unsigned int, unsigned int);
+    ADDG6S_32
+  unsigned long long __builtin_addg6s (unsigned long long, unsigned long long);
+    ADDG6S
+
 [VEC_ABS, vec_abs, __builtin_vec_abs]
   vsc __builtin_vec_abs (vsc);
     ABS_V16QI
   vss __builtin_vec_abs (vss);
     ABS_V8HI
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index ad5a4cf2ef83..b172ffd097ab 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -14534,14 +14534,14 @@ (define_peephole2
   operands[5] = change_address (mem, <ALTIVEC_DFORM:MODE>mode, new_addr);
 })
    
 
 ;; Miscellaneous ISA 2.06 (power7) instructions
-(define_insn "addg6s"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-	(unspec:SI [(match_operand:SI 1 "register_operand" "r")
-		    (match_operand:SI 2 "register_operand" "r")]
+(define_insn "addg6s<mode>3"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+	(unspec:GPR [(match_operand:GPR 1 "register_operand" "r")
+		    (match_operand:GPR 2 "register_operand" "r")]
 		   UNSPEC_ADDG6S))]
   "TARGET_POPCNTD"
   "addg6s %0,%1,%2"
   [(set_attr "type" "integer")])
 
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index a5afb467d235..d393062e790f 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -18139,10 +18139,11 @@ addition to the @option{-maltivec}, @option{-mpopcntd}, and
 @option{-mvsx} options.
 
 The following basic built-in functions require @option{-mpopcntd}:
 @smallexample
 unsigned int __builtin_addg6s (unsigned int, unsigned int);
+unsigned long long __builtin_addg6s (unsigned long long, unsigned long long);
 long long __builtin_bpermd (long long, long long);
 unsigned int __builtin_cbcdtd (unsigned int);
 unsigned int __builtin_cdtbcd (unsigned int);
 long long __builtin_divde (long long, long long);
 unsigned long long __builtin_divdeu (unsigned long long, unsigned long long);
diff --git a/gcc/testsuite/gcc.target/powerpc/pr100693-compile.c b/gcc/testsuite/gcc.target/powerpc/pr100693-compile.c
new file mode 100644
index 000000000000..113936a3d9f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr100693-compile.c
@@ -0,0 +1,30 @@
+/* { dg-do compile { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mdejagnu-cpu=power7 -O3" } */
+/* { dg-final { scan-assembler-times {\maddg6s\M} 4 } } */
+/* { dg-final { scan-assembler-not    "bl __builtin" } } */
+
+/* Test case for the addg6s builtin, exercising both
+   unsigned int and unsigned long long arguments. */
+
+unsigned long long test2_ull (unsigned long long a, unsigned long long b)
+{
+    return __builtin_addg6s (a, b);
+}
+
+unsigned int test1_ui (unsigned int a, unsigned int b)
+{
+    return __builtin_addg6s (a, b);
+}
+
+unsigned int test3_ui (unsigned int *a, unsigned int *b)
+{
+	return __builtin_addg6s(*a, *b);
+}
+
+unsigned long long test4_ull (unsigned long long *a, unsigned long long *b)
+{
+	return __builtin_addg6s(*a, *b);
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/pr100693-run.c b/gcc/testsuite/gcc.target/powerpc/pr100693-run.c
new file mode 100644
index 000000000000..3694010b10ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr100693-run.c
@@ -0,0 +1,78 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mdejagnu-cpu=power7 -O3" } */
+
+/* Test case for the addg6s builtin, exercising both
+   unsigned int and unsigned long long arguments.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+unsigned int test_addg6s_int (unsigned int a, unsigned int b)
+{
+    return __builtin_addg6s (a, b);
+}
+
+unsigned long long test_addg6s_longlong (unsigned long long a, unsigned long long b)
+{
+    return __builtin_addg6s (a, b);
+}
+
+/* Table of expected values.  */
+
+unsigned int exp_i[] = {
+0x66666660,
+0x66666606,
+0x66666066,
+0x66660666,
+0x66606666,
+0x66066666,
+0x60666666,
+0x06666666,
+0x77777777
+};
+
+unsigned long long exp_ll[] = {
+0x6666666666666660,
+0x6666666666666606,
+0x6666666666666066,
+0x6666666666660666,
+0x6666666666606666,
+0x6666666666066666,
+0x6666666660666666,
+0x6666666606666666,
+0x6666666066666666,
+0x6666660666666666,
+0x6666606666666666,
+0x6666066666666666,
+0x6660666666666666, 
+0x6606666666666666, 
+0x6066666666666666, 
+0x0666666666666666, 
+0x7777777777777777
+};
+
+int main() {
+	unsigned int intresult;
+	unsigned long long longresult;
+	int idx;
+	int fail=0;
+
+	for (idx=0; idx<8; idx++) {
+	   intresult = test_addg6s_int (0x01<<4*idx, 0x0f<<4*idx);
+	   if (exp_i[idx] != intresult)
+	      printf("index:%2d Got:%8x Expected:%8x %d\n",
+			idx, intresult, exp_i[idx], ++fail);
+	}
+
+	for (idx=0; idx<16; idx++) {
+	   longresult = test_addg6s_longlong (0x01ULL<<4*idx, 0x0fULL<<4*idx);
+	   if (exp_ll[idx] != longresult)
+	      printf("index:%2d Got:%16llx Expected:%16llx %d\n",
+			idx, longresult, exp_ll[idx], ++fail);
+	}
+	if (fail)
+		abort();
+}
+
