[clang] [llvm] NEON intrinsic compilation error with -fno-lax-vector-conversion flag fix (PR #149329)

Amina Chabane via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 17 08:01:57 PDT 2025


https://github.com/Amichaxx created https://github.com/llvm/llvm-project/pull/149329

Issue originally raised in https://github.com/llvm/llvm-project/issues/71362#issuecomment-3028515618. Certain NEON intrinsics that operate on poly types (e.g. poly8x8_t) failed to compile with the -fno-lax-vector-conversions flag. This patch updates NeonEmitter.cpp to insert an explicit __builtin_bit_cast from poly types to the required signed integer vector types when generating lane-related intrinsics. A test 'neon-bitcast-poly.ll' is included.

>From 2895e5e7b56c1c611b39a5c85de92d18f3aae71a Mon Sep 17 00:00:00 2001
From: Amina Chabane <amina.chabane at arm.com>
Date: Tue, 15 Jul 2025 15:56:49 +0000
Subject: [PATCH 1/3] [AArch64][NEON] Fix poly lane intrinsics under
 -fno-lax-vector-conversions. Issue originally raised in
 https://github.com/llvm/llvm-project/issues/71362#issuecomment-3028515618.
 Certain NEON intrinsics that operate on poly types (e.g. poly8x8_t) failed to
 compile with the -fno-lax-vector-conversions flag. This patch updates
 NeonEmitter.cpp to insert an explicit __builtin_bit_cast from poly types to
 the required signed integer vector types when generating lane-based
 intrinsics. A test neon-bitcast-poly is included.

---
 clang/utils/TableGen/NeonEmitter.cpp          | 10 +++-
 .../test/CodeGen/AArch64/neon-bitcast-poly.ll | 51 +++++++++++++++++++
 2 files changed, 60 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/AArch64/neon-bitcast-poly.ll

diff --git a/clang/utils/TableGen/NeonEmitter.cpp b/clang/utils/TableGen/NeonEmitter.cpp
index 409f1c4f71834..574a29d0e4dd9 100644
--- a/clang/utils/TableGen/NeonEmitter.cpp
+++ b/clang/utils/TableGen/NeonEmitter.cpp
@@ -1401,12 +1401,20 @@ void Intrinsic::emitBodyAsBuiltinCall() {
       if (LocalCK == ClassB || (T.isHalf() && !T.isScalarForMangling())) {
         CastToType.makeInteger(8, true);
         Arg = "__builtin_bit_cast(" + CastToType.str() + ", " + Arg + ")";
+      }
+      else if ((T.isPoly() ||
+          (T.isInteger() && !T.isSigned() &&
+           StringRef(Name).contains("_p8")) ||
+          StringRef(Name).contains("_p16") ||
+          StringRef(Name).contains("_p64"))) {
+            CastToType.makeSigned();
+            Arg = "__builtin_bit_cast(" + CastToType.str() + ", " + Arg + ")";
+      }
       } else if (LocalCK == ClassI) {
         if (CastToType.isInteger()) {
           CastToType.makeSigned();
           Arg = "__builtin_bit_cast(" + CastToType.str() + ", " + Arg + ")";
         }
-      }
     }
 
     S += Arg + ", ";
diff --git a/llvm/test/CodeGen/AArch64/neon-bitcast-poly.ll b/llvm/test/CodeGen/AArch64/neon-bitcast-poly.ll
new file mode 100644
index 0000000000000..b577eb1e34b09
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/neon-bitcast-poly.ll
@@ -0,0 +1,51 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=aarch64-linux-gnu -o - %s | FileCheck %s
+
+; This test verifies that NEON intrinsics using polynomial types (poly8/16/64) emit correct AArch64 instructions
+; after bitcasting to signed integer vectors. These intrinsics would previously fail under -fno-lax-vector-conversions.
+
+define <8 x i8> @_Z18test_vcopy_lane_p811__Poly8x8_tS_(<8 x i8> %a, <8 x i8> %b) {
+; CHECK-LABEL: _Z18test_vcopy_lane_p811__Poly8x8_tS_:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-NEXT:    // kill: def $d1 killed $d1 def $q1
+; CHECK-NEXT:    mov v0.b[0], v1.b[0]
+; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT:    ret
+entry:
+  %vset_lane = shufflevector <8 x i8> %b, <8 x i8> %a, <8 x i32> <i32 0, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+  ret <8 x i8> %vset_lane
+}
+
+define <4 x i16> @_Z18test_vset_lane_p16t12__Poly16x4_t(i16 %val, <4 x i16> %vec) {
+; CHECK-LABEL: _Z18test_vset_lane_p16t12__Poly16x4_t:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-NEXT:    mov v0.h[0], w0
+; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT:    ret
+entry:
+  %vset_lane = insertelement <4 x i16> %vec, i16 %val, i64 0
+  ret <4 x i16> %vset_lane
+}
+
+define i64 @_Z18test_vget_lane_p6412__Poly64x1_t(<1 x i64> %vec){
+; CHECK-LABEL: _Z18test_vget_lane_p6412__Poly64x1_t:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-NEXT:    fmov x0, d0
+; CHECK-NEXT:    ret
+entry:
+  %vget_lane = extractelement <1 x i64> %vec, i64 0
+  ret i64 %vget_lane
+}
+
+define <16 x i8> @_Z18test_vsetq_lane_p8h12__Poly8x16_t(i8 %val, <16 x i8> %vec){
+; CHECK-LABEL: _Z18test_vsetq_lane_p8h12__Poly8x16_t:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    mov v0.b[0], w0
+; CHECK-NEXT:    ret
+entry:
+  %vset_lane = insertelement <16 x i8> %vec, i8 %val, i64 0
+  ret <16 x i8> %vset_lane
+}

>From c300ab6ced97df16728fac0a07c94e38792a2047 Mon Sep 17 00:00:00 2001
From: Amina Chabane <amina.chabane at arm.com>
Date: Wed, 16 Jul 2025 13:53:30 +0000
Subject: [PATCH 2/3] Added isVector() condition to avoid scalar constants.

---
 clang/utils/TableGen/NeonEmitter.cpp | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/clang/utils/TableGen/NeonEmitter.cpp b/clang/utils/TableGen/NeonEmitter.cpp
index 574a29d0e4dd9..d3dd1c5589920 100644
--- a/clang/utils/TableGen/NeonEmitter.cpp
+++ b/clang/utils/TableGen/NeonEmitter.cpp
@@ -1401,22 +1401,19 @@ void Intrinsic::emitBodyAsBuiltinCall() {
       if (LocalCK == ClassB || (T.isHalf() && !T.isScalarForMangling())) {
         CastToType.makeInteger(8, true);
         Arg = "__builtin_bit_cast(" + CastToType.str() + ", " + Arg + ")";
+      } else if ((T.isPoly() || (T.isVector() && T.isInteger() && !T.isSigned() &&
+                  (StringRef(Name).contains("_p8") ||
+                    StringRef(Name).contains("_p16") ||
+                    StringRef(Name).contains("_p64"))))) {
+        CastToType.makeSigned();
+        Arg = "__builtin_bit_cast(" + CastToType.str() + ", " + Arg + ")";
+      } else if (LocalCK == ClassI && CastToType.isInteger()) {
+        CastToType.makeSigned();
+        Arg = "__builtin_bit_cast(" + CastToType.str() + ", " + Arg + ")";
       }
-      else if ((T.isPoly() ||
-          (T.isInteger() && !T.isSigned() &&
-           StringRef(Name).contains("_p8")) ||
-          StringRef(Name).contains("_p16") ||
-          StringRef(Name).contains("_p64"))) {
-            CastToType.makeSigned();
-            Arg = "__builtin_bit_cast(" + CastToType.str() + ", " + Arg + ")";
-      }
-      } else if (LocalCK == ClassI) {
-        if (CastToType.isInteger()) {
-          CastToType.makeSigned();
-          Arg = "__builtin_bit_cast(" + CastToType.str() + ", " + Arg + ")";
-        }
     }
 
+
     S += Arg + ", ";
   }
 

>From 102ca6f20dac9e2c5a458ee5e637e517f242c949 Mon Sep 17 00:00:00 2001
From: Amina Chabane <amina.chabane at arm.com>
Date: Thu, 17 Jul 2025 14:42:43 +0000
Subject: [PATCH 3/3] Newline deletion

---
 clang/utils/TableGen/NeonEmitter.cpp | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/clang/utils/TableGen/NeonEmitter.cpp b/clang/utils/TableGen/NeonEmitter.cpp
index d3dd1c5589920..1bd8c8b58c396 100644
--- a/clang/utils/TableGen/NeonEmitter.cpp
+++ b/clang/utils/TableGen/NeonEmitter.cpp
@@ -1402,9 +1402,9 @@ void Intrinsic::emitBodyAsBuiltinCall() {
         CastToType.makeInteger(8, true);
         Arg = "__builtin_bit_cast(" + CastToType.str() + ", " + Arg + ")";
       } else if ((T.isPoly() || (T.isVector() && T.isInteger() && !T.isSigned() &&
-                  (StringRef(Name).contains("_p8") ||
-                    StringRef(Name).contains("_p16") ||
-                    StringRef(Name).contains("_p64"))))) {
+                (StringRef(Name).contains("_p8") ||
+                  StringRef(Name).contains("_p16") ||
+                  StringRef(Name).contains("_p64"))))) {
         CastToType.makeSigned();
         Arg = "__builtin_bit_cast(" + CastToType.str() + ", " + Arg + ")";
       } else if (LocalCK == ClassI && CastToType.isInteger()) {
@@ -1412,8 +1412,6 @@ void Intrinsic::emitBodyAsBuiltinCall() {
         Arg = "__builtin_bit_cast(" + CastToType.str() + ", " + Arg + ")";
       }
     }
-
-
     S += Arg + ", ";
   }
 



More information about the cfe-commits mailing list