[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