[llvm] [GlobalOpt] Preven widenDestArray from shrinking an alloca. (PR #144641)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 17 22:54:56 PDT 2025


https://github.com/topperc created https://github.com/llvm/llvm-project/pull/144641

If the destination alloca for one of the memcpy calls we are
modifying is already larger than our desired size, we shouldn't
replace it with a smaller alloca.

>From 0eebbdcd0bfaf93763899360f41256af30f11b2e Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 17 Jun 2025 22:35:27 -0700
Subject: [PATCH 1/2] Pre-commit test

---
 .../GlobalOpt/ARM/arm-widen-large-alloca.ll   | 27 +++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 llvm/test/Transforms/GlobalOpt/ARM/arm-widen-large-alloca.ll

diff --git a/llvm/test/Transforms/GlobalOpt/ARM/arm-widen-large-alloca.ll b/llvm/test/Transforms/GlobalOpt/ARM/arm-widen-large-alloca.ll
new file mode 100644
index 0000000000000..bfb1a8a8a2ef0
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/ARM/arm-widen-large-alloca.ll
@@ -0,0 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -mtriple=arm-none-eabi -passes=globalopt -S | FileCheck %s
+
+ at .i8 = private unnamed_addr constant [3 x i8] [i8 1, i8 2, i8 3] , align 1
+
+define void @memcpy()  {
+; CHECK-LABEL: define void @memcpy() local_unnamed_addr {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ALLOCA1:%.*]] = alloca [4 x i8], align 1
+; CHECK-NEXT:    [[ALLOCA2:%.*]] = alloca [4 x i8], align 1
+; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @bar(ptr nonnull [[ALLOCA1]])
+; CHECK-NEXT:    [[CALL2:%.*]] = call i32 @bar(ptr nonnull [[ALLOCA2]])
+; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(3) [[ALLOCA1]], ptr noundef nonnull align 1 dereferenceable(3) @.i8, i32 4, i1 false)
+; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(5) [[ALLOCA2]], ptr noundef nonnull align 1 dereferenceable(3) @.i8, i32 4, i1 false)
+; CHECK-NEXT:    ret void
+;
+entry:
+  %alloca1 = alloca [3 x i8], align 1
+  %alloca2 = alloca [5 x i8], align 1
+  %call1 = call i32 @bar(ptr nonnull %alloca1)
+  %call2 = call i32 @bar(ptr nonnull %alloca2)
+  call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(3) %alloca1, ptr noundef nonnull align 1 dereferenceable(3) @.i8, i32 3, i1 false)
+  call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(5) %alloca2, ptr noundef nonnull align 1 dereferenceable(3) @.i8, i32 3, i1 false)
+  ret void
+}
+
+declare i32 @bar(...)

>From 4f5b59fad54e891c09c129e99fe82a921eed6432 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Tue, 17 Jun 2025 22:52:17 -0700
Subject: [PATCH 2/2] [GlobalOpt] Preven widenDestArray from shrinking an
 alloca.

If the destination alloca for one of the memcpy calls we are
modifying is already larger than our desired size, we shouldn't
replace it with a smaller alloca.
---
 llvm/lib/Transforms/IPO/GlobalOpt.cpp                        | 4 ++++
 llvm/test/Transforms/GlobalOpt/ARM/arm-widen-large-alloca.ll | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
index 7db0586386506..f0cd00df23959 100644
--- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
@@ -2103,6 +2103,10 @@ static void widenDestArray(CallInst *CI, const unsigned NumBytesToPad,
     unsigned ElementByteWidth = SourceDataArray->getElementByteSize();
     unsigned int TotalBytes = NumBytesToCopy + NumBytesToPad;
     unsigned NumElementsToCopy = divideCeil(TotalBytes, ElementByteWidth);
+    // Don't change size if already wide enough.
+    if (Alloca->getAllocatedType()->getArrayNumElements() >= NumElementsToCopy)
+      return;
+
     // Update destination array to be word aligned (memcpy(X,...,...))
     IRBuilder<> BuildAlloca(Alloca);
     AllocaInst *NewAlloca = BuildAlloca.CreateAlloca(ArrayType::get(
diff --git a/llvm/test/Transforms/GlobalOpt/ARM/arm-widen-large-alloca.ll b/llvm/test/Transforms/GlobalOpt/ARM/arm-widen-large-alloca.ll
index bfb1a8a8a2ef0..4fca1ffefdcaf 100644
--- a/llvm/test/Transforms/GlobalOpt/ARM/arm-widen-large-alloca.ll
+++ b/llvm/test/Transforms/GlobalOpt/ARM/arm-widen-large-alloca.ll
@@ -7,7 +7,7 @@ define void @memcpy()  {
 ; CHECK-LABEL: define void @memcpy() local_unnamed_addr {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
 ; CHECK-NEXT:    [[ALLOCA1:%.*]] = alloca [4 x i8], align 1
-; CHECK-NEXT:    [[ALLOCA2:%.*]] = alloca [4 x i8], align 1
+; CHECK-NEXT:    [[ALLOCA2:%.*]] = alloca [5 x i8], align 1
 ; CHECK-NEXT:    [[CALL1:%.*]] = call i32 @bar(ptr nonnull [[ALLOCA1]])
 ; CHECK-NEXT:    [[CALL2:%.*]] = call i32 @bar(ptr nonnull [[ALLOCA2]])
 ; CHECK-NEXT:    call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(3) [[ALLOCA1]], ptr noundef nonnull align 1 dereferenceable(3) @.i8, i32 4, i1 false)



More information about the llvm-commits mailing list