[llvm] [ConstantFolding] Increase folding limit for vector loads to 128 bytes (PR #192775)
Wenju He via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 21 01:49:59 PDT 2026
https://github.com/wenju-he updated https://github.com/llvm/llvm-project/pull/192775
>From 7a0112027addd65649c075d033c22441ad7ea2e2 Mon Sep 17 00:00:00 2001
From: Wenju He <wenju.he at intel.com>
Date: Sat, 18 Apr 2026 01:07:24 -0700
Subject: [PATCH 1/7] [ConstantFolding] Fold array to vector in
ConstantFoldLoadThroughBitcast
In FoldReinterpretLoadFromConst, ReadDataFromGlobal bails out when
BytesLoaded exceeds 32 bytes. This prevent folding in our downstream
OpenCL case where global constant is [16 x float] array and is loaded
as float16 vector, which is 64 bytes.
This PR addresses the issue in ConstantFoldLoadThroughBitcast by folding
array to vector when element type and count are the same.
---
llvm/lib/Analysis/ConstantFolding.cpp | 15 +++++++++++++++
.../EarlyCSE/load-constant-array-as-vector.ll | 10 ++++++++++
2 files changed, 25 insertions(+)
create mode 100644 llvm/test/Transforms/EarlyCSE/load-constant-array-as-vector.ll
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index cb8ecc3872c0c..7fff92d28d03f 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -381,6 +381,21 @@ Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy,
if (CastInst::castIsValid(Cast, C, DestTy))
return ConstantFoldCastOperand(Cast, C, DestTy, DL);
+
+ // Fold [N x T] array to <N x T> vector.
+ auto *FVTy = dyn_cast<FixedVectorType>(DestTy);
+ auto *ArrTy = dyn_cast<ArrayType>(SrcTy);
+ if (FVTy && ArrTy && ArrTy->getNumElements() == FVTy->getNumElements() &&
+ ArrTy->getElementType() == FVTy->getElementType()) {
+ SmallVector<Constant *, 16> Elems;
+ for (unsigned I = 0, E = ArrTy->getNumElements(); I != E; ++I) {
+ Constant *Elt = C->getAggregateElement(I);
+ if (!Elt)
+ return nullptr;
+ Elems.push_back(Elt);
+ }
+ return ConstantVector::get(Elems);
+ }
}
// If this isn't an aggregate type, there is nothing we can do to drill down
diff --git a/llvm/test/Transforms/EarlyCSE/load-constant-array-as-vector.ll b/llvm/test/Transforms/EarlyCSE/load-constant-array-as-vector.ll
new file mode 100644
index 0000000000000..12d2f53237bf2
--- /dev/null
+++ b/llvm/test/Transforms/EarlyCSE/load-constant-array-as-vector.ll
@@ -0,0 +1,10 @@
+; RUN: opt -passes=early-cse -S < %s | FileCheck %s
+
+ at d16 = private constant [16 x double] [double 1.0, double 2.0, double 3.0, double 4.0, double 5.0, double 6.0, double 7.0, double 8.0, double 9.0, double 10.0, double 11.0, double 12.0, double 13.0, double 14.0, double 15.0, double 16.0], align 128
+
+define double @fold_16xdouble_load() {
+ ; CHECK: ret double 2.000000e+00
+ %v = load <16 x double>, ptr @d16, align 128
+ %e = extractelement <16 x double> %v, i32 1
+ ret double %e
+}
>From 9a91a15e938670d9dab3bcbc16f65403dcadf571 Mon Sep 17 00:00:00 2001
From: Wenju He <wenju.he at intel.com>
Date: Mon, 20 Apr 2026 09:29:59 +0200
Subject: [PATCH 2/7] revert ConstantFoldLoadThroughBitcast change; increase
BytesLoaded cap to 128 bytes
---
llvm/lib/Analysis/ConstantFolding.cpp | 37 +++++------
.../EarlyCSE/load-constant-array-as-vector.ll | 10 ---
.../load-constant-as-int-or-vector.ll | 62 +++++++++++++++++++
3 files changed, 81 insertions(+), 28 deletions(-)
delete mode 100644 llvm/test/Transforms/EarlyCSE/load-constant-array-as-vector.ll
create mode 100644 llvm/test/Transforms/EarlyCSE/load-constant-as-int-or-vector.ll
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 7fff92d28d03f..54ae48ea72136 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -348,6 +348,15 @@ bool llvm::IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV,
return true;
}
+static bool shouldPreserveLargeStringLoad(Constant *C,
+ uint64_t LoadBytes) {
+ if (LoadBytes <= 32)
+ return false;
+
+ auto *CDS = dyn_cast<ConstantDataSequential>(C);
+ return CDS && CDS->isString();
+}
+
Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy,
const DataLayout &DL) {
do {
@@ -365,6 +374,10 @@ Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy,
if (Constant *Res = ConstantFoldLoadFromUniformValue(C, DestTy, DL))
return Res;
+ if (SrcTy != DestTy && !DestSize.isScalable() &&
+ shouldPreserveLargeStringLoad(C, DestSize.getFixedValue() / 8))
+ return nullptr;
+
// If the type sizes are the same and a cast is legal, just directly
// cast the constant.
// But be careful not to coerce non-integral pointers illegally.
@@ -381,21 +394,6 @@ Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy,
if (CastInst::castIsValid(Cast, C, DestTy))
return ConstantFoldCastOperand(Cast, C, DestTy, DL);
-
- // Fold [N x T] array to <N x T> vector.
- auto *FVTy = dyn_cast<FixedVectorType>(DestTy);
- auto *ArrTy = dyn_cast<ArrayType>(SrcTy);
- if (FVTy && ArrTy && ArrTy->getNumElements() == FVTy->getNumElements() &&
- ArrTy->getElementType() == FVTy->getElementType()) {
- SmallVector<Constant *, 16> Elems;
- for (unsigned I = 0, E = ArrTy->getNumElements(); I != E; ++I) {
- Constant *Elt = C->getAggregateElement(I);
- if (!Elt)
- return nullptr;
- Elems.push_back(Elt);
- }
- return ConstantVector::get(Elems);
- }
}
// If this isn't an aggregate type, there is nothing we can do to drill down
@@ -613,7 +611,10 @@ Constant *FoldReinterpretLoadFromConst(Constant *C, Type *LoadTy,
}
unsigned BytesLoaded = (IntType->getBitWidth() + 7) / 8;
- if (BytesLoaded > 32 || BytesLoaded == 0)
+ if (BytesLoaded > 128 || BytesLoaded == 0)
+ return nullptr;
+
+ if (shouldPreserveLargeStringLoad(C, BytesLoaded))
return nullptr;
// If we're not accessing anything in this constant, the result is undefined.
@@ -629,8 +630,8 @@ Constant *FoldReinterpretLoadFromConst(Constant *C, Type *LoadTy,
if (Offset >= (int64_t)InitializerSize.getFixedValue())
return PoisonValue::get(IntType);
- unsigned char RawBytes[32] = {0};
- unsigned char *CurPtr = RawBytes;
+ SmallVector<unsigned char, 64> RawBytes(BytesLoaded);
+ unsigned char *CurPtr = RawBytes.data();
unsigned BytesLeft = BytesLoaded;
// If we're loading off the beginning of the global, some bytes may be valid.
diff --git a/llvm/test/Transforms/EarlyCSE/load-constant-array-as-vector.ll b/llvm/test/Transforms/EarlyCSE/load-constant-array-as-vector.ll
deleted file mode 100644
index 12d2f53237bf2..0000000000000
--- a/llvm/test/Transforms/EarlyCSE/load-constant-array-as-vector.ll
+++ /dev/null
@@ -1,10 +0,0 @@
-; RUN: opt -passes=early-cse -S < %s | FileCheck %s
-
- at d16 = private constant [16 x double] [double 1.0, double 2.0, double 3.0, double 4.0, double 5.0, double 6.0, double 7.0, double 8.0, double 9.0, double 10.0, double 11.0, double 12.0, double 13.0, double 14.0, double 15.0, double 16.0], align 128
-
-define double @fold_16xdouble_load() {
- ; CHECK: ret double 2.000000e+00
- %v = load <16 x double>, ptr @d16, align 128
- %e = extractelement <16 x double> %v, i32 1
- ret double %e
-}
diff --git a/llvm/test/Transforms/EarlyCSE/load-constant-as-int-or-vector.ll b/llvm/test/Transforms/EarlyCSE/load-constant-as-int-or-vector.ll
new file mode 100644
index 0000000000000..181ae68890be3
--- /dev/null
+++ b/llvm/test/Transforms/EarlyCSE/load-constant-as-int-or-vector.ll
@@ -0,0 +1,62 @@
+; RUN: opt -passes=early-cse -S < %s | FileCheck %s
+
+ at d8 = private constant [8 x double] [double 1.0, double 2.0, double 3.0, double 4.0, double 5.0, double 6.0, double 7.0, double 8.0], align 64
+ at d16 = private constant [16 x double] [double 1.0, double 2.0, double 3.0, double 4.0, double 5.0, double 6.0, double 7.0, double 8.0, double 9.0, double 10.0, double 11.0, double 12.0, double 13.0, double 14.0, double 15.0, double 16.0], align 128
+ at w32 = private constant [32 x i16] [
+ i16 42, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7,
+ i16 8, i16 9, i16 10, i16 11, i16 12, i16 13, i16 14, i16 15,
+ i16 16, i16 17, i16 18, i16 19, i16 20, i16 21, i16 22, i16 23,
+ i16 24, i16 25, i16 26, i16 27, i16 28, i16 29, i16 30, i16 31
+], align 2
+ at str64 = private constant [64 x i8] c"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", align 1
+
+define <8 x double> @fold_8xdouble_load() {
+ ; CHECK-LABEL: @fold_8xdouble_load(
+ ; CHECK: ret <8 x double> <double 1.000000e+00, double 2.000000e+00, double 3.000000e+00, double 4.000000e+00, double 5.000000e+00, double 6.000000e+00, double 7.000000e+00, double 8.000000e+00>
+ %v = load <8 x double>, ptr @d8, align 64
+ ret <8 x double> %v
+}
+
+define double @fold_16xdouble_load() {
+ ; CHECK-LABEL: @fold_16xdouble_load(
+ ; CHECK: ret double 2.000000e+00
+ %v = load <16 x double>, ptr @d16, align 128
+ %e = extractelement <16 x double> %v, i32 1
+ ret double %e
+}
+
+define i16 @fold_array_to_i512() {
+ ; CHECK-LABEL: @fold_array_to_i512(
+ ; CHECK: ret i16 42
+ %v = load i512, ptr @w32, align 2
+ %e = trunc i512 %v to i16
+ ret i16 %e
+}
+
+define i16 @fold_array_to_vec() {
+ ; CHECK-LABEL: @fold_array_to_vec(
+ ; CHECK: ret i16 42
+ %v = load <32 x i16>, ptr @w32, align 2
+ %e = extractelement <32 x i16> %v, i32 0
+ ret i16 %e
+}
+
+define i8 @not_fold_string_to_i512() {
+ ; CHECK-LABEL: @not_fold_string_to_i512(
+ ; CHECK: %v = load i512, ptr @str64, align 1
+ ; CHECK: %e = trunc i512 %v to i8
+ ; CHECK: ret i8 %e
+ %v = load i512, ptr @str64, align 1
+ %e = trunc i512 %v to i8
+ ret i8 %e
+}
+
+define i8 @not_fold_string_to_vec() {
+ ; CHECK-LABEL: @not_fold_string_to_vec(
+ ; CHECK: %v = load <64 x i8>, ptr @str64, align 1
+ ; CHECK: %e = extractelement <64 x i8> %v, i32 0
+ ; CHECK: ret i8 %e
+ %v = load <64 x i8>, ptr @str64, align 1
+ %e = extractelement <64 x i8> %v, i32 0
+ ret i8 %e
+}
>From 3513c4e5244e40b5af15adf782c36ac8ab6cf9f4 Mon Sep 17 00:00:00 2001
From: Wenju He <wenju.he at intel.com>
Date: Mon, 20 Apr 2026 09:56:58 +0200
Subject: [PATCH 3/7] clang-format
---
llvm/lib/Analysis/ConstantFolding.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 54ae48ea72136..3b40bbd90c933 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -348,8 +348,7 @@ bool llvm::IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV,
return true;
}
-static bool shouldPreserveLargeStringLoad(Constant *C,
- uint64_t LoadBytes) {
+static bool shouldPreserveLargeStringLoad(Constant *C, uint64_t LoadBytes) {
if (LoadBytes <= 32)
return false;
>From c8da43d9affbcd0f90a82f148b6daca11829b9d8 Mon Sep 17 00:00:00 2001
From: Wenju He <wenju.he at intel.com>
Date: Mon, 20 Apr 2026 13:52:10 +0200
Subject: [PATCH 4/7] folder vector load, but not large integer load
---
llvm/lib/Analysis/ConstantFolding.cpp | 22 ++-----
.../load-constant-as-int-or-vector.ll | 62 -------------------
.../InstSimplify/ConstProp/loads.ll | 62 +++++++++++++++++++
3 files changed, 68 insertions(+), 78 deletions(-)
delete mode 100644 llvm/test/Transforms/EarlyCSE/load-constant-as-int-or-vector.ll
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 3b40bbd90c933..8a911d26673c1 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -348,14 +348,6 @@ bool llvm::IsConstantOffsetFromGlobal(Constant *C, GlobalValue *&GV,
return true;
}
-static bool shouldPreserveLargeStringLoad(Constant *C, uint64_t LoadBytes) {
- if (LoadBytes <= 32)
- return false;
-
- auto *CDS = dyn_cast<ConstantDataSequential>(C);
- return CDS && CDS->isString();
-}
-
Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy,
const DataLayout &DL) {
do {
@@ -373,10 +365,6 @@ Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy,
if (Constant *Res = ConstantFoldLoadFromUniformValue(C, DestTy, DL))
return Res;
- if (SrcTy != DestTy && !DestSize.isScalable() &&
- shouldPreserveLargeStringLoad(C, DestSize.getFixedValue() / 8))
- return nullptr;
-
// If the type sizes are the same and a cast is legal, just directly
// cast the constant.
// But be careful not to coerce non-integral pointers illegally.
@@ -570,7 +558,8 @@ bool ReadDataFromGlobal(Constant *C, uint64_t ByteOffset, unsigned char *CurPtr,
}
Constant *FoldReinterpretLoadFromConst(Constant *C, Type *LoadTy,
- int64_t Offset, const DataLayout &DL) {
+ Type *RequestedLoadTy, int64_t Offset,
+ const DataLayout &DL) {
// Bail out early. Not expect to load from scalable global variable.
if (isa<ScalableVectorType>(LoadTy))
return nullptr;
@@ -589,7 +578,8 @@ Constant *FoldReinterpretLoadFromConst(Constant *C, Type *LoadTy,
Type *MapTy = Type::getIntNTy(C->getContext(),
DL.getTypeSizeInBits(LoadTy).getFixedValue());
- if (Constant *Res = FoldReinterpretLoadFromConst(C, MapTy, Offset, DL)) {
+ if (Constant *Res = FoldReinterpretLoadFromConst(C, MapTy, RequestedLoadTy,
+ Offset, DL)) {
if (Res->isNullValue() && !LoadTy->isX86_AMXTy())
// Materializing a zero can be done trivially without a bitcast
return Constant::getNullValue(LoadTy);
@@ -613,7 +603,7 @@ Constant *FoldReinterpretLoadFromConst(Constant *C, Type *LoadTy,
if (BytesLoaded > 128 || BytesLoaded == 0)
return nullptr;
- if (shouldPreserveLargeStringLoad(C, BytesLoaded))
+ if (BytesLoaded > 32 && RequestedLoadTy->isIntegerTy())
return nullptr;
// If we're not accessing anything in this constant, the result is undefined.
@@ -742,7 +732,7 @@ Constant *llvm::ConstantFoldLoadFromConst(Constant *C, Type *Ty,
// Try hard to fold loads from bitcasted strange and non-type-safe things.
if (Offset.getSignificantBits() <= 64)
if (Constant *Result =
- FoldReinterpretLoadFromConst(C, Ty, Offset.getSExtValue(), DL))
+ FoldReinterpretLoadFromConst(C, Ty, Ty, Offset.getSExtValue(), DL))
return Result;
return nullptr;
diff --git a/llvm/test/Transforms/EarlyCSE/load-constant-as-int-or-vector.ll b/llvm/test/Transforms/EarlyCSE/load-constant-as-int-or-vector.ll
deleted file mode 100644
index 181ae68890be3..0000000000000
--- a/llvm/test/Transforms/EarlyCSE/load-constant-as-int-or-vector.ll
+++ /dev/null
@@ -1,62 +0,0 @@
-; RUN: opt -passes=early-cse -S < %s | FileCheck %s
-
- at d8 = private constant [8 x double] [double 1.0, double 2.0, double 3.0, double 4.0, double 5.0, double 6.0, double 7.0, double 8.0], align 64
- at d16 = private constant [16 x double] [double 1.0, double 2.0, double 3.0, double 4.0, double 5.0, double 6.0, double 7.0, double 8.0, double 9.0, double 10.0, double 11.0, double 12.0, double 13.0, double 14.0, double 15.0, double 16.0], align 128
- at w32 = private constant [32 x i16] [
- i16 42, i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7,
- i16 8, i16 9, i16 10, i16 11, i16 12, i16 13, i16 14, i16 15,
- i16 16, i16 17, i16 18, i16 19, i16 20, i16 21, i16 22, i16 23,
- i16 24, i16 25, i16 26, i16 27, i16 28, i16 29, i16 30, i16 31
-], align 2
- at str64 = private constant [64 x i8] c"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", align 1
-
-define <8 x double> @fold_8xdouble_load() {
- ; CHECK-LABEL: @fold_8xdouble_load(
- ; CHECK: ret <8 x double> <double 1.000000e+00, double 2.000000e+00, double 3.000000e+00, double 4.000000e+00, double 5.000000e+00, double 6.000000e+00, double 7.000000e+00, double 8.000000e+00>
- %v = load <8 x double>, ptr @d8, align 64
- ret <8 x double> %v
-}
-
-define double @fold_16xdouble_load() {
- ; CHECK-LABEL: @fold_16xdouble_load(
- ; CHECK: ret double 2.000000e+00
- %v = load <16 x double>, ptr @d16, align 128
- %e = extractelement <16 x double> %v, i32 1
- ret double %e
-}
-
-define i16 @fold_array_to_i512() {
- ; CHECK-LABEL: @fold_array_to_i512(
- ; CHECK: ret i16 42
- %v = load i512, ptr @w32, align 2
- %e = trunc i512 %v to i16
- ret i16 %e
-}
-
-define i16 @fold_array_to_vec() {
- ; CHECK-LABEL: @fold_array_to_vec(
- ; CHECK: ret i16 42
- %v = load <32 x i16>, ptr @w32, align 2
- %e = extractelement <32 x i16> %v, i32 0
- ret i16 %e
-}
-
-define i8 @not_fold_string_to_i512() {
- ; CHECK-LABEL: @not_fold_string_to_i512(
- ; CHECK: %v = load i512, ptr @str64, align 1
- ; CHECK: %e = trunc i512 %v to i8
- ; CHECK: ret i8 %e
- %v = load i512, ptr @str64, align 1
- %e = trunc i512 %v to i8
- ret i8 %e
-}
-
-define i8 @not_fold_string_to_vec() {
- ; CHECK-LABEL: @not_fold_string_to_vec(
- ; CHECK: %v = load <64 x i8>, ptr @str64, align 1
- ; CHECK: %e = extractelement <64 x i8> %v, i32 0
- ; CHECK: ret i8 %e
- %v = load <64 x i8>, ptr @str64, align 1
- %e = extractelement <64 x i8> %v, i32 0
- ret i8 %e
-}
diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll b/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll
index 061c6834eb97d..d34d08470e83f 100644
--- a/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll
+++ b/llvm/test/Transforms/InstSimplify/ConstProp/loads.ll
@@ -477,3 +477,65 @@ define i16 @load_i40_array_partial_padding() {
%v = load i16, ptr getelementptr (i8, ptr @i40_array, i64 4)
ret i16 %v
}
+
+ at g_double17 = private constant [17 x double] [double 1.0, double 2.0, double 3.0, double 4.0, double 5.0, double 6.0, double 7.0, double 8.0, double 9.0, double 10.0, double 11.0, double 12.0, double 13.0, double 14.0, double 15.0, double 16.0, double 17.0], align 128
+
+define double @load_large_vector() {
+; CHECK-LABEL: @load_large_vector(
+; CHECK-NEXT: ret double 2.000000e+00
+;
+ %v = load <16 x double>, ptr @g_double17, align 128
+ %e = extractelement <16 x double> %v, i32 1
+ ret double %e
+}
+
+define double @load_over_limit_vector() {
+; CHECK-LABEL: @load_over_limit_vector(
+; CHECK-NEXT: [[V:%.*]] = load <17 x double>, ptr @g_double17, align 16
+; CHECK-NEXT: [[E:%.*]] = extractelement <17 x double> [[V]], i32 1
+; CHECK-NEXT: ret double [[E]]
+;
+ %v = load <17 x double>, ptr @g_double17, align 16
+ %e = extractelement <17 x double> %v, i32 1
+ ret double %e
+}
+
+define i256 @load_large_integer() {
+; LE-LABEL: @load_large_integer(
+; LE-NEXT: ret i256 28976291862365503006736120693800966795043933029805877287682190766152806825984
+;
+; BE-LABEL: @load_large_integer(
+; BE-NEXT: ret i256 28919752756292594708188688926006760458108315909967150605051527249320239693824
+;
+ %v = load i256, ptr @g_double17, align 32
+ ret i256 %v
+}
+
+define i257 @load_over_limit_integer() {
+; CHECK-LABEL: @load_over_limit_integer(
+; CHECK-NEXT: [[V:%.*]] = load i257, ptr @g_double17, align 64
+; CHECK-NEXT: ret i257 [[V]]
+;
+ %v = load i257, ptr @g_double17, align 64
+ ret i257 %v
+}
+
+ at g_str64 = private constant [64 x i8] c"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", align 1
+
+define i512 @load_large_integer_from_string() {
+; CHECK-LABEL: @load_large_integer_from_string(
+; CHECK-NEXT: [[I:%.*]] = load i512, ptr @g_str64, align 1
+; CHECK-NEXT: ret i512 [[I]]
+;
+ %i = load i512, ptr @g_str64, align 1
+ ret i512 %i
+}
+
+define i8 @load_vector_from_string() {
+; CHECK-LABEL: @load_vector_from_string(
+; CHECK-NEXT: ret i8 49
+;
+ %v = load <64 x i8>, ptr @g_str64, align 1
+ %e = extractelement <64 x i8> %v, i32 1
+ ret i8 %e
+}
>From 4de1a9b15293e5792f41897ff2584502d3afdae6 Mon Sep 17 00:00:00 2001
From: Wenju He <wenju.he at intel.com>
Date: Tue, 21 Apr 2026 02:24:30 +0200
Subject: [PATCH 5/7] add comment for 128, 32 limits and OrigLoadTy
---
llvm/lib/Analysis/ConstantFolding.cpp | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 8a911d26673c1..b3d838edf518a 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -557,8 +557,10 @@ bool ReadDataFromGlobal(Constant *C, uint64_t ByteOffset, unsigned char *CurPtr,
return false;
}
+/// OrigLoadTy is the original type being loaded, while LoadTy is the type
+/// currently being folded (which may be integer type mapped from OrigLoadTy).
Constant *FoldReinterpretLoadFromConst(Constant *C, Type *LoadTy,
- Type *RequestedLoadTy, int64_t Offset,
+ Type *OrigLoadTy, int64_t Offset,
const DataLayout &DL) {
// Bail out early. Not expect to load from scalable global variable.
if (isa<ScalableVectorType>(LoadTy))
@@ -578,8 +580,8 @@ Constant *FoldReinterpretLoadFromConst(Constant *C, Type *LoadTy,
Type *MapTy = Type::getIntNTy(C->getContext(),
DL.getTypeSizeInBits(LoadTy).getFixedValue());
- if (Constant *Res = FoldReinterpretLoadFromConst(C, MapTy, RequestedLoadTy,
- Offset, DL)) {
+ if (Constant *Res =
+ FoldReinterpretLoadFromConst(C, MapTy, OrigLoadTy, Offset, DL)) {
if (Res->isNullValue() && !LoadTy->isX86_AMXTy())
// Materializing a zero can be done trivially without a bitcast
return Constant::getNullValue(LoadTy);
@@ -600,10 +602,13 @@ Constant *FoldReinterpretLoadFromConst(Constant *C, Type *LoadTy,
}
unsigned BytesLoaded = (IntType->getBitWidth() + 7) / 8;
+ // Allow folding of large type loads (e.g. <16 x double>).
if (BytesLoaded > 128 || BytesLoaded == 0)
return nullptr;
- if (BytesLoaded > 32 && RequestedLoadTy->isIntegerTy())
+ // For scalar integer load, use smaller limit to avoid regression when loading
+ // from string literal. Codegen may generate inefficient string operations.
+ if (BytesLoaded > 32 && OrigLoadTy->isIntegerTy())
return nullptr;
// If we're not accessing anything in this constant, the result is undefined.
>From 68a0113e4d04fb76e3b79f8c1ce617b3f834185d Mon Sep 17 00:00:00 2001
From: Wenju He <wenju.he at intel.com>
Date: Tue, 21 Apr 2026 16:48:17 +0800
Subject: [PATCH 6/7] Update llvm/lib/Analysis/ConstantFolding.cpp
Co-authored-by: Nikita Popov <github at npopov.com>
---
llvm/lib/Analysis/ConstantFolding.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index b3d838edf518a..2fa6a922a987c 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -607,7 +607,7 @@ Constant *FoldReinterpretLoadFromConst(Constant *C, Type *LoadTy,
return nullptr;
// For scalar integer load, use smaller limit to avoid regression when loading
- // from string literal. Codegen may generate inefficient string operations.
+ // during memcmp expansion. Codegen may generate inefficient string operations.
if (BytesLoaded > 32 && OrigLoadTy->isIntegerTy())
return nullptr;
>From 449b3466dd20b2bf627fea606449101b782f1a87 Mon Sep 17 00:00:00 2001
From: Wenju He <wenju.he at intel.com>
Date: Tue, 21 Apr 2026 10:49:31 +0200
Subject: [PATCH 7/7] remove 'when loading'
---
llvm/lib/Analysis/ConstantFolding.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 2fa6a922a987c..730bdf186fa4f 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -606,8 +606,8 @@ Constant *FoldReinterpretLoadFromConst(Constant *C, Type *LoadTy,
if (BytesLoaded > 128 || BytesLoaded == 0)
return nullptr;
- // For scalar integer load, use smaller limit to avoid regression when loading
- // during memcmp expansion. Codegen may generate inefficient string operations.
+ // For scalar integer load, use smaller limit to avoid regression during
+ // memcmp expansion. Codegen may generate inefficient string operations.
if (BytesLoaded > 32 && OrigLoadTy->isIntegerTy())
return nullptr;
More information about the llvm-commits
mailing list