[llvm] [SLP]Invalid cost for non-power-of-2 bswaps (PR #185407)

Alexey Bataev via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 9 05:41:11 PDT 2026


https://github.com/alexey-bataev updated https://github.com/llvm/llvm-project/pull/185407

>From 2ec8414a243ff81da4eb8231882f80eea8c3eaa8 Mon Sep 17 00:00:00 2001
From: Alexey Bataev <a.bataev at outlook.com>
Date: Mon, 9 Mar 2026 05:38:59 -0700
Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20in?=
 =?UTF-8?q?itial=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.7
---
 .../llvm/Analysis/TargetTransformInfoImpl.h   |  3 ++
 .../SLPVectorizer/non-power-of-2-bswap.ll     | 33 +++++++++++++++++++
 2 files changed, 36 insertions(+)
 create mode 100644 llvm/test/Transforms/SLPVectorizer/non-power-of-2-bswap.ll

diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
index 6e5d7d308be21..9cbed31dc8e3f 100644
--- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
+++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h
@@ -947,6 +947,9 @@ class TargetTransformInfoImplBase {
     case Intrinsic::ssa_copy:
       // These intrinsics don't actually represent code after lowering.
       return 0;
+    case Intrinsic::bswap:
+      if (!isPowerOf2_64(DL.getTypeSizeInBits(ICA.getReturnType())))
+        return InstructionCost::getInvalid();
     }
     return 1;
   }
diff --git a/llvm/test/Transforms/SLPVectorizer/non-power-of-2-bswap.ll b/llvm/test/Transforms/SLPVectorizer/non-power-of-2-bswap.ll
new file mode 100644
index 0000000000000..42e69b9b44083
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/non-power-of-2-bswap.ll
@@ -0,0 +1,33 @@
+; RUN: opt -passes=slp-vectorizer -S -slp-vectorize-non-power-of-2 < %s | FileCheck %s
+
+define i64 @bswap_i24(ptr noalias %p, ptr noalias %p1) {
+  %g1 = getelementptr i8, ptr %p, i32 1
+  %g2 = getelementptr i8, ptr %p, i32 2
+
+  %t0 = load i8, ptr %p
+  %t1 = load i8, ptr %g1
+  %t2 = load i8, ptr %g2
+
+  %g11 = getelementptr i8, ptr %p1, i32 1
+  %g12 = getelementptr i8, ptr %p1, i32 2
+
+  %t10 = load i8, ptr %p1
+  %t11 = load i8, ptr %g11
+  %t12 = load i8, ptr %g12
+
+  %a0 = add i8 %t0, %t10
+  %a1 = add i8 %t1, %t11
+  %a2 = add i8 %t2, %t12
+
+  %z0 = zext i8 %a0 to i64
+  %z1 = zext i8 %a1 to i64
+  %z2 = zext i8 %a2 to i64
+
+  %sh0 = shl nuw i64 %z0, 16
+  %sh1 = shl nuw nsw i64 %z1, 8
+
+  %or01 = or disjoint i64 %sh0, %sh1
+  %or012 = or disjoint i64 %or01, %z2
+
+  ret i64 %or012
+}

>From daf873444471073da9fa4921ae259d83b6a132db Mon Sep 17 00:00:00 2001
From: Alexey Bataev <a.bataev at outlook.com>
Date: Mon, 9 Mar 2026 05:41:01 -0700
Subject: [PATCH 2/2] Add checks

Created using spr 1.3.7
---
 .../SLPVectorizer/non-power-of-2-bswap.ll     | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/llvm/test/Transforms/SLPVectorizer/non-power-of-2-bswap.ll b/llvm/test/Transforms/SLPVectorizer/non-power-of-2-bswap.ll
index 42e69b9b44083..f0369e06d07fc 100644
--- a/llvm/test/Transforms/SLPVectorizer/non-power-of-2-bswap.ll
+++ b/llvm/test/Transforms/SLPVectorizer/non-power-of-2-bswap.ll
@@ -1,6 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
 ; RUN: opt -passes=slp-vectorizer -S -slp-vectorize-non-power-of-2 < %s | FileCheck %s
 
 define i64 @bswap_i24(ptr noalias %p, ptr noalias %p1) {
+; CHECK-LABEL: define i64 @bswap_i24(
+; CHECK-SAME: ptr noalias [[P:%.*]], ptr noalias [[P1:%.*]]) {
+; CHECK-NEXT:    [[G2:%.*]] = getelementptr i8, ptr [[P]], i32 2
+; CHECK-NEXT:    [[T2:%.*]] = load i8, ptr [[G2]], align 1
+; CHECK-NEXT:    [[G12:%.*]] = getelementptr i8, ptr [[P1]], i32 2
+; CHECK-NEXT:    [[T12:%.*]] = load i8, ptr [[G12]], align 1
+; CHECK-NEXT:    [[A2:%.*]] = add i8 [[T2]], [[T12]]
+; CHECK-NEXT:    [[Z2:%.*]] = zext i8 [[A2]] to i64
+; CHECK-NEXT:    [[TMP1:%.*]] = load <2 x i8>, ptr [[P]], align 1
+; CHECK-NEXT:    [[TMP2:%.*]] = load <2 x i8>, ptr [[P1]], align 1
+; CHECK-NEXT:    [[TMP3:%.*]] = add <2 x i8> [[TMP1]], [[TMP2]]
+; CHECK-NEXT:    [[TMP4:%.*]] = zext <2 x i8> [[TMP3]] to <2 x i32>
+; CHECK-NEXT:    [[TMP5:%.*]] = shl <2 x i32> [[TMP4]], <i32 16, i32 8>
+; CHECK-NEXT:    [[TMP6:%.*]] = extractelement <2 x i32> [[TMP5]], i32 0
+; CHECK-NEXT:    [[TMP7:%.*]] = zext i32 [[TMP6]] to i64
+; CHECK-NEXT:    [[TMP8:%.*]] = extractelement <2 x i32> [[TMP5]], i32 1
+; CHECK-NEXT:    [[TMP9:%.*]] = zext i32 [[TMP8]] to i64
+; CHECK-NEXT:    [[OR01:%.*]] = or disjoint i64 [[TMP7]], [[TMP9]]
+; CHECK-NEXT:    [[OR012:%.*]] = or disjoint i64 [[OR01]], [[Z2]]
+; CHECK-NEXT:    ret i64 [[OR012]]
+;
   %g1 = getelementptr i8, ptr %p, i32 1
   %g2 = getelementptr i8, ptr %p, i32 2
 



More information about the llvm-commits mailing list