[llvm] [LLVM][ValueTracking] Add vector ConstantInt/FP support to isBytewiseValue(). (PR #182519)

Paul Walker via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 20 08:02:17 PST 2026


https://github.com/paulwalker-arm created https://github.com/llvm/llvm-project/pull/182519

None

>From 3a17ea989d5ba69b6d97035734a258925a1971ca Mon Sep 17 00:00:00 2001
From: Paul Walker <paul.walker at arm.com>
Date: Wed, 18 Feb 2026 18:00:15 +0000
Subject: [PATCH 1/2] Add tests showing missed optimisation/assertion when
 using ConstantInt/FP for vector constants.

---
 .../store-to-memset-constant-splat.ll         | 44 +++++++++++++++++++
 1 file changed, 44 insertions(+)
 create mode 100644 llvm/test/Transforms/MemCpyOpt/store-to-memset-constant-splat.ll

diff --git a/llvm/test/Transforms/MemCpyOpt/store-to-memset-constant-splat.ll b/llvm/test/Transforms/MemCpyOpt/store-to-memset-constant-splat.ll
new file mode 100644
index 0000000000000..b32c245871943
--- /dev/null
+++ b/llvm/test/Transforms/MemCpyOpt/store-to-memset-constant-splat.ll
@@ -0,0 +1,44 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=memcpyopt < %s | FileCheck %s --check-prefix=CHECK
+; RUN: opt -S -passes=memcpyopt -use-constant-fp-for-fixed-length-splat < %s | FileCheck %s --check-prefix=CHECK-CFP
+
+; NOTE: -use-constant-int-for-fixed-length-splat triggers an assert.
+define void @store_to_memst_vec_constant_int(ptr %p) {
+; CHECK-LABEL: define void @store_to_memst_vec_constant_int(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P]], i64 16
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 16 [[P]], i8 1, i64 32, i1 false)
+; CHECK-NEXT:    ret void
+;
+; CHECK-CFP-LABEL: define void @store_to_memst_vec_constant_int(
+; CHECK-CFP-SAME: ptr [[P:%.*]]) {
+; CHECK-CFP-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P]], i64 16
+; CHECK-CFP-NEXT:    call void @llvm.memset.p0.i64(ptr align 16 [[P]], i8 1, i64 32, i1 false)
+; CHECK-CFP-NEXT:    ret void
+;
+  store <16 x i8> splat (i8 1), ptr %p, align 16
+  %p1 = getelementptr i8, ptr %p, i64 16
+  store <16 x i8> splat (i8 1), ptr %p1, align 16
+  ret void
+}
+
+define void @store_to_memst_vec_constant_fp(ptr %p) {
+; CHECK-LABEL: define void @store_to_memst_vec_constant_fp(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P]], i64 16
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 16 [[P]], i8 1, i64 32, i1 false)
+; CHECK-NEXT:    ret void
+;
+; CHECK-CFP-LABEL: define void @store_to_memst_vec_constant_fp(
+; CHECK-CFP-SAME: ptr [[P:%.*]]) {
+; CHECK-CFP-NEXT:    store <4 x float> splat (float 0x3820202020000000), ptr [[P]], align 16
+; CHECK-CFP-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P]], i64 16
+; CHECK-CFP-NEXT:    store <4 x float> splat (float 0x3820202020000000), ptr [[P1]], align 16
+; CHECK-CFP-NEXT:    ret void
+;
+  store <4 x float> splat (float 2.3694278276172396e-38), ptr %p, align 16
+  %p1 = getelementptr i8, ptr %p, i64 16
+  store <4 x float> splat (float 2.3694278276172396e-38), ptr %p1, align 16
+  ret void
+}
+

>From 3538461964204f34103d051543441e9b848208f4 Mon Sep 17 00:00:00 2001
From: Paul Walker <paul.walker at arm.com>
Date: Thu, 19 Feb 2026 10:54:07 +0000
Subject: [PATCH 2/2] [LLVM][ValueTracking] Add vector ConstantInt/FP support
 to isBytewiseValue.

---
 llvm/lib/Analysis/ValueTracking.cpp            | 16 ++++++----------
 .../store-to-memset-constant-splat.ll          | 18 ++----------------
 2 files changed, 8 insertions(+), 26 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 2d78aa4be3455..3e46b6eb23ad9 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -6282,22 +6282,18 @@ Value *llvm::isBytewiseValue(Value *V, const DataLayout &DL) {
   // Constant floating-point values can be handled as integer values if the
   // corresponding integer value is "byteable".  An important case is 0.0.
   if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
-    Type *Ty = nullptr;
-    if (CFP->getType()->isHalfTy())
-      Ty = Type::getInt16Ty(Ctx);
-    else if (CFP->getType()->isFloatTy())
-      Ty = Type::getInt32Ty(Ctx);
-    else if (CFP->getType()->isDoubleTy())
-      Ty = Type::getInt64Ty(Ctx);
+    Type *ScalarTy = CFP->getType()->getScalarType();
+    if (ScalarTy->isHalfTy() || ScalarTy->isFloatTy() || ScalarTy->isDoubleTy())
+      return isBytewiseValue(
+          ConstantInt::get(Ctx, CFP->getValue().bitcastToAPInt()), DL);
+
     // Don't handle long double formats, which have strange constraints.
-    return Ty ? isBytewiseValue(ConstantExpr::getBitCast(CFP, Ty), DL)
-              : nullptr;
+    return nullptr;
   }
 
   // We can handle constant integers that are multiple of 8 bits.
   if (ConstantInt *CI = dyn_cast<ConstantInt>(C)) {
     if (CI->getBitWidth() % 8 == 0) {
-      assert(CI->getBitWidth() > 8 && "8 bits should be handled above!");
       if (!CI->getValue().isSplat(8))
         return nullptr;
       return ConstantInt::get(Ctx, CI->getValue().trunc(8));
diff --git a/llvm/test/Transforms/MemCpyOpt/store-to-memset-constant-splat.ll b/llvm/test/Transforms/MemCpyOpt/store-to-memset-constant-splat.ll
index b32c245871943..55c68fad8dfaa 100644
--- a/llvm/test/Transforms/MemCpyOpt/store-to-memset-constant-splat.ll
+++ b/llvm/test/Transforms/MemCpyOpt/store-to-memset-constant-splat.ll
@@ -1,20 +1,13 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
-; RUN: opt -S -passes=memcpyopt < %s | FileCheck %s --check-prefix=CHECK
-; RUN: opt -S -passes=memcpyopt -use-constant-fp-for-fixed-length-splat < %s | FileCheck %s --check-prefix=CHECK-CFP
+; RUN: opt -S -passes=memcpyopt < %s | FileCheck %s
+; RUN: opt -S -passes=memcpyopt -use-constant-int-for-fixed-length-splat -use-constant-fp-for-fixed-length-splat < %s | FileCheck %s
 
-; NOTE: -use-constant-int-for-fixed-length-splat triggers an assert.
 define void @store_to_memst_vec_constant_int(ptr %p) {
 ; CHECK-LABEL: define void @store_to_memst_vec_constant_int(
 ; CHECK-SAME: ptr [[P:%.*]]) {
 ; CHECK-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P]], i64 16
 ; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 16 [[P]], i8 1, i64 32, i1 false)
 ; CHECK-NEXT:    ret void
-;
-; CHECK-CFP-LABEL: define void @store_to_memst_vec_constant_int(
-; CHECK-CFP-SAME: ptr [[P:%.*]]) {
-; CHECK-CFP-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P]], i64 16
-; CHECK-CFP-NEXT:    call void @llvm.memset.p0.i64(ptr align 16 [[P]], i8 1, i64 32, i1 false)
-; CHECK-CFP-NEXT:    ret void
 ;
   store <16 x i8> splat (i8 1), ptr %p, align 16
   %p1 = getelementptr i8, ptr %p, i64 16
@@ -28,13 +21,6 @@ define void @store_to_memst_vec_constant_fp(ptr %p) {
 ; CHECK-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P]], i64 16
 ; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 16 [[P]], i8 1, i64 32, i1 false)
 ; CHECK-NEXT:    ret void
-;
-; CHECK-CFP-LABEL: define void @store_to_memst_vec_constant_fp(
-; CHECK-CFP-SAME: ptr [[P:%.*]]) {
-; CHECK-CFP-NEXT:    store <4 x float> splat (float 0x3820202020000000), ptr [[P]], align 16
-; CHECK-CFP-NEXT:    [[P1:%.*]] = getelementptr i8, ptr [[P]], i64 16
-; CHECK-CFP-NEXT:    store <4 x float> splat (float 0x3820202020000000), ptr [[P1]], align 16
-; CHECK-CFP-NEXT:    ret void
 ;
   store <4 x float> splat (float 2.3694278276172396e-38), ptr %p, align 16
   %p1 = getelementptr i8, ptr %p, i64 16



More information about the llvm-commits mailing list