[all-commits] [llvm/llvm-project] 832df1: [SROA] Enable alloca promotion for stores through ...
Yonah Goldberg via All-commits
all-commits at lists.llvm.org
Mon Sep 21 12:08:39 PDT 2026
Branch: refs/heads/main
Home: https://github.com/llvm/llvm-project
Commit: 832df12314030ea46e1ea506cabd98d805ae7ce7
https://github.com/llvm/llvm-project/commit/832df12314030ea46e1ea506cabd98d805ae7ce7
Author: Yonah Goldberg <ygoldberg at nvidia.com>
Date: 2026-09-21 (Mon, 21 Sep 2026)
Changed paths:
M llvm/lib/Transforms/Scalar/SROA.cpp
M llvm/test/CodeGen/NVPTX/lower-byval-args.ll
M llvm/test/Transforms/SROA/phi-and-select.ll
A llvm/test/Transforms/SROA/phi-store.ll
Log Message:
-----------
[SROA] Enable alloca promotion for stores through pointer PHIs (#222893)
A store to an alloca through a phi-node prevents promotion of that
alloca in mem2reg. Mem2reg requires all users of the alloca to be
loads/stores. Fixes https://github.com/llvm/llvm-project/issues/202670.
The following is a motivating example:
```llvm
define i32 @store_to_phi(i1 %cond, i32 %value) {
entry:
%a = alloca i32, align 4
%b = alloca i32, align 4
store i32 0, ptr %a, align 4
store i32 0, ptr %b, align 4
br i1 %cond, label %left, label %right
left:
br label %merge
right:
br label %merge
merge:
%ptr = phi ptr [ %a, %left ], [ %b, %right ]
store i32 %value, ptr %ptr, align 4
%a.value = load i32, ptr %a, align 4
%b.value = load i32, ptr %b, align 4
%result = add i32 %a.value, %b.value
ret i32 %result
}
```
To promote, we can rewrite this so that we store on each branch, before
the phi:
```llvm
define i32 @store_to_phi(i1 %cond, i32 %value) {
entry:
%a = alloca i32, align 4
%b = alloca i32, align 4
store i32 0, ptr %a, align 4
store i32 0, ptr %b, align 4
br i1 %cond, label %left, label %right
left:
store i32 %value, ptr %a, align 4
br label %merge
right:
store i32 %value, ptr %b, align 4
br label %merge
merge:
%a.value = load i32, ptr %a, align 4
%b.value = load i32, ptr %b, align 4
%result = add i32 %a.value, %b.value
ret i32 %result
}
```
Now we can promote.
```llvm
define i32 @store_to_phi(i1 %cond, i32 %value) {
entry:
br i1 %cond, label %left, label %right
left:
br label %merge
right:
br label %merge
merge:
%a.value = phi i32 [ %value, %left ], [ 0, %right ]
%b.value = phi i32 [ 0, %left ], [ %value, %right ]
%result = add i32 %a.value, %b.value
ret i32 %result
}
```
Later optimizations can reduce this to just `ret i32 %value`.
You can't always move the store directly into the phi's direct
predecessor. You can only do this if that predecessor's only has one
successor. Consider the following example:
```llvm
define void @store_to_phi_split_edge(
i1 %choose_right, i1 %take_store, i32 %value, ptr %out) {
entry:
%a = alloca i32, align 4
br i1 %choose_right, label %right, label %left
left:
br label %merge
right:
br i1 %take_store, label %merge, label %exit
merge:
%ptr = phi ptr [ %a, %left ], [ %out, %right ]
store i32 %value, ptr %ptr, align 4
br label %exit
exit:
ret void
}
```
If we moved the store into the `right` branch, then we will now execute
the store when `right` branches directly to `exit`, whereas previously
we didn't. We fix this by splitting the `right` branch:
```llvm
define void @store_to_phi_split_edge(
i1 %choose_right, i1 %take_store, i32 %value, ptr %out) {
entry:
%a = alloca i32, align 4
br i1 %choose_right, label %right, label %left
left:
store i32 %value, ptr %a, align 4
br label %merge
right:
br i1 %take_store, label %right.to.merge, label %exit
right.to.merge:
store i32 %value, ptr %out, align 4
br label %merge
merge:
br label %exit
exit:
ret void
}
```
AI assisted.
To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications
More information about the All-commits
mailing list