[clang] [Clang][CIR] Vector-Saturating-shift-left intrinsics (PR #190728)

Kartik Ohlan via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 23 20:53:03 PDT 2026


https://github.com/Ko496-glitch updated https://github.com/llvm/llvm-project/pull/190728

>From d03d70432915e3513200f66ea7e2031ba0d12b1c Mon Sep 17 00:00:00 2001
From: kartikohlan <kartik7ohlan at gmail.com>
Date: Tue, 7 Apr 2026 00:20:16 -0400
Subject: [PATCH 1/8] [Clang][CIR] Add vqshlud and vqshld AArch64 builtins

---
 .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp  | 23 +++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 3a9e7e2650500..c54781ea21464 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -2177,9 +2177,28 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr,
   case NEON::BI__builtin_neon_vsubd_u64:
   case NEON::BI__builtin_neon_vqdmlalh_s16:
   case NEON::BI__builtin_neon_vqdmlslh_s16:
-  case NEON::BI__builtin_neon_vqshlud_n_s64:
+  case NEON::BI__builtin_neon_vqshlud_n_s64: {
+    cir::IntType intType = builder.getSInt64Ty();
+    std::optional<llvm::APSInt> amt =
+        expr->getArg(1)->getIntegerConstantExpr(getContext());
+    assert(amt && "Expected argument to be a constant");
+    ops[1] = builder.getSInt64(amt->getZExtValue(), loc);
+    return emitNeonCall(cgm, builder, {intType, intType}, ops,
+                        "aarch64.neon.sqshlu", convertType(expr->getType()),
+                        loc);
+  }
   case NEON::BI__builtin_neon_vqshld_n_u64:
-  case NEON::BI__builtin_neon_vqshld_n_s64:
+  case NEON::BI__builtin_neon_vqshld_n_s64: {
+    cir::IntType intType = builtinID == NEON::BI__builtin_neon_vqshld_n_u64
+                               ? builder.getUInt64Ty()
+                               : builder.getSInt64Ty();
+    llvm::StringRef intrinsicName =
+        builtinID == NEON::BI__builtin_neon_vqshld_n_u64 ? "aarch64.neon.uqshl"
+                                                         : "aarch64.neon.sqshl";
+    ops[1] = builder.createIntCast(ops[1], intType);
+    return emitNeonCall(cgm, builder, {intType, intType}, ops, intrinsicName,
+                        convertType(expr->getType()), loc);
+  }
   case NEON::BI__builtin_neon_vrshrd_n_u64:
   case NEON::BI__builtin_neon_vrshrd_n_s64:
   case NEON::BI__builtin_neon_vrsrad_n_u64:

>From 9b66ee9a877f824b45b107b372bac76951525fd2 Mon Sep 17 00:00:00 2001
From: kartikohlan <kartik7ohlan at gmail.com>
Date: Tue, 7 Apr 2026 12:45:28 -0400
Subject: [PATCH 2/8] refactored to use lower ICE arguement

---
 .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp  |  5 +-
 .../CodeGen/AArch64/neon/vector-sat-left.c    | 81 +++++++++++++++++++
 2 files changed, 82 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/CodeGen/AArch64/neon/vector-sat-left.c

diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index c54781ea21464..60ac79c514350 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -2179,10 +2179,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr,
   case NEON::BI__builtin_neon_vqdmlslh_s16:
   case NEON::BI__builtin_neon_vqshlud_n_s64: {
     cir::IntType intType = builder.getSInt64Ty();
-    std::optional<llvm::APSInt> amt =
-        expr->getArg(1)->getIntegerConstantExpr(getContext());
-    assert(amt && "Expected argument to be a constant");
-    ops[1] = builder.getSInt64(amt->getZExtValue(), loc);
+    ops[1] = builder.getSInt64(getZExtIntValueFromConstOp(ops[1]), loc);
     return emitNeonCall(cgm, builder, {intType, intType}, ops,
                         "aarch64.neon.sqshlu", convertType(expr->getType()),
                         loc);
diff --git a/clang/test/CodeGen/AArch64/neon/vector-sat-left.c b/clang/test/CodeGen/AArch64/neon/vector-sat-left.c
new file mode 100644
index 0000000000000..8759346136117
--- /dev/null
+++ b/clang/test/CodeGen/AArch64/neon/vector-sat-left.c
@@ -0,0 +1,81 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +neon \
+// RUN:   -emit-llvm -o - %s \
+// RUN: | FileCheck %s --check-prefix=LLVM
+#include<arm_neon.h>
+
+
+// LLVM-LABEL: define dso_local i64 @test_vqshlud_n_s64(
+// LLVM-SAME: i64 noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] {
+// LLVM-NEXT:  [[ENTRY:.*:]]
+// LLVM-NEXT:    [[A_ADDR:%.*]] = alloca i64, align 8
+// LLVM-NEXT:    [[__RET:%.*]] = alloca i64, align 8
+// LLVM-NEXT:    [[__S0:%.*]] = alloca i64, align 8
+// LLVM-NEXT:    [[REF_TMP:%.*]] = alloca i64, align 8
+// LLVM-NEXT:    [[TMP:%.*]] = alloca i64, align 8
+// LLVM-NEXT:    store i64 [[A]], ptr [[A_ADDR]], align 8
+// LLVM-NEXT:    [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8
+// LLVM-NEXT:    store i64 [[TMP0]], ptr [[__S0]], align 8
+// LLVM-NEXT:    [[TMP1:%.*]] = load i64, ptr [[__S0]], align 8
+// LLVM-NEXT:    [[VQSHLU_N:%.*]] = call i64 @llvm.aarch64.neon.sqshlu.i64(i64 [[TMP1]], i64 1)
+// LLVM-NEXT:    store i64 [[VQSHLU_N]], ptr [[REF_TMP]], align 8
+// LLVM-NEXT:    [[TMP2:%.*]] = load i64, ptr [[REF_TMP]], align 8
+// LLVM-NEXT:    store i64 [[TMP2]], ptr [[__RET]], align 8
+// LLVM-NEXT:    [[TMP3:%.*]] = load i64, ptr [[__RET]], align 8
+// LLVM-NEXT:    store i64 [[TMP3]], ptr [[TMP]], align 8
+// LLVM-NEXT:    [[TMP4:%.*]] = load i64, ptr [[TMP]], align 8
+// LLVM-NEXT:    ret i64 [[TMP4]]
+//
+int64_t test_vqshlud_n_s64(int64_t a) {
+  return vqshlud_n_s64(a, 1);
+}
+
+// LLVM-LABEL: define dso_local i64 @test_vqshld_n_s64(
+// LLVM-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] {
+// LLVM-NEXT:  [[ENTRY:.*:]]
+// LLVM-NEXT:    [[A_ADDR:%.*]] = alloca i64, align 8
+// LLVM-NEXT:    [[__RET:%.*]] = alloca i64, align 8
+// LLVM-NEXT:    [[__S0:%.*]] = alloca i64, align 8
+// LLVM-NEXT:    [[REF_TMP:%.*]] = alloca i64, align 8
+// LLVM-NEXT:    [[TMP:%.*]] = alloca i64, align 8
+// LLVM-NEXT:    store i64 [[A]], ptr [[A_ADDR]], align 8
+// LLVM-NEXT:    [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8
+// LLVM-NEXT:    store i64 [[TMP0]], ptr [[__S0]], align 8
+// LLVM-NEXT:    [[TMP1:%.*]] = load i64, ptr [[__S0]], align 8
+// LLVM-NEXT:    [[VQSHL_N:%.*]] = call i64 @llvm.aarch64.neon.sqshl.i64(i64 [[TMP1]], i64 1)
+// LLVM-NEXT:    store i64 [[VQSHL_N]], ptr [[REF_TMP]], align 8
+// LLVM-NEXT:    [[TMP2:%.*]] = load i64, ptr [[REF_TMP]], align 8
+// LLVM-NEXT:    store i64 [[TMP2]], ptr [[__RET]], align 8
+// LLVM-NEXT:    [[TMP3:%.*]] = load i64, ptr [[__RET]], align 8
+// LLVM-NEXT:    store i64 [[TMP3]], ptr [[TMP]], align 8
+// LLVM-NEXT:    [[TMP4:%.*]] = load i64, ptr [[TMP]], align 8
+// LLVM-NEXT:    ret i64 [[TMP4]]
+//
+int64_t test_vqshld_n_s64(int64_t a) {
+  return vqshld_n_s64(a, 1);
+}
+
+// LLVM-LABEL: define dso_local i64 @test_vqshld_n_u64(
+// LLVM-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] {
+// LLVM-NEXT:  [[ENTRY:.*:]]
+// LLVM-NEXT:    [[A_ADDR:%.*]] = alloca i64, align 8
+// LLVM-NEXT:    [[__RET:%.*]] = alloca i64, align 8
+// LLVM-NEXT:    [[__S0:%.*]] = alloca i64, align 8
+// LLVM-NEXT:    [[REF_TMP:%.*]] = alloca i64, align 8
+// LLVM-NEXT:    [[TMP:%.*]] = alloca i64, align 8
+// LLVM-NEXT:    store i64 [[A]], ptr [[A_ADDR]], align 8
+// LLVM-NEXT:    [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8
+// LLVM-NEXT:    store i64 [[TMP0]], ptr [[__S0]], align 8
+// LLVM-NEXT:    [[TMP1:%.*]] = load i64, ptr [[__S0]], align 8
+// LLVM-NEXT:    [[VQSHL_N:%.*]] = call i64 @llvm.aarch64.neon.uqshl.i64(i64 [[TMP1]], i64 1)
+// LLVM-NEXT:    store i64 [[VQSHL_N]], ptr [[REF_TMP]], align 8
+// LLVM-NEXT:    [[TMP2:%.*]] = load i64, ptr [[REF_TMP]], align 8
+// LLVM-NEXT:    store i64 [[TMP2]], ptr [[__RET]], align 8
+// LLVM-NEXT:    [[TMP3:%.*]] = load i64, ptr [[__RET]], align 8
+// LLVM-NEXT:    store i64 [[TMP3]], ptr [[TMP]], align 8
+// LLVM-NEXT:    [[TMP4:%.*]] = load i64, ptr [[TMP]], align 8
+// LLVM-NEXT:    ret i64 [[TMP4]]
+//
+uint64_t test_vqshld_n_u64(uint64_t a) {
+  return vqshld_n_u64(a, 1);
+}

>From f7910a9c3db04b7ff6898630c2a2736766b6d7e0 Mon Sep 17 00:00:00 2001
From: Kartik Ohlan <kartik7ohlan at gmail.com>
Date: Fri, 17 Apr 2026 15:25:47 -0400
Subject: [PATCH 3/8] Deleted the redundant test file

---
 clang/test/CodeGen/AArch64/neon/intrinsics.c  | 36 +++++++++
 .../CodeGen/AArch64/neon/vector-sat-left.c    | 81 -------------------
 2 files changed, 36 insertions(+), 81 deletions(-)
 delete mode 100644 clang/test/CodeGen/AArch64/neon/vector-sat-left.c

diff --git a/clang/test/CodeGen/AArch64/neon/intrinsics.c b/clang/test/CodeGen/AArch64/neon/intrinsics.c
index e2708a846edc4..5e05fc555eb9f 100644
--- a/clang/test/CodeGen/AArch64/neon/intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon/intrinsics.c
@@ -24,6 +24,42 @@
 
 #include <arm_neon.h>
 
+// LLVM-LABEL: @test_vqshlud_n_s64(
+// CIR-LABEL: @test_vqshlud_n_s64(
+int64_t test_vqshlud_n_s64(int64_t a) {
+// CIR:   [[CONST:%.*]] = cir.const #cir.int<63> : !s64i
+// CIR:   {{%.*}} = cir.call_llvm_intrinsic "aarch64.neon.sqshlu" {{%.*}}, [[CONST]] : (!s64i, !s64i) -> !s64i
+
+// LLVM-SAME: i64 {{.*}}[[A:%.*]])
+// LLVM:      [[VQSHLU_N:%.*]] = call i64 @llvm.aarch64.neon.sqshlu.i64(i64 [[A]], i64 63)
+// LLVM:      ret i64 [[VQSHLU_N]]
+  return (int64_t)vqshlud_n_s64(a, 63);
+}
+
+// LLVM-LABEL: @test_vqshld_n_u64(
+// CIR-LABEL: @test_vqshld_n_u64(
+uint64_t test_vqshld_n_u64(uint64_t a) {
+// CIR:   [[CONST:%.*]] = cir.const #cir.int<63> : !u64i
+// CIR:   {{%.*}} = cir.call_llvm_intrinsic "aarch64.neon.uqshl" {{%.*}}, [[CONST]] : (!u64i, !u64i) -> !u64i
+
+// LLVM-SAME: i64 {{.*}}[[A:%.*]])
+// LLVM:      [[VQSHLD_N_U64:%.*]] = call i64 @llvm.aarch64.neon.uqshl.i64(i64 [[A]], i64 63)
+// LLVM:      ret i64 [[VQSHLD_N_U64]]
+  return vqshld_n_u64(a, 63);
+}
+
+// LLVM-LABEL: @test_vqshld_n_s64(
+// CIR-LABEL: @test_vqshld_n_s64(
+int64_t test_vqshld_n_s64(int64_t a) {
+// CIR:   [[CONST:%.*]] = cir.const #cir.int<63> : !s64i
+// CIR:   {{%.*}} = cir.call_llvm_intrinsic "aarch64.neon.sqshl" {{%.*}}, [[CONST]] : (!s64i, !s64i) -> !s64i
+
+// LLVM-SAME: i64 {{.*}}[[A:%.*]])
+// LLVM:      [[VQSHL_N:%.*]] = call i64 @llvm.aarch64.neon.sqshl.i64(i64 [[A]], i64 63)
+// LLVM:      ret i64 [[VQSHL_N]]
+  return (int64_t)vqshld_n_s64(a, 63);
+}
+
 // LLVM-LABEL: @test_vnegd_s64
 // CIR-LABEL: @vnegd_s64
 int64_t test_vnegd_s64(int64_t a) {
diff --git a/clang/test/CodeGen/AArch64/neon/vector-sat-left.c b/clang/test/CodeGen/AArch64/neon/vector-sat-left.c
deleted file mode 100644
index 8759346136117..0000000000000
--- a/clang/test/CodeGen/AArch64/neon/vector-sat-left.c
+++ /dev/null
@@ -1,81 +0,0 @@
-// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
-// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +neon \
-// RUN:   -emit-llvm -o - %s \
-// RUN: | FileCheck %s --check-prefix=LLVM
-#include<arm_neon.h>
-
-
-// LLVM-LABEL: define dso_local i64 @test_vqshlud_n_s64(
-// LLVM-SAME: i64 noundef [[A:%.*]]) #[[ATTR0:[0-9]+]] {
-// LLVM-NEXT:  [[ENTRY:.*:]]
-// LLVM-NEXT:    [[A_ADDR:%.*]] = alloca i64, align 8
-// LLVM-NEXT:    [[__RET:%.*]] = alloca i64, align 8
-// LLVM-NEXT:    [[__S0:%.*]] = alloca i64, align 8
-// LLVM-NEXT:    [[REF_TMP:%.*]] = alloca i64, align 8
-// LLVM-NEXT:    [[TMP:%.*]] = alloca i64, align 8
-// LLVM-NEXT:    store i64 [[A]], ptr [[A_ADDR]], align 8
-// LLVM-NEXT:    [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8
-// LLVM-NEXT:    store i64 [[TMP0]], ptr [[__S0]], align 8
-// LLVM-NEXT:    [[TMP1:%.*]] = load i64, ptr [[__S0]], align 8
-// LLVM-NEXT:    [[VQSHLU_N:%.*]] = call i64 @llvm.aarch64.neon.sqshlu.i64(i64 [[TMP1]], i64 1)
-// LLVM-NEXT:    store i64 [[VQSHLU_N]], ptr [[REF_TMP]], align 8
-// LLVM-NEXT:    [[TMP2:%.*]] = load i64, ptr [[REF_TMP]], align 8
-// LLVM-NEXT:    store i64 [[TMP2]], ptr [[__RET]], align 8
-// LLVM-NEXT:    [[TMP3:%.*]] = load i64, ptr [[__RET]], align 8
-// LLVM-NEXT:    store i64 [[TMP3]], ptr [[TMP]], align 8
-// LLVM-NEXT:    [[TMP4:%.*]] = load i64, ptr [[TMP]], align 8
-// LLVM-NEXT:    ret i64 [[TMP4]]
-//
-int64_t test_vqshlud_n_s64(int64_t a) {
-  return vqshlud_n_s64(a, 1);
-}
-
-// LLVM-LABEL: define dso_local i64 @test_vqshld_n_s64(
-// LLVM-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] {
-// LLVM-NEXT:  [[ENTRY:.*:]]
-// LLVM-NEXT:    [[A_ADDR:%.*]] = alloca i64, align 8
-// LLVM-NEXT:    [[__RET:%.*]] = alloca i64, align 8
-// LLVM-NEXT:    [[__S0:%.*]] = alloca i64, align 8
-// LLVM-NEXT:    [[REF_TMP:%.*]] = alloca i64, align 8
-// LLVM-NEXT:    [[TMP:%.*]] = alloca i64, align 8
-// LLVM-NEXT:    store i64 [[A]], ptr [[A_ADDR]], align 8
-// LLVM-NEXT:    [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8
-// LLVM-NEXT:    store i64 [[TMP0]], ptr [[__S0]], align 8
-// LLVM-NEXT:    [[TMP1:%.*]] = load i64, ptr [[__S0]], align 8
-// LLVM-NEXT:    [[VQSHL_N:%.*]] = call i64 @llvm.aarch64.neon.sqshl.i64(i64 [[TMP1]], i64 1)
-// LLVM-NEXT:    store i64 [[VQSHL_N]], ptr [[REF_TMP]], align 8
-// LLVM-NEXT:    [[TMP2:%.*]] = load i64, ptr [[REF_TMP]], align 8
-// LLVM-NEXT:    store i64 [[TMP2]], ptr [[__RET]], align 8
-// LLVM-NEXT:    [[TMP3:%.*]] = load i64, ptr [[__RET]], align 8
-// LLVM-NEXT:    store i64 [[TMP3]], ptr [[TMP]], align 8
-// LLVM-NEXT:    [[TMP4:%.*]] = load i64, ptr [[TMP]], align 8
-// LLVM-NEXT:    ret i64 [[TMP4]]
-//
-int64_t test_vqshld_n_s64(int64_t a) {
-  return vqshld_n_s64(a, 1);
-}
-
-// LLVM-LABEL: define dso_local i64 @test_vqshld_n_u64(
-// LLVM-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] {
-// LLVM-NEXT:  [[ENTRY:.*:]]
-// LLVM-NEXT:    [[A_ADDR:%.*]] = alloca i64, align 8
-// LLVM-NEXT:    [[__RET:%.*]] = alloca i64, align 8
-// LLVM-NEXT:    [[__S0:%.*]] = alloca i64, align 8
-// LLVM-NEXT:    [[REF_TMP:%.*]] = alloca i64, align 8
-// LLVM-NEXT:    [[TMP:%.*]] = alloca i64, align 8
-// LLVM-NEXT:    store i64 [[A]], ptr [[A_ADDR]], align 8
-// LLVM-NEXT:    [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8
-// LLVM-NEXT:    store i64 [[TMP0]], ptr [[__S0]], align 8
-// LLVM-NEXT:    [[TMP1:%.*]] = load i64, ptr [[__S0]], align 8
-// LLVM-NEXT:    [[VQSHL_N:%.*]] = call i64 @llvm.aarch64.neon.uqshl.i64(i64 [[TMP1]], i64 1)
-// LLVM-NEXT:    store i64 [[VQSHL_N]], ptr [[REF_TMP]], align 8
-// LLVM-NEXT:    [[TMP2:%.*]] = load i64, ptr [[REF_TMP]], align 8
-// LLVM-NEXT:    store i64 [[TMP2]], ptr [[__RET]], align 8
-// LLVM-NEXT:    [[TMP3:%.*]] = load i64, ptr [[__RET]], align 8
-// LLVM-NEXT:    store i64 [[TMP3]], ptr [[TMP]], align 8
-// LLVM-NEXT:    [[TMP4:%.*]] = load i64, ptr [[TMP]], align 8
-// LLVM-NEXT:    ret i64 [[TMP4]]
-//
-uint64_t test_vqshld_n_u64(uint64_t a) {
-  return vqshld_n_u64(a, 1);
-}

>From 44a8b08aa6abbc0a1dba1c2dfd58ec51a1f6e3c2 Mon Sep 17 00:00:00 2001
From: Kartik Ohlan <kartik7ohlan at gmail.com>
Date: Tue, 21 Apr 2026 12:53:16 -0400
Subject: [PATCH 4/8] Added vqshl_v and vqshlq_v

---
 clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 60ac79c514350..82f5216d51421 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -421,6 +421,16 @@ static mlir::Value emitCommonNeonBuiltinExpr(
   case NEON::BI__builtin_neon_vqdmulh_laneq_v:
   case NEON::BI__builtin_neon_vqrdmulhq_laneq_v:
   case NEON::BI__builtin_neon_vqrdmulh_laneq_v:
+  case NEON::BI__builtin_neon_vqshl_v:
+  case NEON::BI__builtin_neon_vqshlq_v: {
+    llvm::StringRef llvmIntrName =
+        getLLVMIntrNameNoPrefix(static_cast<llvm::Intrinsic::ID>(
+            usgn ? llvmIntrinsic : altLLVMIntrinsic));
+    return emitNeonCall(cgf.getCIRGenModule(), cgf.getBuilder(), {vTy, vTy},
+                        ops, llvmIntrName, vTy, loc);
+          )
+      )
+  }
   case NEON::BI__builtin_neon_vqshl_n_v:
   case NEON::BI__builtin_neon_vqshlq_n_v:
   case NEON::BI__builtin_neon_vqshlu_n_v:

>From 782f0110a86855111e973833899b723e6e818534 Mon Sep 17 00:00:00 2001
From: Kartik Ohlan <kartik7ohlan at gmail.com>
Date: Wed, 22 Apr 2026 10:02:04 -0400
Subject: [PATCH 5/8] Revert to orginal version

---
 .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp  | 10 -------
 clang/test/CodeGen/AArch64/neon-intrinsics.c  | 30 -------------------
 clang/test/CodeGen/AArch64/neon/intrinsics.c  |  4 +++
 3 files changed, 4 insertions(+), 40 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 82f5216d51421..60ac79c514350 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -421,16 +421,6 @@ static mlir::Value emitCommonNeonBuiltinExpr(
   case NEON::BI__builtin_neon_vqdmulh_laneq_v:
   case NEON::BI__builtin_neon_vqrdmulhq_laneq_v:
   case NEON::BI__builtin_neon_vqrdmulh_laneq_v:
-  case NEON::BI__builtin_neon_vqshl_v:
-  case NEON::BI__builtin_neon_vqshlq_v: {
-    llvm::StringRef llvmIntrName =
-        getLLVMIntrNameNoPrefix(static_cast<llvm::Intrinsic::ID>(
-            usgn ? llvmIntrinsic : altLLVMIntrinsic));
-    return emitNeonCall(cgf.getCIRGenModule(), cgf.getBuilder(), {vTy, vTy},
-                        ops, llvmIntrName, vTy, loc);
-          )
-      )
-  }
   case NEON::BI__builtin_neon_vqshl_n_v:
   case NEON::BI__builtin_neon_vqshlq_n_v:
   case NEON::BI__builtin_neon_vqshlu_n_v:
diff --git a/clang/test/CodeGen/AArch64/neon-intrinsics.c b/clang/test/CodeGen/AArch64/neon-intrinsics.c
index 4d511e508430d..57d59d0572504 100644
--- a/clang/test/CodeGen/AArch64/neon-intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon-intrinsics.c
@@ -17287,16 +17287,6 @@ int32_t test_vqshls_n_s32(int32_t a) {
   return (int32_t)vqshls_n_s32(a, 31);
 }
 
-// CHECK-LABEL: define dso_local i64 @test_vqshld_n_s64(
-// CHECK-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[VQSHL_N:%.*]] = call i64 @llvm.aarch64.neon.sqshl.i64(i64 [[A]], i64 63)
-// CHECK-NEXT:    ret i64 [[VQSHL_N]]
-//
-int64_t test_vqshld_n_s64(int64_t a) {
-  return (int64_t)vqshld_n_s64(a, 63);
-}
-
 // CHECK-LABEL: define dso_local <8 x i8> @test_vqshl_n_s8(
 // CHECK-SAME: <8 x i8> noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
@@ -17503,16 +17493,6 @@ uint32_t test_vqshls_n_u32(uint32_t a) {
   return (uint32_t)vqshls_n_u32(a, 31);
 }
 
-// CHECK-LABEL: define dso_local i64 @test_vqshld_n_u64(
-// CHECK-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[VQSHL_N:%.*]] = call i64 @llvm.aarch64.neon.uqshl.i64(i64 [[A]], i64 63)
-// CHECK-NEXT:    ret i64 [[VQSHL_N]]
-//
-uint64_t test_vqshld_n_u64(uint64_t a) {
-  return (uint64_t)vqshld_n_u64(a, 63);
-}
-
 // CHECK-LABEL: define dso_local <1 x i64> @test_vqshl_n_u64(
 // CHECK-SAME: <1 x i64> noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
@@ -17559,16 +17539,6 @@ int32_t test_vqshlus_n_s32(int32_t a) {
   return (int32_t)vqshlus_n_s32(a, 31);
 }
 
-// CHECK-LABEL: define dso_local i64 @test_vqshlud_n_s64(
-// CHECK-SAME: i64 noundef [[A:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  [[ENTRY:.*:]]
-// CHECK-NEXT:    [[VQSHLU_N:%.*]] = call i64 @llvm.aarch64.neon.sqshlu.i64(i64 [[A]], i64 63)
-// CHECK-NEXT:    ret i64 [[VQSHLU_N]]
-//
-int64_t test_vqshlud_n_s64(int64_t a) {
-  return (int64_t)vqshlud_n_s64(a, 63);
-}
-
 // CHECK-LABEL: define dso_local <1 x i64> @test_vqshlu_n_s64(
 // CHECK-SAME: <1 x i64> noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
diff --git a/clang/test/CodeGen/AArch64/neon/intrinsics.c b/clang/test/CodeGen/AArch64/neon/intrinsics.c
index 5e05fc555eb9f..0021c7822b8d5 100644
--- a/clang/test/CodeGen/AArch64/neon/intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon/intrinsics.c
@@ -24,6 +24,10 @@
 
 #include <arm_neon.h>
 
+//===------------------------------------------------------===//
+// 2.1.3.1 Vector Saturating left
+//===------------------------------------------------------===//
+
 // LLVM-LABEL: @test_vqshlud_n_s64(
 // CIR-LABEL: @test_vqshlud_n_s64(
 int64_t test_vqshlud_n_s64(int64_t a) {

>From 1ab790e1d716601b4c22f857d6f50703cc76a5d3 Mon Sep 17 00:00:00 2001
From: Kartik Ohlan <kartik7ohlan at gmail.com>
Date: Wed, 22 Apr 2026 17:26:24 -0400
Subject: [PATCH 6/8] Added cgm.error.nyi

---
 .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp  | 22 ++++++++++++-------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 60ac79c514350..505863cd8af40 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -2178,23 +2178,29 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr,
   case NEON::BI__builtin_neon_vqdmlalh_s16:
   case NEON::BI__builtin_neon_vqdmlslh_s16:
   case NEON::BI__builtin_neon_vqshlud_n_s64: {
-    cir::IntType intType = builder.getSInt64Ty();
+    cgm.errorNYI(expr->getSourceRange(),
+                 std::string("unimplemented AArch64 builtin call: ") +
+                     getContext().BuiltinInfo.getName(builtinID));
+    cir::IntType int64Type = builder.getSInt64Ty();
     ops[1] = builder.getSInt64(getZExtIntValueFromConstOp(ops[1]), loc);
-    return emitNeonCall(cgm, builder, {intType, intType}, ops,
+    return emitNeonCall(cgm, builder, {int64Type, int64Type}, ops,
                         "aarch64.neon.sqshlu", convertType(expr->getType()),
                         loc);
   }
   case NEON::BI__builtin_neon_vqshld_n_u64:
   case NEON::BI__builtin_neon_vqshld_n_s64: {
-    cir::IntType intType = builtinID == NEON::BI__builtin_neon_vqshld_n_u64
-                               ? builder.getUInt64Ty()
-                               : builder.getSInt64Ty();
+    cgm.errorNYI(expr->getSourceRange(),
+                 std::string("unimplemented AArch64 builtin call: ") +
+                     getContext().BuiltinInfo.getName(builtinID));
+    cir::IntType int64Type = builtinID == NEON::BI__builtin_neon_vqshld_n_u64
+                                 ? builder.getUInt64Ty()
+                                 : builder.getSInt64Ty();
     llvm::StringRef intrinsicName =
         builtinID == NEON::BI__builtin_neon_vqshld_n_u64 ? "aarch64.neon.uqshl"
                                                          : "aarch64.neon.sqshl";
-    ops[1] = builder.createIntCast(ops[1], intType);
-    return emitNeonCall(cgm, builder, {intType, intType}, ops, intrinsicName,
-                        convertType(expr->getType()), loc);
+    ops[1] = builder.getSInt64(getZExtIntValueFromConstOp(ops[1]), loc);
+    return emitNeonCall(cgm, builder, {int64Type, int64Type}, ops,
+                        intrinsicName, convertType(expr->getType()), loc);
   }
   case NEON::BI__builtin_neon_vrshrd_n_u64:
   case NEON::BI__builtin_neon_vrshrd_n_s64:

>From 133bbcabdd2d0a054a1ad9f031c2eb52165350e3 Mon Sep 17 00:00:00 2001
From: Kartik Ohlan <kartik7ohlan at gmail.com>
Date: Thu, 23 Apr 2026 23:21:34 -0400
Subject: [PATCH 7/8] fixed the cgm

---
 clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 505863cd8af40..06bbe0490ee77 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -2177,10 +2177,11 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr,
   case NEON::BI__builtin_neon_vsubd_u64:
   case NEON::BI__builtin_neon_vqdmlalh_s16:
   case NEON::BI__builtin_neon_vqdmlslh_s16:
-  case NEON::BI__builtin_neon_vqshlud_n_s64: {
     cgm.errorNYI(expr->getSourceRange(),
                  std::string("unimplemented AArch64 builtin call: ") +
                      getContext().BuiltinInfo.getName(builtinID));
+    return mlir::Value{};
+  case NEON::BI__builtin_neon_vqshlud_n_s64: {
     cir::IntType int64Type = builder.getSInt64Ty();
     ops[1] = builder.getSInt64(getZExtIntValueFromConstOp(ops[1]), loc);
     return emitNeonCall(cgm, builder, {int64Type, int64Type}, ops,
@@ -2189,9 +2190,6 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr,
   }
   case NEON::BI__builtin_neon_vqshld_n_u64:
   case NEON::BI__builtin_neon_vqshld_n_s64: {
-    cgm.errorNYI(expr->getSourceRange(),
-                 std::string("unimplemented AArch64 builtin call: ") +
-                     getContext().BuiltinInfo.getName(builtinID));
     cir::IntType int64Type = builtinID == NEON::BI__builtin_neon_vqshld_n_u64
                                  ? builder.getUInt64Ty()
                                  : builder.getSInt64Ty();

>From f5fd34dcd694a78ab41db38145681f85bb8a7174 Mon Sep 17 00:00:00 2001
From: Kartik Ohlan <kartik7ohlan at gmail.com>
Date: Thu, 23 Apr 2026 23:52:25 -0400
Subject: [PATCH 8/8] fixed the test case

---
 clang/test/CodeGen/AArch64/neon/intrinsics.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/clang/test/CodeGen/AArch64/neon/intrinsics.c b/clang/test/CodeGen/AArch64/neon/intrinsics.c
index 0021c7822b8d5..e1a263565f140 100644
--- a/clang/test/CodeGen/AArch64/neon/intrinsics.c
+++ b/clang/test/CodeGen/AArch64/neon/intrinsics.c
@@ -43,8 +43,9 @@ int64_t test_vqshlud_n_s64(int64_t a) {
 // LLVM-LABEL: @test_vqshld_n_u64(
 // CIR-LABEL: @test_vqshld_n_u64(
 uint64_t test_vqshld_n_u64(uint64_t a) {
-// CIR:   [[CONST:%.*]] = cir.const #cir.int<63> : !u64i
-// CIR:   {{%.*}} = cir.call_llvm_intrinsic "aarch64.neon.uqshl" {{%.*}}, [[CONST]] : (!u64i, !u64i) -> !u64i
+// CIR:   [[CONST:%.*]] = cir.const #cir.int<63> : !s64i
+// CIR:   [[CAST:%.*]] = cir.cast bitcast [[CONST]] : !s64i -> !u64i
+// CIR:   {{%.*}} = cir.call_llvm_intrinsic "aarch64.neon.uqshl" {{%.*}}, [[CAST]] : (!u64i, !u64i) -> !u64i
 
 // LLVM-SAME: i64 {{.*}}[[A:%.*]])
 // LLVM:      [[VQSHLD_N_U64:%.*]] = call i64 @llvm.aarch64.neon.uqshl.i64(i64 [[A]], i64 63)



More information about the cfe-commits mailing list