[clang] [llvm] [PowerPC] Add AES Builtins (PR #186895)

Lei Huang via cfe-commits cfe-commits at lists.llvm.org
Tue May 5 10:05:24 PDT 2026


https://github.com/lei137 updated https://github.com/llvm/llvm-project/pull/186895

>From 8e534f1b341e5be3244f97c1e68564b890ed6381 Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Tue, 3 Mar 2026 15:45:59 -0500
Subject: [PATCH 1/3] Implement builtins for aes builtins

---
 clang/include/clang/Basic/BuiltinsPPC.def     |  38 +++
 clang/lib/CodeGen/TargetBuiltins/PPC.cpp      |  92 ++++--
 .../PowerPC/builtins-aes-acceleration.c       | 205 ++++++++++++++
 .../PowerPC/builtins-aes-acceleration-error.c | 263 ++++++++++++++++++
 llvm/include/llvm/IR/IntrinsicsPowerPC.td     |  21 ++
 llvm/lib/Target/PowerPC/PPCInstrFuture.td     |  34 ++-
 .../PowerPC/builtins-ppc-aes-acceleration.ll  | 174 ++++++++++++
 7 files changed, 802 insertions(+), 25 deletions(-)
 create mode 100644 clang/test/CodeGen/PowerPC/builtins-aes-acceleration.c
 create mode 100644 clang/test/Sema/PowerPC/builtins-aes-acceleration-error.c
 create mode 100644 llvm/test/CodeGen/PowerPC/builtins-ppc-aes-acceleration.ll

diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def
index 8c3d0179d991a..0cb48c6d4fe93 100644
--- a/clang/include/clang/Basic/BuiltinsPPC.def
+++ b/clang/include/clang/Basic/BuiltinsPPC.def
@@ -1237,6 +1237,44 @@ TARGET_BUILTIN(__builtin_altivec_vupkint4tofp32, "V16UcV16UcIi", "",
 TARGET_BUILTIN(__builtin_altivec_vupkint8tofp32, "V16UcV16UcIi", "",
                "isa-future-instructions")
 
+// AES Encrypt Paired builtins
+UNALIASED_CUSTOM_BUILTIN(aes_encrypt_paired, "W256W256W256i2", false,
+                         "future-vector,paired-vector-memops")
+CUSTOM_BUILTIN(aes128_encrypt_paired, aes_encrypt_paired, "W256W256W256", false,
+               "future-vector,paired-vector-memops")
+CUSTOM_BUILTIN(aes192_encrypt_paired, aes_encrypt_paired, "W256W256W256", false,
+               "future-vector,paired-vector-memops")
+CUSTOM_BUILTIN(aes256_encrypt_paired, aes_encrypt_paired, "W256W256W256", false,
+               "future-vector,paired-vector-memops")
+
+// AES Decrypt Paired builtins
+UNALIASED_CUSTOM_BUILTIN(aes_decrypt_paired, "W256W256W256i2", false,
+                         "future-vector,paired-vector-memops")
+CUSTOM_BUILTIN(aes128_decrypt_paired, aes_decrypt_paired, "W256W256W256", false,
+               "future-vector,paired-vector-memops")
+CUSTOM_BUILTIN(aes192_decrypt_paired, aes_decrypt_paired, "W256W256W256", false,
+               "future-vector,paired-vector-memops")
+CUSTOM_BUILTIN(aes256_decrypt_paired, aes_decrypt_paired, "W256W256W256", false,
+               "future-vector,paired-vector-memops")
+
+// AES Generate Last Key Paired builtins
+UNALIASED_CUSTOM_BUILTIN(aes_genlastkey_paired, "W256W256i2", false,
+                         "future-vector,paired-vector-memops")
+CUSTOM_BUILTIN(aes128_genlastkey_paired, aes_genlastkey_paired, "W256W256", false,
+               "future-vector,paired-vector-memops")
+CUSTOM_BUILTIN(aes192_genlastkey_paired, aes_genlastkey_paired, "W256W256", false,
+               "future-vector,paired-vector-memops")
+CUSTOM_BUILTIN(aes256_genlastkey_paired, aes_genlastkey_paired, "W256W256", false,
+               "future-vector,paired-vector-memops")
+
+// Galois Field Multiplication builtins
+UNALIASED_CUSTOM_BUILTIN(galois_field_mult, "VVVi1", false,
+                         "future-vector")
+CUSTOM_BUILTIN(galois_field_mult_gcm, galois_field_mult, "VVV", false,
+               "future-vector")
+CUSTOM_BUILTIN(galois_field_mult_xts, galois_field_mult, "VVV", false,
+               "future-vector")
+
 // FIXME: Obviously incomplete.
 
 #undef BUILTIN
diff --git a/clang/lib/CodeGen/TargetBuiltins/PPC.cpp b/clang/lib/CodeGen/TargetBuiltins/PPC.cpp
index 796efb7a8ad18..f75458e13e5d1 100644
--- a/clang/lib/CodeGen/TargetBuiltins/PPC.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/PPC.cpp
@@ -1138,20 +1138,84 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
       break;
   #include "clang/Basic/BuiltinsPPC.def"
     }
-    if (BuiltinID == PPC::BI__builtin_vsx_lxvp ||
-        BuiltinID == PPC::BI__builtin_vsx_stxvp ||
-        BuiltinID == PPC::BI__builtin_mma_lxvp ||
-        BuiltinID == PPC::BI__builtin_mma_stxvp) {
-      if (BuiltinID == PPC::BI__builtin_vsx_lxvp ||
-          BuiltinID == PPC::BI__builtin_mma_lxvp) {
-        Ops[0] = Builder.CreateGEP(Int8Ty, Ops[1], Ops[0]);
-      } else {
-        Ops[1] = Builder.CreateGEP(Int8Ty, Ops[2], Ops[1]);
-      }
+    // Handle Accumulate=false custom builtins that returns directly.
+    switch (BuiltinID) {
+    case PPC::BI__builtin_vsx_lxvp:
+    case PPC::BI__builtin_mma_lxvp:
+      Ops[0] = Builder.CreateGEP(Int8Ty, Ops[1], Ops[0]);
+      Ops.pop_back();
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+    case PPC::BI__builtin_vsx_stxvp:
+    case PPC::BI__builtin_mma_stxvp:
+      Ops[1] = Builder.CreateGEP(Int8Ty, Ops[2], Ops[1]);
       Ops.pop_back();
-      llvm::Function *F = CGM.getIntrinsic(ID);
-      return Builder.CreateCall(F, Ops, "");
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+    case PPC::BI__builtin_disassemble_dmr:
+      Ops[1] = Builder.CreateLoad(EmitPointerWithAlignment(E->getArg(1)));
+      return Builder.CreateAlignedStore(Ops[1], Ops[0], MaybeAlign());
+
+    // Handle AES encrypt paired builtins - they return a value directly.
+    // For variant builtins, add the appropriate immediate value.
+    case PPC::BI__builtin_aes128_encrypt_paired:
+      Ops.push_back(llvm::ConstantInt::get(Int32Ty, 0));
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+    case PPC::BI__builtin_aes192_encrypt_paired:
+      Ops.push_back(llvm::ConstantInt::get(Int32Ty, 1));
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+    case PPC::BI__builtin_aes256_encrypt_paired:
+      Ops.push_back(llvm::ConstantInt::get(Int32Ty, 2));
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+    case PPC::BI__builtin_aes_encrypt_paired:
+      // For base builtin, Ops already has all 3 arguments.
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+
+    // Handle AES decrypt paired builtins - they return a value directly.
+    // For variant builtins, add the appropriate immediate value.
+    case PPC::BI__builtin_aes128_decrypt_paired:
+      Ops.push_back(llvm::ConstantInt::get(Int32Ty, 0));
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+    case PPC::BI__builtin_aes192_decrypt_paired:
+      Ops.push_back(llvm::ConstantInt::get(Int32Ty, 1));
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+    case PPC::BI__builtin_aes256_decrypt_paired:
+      Ops.push_back(llvm::ConstantInt::get(Int32Ty, 2));
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+    case PPC::BI__builtin_aes_decrypt_paired:
+      // For base builtin, Ops already has all 3 arguments.
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+
+    // Handle AES genlastkey paired builtins.
+    case PPC::BI__builtin_aes128_genlastkey_paired:
+      Ops.push_back(llvm::ConstantInt::get(Int32Ty, 0));
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+    case PPC::BI__builtin_aes192_genlastkey_paired:
+      Ops.push_back(llvm::ConstantInt::get(Int32Ty, 1));
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+    case PPC::BI__builtin_aes256_genlastkey_paired:
+      Ops.push_back(llvm::ConstantInt::get(Int32Ty, 2));
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+    case PPC::BI__builtin_aes_genlastkey_paired:
+      // For base builtin, Ops already has all 2 arguments.
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+
+    // Handle Galois Field multiplication builtins.
+    case PPC::BI__builtin_galois_field_mult_gcm:
+      Ops.push_back(llvm::ConstantInt::get(Int32Ty, 0));
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+    case PPC::BI__builtin_galois_field_mult_xts:
+      Ops.push_back(llvm::ConstantInt::get(Int32Ty, 1));
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+    case PPC::BI__builtin_galois_field_mult:
+      // For base builtin, Ops already has all 3 arguments.
+      return Builder.CreateCall(CGM.getIntrinsic(ID), Ops, "");
+
+    default:
+      break;
     }
+
+    // Handle Accumulate = true custom builtins that need to load the existing
+    // accumulator value from the first argument (a pointer) and pass it as the
+    // first operand to the intrinsic call.
     SmallVector<Value*, 4> CallOps;
     if (Accumulate) {
       Address Addr = EmitPointerWithAlignment(E->getArg(0));
@@ -1166,10 +1230,6 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
       Ops[1] = Builder.CreateLoad(Addr);
       break;
     }
-    case PPC::BI__builtin_disassemble_dmr: {
-      Ops[1] = Builder.CreateLoad(EmitPointerWithAlignment(E->getArg(1)));
-      return Builder.CreateAlignedStore(Ops[1], Ops[0], MaybeAlign());
-    }
     case PPC::BI__builtin_dmsha256hash:
     case PPC::BI__builtin_dmsha512hash: {
       Ops[1] = Builder.CreateLoad(EmitPointerWithAlignment(E->getArg(1)));
diff --git a/clang/test/CodeGen/PowerPC/builtins-aes-acceleration.c b/clang/test/CodeGen/PowerPC/builtins-aes-acceleration.c
new file mode 100644
index 0000000000000..d6e5bec7bb923
--- /dev/null
+++ b/clang/test/CodeGen/PowerPC/builtins-aes-acceleration.c
@@ -0,0 +1,205 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -O3 -triple powerpc64le-unknown-unknown -target-cpu future \
+// RUN:   -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -O3 -triple powerpc64-unknown-unknown -target-cpu future \
+// RUN:   -emit-llvm %s -o - | FileCheck %s
+
+// Made with AI
+
+// CHECK-LABEL: @test_aes_encrypt_paired(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6:![0-9]+]]
+// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 0)
+// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    ret void
+//
+void test_aes_encrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
+  __vector_pair vp1 = *((__vector_pair *)vpp1);
+  __vector_pair vp2 = *((__vector_pair *)vpp2);
+  __vector_pair res = __builtin_aes_encrypt_paired(vp1, vp2, 0);
+  *((__vector_pair *)resp) = res;
+}
+
+// CHECK-LABEL: @test_aes128_encrypt_paired(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 0)
+// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    ret void
+//
+void test_aes128_encrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
+  __vector_pair vp1 = *((__vector_pair *)vpp1);
+  __vector_pair vp2 = *((__vector_pair *)vpp2);
+  __vector_pair res = __builtin_aes128_encrypt_paired(vp1, vp2);
+  *((__vector_pair *)resp) = res;
+}
+
+// CHECK-LABEL: @test_aes192_encrypt_paired(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 1)
+// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    ret void
+//
+void test_aes192_encrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
+  __vector_pair vp1 = *((__vector_pair *)vpp1);
+  __vector_pair vp2 = *((__vector_pair *)vpp2);
+  __vector_pair res = __builtin_aes192_encrypt_paired(vp1, vp2);
+  *((__vector_pair *)resp) = res;
+}
+
+// CHECK-LABEL: @test_aes256_encrypt_paired(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 2)
+// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    ret void
+//
+void test_aes256_encrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
+  __vector_pair vp1 = *((__vector_pair *)vpp1);
+  __vector_pair vp2 = *((__vector_pair *)vpp2);
+  __vector_pair res = __builtin_aes256_encrypt_paired(vp1, vp2);
+  *((__vector_pair *)resp) = res;
+}
+
+// CHECK-LABEL: @test_aes_decrypt_paired(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 0)
+// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    ret void
+//
+void test_aes_decrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
+  __vector_pair vp1 = *((__vector_pair *)vpp1);
+  __vector_pair vp2 = *((__vector_pair *)vpp2);
+  __vector_pair res = __builtin_aes_decrypt_paired(vp1, vp2, 0);
+  *((__vector_pair *)resp) = res;
+}
+
+// CHECK-LABEL: @test_aes128_decrypt_paired(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 0)
+// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    ret void
+//
+void test_aes128_decrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
+  __vector_pair vp1 = *((__vector_pair *)vpp1);
+  __vector_pair vp2 = *((__vector_pair *)vpp2);
+  __vector_pair res = __builtin_aes128_decrypt_paired(vp1, vp2);
+  *((__vector_pair *)resp) = res;
+}
+
+// CHECK-LABEL: @test_aes192_decrypt_paired(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 1)
+// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    ret void
+//
+void test_aes192_decrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
+  __vector_pair vp1 = *((__vector_pair *)vpp1);
+  __vector_pair vp2 = *((__vector_pair *)vpp2);
+  __vector_pair res = __builtin_aes192_decrypt_paired(vp1, vp2);
+  *((__vector_pair *)resp) = res;
+}
+
+// CHECK-LABEL: @test_aes256_decrypt_paired(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 2)
+// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    ret void
+//
+void test_aes256_decrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
+  __vector_pair vp1 = *((__vector_pair *)vpp1);
+  __vector_pair vp2 = *((__vector_pair *)vpp2);
+  __vector_pair res = __builtin_aes256_decrypt_paired(vp1, vp2);
+  *((__vector_pair *)resp) = res;
+}
+// CHECK-LABEL: @test_aes_genlastkey_paired(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1> [[TMP0]], i32 0)
+// CHECK-NEXT:    store <256 x i1> [[TMP1]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    ret void
+//
+void test_aes_genlastkey_paired(unsigned char *vpp1, unsigned char *resp) {
+  __vector_pair vp1 = *((__vector_pair *)vpp1);
+  __vector_pair res = __builtin_aes_genlastkey_paired(vp1, 0);
+  *((__vector_pair *)resp) = res;
+}
+
+// CHECK-LABEL: @test_aes128_genlastkey_paired(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1> [[TMP0]], i32 0)
+// CHECK-NEXT:    store <256 x i1> [[TMP1]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    ret void
+//
+void test_aes128_genlastkey_paired(unsigned char *vpp1, unsigned char *resp) {
+  __vector_pair vp1 = *((__vector_pair *)vpp1);
+  __vector_pair res = __builtin_aes128_genlastkey_paired(vp1);
+  *((__vector_pair *)resp) = res;
+}
+
+// CHECK-LABEL: @test_aes192_genlastkey_paired(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1> [[TMP0]], i32 1)
+// CHECK-NEXT:    store <256 x i1> [[TMP1]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    ret void
+//
+void test_aes192_genlastkey_paired(unsigned char *vpp1, unsigned char *resp) {
+  __vector_pair vp1 = *((__vector_pair *)vpp1);
+  __vector_pair res = __builtin_aes192_genlastkey_paired(vp1);
+  *((__vector_pair *)resp) = res;
+}
+
+// CHECK-LABEL: @test_aes256_genlastkey_paired(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    [[TMP1:%.*]] = tail call <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1> [[TMP0]], i32 2)
+// CHECK-NEXT:    store <256 x i1> [[TMP1]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
+// CHECK-NEXT:    ret void
+//
+void test_aes256_genlastkey_paired(unsigned char *vpp1, unsigned char *resp) {
+  __vector_pair vp1 = *((__vector_pair *)vpp1);
+  __vector_pair res = __builtin_aes256_genlastkey_paired(vp1);
+  *((__vector_pair *)resp) = res;
+}
+
+// CHECK-LABEL: @test_galois_field_mult(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call <16 x i8> @llvm.ppc.galois.field.mult(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 0)
+// CHECK-NEXT:    ret <16 x i8> [[TMP0]]
+//
+vector unsigned char test_galois_field_mult(vector unsigned char a, vector unsigned char b) {
+  return __builtin_galois_field_mult(a, b, 0);
+}
+
+// CHECK-LABEL: @test_galois_field_mult_gcm(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call <16 x i8> @llvm.ppc.galois.field.mult(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 0)
+// CHECK-NEXT:    ret <16 x i8> [[TMP0]]
+//
+vector unsigned char test_galois_field_mult_gcm(vector unsigned char a, vector unsigned char b) {
+  return __builtin_galois_field_mult_gcm(a, b);
+}
+
+// CHECK-LABEL: @test_galois_field_mult_xts(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = tail call <16 x i8> @llvm.ppc.galois.field.mult(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 1)
+// CHECK-NEXT:    ret <16 x i8> [[TMP0]]
+//
+vector unsigned char test_galois_field_mult_xts(vector unsigned char a, vector unsigned char b) {
+  return __builtin_galois_field_mult_xts(a, b);
+}
diff --git a/clang/test/Sema/PowerPC/builtins-aes-acceleration-error.c b/clang/test/Sema/PowerPC/builtins-aes-acceleration-error.c
new file mode 100644
index 0000000000000..0fc640c1c3146
--- /dev/null
+++ b/clang/test/Sema/PowerPC/builtins-aes-acceleration-error.c
@@ -0,0 +1,263 @@
+// REQUIRES: powerpc-registered-target
+// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -target-cpu future \
+// RUN:   -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -target-cpu future \
+// RUN:   -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -target-cpu pwr11 \
+// RUN:   -fsyntax-only -verify=pwr11 %s
+
+// Made with AI
+
+void test_aes_encrypt_paired_invalid_imm(void) {
+  __vector_pair vp1, vp2;
+
+  // Test invalid immediate values (valid range is 0-2)
+  // expected-error at +2 {{argument value 3 is outside the valid range}}
+  // pwr11-error at +1 {{'__builtin_aes_encrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res1 = __builtin_aes_encrypt_paired(vp1, vp2, 3);
+  // expected-error at +2 {{argument value -1 is outside the valid range}}
+  // pwr11-error at +1 {{'__builtin_aes_encrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res2 = __builtin_aes_encrypt_paired(vp1, vp2, -1);
+  // expected-error at +2 {{argument value 10 is outside the valid range}}
+  // pwr11-error at +1 {{'__builtin_aes_encrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res3 = __builtin_aes_encrypt_paired(vp1, vp2, 10);
+}
+
+void test_aes_encrypt_paired_type_mismatch(void) {
+  __vector_pair vp;
+  vector unsigned char vc;
+
+  // Test type mismatches
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes_encrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res1 = __builtin_aes_encrypt_paired(vc, vp, 0);
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes_encrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res2 = __builtin_aes_encrypt_paired(vp, vc, 0);
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type 'int'}}
+  // pwr11-error at +1 {{'__builtin_aes_encrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res3 = __builtin_aes_encrypt_paired(vp, vp, vc);
+}
+
+void test_aes128_encrypt_paired_type_mismatch(void) {
+  __vector_pair vp;
+  vector unsigned char vc;
+
+  // Test type mismatches for aes128 variant
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes128_encrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res1 = __builtin_aes128_encrypt_paired(vc, vp);
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes128_encrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res2 = __builtin_aes128_encrypt_paired(vp, vc);
+}
+
+void test_aes192_encrypt_paired_type_mismatch(void) {
+  __vector_pair vp;
+  vector unsigned char vc;
+
+  // Test type mismatches for aes192 variant
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes192_encrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res1 = __builtin_aes192_encrypt_paired(vc, vp);
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes192_encrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res2 = __builtin_aes192_encrypt_paired(vp, vc);
+}
+
+void test_aes256_encrypt_paired_type_mismatch(void) {
+  __vector_pair vp;
+  vector unsigned char vc;
+
+  // Test type mismatches for aes256 variant
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes256_encrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res1 = __builtin_aes256_encrypt_paired(vc, vp);
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes256_encrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res2 = __builtin_aes256_encrypt_paired(vp, vc);
+}
+
+void test_aes_decrypt_paired_invalid_imm(void) {
+  __vector_pair vp1, vp2;
+
+  // Test invalid immediate values (valid range is 0-2)
+  // expected-error at +2 {{argument value 3 is outside the valid range}}
+  // pwr11-error at +1 {{'__builtin_aes_decrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res1 = __builtin_aes_decrypt_paired(vp1, vp2, 3);
+  // expected-error at +2 {{argument value -1 is outside the valid range}}
+  // pwr11-error at +1 {{'__builtin_aes_decrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res2 = __builtin_aes_decrypt_paired(vp1, vp2, -1);
+  // expected-error at +2 {{argument value 10 is outside the valid range}}
+  // pwr11-error at +1 {{'__builtin_aes_decrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res3 = __builtin_aes_decrypt_paired(vp1, vp2, 10);
+}
+
+void test_aes_decrypt_paired_type_mismatch(void) {
+  __vector_pair vp;
+  vector unsigned char vc;
+
+  // Test type mismatches
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes_decrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res1 = __builtin_aes_decrypt_paired(vc, vp, 0);
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes_decrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res2 = __builtin_aes_decrypt_paired(vp, vc, 0);
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type 'int'}}
+  // pwr11-error at +1 {{'__builtin_aes_decrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res3 = __builtin_aes_decrypt_paired(vp, vp, vc);
+}
+
+void test_aes128_decrypt_paired_type_mismatch(void) {
+  __vector_pair vp;
+  vector unsigned char vc;
+
+  // Test type mismatches for aes128 variant
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes128_decrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res1 = __builtin_aes128_decrypt_paired(vc, vp);
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes128_decrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res2 = __builtin_aes128_decrypt_paired(vp, vc);
+}
+
+void test_aes192_decrypt_paired_type_mismatch(void) {
+  __vector_pair vp;
+  vector unsigned char vc;
+
+  // Test type mismatches for aes192 variant
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes192_decrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res1 = __builtin_aes192_decrypt_paired(vc, vp);
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes192_decrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res2 = __builtin_aes192_decrypt_paired(vp, vc);
+}
+
+void test_aes256_decrypt_paired_type_mismatch(void) {
+  __vector_pair vp;
+  vector unsigned char vc;
+
+  // Test type mismatches for aes256 variant
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes256_decrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res1 = __builtin_aes256_decrypt_paired(vc, vp);
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes256_decrypt_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res2 = __builtin_aes256_decrypt_paired(vp, vc);
+}
+void test_aes_genlastkey_paired_invalid_imm(void) {
+  __vector_pair vp1;
+
+  // Test invalid immediate values (valid range is 0-2)
+  // expected-error at +2 {{argument value 3 is outside the valid range}}
+  // pwr11-error at +1 {{'__builtin_aes_genlastkey_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res1 = __builtin_aes_genlastkey_paired(vp1, 3);
+  // expected-error at +2 {{argument value -1 is outside the valid range}}
+  // pwr11-error at +1 {{'__builtin_aes_genlastkey_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res2 = __builtin_aes_genlastkey_paired(vp1, -1);
+  // expected-error at +2 {{argument value 10 is outside the valid range}}
+  // pwr11-error at +1 {{'__builtin_aes_genlastkey_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res3 = __builtin_aes_genlastkey_paired(vp1, 10);
+}
+
+void test_aes_genlastkey_paired_type_mismatch(void) {
+  __vector_pair vp;
+  vector unsigned char vc;
+
+  // Test type mismatches
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes_genlastkey_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res1 = __builtin_aes_genlastkey_paired(vc, 0);
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type 'int'}}
+  // pwr11-error at +1 {{'__builtin_aes_genlastkey_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res2 = __builtin_aes_genlastkey_paired(vp, vc);
+}
+
+void test_aes128_genlastkey_paired_type_mismatch(void) {
+  __vector_pair vp;
+  vector unsigned char vc;
+
+  // Test type mismatches for aes128 variant
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes128_genlastkey_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res1 = __builtin_aes128_genlastkey_paired(vc);
+}
+
+void test_aes192_genlastkey_paired_type_mismatch(void) {
+  __vector_pair vp;
+  vector unsigned char vc;
+
+  // Test type mismatches for aes192 variant
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes192_genlastkey_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res1 = __builtin_aes192_genlastkey_paired(vc);
+}
+
+void test_aes256_genlastkey_paired_type_mismatch(void) {
+  __vector_pair vp;
+  vector unsigned char vc;
+
+  // Test type mismatches for aes256 variant
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type '__vector_pair'}}
+  // pwr11-error at +1 {{'__builtin_aes256_genlastkey_paired' needs target feature future-vector,paired-vector-memops}}
+  __vector_pair res1 = __builtin_aes256_genlastkey_paired(vc);
+}
+
+void test_galois_field_mult_invalid_imm(void) {
+  vector unsigned char a, b;
+
+  // Test invalid immediate values (valid range is 0-1)
+  // expected-error at +2 {{argument value 2 is outside the valid range}}
+  // pwr11-error at +1 {{'__builtin_galois_field_mult' needs target feature future-vector}}
+  vector unsigned char res1 = __builtin_galois_field_mult(a, b, 2);
+  // expected-error at +2 {{argument value -1 is outside the valid range}}
+  // pwr11-error at +1 {{'__builtin_galois_field_mult' needs target feature future-vector}}
+  vector unsigned char res2 = __builtin_galois_field_mult(a, b, -1);
+  // expected-error at +2 {{argument value 10 is outside the valid range}}
+  // pwr11-error at +1 {{'__builtin_galois_field_mult' needs target feature future-vector}}
+  vector unsigned char res3 = __builtin_galois_field_mult(a, b, 10);
+}
+
+void test_galois_field_mult_type_mismatch(void) {
+  vector unsigned char vc;
+  __vector_pair vp;
+
+  // Test type mismatches
+  // expected-error at +2 {{passing '__vector_pair' to parameter of incompatible type '__vector unsigned char' (vector of 16 'unsigned char' values)}}
+  // pwr11-error at +1 {{'__builtin_galois_field_mult' needs target feature future-vector}}
+  vector unsigned char res1 = __builtin_galois_field_mult(vp, vc, 0);
+  // expected-error at +2 {{passing '__vector_pair' to parameter of incompatible type '__vector unsigned char' (vector of 16 'unsigned char' values)}}
+  // pwr11-error at +1 {{'__builtin_galois_field_mult' needs target feature future-vector}}
+  vector unsigned char res2 = __builtin_galois_field_mult(vc, vp, 0);
+  // expected-error at +2 {{passing '__vector unsigned char' (vector of 16 'unsigned char' values) to parameter of incompatible type 'int'}}
+  // pwr11-error at +1 {{'__builtin_galois_field_mult' needs target feature future-vector}}
+  vector unsigned char res3 = __builtin_galois_field_mult(vc, vc, vc);
+}
+
+void test_galois_field_mult_gcm_type_mismatch(void) {
+  vector unsigned char vc;
+  __vector_pair vp;
+
+  // Test type mismatches for gcm variant
+  // expected-error at +2 {{passing '__vector_pair' to parameter of incompatible type '__vector unsigned char' (vector of 16 'unsigned char' values)}}
+  // pwr11-error at +1 {{'__builtin_galois_field_mult_gcm' needs target feature future-vector}}
+  vector unsigned char res1 = __builtin_galois_field_mult_gcm(vp, vc);
+  // expected-error at +2 {{passing '__vector_pair' to parameter of incompatible type '__vector unsigned char' (vector of 16 'unsigned char' values)}}
+  // pwr11-error at +1 {{'__builtin_galois_field_mult_gcm' needs target feature future-vector}}
+  vector unsigned char res2 = __builtin_galois_field_mult_gcm(vc, vp);
+}
+
+void test_galois_field_mult_xts_type_mismatch(void) {
+  vector unsigned char vc;
+  __vector_pair vp;
+
+  // Test type mismatches for xts variant
+  // expected-error at +2 {{passing '__vector_pair' to parameter of incompatible type '__vector unsigned char' (vector of 16 'unsigned char' values)}}
+  // pwr11-error at +1 {{'__builtin_galois_field_mult_xts' needs target feature future-vector}}
+  vector unsigned char res1 = __builtin_galois_field_mult_xts(vp, vc);
+  // expected-error at +2 {{passing '__vector_pair' to parameter of incompatible type '__vector unsigned char' (vector of 16 'unsigned char' values)}}
+  // pwr11-error at +1 {{'__builtin_galois_field_mult_xts' needs target feature future-vector}}
+  vector unsigned char res2 = __builtin_galois_field_mult_xts(vc, vp);
+}
diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td
index 392c47ee7e456..b955a9f081094 100644
--- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td
+++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td
@@ -1755,6 +1755,27 @@ let TargetPrefix = "ppc" in {
       DefaultAttrsIntrinsic<[llvm_v16i8_ty, llvm_v16i8_ty],
                             [llvm_v256i1_ty], [IntrNoMem]>;
 
+  // AES Encrypt Paired Instructions.
+  def int_ppc_aes_encrypt_paired :
+      DefaultAttrsIntrinsic<[llvm_v256i1_ty],
+                            [llvm_v256i1_ty, llvm_v256i1_ty, llvm_i32_ty],
+                            [IntrNoMem, ImmArg<ArgIndex<2>>]>;
+  // AES Decrypt Paired Instructions.
+  def int_ppc_aes_decrypt_paired :
+      DefaultAttrsIntrinsic<[llvm_v256i1_ty],
+                            [llvm_v256i1_ty, llvm_v256i1_ty, llvm_i32_ty],
+                            [IntrNoMem, ImmArg<ArgIndex<2>>]>;
+  // AES Generate Last Key Paired Instructions.
+  def int_ppc_aes_genlastkey_paired :
+      DefaultAttrsIntrinsic<[llvm_v256i1_ty],
+                            [llvm_v256i1_ty, llvm_i32_ty],
+                            [IntrNoMem, ImmArg<ArgIndex<1>>]>;
+  // Galois Field Multiplication Instructions.
+  def int_ppc_galois_field_mult :
+      DefaultAttrsIntrinsic<[llvm_v16i8_ty],
+                            [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty],
+                            [IntrNoMem, ImmArg<ArgIndex<2>>]>;
+
   def int_ppc_mma_assemble_acc :
       DefaultAttrsIntrinsic<[llvm_v512i1_ty],
                             [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty,
diff --git a/llvm/lib/Target/PowerPC/PPCInstrFuture.td b/llvm/lib/Target/PowerPC/PPCInstrFuture.td
index c1f95de578dbe..2ddc25a938c8a 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrFuture.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrFuture.td
@@ -492,17 +492,30 @@ let Predicates = [HasFutureVector] in {
                             "xvrlw $XT, $XA, $XB",
                             [(set v4i32:$XT, (int_ppc_vsx_xvrlw v4i32:$XA,
                                                  v4i32:$XB))]>;
+}
 
   // AES Acceleration Instructions
-  def XXAESENCP : XX3Form_XTABp5_M2<194, (outs vsrprc:$XTp),
-                                    (ins vsrprc:$XAp, vsrprc:$XBp, u2imm:$M),
-                                    "xxaesencp $XTp, $XAp, $XBp, $M", []>;
-  def XXAESDECP : XX3Form_XTABp5_M2<202, (outs vsrprc:$XTp),
-                                    (ins vsrprc:$XAp, vsrprc:$XBp, u2imm:$M),
-                                    "xxaesdecp $XTp, $XAp, $XBp, $M", []>;
-  def XXAESGENLKP : XX3Form_XTBp5_M2<420, (outs vsrprc:$XTp),
-                                     (ins vsrprc:$XBp, u2imm:$M),
-                                     "xxaesgenlkp $XTp, $XBp, $M", []>;
+let Predicates = [HasFutureVector, PairedVectorMemops] in {
+  def XXAESENCP
+      : XX3Form_XTABp5_M2<194, (outs vsrprc:$XTp),
+                          (ins vsrprc:$XAp, vsrprc:$XBp, u2imm:$M),
+                          "xxaesencp $XTp, $XAp, $XBp, $M",
+                          [(set v256i1:$XTp,
+                                (int_ppc_aes_encrypt_paired v256i1:$XAp, v256i1:$XBp, u2imm_timm:$M))]>;
+  def XXAESDECP
+      : XX3Form_XTABp5_M2<202, (outs vsrprc:$XTp),
+                          (ins vsrprc:$XAp, vsrprc:$XBp, u2imm:$M),
+                          "xxaesdecp $XTp, $XAp, $XBp, $M",
+                          [(set v256i1:$XTp,
+                                (int_ppc_aes_decrypt_paired v256i1:$XAp, v256i1:$XBp, u2imm_timm:$M))]>;
+  def XXAESGENLKP
+      : XX3Form_XTBp5_M2<420, (outs vsrprc:$XTp), (ins vsrprc:$XBp, u2imm:$M),
+                         "xxaesgenlkp $XTp, $XBp, $M",
+                         [(set v256i1:$XTp,
+                               (int_ppc_aes_genlastkey_paired v256i1:$XBp, u2imm_timm:$M))]>;
+}
+
+let Predicates = [HasFutureVector] in {
   def XXGFMUL128 : XX3Form_XTAB6_P1<26, (outs vsrc:$XT),
                                     (ins vsrc:$XA, vsrc:$XB, u1imm:$P),
                                     "xxgfmul128 $XT, $XA, $XB, $P", []>;
@@ -621,6 +634,9 @@ def : Pat<(int_ppc_vsx_stxvprl v256i1:$XTp, addr:$RA, i64:$RB), (STXVPRL $XTp,
 def : Pat<(int_ppc_vsx_stxvprll v256i1:$XTp, addr:$RA, i64:$RB), (STXVPRLL $XTp,
                                                                      $RA, $RB)>;
 
+def: Pat<(v16i8 (int_ppc_galois_field_mult v16i8:$XA, v16i8:$XB, u1imm_timm:$IMM)),
+         (COPY_TO_REGCLASS (XXGFMUL128 RCCp.AToVSRC, RCCp.BToVSRC, $IMM), VSRC)>;
+
 // Regular load/store patterns for v256i1 (for ISA Future)
 let Predicates = [HasFutureVector, PairedVectorMemops] in {
   def : Pat<(v256i1 (load iaddrX16:$src)), (LXVP iaddrX16:$src)>;
diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-aes-acceleration.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-aes-acceleration.ll
new file mode 100644
index 0000000000000..18864bb5592fc
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-aes-acceleration.ll
@@ -0,0 +1,174 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
+; RUN:   -mcpu=future -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr \
+; RUN:   < %s | FileCheck %s
+; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \
+; RUN:   -mcpu=future -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr \
+; RUN:   < %s | FileCheck %s
+
+; Generated by AI.
+
+declare <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1>, i32)
+declare <16 x i8> @llvm.ppc.galois.field.mult(<16 x i8>, <16 x i8>, i32)
+declare <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1>, <256 x i1>, i32)
+declare <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1>, <256 x i1>, i32)
+
+define void @test_aes_encrypt_paired_imm0(ptr %ptr, ptr %vpp1, ptr %vpp2) {
+; CHECK-LABEL: test_aes_encrypt_paired_imm0:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    lxvp vsp34, 0(r4)
+; CHECK-NEXT:    lxvp vsp36, 0(r5)
+; CHECK-NEXT:    xxaes128encp vsp34, vsp34, vsp36
+; CHECK-NEXT:    stxvp vsp34, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %vp1 = load <256 x i1>, ptr %vpp1, align 32
+  %vp2 = load <256 x i1>, ptr %vpp2, align 32
+  %0 = tail call <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1> %vp1, <256 x i1> %vp2, i32 0)
+  store <256 x i1> %0, ptr %ptr, align 32
+  ret void
+}
+
+define void @test_aes_encrypt_paired_imm1(ptr %ptr, ptr %vpp1, ptr %vpp2) {
+; CHECK-LABEL: test_aes_encrypt_paired_imm1:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    lxvp vsp34, 0(r4)
+; CHECK-NEXT:    lxvp vsp36, 0(r5)
+; CHECK-NEXT:    xxaes192encp vsp34, vsp34, vsp36
+; CHECK-NEXT:    stxvp vsp34, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %vp1 = load <256 x i1>, ptr %vpp1, align 32
+  %vp2 = load <256 x i1>, ptr %vpp2, align 32
+  %0 = tail call <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1> %vp1, <256 x i1> %vp2, i32 1)
+  store <256 x i1> %0, ptr %ptr, align 32
+  ret void
+}
+
+define void @test_aes_encrypt_paired_imm2(ptr %ptr, ptr %vpp1, ptr %vpp2) {
+; CHECK-LABEL: test_aes_encrypt_paired_imm2:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    lxvp vsp34, 0(r4)
+; CHECK-NEXT:    lxvp vsp36, 0(r5)
+; CHECK-NEXT:    xxaes256encp vsp34, vsp34, vsp36
+; CHECK-NEXT:    stxvp vsp34, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %vp1 = load <256 x i1>, ptr %vpp1, align 32
+  %vp2 = load <256 x i1>, ptr %vpp2, align 32
+  %0 = tail call <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1> %vp1, <256 x i1> %vp2, i32 2)
+  store <256 x i1> %0, ptr %ptr, align 32
+  ret void
+}
+
+
+define void @test_aes_decrypt_paired_imm0(ptr %ptr, ptr %vpp1, ptr %vpp2) {
+; CHECK-LABEL: test_aes_decrypt_paired_imm0:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    lxvp vsp34, 0(r4)
+; CHECK-NEXT:    lxvp vsp36, 0(r5)
+; CHECK-NEXT:    xxaes128decp vsp34, vsp34, vsp36
+; CHECK-NEXT:    stxvp vsp34, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %vp1 = load <256 x i1>, ptr %vpp1, align 32
+  %vp2 = load <256 x i1>, ptr %vpp2, align 32
+  %0 = tail call <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1> %vp1, <256 x i1> %vp2, i32 0)
+  store <256 x i1> %0, ptr %ptr, align 32
+  ret void
+}
+
+define void @test_aes_decrypt_paired_imm1(ptr %ptr, ptr %vpp1, ptr %vpp2) {
+; CHECK-LABEL: test_aes_decrypt_paired_imm1:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    lxvp vsp34, 0(r4)
+; CHECK-NEXT:    lxvp vsp36, 0(r5)
+; CHECK-NEXT:    xxaes192decp vsp34, vsp34, vsp36
+; CHECK-NEXT:    stxvp vsp34, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %vp1 = load <256 x i1>, ptr %vpp1, align 32
+  %vp2 = load <256 x i1>, ptr %vpp2, align 32
+  %0 = tail call <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1> %vp1, <256 x i1> %vp2, i32 1)
+  store <256 x i1> %0, ptr %ptr, align 32
+  ret void
+}
+
+define void @test_aes_decrypt_paired_imm2(ptr %ptr, ptr %vpp1, ptr %vpp2) {
+; CHECK-LABEL: test_aes_decrypt_paired_imm2:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    lxvp vsp34, 0(r4)
+; CHECK-NEXT:    lxvp vsp36, 0(r5)
+; CHECK-NEXT:    xxaes256decp vsp34, vsp34, vsp36
+; CHECK-NEXT:    stxvp vsp34, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %vp1 = load <256 x i1>, ptr %vpp1, align 32
+  %vp2 = load <256 x i1>, ptr %vpp2, align 32
+  %0 = tail call <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1> %vp1, <256 x i1> %vp2, i32 2)
+  store <256 x i1> %0, ptr %ptr, align 32
+  ret void
+}
+
+
+define void @test_aes_genlastkey_paired_imm0(ptr %ptr, ptr %vpp1) {
+; CHECK-LABEL: test_aes_genlastkey_paired_imm0:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    lxvp vsp34, 0(r4)
+; CHECK-NEXT:    xxaes128genlkp vsp34, vsp34
+; CHECK-NEXT:    stxvp vsp34, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %vp1 = load <256 x i1>, ptr %vpp1, align 32
+  %0 = tail call <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1> %vp1, i32 0)
+  store <256 x i1> %0, ptr %ptr, align 32
+  ret void
+}
+
+define void @test_aes_genlastkey_paired_imm1(ptr %ptr, ptr %vpp1) {
+; CHECK-LABEL: test_aes_genlastkey_paired_imm1:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    lxvp vsp34, 0(r4)
+; CHECK-NEXT:    xxaes192genlkp vsp34, vsp34
+; CHECK-NEXT:    stxvp vsp34, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %vp1 = load <256 x i1>, ptr %vpp1, align 32
+  %0 = tail call <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1> %vp1, i32 1)
+  store <256 x i1> %0, ptr %ptr, align 32
+  ret void
+}
+
+define void @test_aes_genlastkey_paired_imm2(ptr %ptr, ptr %vpp1) {
+; CHECK-LABEL: test_aes_genlastkey_paired_imm2:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    lxvp vsp34, 0(r4)
+; CHECK-NEXT:    xxaes256genlkp vsp34, vsp34
+; CHECK-NEXT:    stxvp vsp34, 0(r3)
+; CHECK-NEXT:    blr
+entry:
+  %vp1 = load <256 x i1>, ptr %vpp1, align 32
+  %0 = tail call <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1> %vp1, i32 2)
+  store <256 x i1> %0, ptr %ptr, align 32
+  ret void
+}
+
+define <16 x i8> @test_galois_field_mult_imm0(<16 x i8> %a, <16 x i8> %b) {
+; CHECK-LABEL: test_galois_field_mult_imm0:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xxgfmul128gcm v2, v2, v3
+; CHECK-NEXT:    blr
+entry:
+  %0 = tail call <16 x i8> @llvm.ppc.galois.field.mult(<16 x i8> %a, <16 x i8> %b, i32 0)
+  ret <16 x i8> %0
+}
+
+define <16 x i8> @test_galois_field_mult_imm1(<16 x i8> %a, <16 x i8> %b) {
+; CHECK-LABEL: test_galois_field_mult_imm1:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xxgfmul128xts v2, v2, v3
+; CHECK-NEXT:    blr
+entry:
+  %0 = tail call <16 x i8> @llvm.ppc.galois.field.mult(<16 x i8> %a, <16 x i8> %b, i32 1)
+  ret <16 x i8> %0
+}

>From ce12bbdeba8f5464a42239e2fb09af965055dc95 Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Tue, 28 Apr 2026 09:43:31 -0400
Subject: [PATCH 2/3] address Digger's comments

---
 .../PowerPC/builtins-aes-acceleration.c       | 218 +++++++-----------
 .../PowerPC/builtins-aes-acceleration-error.c |  12 -
 2 files changed, 77 insertions(+), 153 deletions(-)

diff --git a/clang/test/CodeGen/PowerPC/builtins-aes-acceleration.c b/clang/test/CodeGen/PowerPC/builtins-aes-acceleration.c
index d6e5bec7bb923..506c2e10b6891 100644
--- a/clang/test/CodeGen/PowerPC/builtins-aes-acceleration.c
+++ b/clang/test/CodeGen/PowerPC/builtins-aes-acceleration.c
@@ -1,205 +1,141 @@
-// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
-// RUN: %clang_cc1 -O3 -triple powerpc64le-unknown-unknown -target-cpu future \
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
+// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -target-cpu future \
 // RUN:   -emit-llvm %s -o - | FileCheck %s
-// RUN: %clang_cc1 -O3 -triple powerpc64-unknown-unknown -target-cpu future \
+// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -target-cpu future \
 // RUN:   -emit-llvm %s -o - | FileCheck %s
 
-// Made with AI
-
 // CHECK-LABEL: @test_aes_encrypt_paired(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6:![0-9]+]]
-// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 0)
-// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    ret void
-//
-void test_aes_encrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
-  __vector_pair vp1 = *((__vector_pair *)vpp1);
-  __vector_pair vp2 = *((__vector_pair *)vpp2);
+// CHECK:         {{.*}}call <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1> {{.*}}, <256 x i1> {{.*}}, i32 0)
+// CHECK:         ret void
+void test_aes_encrypt_paired(__vector_pair *vpp1, __vector_pair *vpp2, __vector_pair *resp) {
+  __vector_pair vp1 = *vpp1;
+  __vector_pair vp2 = *vpp2;
   __vector_pair res = __builtin_aes_encrypt_paired(vp1, vp2, 0);
-  *((__vector_pair *)resp) = res;
+  *resp = res;
 }
 
 // CHECK-LABEL: @test_aes128_encrypt_paired(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 0)
-// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    ret void
-//
-void test_aes128_encrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
-  __vector_pair vp1 = *((__vector_pair *)vpp1);
-  __vector_pair vp2 = *((__vector_pair *)vpp2);
+// CHECK:         {{.*}}call <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1> {{.*}}, <256 x i1> {{.*}}, i32 0)
+// CHECK:         ret void
+void test_aes128_encrypt_paired(__vector_pair *vpp1, __vector_pair *vpp2, __vector_pair *resp) {
+  __vector_pair vp1 = *vpp1;
+  __vector_pair vp2 = *vpp2;
   __vector_pair res = __builtin_aes128_encrypt_paired(vp1, vp2);
-  *((__vector_pair *)resp) = res;
+  *resp = res;
 }
 
 // CHECK-LABEL: @test_aes192_encrypt_paired(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 1)
-// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    ret void
-//
-void test_aes192_encrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
-  __vector_pair vp1 = *((__vector_pair *)vpp1);
-  __vector_pair vp2 = *((__vector_pair *)vpp2);
+// CHECK:         {{.*}}call <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1> {{.*}}, <256 x i1> {{.*}}, i32 1)
+// CHECK:         ret void
+void test_aes192_encrypt_paired(__vector_pair *vpp1, __vector_pair *vpp2, __vector_pair *resp) {
+  __vector_pair vp1 = *vpp1;
+  __vector_pair vp2 = *vpp2;
   __vector_pair res = __builtin_aes192_encrypt_paired(vp1, vp2);
-  *((__vector_pair *)resp) = res;
+  *resp = res;
 }
 
 // CHECK-LABEL: @test_aes256_encrypt_paired(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 2)
-// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    ret void
-//
-void test_aes256_encrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
-  __vector_pair vp1 = *((__vector_pair *)vpp1);
-  __vector_pair vp2 = *((__vector_pair *)vpp2);
+// CHECK:         {{.*}}call <256 x i1> @llvm.ppc.aes.encrypt.paired(<256 x i1> {{.*}}, <256 x i1> {{.*}}, i32 2)
+// CHECK:         ret void
+void test_aes256_encrypt_paired(__vector_pair *vpp1, __vector_pair *vpp2, __vector_pair *resp) {
+  __vector_pair vp1 = *vpp1;
+  __vector_pair vp2 = *vpp2;
   __vector_pair res = __builtin_aes256_encrypt_paired(vp1, vp2);
-  *((__vector_pair *)resp) = res;
+  *resp = res;
 }
 
 // CHECK-LABEL: @test_aes_decrypt_paired(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 0)
-// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    ret void
-//
-void test_aes_decrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
-  __vector_pair vp1 = *((__vector_pair *)vpp1);
-  __vector_pair vp2 = *((__vector_pair *)vpp2);
+// CHECK:         {{.*}}call <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1> {{.*}}, <256 x i1> {{.*}}, i32 0)
+// CHECK:         ret void
+void test_aes_decrypt_paired(__vector_pair *vpp1, __vector_pair *vpp2, __vector_pair *resp) {
+  __vector_pair vp1 = *vpp1;
+  __vector_pair vp2 = *vpp2;
   __vector_pair res = __builtin_aes_decrypt_paired(vp1, vp2, 0);
-  *((__vector_pair *)resp) = res;
+  *resp = res;
 }
 
 // CHECK-LABEL: @test_aes128_decrypt_paired(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 0)
-// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    ret void
-//
-void test_aes128_decrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
-  __vector_pair vp1 = *((__vector_pair *)vpp1);
-  __vector_pair vp2 = *((__vector_pair *)vpp2);
+// CHECK:         {{.*}}call <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1> {{.*}}, <256 x i1> {{.*}}, i32 0)
+// CHECK:         ret void
+void test_aes128_decrypt_paired(__vector_pair *vpp1, __vector_pair *vpp2, __vector_pair *resp) {
+  __vector_pair vp1 = *vpp1;
+  __vector_pair vp2 = *vpp2;
   __vector_pair res = __builtin_aes128_decrypt_paired(vp1, vp2);
-  *((__vector_pair *)resp) = res;
+  *resp = res;
 }
 
 // CHECK-LABEL: @test_aes192_decrypt_paired(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 1)
-// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    ret void
-//
-void test_aes192_decrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
-  __vector_pair vp1 = *((__vector_pair *)vpp1);
-  __vector_pair vp2 = *((__vector_pair *)vpp2);
+// CHECK:         {{.*}}call <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1> {{.*}}, <256 x i1> {{.*}}, i32 1)
+// CHECK:         ret void
+void test_aes192_decrypt_paired(__vector_pair *vpp1, __vector_pair *vpp2, __vector_pair *resp) {
+  __vector_pair vp1 = *vpp1;
+  __vector_pair vp2 = *vpp2;
   __vector_pair res = __builtin_aes192_decrypt_paired(vp1, vp2);
-  *((__vector_pair *)resp) = res;
+  *resp = res;
 }
 
 // CHECK-LABEL: @test_aes256_decrypt_paired(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP1:%.*]] = load <256 x i1>, ptr [[VPP2:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP2:%.*]] = tail call <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1> [[TMP0]], <256 x i1> [[TMP1]], i32 2)
-// CHECK-NEXT:    store <256 x i1> [[TMP2]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    ret void
-//
-void test_aes256_decrypt_paired(unsigned char *vpp1, unsigned char *vpp2, unsigned char *resp) {
-  __vector_pair vp1 = *((__vector_pair *)vpp1);
-  __vector_pair vp2 = *((__vector_pair *)vpp2);
+// CHECK:         {{.*}}call <256 x i1> @llvm.ppc.aes.decrypt.paired(<256 x i1> {{.*}}, <256 x i1> {{.*}}, i32 2)
+// CHECK:         ret void
+void test_aes256_decrypt_paired(__vector_pair *vpp1, __vector_pair *vpp2, __vector_pair *resp) {
+  __vector_pair vp1 = *vpp1;
+  __vector_pair vp2 = *vpp2;
   __vector_pair res = __builtin_aes256_decrypt_paired(vp1, vp2);
-  *((__vector_pair *)resp) = res;
+  *resp = res;
 }
 // CHECK-LABEL: @test_aes_genlastkey_paired(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP1:%.*]] = tail call <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1> [[TMP0]], i32 0)
-// CHECK-NEXT:    store <256 x i1> [[TMP1]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    ret void
-//
-void test_aes_genlastkey_paired(unsigned char *vpp1, unsigned char *resp) {
-  __vector_pair vp1 = *((__vector_pair *)vpp1);
+// CHECK:         {{.*}}call <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1> {{.*}}, i32 0)
+// CHECK:         ret void
+void test_aes_genlastkey_paired(__vector_pair *vpp1, __vector_pair *resp) {
+  __vector_pair vp1 = *vpp1;
   __vector_pair res = __builtin_aes_genlastkey_paired(vp1, 0);
-  *((__vector_pair *)resp) = res;
+  *resp = res;
 }
 
 // CHECK-LABEL: @test_aes128_genlastkey_paired(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP1:%.*]] = tail call <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1> [[TMP0]], i32 0)
-// CHECK-NEXT:    store <256 x i1> [[TMP1]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    ret void
-//
-void test_aes128_genlastkey_paired(unsigned char *vpp1, unsigned char *resp) {
-  __vector_pair vp1 = *((__vector_pair *)vpp1);
+// CHECK:         {{.*}}call <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1> {{.*}}, i32 0)
+// CHECK:         ret void
+void test_aes128_genlastkey_paired(__vector_pair *vpp1, __vector_pair *resp) {
+  __vector_pair vp1 = *vpp1;
   __vector_pair res = __builtin_aes128_genlastkey_paired(vp1);
-  *((__vector_pair *)resp) = res;
+  *resp = res;
 }
 
 // CHECK-LABEL: @test_aes192_genlastkey_paired(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP1:%.*]] = tail call <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1> [[TMP0]], i32 1)
-// CHECK-NEXT:    store <256 x i1> [[TMP1]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    ret void
-//
-void test_aes192_genlastkey_paired(unsigned char *vpp1, unsigned char *resp) {
-  __vector_pair vp1 = *((__vector_pair *)vpp1);
+// CHECK:         {{.*}}call <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1> {{.*}}, i32 1)
+// CHECK:         ret void
+void test_aes192_genlastkey_paired(__vector_pair *vpp1, __vector_pair *resp) {
+  __vector_pair vp1 = *vpp1;
   __vector_pair res = __builtin_aes192_genlastkey_paired(vp1);
-  *((__vector_pair *)resp) = res;
+  *resp = res;
 }
 
 // CHECK-LABEL: @test_aes256_genlastkey_paired(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = load <256 x i1>, ptr [[VPP1:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    [[TMP1:%.*]] = tail call <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1> [[TMP0]], i32 2)
-// CHECK-NEXT:    store <256 x i1> [[TMP1]], ptr [[RESP:%.*]], align 32, !tbaa [[TBAA6]]
-// CHECK-NEXT:    ret void
-//
-void test_aes256_genlastkey_paired(unsigned char *vpp1, unsigned char *resp) {
-  __vector_pair vp1 = *((__vector_pair *)vpp1);
+// CHECK:         {{.*}}call <256 x i1> @llvm.ppc.aes.genlastkey.paired(<256 x i1> {{.*}}, i32 2)
+// CHECK:         ret void
+void test_aes256_genlastkey_paired(__vector_pair *vpp1, __vector_pair *resp) {
+  __vector_pair vp1 = *vpp1;
   __vector_pair res = __builtin_aes256_genlastkey_paired(vp1);
-  *((__vector_pair *)resp) = res;
+  *resp = res;
 }
 
 // CHECK-LABEL: @test_galois_field_mult(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = tail call <16 x i8> @llvm.ppc.galois.field.mult(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 0)
-// CHECK-NEXT:    ret <16 x i8> [[TMP0]]
-//
+// CHECK:         {{.*}}call <16 x i8> @llvm.ppc.galois.field.mult(<16 x i8> {{.*}}, <16 x i8> {{.*}}, i32 0)
+// CHECK:         ret <16 x i8>
 vector unsigned char test_galois_field_mult(vector unsigned char a, vector unsigned char b) {
   return __builtin_galois_field_mult(a, b, 0);
 }
 
 // CHECK-LABEL: @test_galois_field_mult_gcm(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = tail call <16 x i8> @llvm.ppc.galois.field.mult(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 0)
-// CHECK-NEXT:    ret <16 x i8> [[TMP0]]
-//
+// CHECK:         {{.*}}call <16 x i8> @llvm.ppc.galois.field.mult(<16 x i8> {{.*}}, <16 x i8> {{.*}}, i32 0)
+// CHECK:         ret <16 x i8>
 vector unsigned char test_galois_field_mult_gcm(vector unsigned char a, vector unsigned char b) {
   return __builtin_galois_field_mult_gcm(a, b);
 }
 
 // CHECK-LABEL: @test_galois_field_mult_xts(
-// CHECK-NEXT:  entry:
-// CHECK-NEXT:    [[TMP0:%.*]] = tail call <16 x i8> @llvm.ppc.galois.field.mult(<16 x i8> [[A:%.*]], <16 x i8> [[B:%.*]], i32 1)
-// CHECK-NEXT:    ret <16 x i8> [[TMP0]]
-//
+// CHECK:         {{.*}}call <16 x i8> @llvm.ppc.galois.field.mult(<16 x i8> {{.*}}, <16 x i8> {{.*}}, i32 1)
+// CHECK:         ret <16 x i8>
 vector unsigned char test_galois_field_mult_xts(vector unsigned char a, vector unsigned char b) {
   return __builtin_galois_field_mult_xts(a, b);
 }
diff --git a/clang/test/Sema/PowerPC/builtins-aes-acceleration-error.c b/clang/test/Sema/PowerPC/builtins-aes-acceleration-error.c
index 0fc640c1c3146..5528ab4ebab95 100644
--- a/clang/test/Sema/PowerPC/builtins-aes-acceleration-error.c
+++ b/clang/test/Sema/PowerPC/builtins-aes-acceleration-error.c
@@ -18,9 +18,6 @@ void test_aes_encrypt_paired_invalid_imm(void) {
   // expected-error at +2 {{argument value -1 is outside the valid range}}
   // pwr11-error at +1 {{'__builtin_aes_encrypt_paired' needs target feature future-vector,paired-vector-memops}}
   __vector_pair res2 = __builtin_aes_encrypt_paired(vp1, vp2, -1);
-  // expected-error at +2 {{argument value 10 is outside the valid range}}
-  // pwr11-error at +1 {{'__builtin_aes_encrypt_paired' needs target feature future-vector,paired-vector-memops}}
-  __vector_pair res3 = __builtin_aes_encrypt_paired(vp1, vp2, 10);
 }
 
 void test_aes_encrypt_paired_type_mismatch(void) {
@@ -88,9 +85,6 @@ void test_aes_decrypt_paired_invalid_imm(void) {
   // expected-error at +2 {{argument value -1 is outside the valid range}}
   // pwr11-error at +1 {{'__builtin_aes_decrypt_paired' needs target feature future-vector,paired-vector-memops}}
   __vector_pair res2 = __builtin_aes_decrypt_paired(vp1, vp2, -1);
-  // expected-error at +2 {{argument value 10 is outside the valid range}}
-  // pwr11-error at +1 {{'__builtin_aes_decrypt_paired' needs target feature future-vector,paired-vector-memops}}
-  __vector_pair res3 = __builtin_aes_decrypt_paired(vp1, vp2, 10);
 }
 
 void test_aes_decrypt_paired_type_mismatch(void) {
@@ -157,9 +151,6 @@ void test_aes_genlastkey_paired_invalid_imm(void) {
   // expected-error at +2 {{argument value -1 is outside the valid range}}
   // pwr11-error at +1 {{'__builtin_aes_genlastkey_paired' needs target feature future-vector,paired-vector-memops}}
   __vector_pair res2 = __builtin_aes_genlastkey_paired(vp1, -1);
-  // expected-error at +2 {{argument value 10 is outside the valid range}}
-  // pwr11-error at +1 {{'__builtin_aes_genlastkey_paired' needs target feature future-vector,paired-vector-memops}}
-  __vector_pair res3 = __builtin_aes_genlastkey_paired(vp1, 10);
 }
 
 void test_aes_genlastkey_paired_type_mismatch(void) {
@@ -215,9 +206,6 @@ void test_galois_field_mult_invalid_imm(void) {
   // expected-error at +2 {{argument value -1 is outside the valid range}}
   // pwr11-error at +1 {{'__builtin_galois_field_mult' needs target feature future-vector}}
   vector unsigned char res2 = __builtin_galois_field_mult(a, b, -1);
-  // expected-error at +2 {{argument value 10 is outside the valid range}}
-  // pwr11-error at +1 {{'__builtin_galois_field_mult' needs target feature future-vector}}
-  vector unsigned char res3 = __builtin_galois_field_mult(a, b, 10);
 }
 
 void test_galois_field_mult_type_mismatch(void) {

>From dde61cb5de057ba9607439b2623500f06accfe7b Mon Sep 17 00:00:00 2001
From: Lei Huang <lei at ca.ibm.com>
Date: Tue, 5 May 2026 13:02:16 -0400
Subject: [PATCH 3/3] add doc to explain the diff sections of custom code
 handling.

---
 clang/lib/CodeGen/TargetBuiltins/PPC.cpp | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/clang/lib/CodeGen/TargetBuiltins/PPC.cpp b/clang/lib/CodeGen/TargetBuiltins/PPC.cpp
index f75458e13e5d1..ee932eb8bb366 100644
--- a/clang/lib/CodeGen/TargetBuiltins/PPC.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/PPC.cpp
@@ -1138,7 +1138,8 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
       break;
   #include "clang/Basic/BuiltinsPPC.def"
     }
-    // Handle Accumulate=false custom builtins that returns directly.
+    // Handle custom builtins that return early without using the common
+    // store-back pattern.
     switch (BuiltinID) {
     case PPC::BI__builtin_vsx_lxvp:
     case PPC::BI__builtin_mma_lxvp:
@@ -1213,15 +1214,25 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
       break;
     }
 
-    // Handle Accumulate = true custom builtins that need to load the existing
-    // accumulator value from the first argument (a pointer) and pass it as the
-    // first operand to the intrinsic call.
     SmallVector<Value*, 4> CallOps;
+
+    // Accumulate = true, are used for builtins where the hardware instruction
+    // reads the old destination value, performs an operation with it, and
+    // writes the result back.
+    // Load the existing value from the first argument (destination pointer) and
+    // add it to CallOps as the first intrinsic operand.
     if (Accumulate) {
       Address Addr = EmitPointerWithAlignment(E->getArg(0));
       Value *Acc = Builder.CreateLoad(Addr);
       CallOps.push_back(Acc);
     }
+
+    // Handles builtins that need special argument handling such as:
+    // - Dereferencing pointer arguments to load actual register values.
+    // - Adding implicit operands required by the intrinsic.
+    // - Transforming or reordering operands.
+    // After preprocessing, the loop at end copies Ops[1..n] into CallOps,
+    // skipping Ops[0] which is the destination pointer for result storage.
     switch (BuiltinID) {
     case PPC::BI__builtin_dmmr:
     case PPC::BI__builtin_dmxor:



More information about the cfe-commits mailing list