diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c
index 9136910cd324a391de929ea9d1a13419dbcfb8bc..20679a5d3f6138f4c55b84f3aff5dfd0341e6787 100644
--- a/gcc/config/aarch64/aarch64-builtins.c
+++ b/gcc/config/aarch64/aarch64-builtins.c
@@ -353,6 +353,11 @@ enum aarch64_builtins
   AARCH64_CRC32_BUILTIN_BASE,
   AARCH64_CRC32_BUILTINS
   AARCH64_CRC32_BUILTIN_MAX,
+  /* ARMv8.3-A Pointer Authentication Builtins.  */
+  AARCH64_PAUTH_BUILTIN_AUTIA1716,
+  AARCH64_PAUTH_BUILTIN_AUTIB1716,
+  AARCH64_PAUTH_BUILTIN_XPACLRI,
+  AARCH64_PAUTH_BUILTIN_PACI1716,
   AARCH64_BUILTIN_MAX
 };
 
@@ -900,6 +905,37 @@ aarch64_init_fp16_types (void)
   aarch64_fp16_ptr_type_node = build_pointer_type (aarch64_fp16_type_node);
 }
 
+/* Pointer authentication builtins that will become NOP on legacy platform.
+   Currently, these builtins are for internal use only (libgcc EH unwinder).  */
+
+void
+aarch64_init_pauth_hint_builtins (void)
+{
+  /* Pointer Authentication builtins.  */
+  tree ftype_pointer_auth
+    = build_function_type_list (ptr_type_node, ptr_type_node,
+				unsigned_intDI_type_node, NULL_TREE);
+  tree ftype_pointer_strip
+    = build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE);
+
+  aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIA1716]
+    = add_builtin_function ("__builtin_aarch64_autia1716", ftype_pointer_auth,
+			    AARCH64_PAUTH_BUILTIN_AUTIA1716, BUILT_IN_MD, NULL,
+			    NULL_TREE);
+  aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_AUTIB1716]
+    = add_builtin_function ("__builtin_aarch64_autib1716", ftype_pointer_auth,
+			    AARCH64_PAUTH_BUILTIN_AUTIB1716, BUILT_IN_MD, NULL,
+			    NULL_TREE);
+  aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_XPACLRI]
+    = add_builtin_function ("__builtin_aarch64_xpaclri", ftype_pointer_strip,
+			    AARCH64_PAUTH_BUILTIN_XPACLRI, BUILT_IN_MD, NULL,
+			    NULL_TREE);
+  aarch64_builtin_decls[AARCH64_PAUTH_BUILTIN_PACI1716]
+    = add_builtin_function ("__builtin_aarch64_paci1716", ftype_pointer_auth,
+			    AARCH64_PAUTH_BUILTIN_PACI1716, BUILT_IN_MD, NULL,
+			    NULL_TREE);
+}
+
 void
 aarch64_init_builtins (void)
 {
@@ -928,6 +964,10 @@ aarch64_init_builtins (void)
 
   aarch64_init_crc32_builtins ();
   aarch64_init_builtin_rsqrt ();
+
+/* Initialize pointer authentication builtins which are backed by instructions
+   in NOP encoding space.  */
+  aarch64_init_pauth_hint_builtins ();
 }
 
 tree
@@ -1270,6 +1310,76 @@ aarch64_expand_builtin (tree exp,
 	}
       emit_insn (pat);
       return target;
+    case AARCH64_PAUTH_BUILTIN_AUTIA1716:
+    case AARCH64_PAUTH_BUILTIN_AUTIB1716:
+    case AARCH64_PAUTH_BUILTIN_PACI1716:
+    case AARCH64_PAUTH_BUILTIN_XPACLRI:
+      arg0 = CALL_EXPR_ARG (exp, 0);
+      op0 = force_reg (Pmode, expand_normal (arg0));
+
+      if (!target)
+	target = gen_reg_rtx (Pmode);
+      else
+	target = force_reg (Pmode, target);
+
+      emit_move_insn (target, op0);
+
+      if (fcode == AARCH64_PAUTH_BUILTIN_XPACLRI)
+	{
+	  rtx lr_reg = gen_rtx_REG (Pmode, R30_REGNUM);
+	  icode = CODE_FOR_strip_lr_sign;
+	  emit_move_insn (lr_reg, op0);
+	  emit_insn (GEN_FCN (icode) (const0_rtx));
+	  emit_move_insn (target, lr_reg);
+	}
+      else
+	{
+	  tree arg1 = CALL_EXPR_ARG (exp, 1);
+	  rtx op1 = expand_normal (arg1);
+	  bool sign_op_p = (fcode == AARCH64_PAUTH_BUILTIN_PACI1716);
+
+	  bool x1716_op_p = (fcode == AARCH64_PAUTH_BUILTIN_AUTIA1716
+			     || fcode == AARCH64_PAUTH_BUILTIN_AUTIB1716
+			     || fcode == AARCH64_PAUTH_BUILTIN_PACI1716);
+
+	  bool a_key_p = (fcode == AARCH64_PAUTH_BUILTIN_AUTIA1716
+			  || (aarch64_pauth_key == AARCH64_PAUTH_IKEY_A
+			      && fcode == AARCH64_PAUTH_BUILTIN_PACI1716));
+	  HOST_WIDE_INT key_index =
+	    a_key_p ? AARCH64_PAUTH_IKEY_A : AARCH64_PAUTH_IKEY_B;
+
+	  if (sign_op_p)
+	    {
+	      if (x1716_op_p)
+		icode = CODE_FOR_sign_reg1716;
+	      else
+		icode = CODE_FOR_sign_reg;
+	    }
+	  else
+	    {
+	      if (x1716_op_p)
+		icode = CODE_FOR_auth_reg1716;
+	      else
+		icode = CODE_FOR_auth_reg;;
+	    }
+
+	  op1 = force_reg (Pmode, op1);
+
+	  if (x1716_op_p)
+	    {
+	      rtx x16_reg = gen_rtx_REG (Pmode, R16_REGNUM);
+	      rtx x17_reg = gen_rtx_REG (Pmode, R17_REGNUM);
+	      emit_move_insn (x17_reg, op0);
+	      emit_move_insn (x16_reg, op1);
+	      emit_insn (GEN_FCN (icode) (GEN_INT (key_index), const0_rtx));
+	      emit_move_insn (target, x17_reg);
+	    }
+	  else
+	    emit_insn (GEN_FCN (icode) (target, target, op1,
+					GEN_INT (key_index), const0_rtx));
+	}
+
+      return target;
     }
 
   if (fcode >= AARCH64_SIMD_BUILTIN_BASE && fcode <= AARCH64_SIMD_BUILTIN_MAX)

